Setup

Include the following script element in your HTML, substituting in the domain your Komo hub is hosted on:

<script>
(function(n,r,t,c,u,e,f){
  n[u]=n[u]||function(q){return new Proxy(q,{
    get(y,s){return s==="q"?y[s]||[]:
    function(...B){(n[u].q=n[u].q||[]).push([s,...B])}}})
  }({});
  e=r.createElement(t);f=r.getElementsByTagName(t)[0];
  e.async=1;e.src=c;f.parentNode.insertBefore(e,f);
})(window,document,"script","https://KOMO_HUB_URL/assets/embed/embed.js","komoEmbed");
</script>

Cards

Live examples on this page load the embed script from Komo’s demo hub (komohub.komo.site) so covers and triggers work as on a real site.

Full-page modal

Open a card in a full-page modal in 3 ways: a generated cover, a click trigger on your own markup, or JavaScript.

  1. Card Covers

    Card covers are an image or image & button which will launch the card experience in a full page modal. To setup a card cover have a HTML element marked with 2 data attributes. The first is data-komo-embed-card-cover. This lets our embed code know that what to look for. The second is data-komo-embed. This holds data for which card and styling options. When the embed code loads, it will find all elements with data-komo-embed-card-cover and replace the element with the card cover. Clicking the cover will load the card in a full-page modal.

    Code - Replace CARD_ID with yours

    <div
      data-komo-embed-card-cover
      data-komo-embed='{"cardId":"CARD_ID","styles":{"embedStyle": "ImageButton","embedWidth": "unset"}}'
    ></div>

    Live Example

  2. Card Triggers

    Card triggers allow you to mark any HTML element as a card trigger. A card trigger will launch the card experience in a full page modal when clicked. To setup an element as a card trigger, simply add data-komo-embed-card-trigger={CARD_ID} as an attribute. When the embed code loads, it will find all elements with data-komo-embed-card-trigger and add an on click handler to load the card in a full-page modal.

    Code - Replace CARD_ID with yours

    <button
      class="bg-yellow-500 hover:bg-yellow-400 text-black font-bold py-2 px-4 rounded"
      data-komo-embed-card-trigger="CARD_ID"
    >
      Show me Komo!
    </button>

    Live Example

  3. Javascript

    Once the setup script is loaded, you will have access to the komoEmbed javascript object. This can be used to programmatically register card triggers or open a card experience directly.

    Code - Replace CARD_ID with yours

    /**
     * Registers a card trigger to open a Komo card when the specified element is clicked.
     *
     * @param {string} cardId - The unique identifier of the card you want to display.
     * @param {string} domSelector - A DOM selector string to select the trigger element(s).
     */
    komoEmbed.registerCardTrigger('CARD_ID', '#yourElementId');

    A domSelector is a DOM selector used to locate elements in your document. You can learn more about DOM selectors here.

    Code - Replace CARD_ID with yours

    /**
     * Opens the specified card experience in a full screen modal.
     */
    komoEmbed.openExperience({ type: 'card', id: 'CARD_ID' });
    /**
     * Closes the currently open experience modal.
     */
    komoEmbed.closeExperience();
    /**
     * Hides the currently open experience modal without closing it.
     * The modal remains open but becomes invisible to the user.
     */
    komoEmbed.hideExperience();
    /**
     * Shows a previously hidden experience modal.
     */
    komoEmbed.unhideExperience();

Loading covers and triggers after the first page load

The SDK scans the document when embed.js first loads. If you inject cover or trigger markup later (SPA route changes, lazy-loaded sections, CMS widgets), call komoEmbed.load() again so the SDK can discover the new elements.

// After inserting a cover or trigger into the DOM:
komoEmbed.load();

For triggers you can also call komoEmbed.registerCardTrigger(cardId, selector) on the new element instead of relying on another full scan.

In-page cards

In-page mounts render the card experience directly in your page layout (no cover teaser, no full-page modal). Mark a placeholder with data-komo-embed-card-in-page and supply card config via data-komo-embed. The iframe grows with card content. Maximum embedWidth is capped at 672px.

Code - Replace CARD_ID with yours

<div
  data-komo-embed-card-in-page
  data-komo-embed='{"cardId":"CARD_ID","styles":{"embedWidth":"672px"}}'
></div>

Loading in-page embeds after the first page load

Same rule as covers and triggers: once an in-page placeholder with the attributes above is in the DOM (for example after an SPA route change or lazy section), call komoEmbed.load() again so the SDK can discover and mount it.

komoEmbed.load();

If you re-insert a placeholder that already includes a stable embedId in data-komo-embed, the SDK treats that id as already mounted and will skip it. Omit embedId (the SDK generates one) or use a new embedId when remounting the same placement after removing it from the DOM.

Form Prefilling

Any form within an experience can be prefilled in the embed experience. We can accomplish this in 2 ways.

  1. URL Query Parameters

    Form fields on cards can be pre-filled with information based on the query string parameters in a given URL (learn more). This also works on the page that the embed is hosted on.

  2. Javascript

    Once the setup script is loaded, you will have access to the komoEmbed javascript object. This can be used to programmatically prefill forms.

    /**
     * Sets a prefill value for a specific form field.
     * @param {string} fieldName - The name of the form field to prefill.
     * @param {string} value - The value to prefill the form field with.
     */
    komoEmbed.setFormPrefillValue('email', 'user@example.com');
    
    /**
     * Sets prefill values for multiple form fields at once.
     * @param {Record<string, string>} values - An object containing key-value pairs
     * where the key is the form field name and the value is the prefill value.
     */
    komoEmbed.setFormPrefillValues({
      first_name: 'John',
      last_name: 'Doe',
      email: 'john.doe@example.com'
    });

Listening for events from the embedded experience

  • You can listen for events from the embedded experience by using the listenToKomoEvents, listenToAuthTokenProcessed, or listenToWindowMessageEvents methods on the komoEmbed object.
  • The listenToKomoEvents method exposes any User Interaction Events from the embedded experience.
  • The listenToAuthTokenProcessed method is triggered after the embedded experience finishes processing an authentication token.
  • The listenToWindowMessageEvents method exposes any window.postMessage events from the embedded experience.
    • Note: User Interaction Events will also appear in the listenToWindowMessageEvents callback. listenToKomoEvents is a more convenient way to listen for Komo User Interaction Events from the embedded experience.

Example Code

/**
 * Convenience method for subscribing to frontend komo-events coming from the embedded experience.
 * @param {Function} callback - The callback to be called when a komo-event is received.
 * @returns {Function} A function to unsubscribe from the event listener.
 */
const unsubscribeFromKomoEvents = komoEmbed.listenToKomoEvents((event) => {
  console.log('Komo event received:', event);
  // event has the structure:
  // {
  //   eventName: string,
  //   eventData: any,
  //   extensionData?: Record<string, string | number | boolean | object>,
  //   trackedData?: Record<string, string | number | boolean | object>
  // }
});

/**
 * Convenience method for subscribing to any window message events raised by the embedded experience.
 * @param {Function} callback - The callback to be called when a window message event is received.
 * @returns {Function} A function to unsubscribe from the event listener.
 */
const unsubscribeFromWindowMessages = komoEmbed.listenToWindowMessageEvents(
  (payload) => {
    console.log('Window message received:', payload);
  }
);

// To stop listening for events, call the unsubscribe functions:
// unsubscribeFromKomoEvents();
// unsubscribeFromWindowMessages();

Extension Data

The browser embed SDK allows you to set extension data on the user interaction events. There are 2 ways to set extension data.

URL Query Parameters

Extension data can be set with information based on the query string parameters in a given URL (learn more). This also works on the page that the embed is hosted on.

Javascript

Once the setup script is loaded, you will have access to the komoEmbed javascript object. This can be used to programmatically set extension data.

/**
 * Sets extension data value for a specific key.
 * @param {string} key - The key of the extension data
 * @param {string | number | boolean | object} value - The extension data value
 */
komoEmbed.setExtensionDataValue('custom_unique_id', 'ABC123');
komoEmbed.setExtensionDataValue('custom_object', {
  some_id: 'ABC123',
  some_measure: 123456
});

/**
 * Sets extension data values for multiple keys at once.
 * @param {Record<string, string | number | boolean | object>} values - An object containing key-value pairs
 * where the key is the extension data key and the value is the extension data value.
 */
komoEmbed.setExtensionDataValues({
  custom_unique_id: 'ABC123',
  custom_object: {
    some_id: 'ABC123',
    some_measure: 123456
  }
});

Query Parameters

Pass custom query parameters (like UTM tracking parameters) to your embedded experiences using three different methods: inline configuration, programmatic API, or query parameter forwarding.

Inline Configuration

Add query parameters directly in your embed configuration.

Card Cover with Query Params

Replace CARD_ID with yours

<div
  data-komo-embed-card-cover
  data-komo-embed='{
    "cardId": "CARD_ID",
    "styles": {
      "embedStyle": "ImageButton",
      "embedWidth": "500px"
    },
    "queryParams": {
      "utm_source": "website",
      "utm_medium": "embed",
      "utm_campaign": "spring-promo",
      "utm_content": "homepage-hero"
    }
  }'
></div>

Card Trigger with Query Params

Replace CARD_ID with yours

<button
  data-komo-embed-card-trigger="CARD_ID"
  data-komo-embed='{
    "queryParams": {
      "utm_source": "newsletter",
      "utm_medium": "email",
      "utm_campaign": "weekly-digest"
    }
  }'
>
  Click to Play
</button>

Programmatic API

Set query parameters using JavaScript before or after page load.

Global Query Params (All Embeds)

/**
 * Apply query parameters to all embeds on the page
 */
komoEmbed.setQueryParam('utm_source', 'homepage');
komoEmbed.setQueryParams({
  utm_medium: 'banner',
  utm_campaign: 'summer-2024'
});

Card-Specific Query Params

/**
 * Apply query parameters only to a specific card embed
 * @param {string} key - The query parameter name
 * @param {string} value - The query parameter value
 * @param {string} cardId - The card ID to apply the parameter to
 */
komoEmbed.setQueryParam('utm_content', 'variant-a', 'your-card-id');
komoEmbed.setQueryParams(
  {
    utm_term: 'keyword',
    custom_param: 'value'
  },
  'your-card-id'
);

Register Trigger with Query Params

/**
 * Register a card trigger with query parameters
 */
komoEmbed.registerCardTrigger('your-card-id', '.my-trigger-button', {
  queryParams: {
    utm_source: 'sidebar',
    utm_medium: 'widget'
  }
});

Open Experience with Query Params

/**
 * Open an experience with query parameters
 */
komoEmbed.openExperience({
  type: 'card',
  id: 'your-card-id',
  options: {
    queryParams: {
      utm_source: 'modal',
      utm_medium: 'popup'
    }
  }
});

Query Parameter Forwarding

Automatically forward query parameters from your host page to the embedded experience.

<div
  data-komo-embed-card-cover
  data-komo-embed='{
    "cardId": "CARD_ID",
    "styles": {"embedStyle": "ImageButton"},
    "forwardQueryParams": true
  }'
></div>

How it works:

  • If your page URL is https://example.com/?utm_source=google&utm_medium=cpc
  • With forwardQueryParams: true, those params are automatically passed to the embed
  • The embedded experience receives: ?utm_source=google&utm_medium=cpc

Parameter Precedence

When multiple sources provide the same query parameter, later sources override earlier ones:

  1. Forwarded params (base layer) - from host page if forwardQueryParams: true
  2. Global params - from setQueryParam() without cardId
  3. Card-specific params - from setQueryParam() with cardId or inline config

Common Use Cases

UTM Tracking for Campaign Attribution

<div
  data-komo-embed-card-cover
  data-komo-embed='{
    "cardId": "prize-wheel",
    "styles": {"embedStyle": "ImageButton"},
    "queryParams": {
      "utm_source": "email",
      "utm_medium": "newsletter",
      "utm_campaign": "black-friday-2024",
      "utm_content": "main-cta"
    }
  }'
></div>

Dynamic Campaign Tracking

// Extract campaign info from your app
const campaignId = getCurrentCampaignId();
const userSegment = getUserSegment();

komoEmbed.setQueryParams({
  utm_campaign: campaignId,
  utm_content: userSegment,
  source: 'web-app'
});

Pass-Through UTM Parameters

Useful when you're running paid ads:

<div
  data-komo-embed-card-cover
  data-komo-embed='{
    "cardId": "contest-entry",
    "styles": {"embedStyle": "ImageButton"},
    "forwardQueryParams": true,
    "queryParams": {
      "utm_medium": "website"
    }
  }'
></div>

Result: If user arrives via ?utm_source=facebook&utm_campaign=q1-promo, the embed receives both those params plus your override for utm_medium=website.

Technical Details

  • Query parameters are added directly to the iframe URL (no prefix)
  • All values must be strings
  • Parameters are available to analytics tools in the embedded experience
  • Can be combined with form prefill and extension data features
  • Supports standard UTM parameters and custom parameters

Authentication

Configured session authentication is the preferred option when your website owns user identity. Use legacy iframe authentication only for older integrations that cannot configure Workspace App session auth.

Configured session authentication

Use a Workspace App ID and getIdentityToken together. Copy the SDK App ID from Komo Portal. It uses {region}_{appId} format, for example au1_00000000-0000-0000-0000-000000000000. See Workspace Apps for setup steps and identity result behavior.

Call komoEmbed.init(...) in the loader snippet before embed.js has loaded. Late init calls after embed.js loads are ignored.

<script>
(function(n,r,t,c,u,e,f){
  n[u]=n[u]||function(q){return new Proxy(q,{
    get(y,s){return s==="q"?y[s]||[]:
    function(...B){(n[u].q=n[u].q||[]).push([s,...B])}}})
  }({});
  e=r.createElement(t);f=r.getElementsByTagName(t)[0];
  e.async=1;e.src=c;f.parentNode.insertBefore(e,f);
})(window,document,"script","https://KOMO_HUB_URL/assets/embed/embed.js","komoEmbed");

komoEmbed.init('au1_00000000-0000-0000-0000-000000000000', {
  getIdentityToken: async () => {
    const token = await getHostJwt();
    return token ? { type: 'jwt', token } : { type: 'anonymous' };
  },
  onAuthenticated: ({ contactId, trustLevel }) => {
    console.log('Komo authenticated', contactId, trustLevel);
  },
  onIdentityChanged: ({ previousContactId, contactId, reason }) => {
    console.log('Komo identity changed', previousContactId, contactId, reason);
  },
  onSessionExpired: ({ reason }) => {
    console.log('Komo session expired', reason);
  }
});
</script>

Identity results

getIdentityToken returns the identity payload Komo exchanges for an SDK session. The examples below show the init options only. Place the init call in the loader snippet before embed.js loads. See When getIdentityToken runs for call frequency and refresh behavior.

Use a host JWT when your website has an authenticated user:

komoEmbed.init('au1_00000000-0000-0000-0000-000000000000', {
  getIdentityToken: async () => ({
    type: 'jwt',
    token: await getHostJwt()
  })
});

Use verified attributes when your website can provide email identity without a host JWT. Attribute keys map to matching Komo contact properties by default, attributes.email is required:

komoEmbed.init('au1_00000000-0000-0000-0000-000000000000', {
  getIdentityToken: async () => ({
    type: 'email',
    attributes: {
      email: currentUser.email,
      first_name: currentUser.firstName,
      last_name: currentUser.lastName
    }
  })
});

Use anonymous identity when no host JWT exists but embeds should work for visitors:

komoEmbed.init('au1_00000000-0000-0000-0000-000000000000', {
  getIdentityToken: () => ({ type: 'anonymous' })
});

Use no-session identity only when your page can handle missing session-backed SDK features:

komoEmbed.init('au1_00000000-0000-0000-0000-000000000000', {
  getIdentityToken: () => ({ type: 'none' })
});

{ type: 'none' } means no Komo session. Session-backed SDK features will not work and no legacy iframe auth fallback occurs.

Session callbacks

Use callbacks for analytics, UI changes, and retry flows:

komoEmbed.init('au1_00000000-0000-0000-0000-000000000000', {
  getIdentityToken: async () => {
    const token = await getHostJwt();
    return token ? { type: 'jwt', token } : { type: 'anonymous' };
  },
  onAuthenticated: ({ contactId, trustLevel }) => {
    trackKomoAuth(contactId, trustLevel);
  },
  onIdentityChanged: ({ previousContactId, contactId, reason }) => {
    trackKomoIdentityChange(previousContactId, contactId, reason);
  },
  onSessionExpired: ({ reason }) => {
    promptUserToSignInAgain(reason);
  }
});

Session helpers

Configured session auth exposes helpers on komoEmbed:

const session = komoEmbed.getCurrentSession();
console.log(session.state);

await komoEmbed.identifyUser();

komoEmbed.logoutUser();
  • getCurrentSession() returns the current configured-auth session snapshot.
  • identifyUser() runs identity exchange again using the latest getIdentityToken result.
  • logoutUser() logs out the current configured-auth session.

Legacy iframe authentication

Use these methods only for legacy no-configured-auth iframe session transfer flows.

  1. Setting authentication data

    You can proactively set an authentication token for the embedded iframe. The token will be sent to the embedded experience.

    komoEmbed.setAuthToken({
      token: 'your-jwt-token-here',
      type: 'jwt'
    });

    You can register a listener to be notified when the embedded experience finishes processing the token:

    const unsubscribeFromAuth = komoEmbed.listenToAuthTokenProcessed(
      ({ success, errorMessage }) => {
        if (success) {
          console.log('Authentication completed');
        } else {
          console.error('Authentication failed', errorMessage);
        }
      }
    );
    
    unsubscribeFromAuth();
  2. Clearing authentication

    If you need to sign the current user out of embedded experiences, call komoEmbed.forgetUser().

    komoEmbed.forgetUser();
  3. Handling authentication requests

    If an embedded Komo experience requires authentication and no token has been set via komoEmbed.setAuthToken, the SDK can call a handler registered with komoEmbed.setAuthRequestHandler(handler).

    komoEmbed.setAuthRequestHandler(async () => {
      try {
        komoEmbed.hideExperience();
    
        const token = await showAuthModal();
    
        komoEmbed.setAuthToken({
          token,
          type: 'jwt'
        });
    
        closeAuthModal();
        komoEmbed.unhideExperience();
      } catch (error) {
        console.error('Authentication failed:', error);
        komoEmbed.unhideExperience();
        throw error;
      }
    });