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.
-
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 isdata-komo-embed. This holds data for which card and styling options. When the embed code loads, it will find all elements withdata-komo-embed-card-coverand replace the element with the card cover. Clicking the cover will load the card in a full-page modal.Code - Replace
CARD_IDwith yours<div data-komo-embed-card-cover data-komo-embed='{"cardId":"CARD_ID","styles":{"embedStyle": "ImageButton","embedWidth": "unset"}}' ></div>Live Example
-
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 withdata-komo-embed-card-triggerand add anon clickhandler to load the card in a full-page modal.Code - Replace
CARD_IDwith 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
-
Javascript
Once the setup script is loaded, you will have access to the
komoEmbedjavascript object. This can be used to programmatically register card triggers or open a card experience directly.Code - Replace
CARD_IDwith 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 selectorused to locate elements in your document. You can learn more aboutDOM selectorshere.Code - Replace
CARD_IDwith 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.
-
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.
-
Javascript
Once the setup script is loaded, you will have access to the
komoEmbedjavascript 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, orlistenToWindowMessageEventsmethods on thekomoEmbedobject. - The
listenToKomoEventsmethod exposes any User Interaction Events from the embedded experience. - The
listenToAuthTokenProcessedmethod is triggered after the embedded experience finishes processing an authentication token. - The
listenToWindowMessageEventsmethod exposes anywindow.postMessageevents from the embedded experience.- Note: User Interaction Events will also appear in the
listenToWindowMessageEventscallback.listenToKomoEventsis a more convenient way to listen for Komo User Interaction Events from the embedded experience.
- Note: User Interaction Events will also appear in the
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:
- Forwarded params (base layer) - from host page if
forwardQueryParams: true - Global params - from
setQueryParam()without cardId - 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 latestgetIdentityTokenresult.logoutUser()logs out the current configured-auth session.
Legacy iframe authentication
Use these methods only for legacy no-configured-auth iframe session transfer flows.
-
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(); -
Clearing authentication
If you need to sign the current user out of embedded experiences, call
komoEmbed.forgetUser().komoEmbed.forgetUser(); -
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 withkomoEmbed.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; } });