# Embed SDK

Learn how to embed Komo experiences into your website or application.

## Setup

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

> **Important Note**
>
> Ensure you substitute in the **KOMO_HUB_HOST** hostname below. Use the Site
> hostname only, without `https://` or a path.

Komo Site URL: `https://my-awesome-hub.komo.site`

```html
<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://my-awesome-hub.komo.site/assets/embed/embed.js","komoEmbed");
</script>
```

## Cards

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

Cards can be embedded in 3 ways.

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 let's 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**

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

   **Live Example**

Live card cover example for card ID `2092eac3-a0b5-4187-a392-f84dc3cae941`.

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**

   ```html
   <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**

Live card trigger button example for card ID `2092eac3-a0b5-4187-a392-f84dc3cae941`.

3. **Javascript**

   Once the [setup script](#setup) 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.

> **Caution**
>
> Ensure any javascript code calling **komoEmbed** are in scripts **below**
> the [setup script](#setup).

   **Code - Replace `CARD_ID` with yours**

   ```js
   /**
    * 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](https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Locating_DOM_elements_using_selectors).

   **Code - Replace `CARD_ID` with yours**

   ```js
   /**
    * Opens the specified card experience in a full screen modal.
    */
   komoEmbed.openExperience({ type: 'card', id: 'CARD_ID' });
   ```

   ```js
   /**
    * Closes the currently open experience modal.
    */
   komoEmbed.closeExperience();
   ```

   ```js
   /**
    * Hides the currently open experience modal without closing it.
    * The modal remains open but becomes invisible to the user.
    */
   komoEmbed.hideExperience();
   ```

   ```js
   /**
    * Shows a previously hidden experience modal.
    */
   komoEmbed.unhideExperience();
   ```

## 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](/forms#pre-filling-from-url-query-parameters)). This also works on the page that the embed is hosted on.

2. **Javascript**

   Once the [setup script](#setup) is loaded, you will have access to the `komoEmbed` javascript object.
   This can be used to programmatically prefill forms.

> **Caution**
>
> Ensure any javascript code calling **komoEmbed** are in scripts **below**
> the [setup script](#setup).

   ```js
   /**
    * 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](/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.

> **Caution**
>
> Ensure any javascript code calling **komoEmbed** are in scripts **below** the
> [setup script](#setup).

### Example Code

```js
/**
 * 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 }
});

/**
 * 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](/user-interaction-events/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](/user-interaction-events/extension-data#1-extension-data-from-url-query-parameters)). This also works on the page that the embed is hosted on.

### Javascript

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

> **Caution**
>
> Ensure any javascript code calling **komoEmbed** are in scripts **below** the
> [setup script](#setup).

```js
/**
 * 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

```html
<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

```html
<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.

> **Caution**
>
> Ensure any javascript code calling **komoEmbed** are in scripts **below** the
> [setup script](#setup).

#### Global Query Params (All Embeds)

```js
/**
 * 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

```js
/**
 * 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

```js
/**
 * 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

```js
/**
 * 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.

```html
<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

```html
<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

```js
// 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:

```html
<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

The browser embed SDK supports authentication for embedded experiences that require user authentication. There are two main approaches:

1. **Setting Authentication Data**

   You can proactively set an authentication token before or after the experience loads. The token will be automatically sent to the embedded experience.

> **Caution**
>
> Ensure any javascript code calling **komoEmbed** are in scripts **below**
> the [setup script](#setup).

   ```js
   /**
    * Sets an authentication token for the embedded experience.
    * This token will be passed to the embedded experience for authentication.
    * @param {Object} payload - The authentication payload
    * @param {string} payload.token - The authentication token (e.g., JWT)
    * @param {string} payload.type - The type of token (currently supports 'jwt')
    */
   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:

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

   // Later, when you no longer need the callback:
   unsubscribeFromAuth();
   ```

2. **Clearing Authentication**

   If you need to sign the current user out of any embedded experiences (for example, when they log out of your host application), call `komoEmbed.forgetUser()`. This clears the active session inside the embed and triggers any necessary cleanup in the Komo experience.

   ```js
   /**
    * Clears any previously provided authentication details for embedded experiences.
    */
   komoEmbed.forgetUser();
   ```

3. **Handling Authentication Requests**

   If an embedded Komo experience requires authentication and no token has been set via `komoEmbed.setAuthToken`, the embed SDK will automatically call a handler function that you can register using `komoEmbed.setAuthRequestHandler(handler)`.

   This allows you to show your own authentication modal, collect credentials, and then provide the token back to the embed.

   ```js
   /**
    * Sets a handler function that will be called when the embedded experience
    * requires authentication.
    * @param {Function} handler - An async function that handles the authentication flow
    */
   komoEmbed.setAuthRequestHandler(async () => {
     try {
       console.log('Komo embed requesting authentication');

       // Hide Komo's modal temporarily to avoid z-index issues
       komoEmbed.hideExperience();

       // Show your authentication modal and wait for user to authenticate
       const token = await showAuthModal();

       // Set the token once authentication is complete
       komoEmbed.setAuthToken({
         token: token,
         type: 'jwt'
       });

       // Close your auth modal
       closeAuthModal();

       // Show Komo's modal again
       komoEmbed.unhideExperience();
     } catch (error) {
       console.error('Authentication failed:', error);

       // Ensure Komo's modal is shown again even on error
       komoEmbed.unhideExperience();

       throw error;
     }
   });
   ```
