React Native Embedding
Komo cards can be embedded into your React Native application through Komo’s NPM package @komo-tech/react-native-widgets .
Installation
npm install @komo-tech/react-native-widgetsNOTE: @komo-tech/react-native-widgets has a peer dependency on react-native-webview , and recommends the latest major version, 13.x.
Basic Usage
- The quickest way to get started with embedding Komo content in react native is by using the
KomoCardWidgetcomponent. - This component combines metadata fetching, card cover display, and modal handling for the card experience.
- The only required prop is
embedMetaUrl. To find this in the Komo portal:- Navigate to the settings of the card to be embedded.
- Select the
Embedtab and click onReact Native codein the right sidebar. - Copy the
Card embed meta URLand use it as the value of theembedMetaUrlprop.
import { KomoCardWidget } from '@komo-tech/react-native-widgets';
// ...
<KomoCardWidget
embedMetaUrl={KomoCardNativeEmbedUrl}
containerStyle={{ maxWidth: '80%' }}
/>;Prefilling form details
- You can pass information through to the Komo experience that will be pre-filled in any forms that the user may encounter.
- Pass a plain
Record<string,string>object of keys and values through to theformPrefillValuesprop onKomoCardWidgetorExperienceModal. - The object keys must match the Unique ID of the form field or contact property from the Komo Platform that you want to prefill.
<KomoCardWidget
embedMetaUrl={KomoCardNativeEmbedUrl}
containerStyle={{ maxWidth: '80%' }}
formPrefillValues={{
email: 'email@domain.com',
first_name: 'Person',
last_name: 'Doe'
}}
/>Advanced usage
Metadata fetching
- The first step to using embedded Komo content involves fetching the card metadata.
- Use the
useFetchCardMetadatahook and theNative embed URLcopied from the platform to fetch the CardEmbedMetadata. - The CardEmbedMetadata has the information required to render the cover image (
imageUrl) and the URL (embedUrl) that the ExperienceModal needs to render the embedded experience. - Note: you can use your own data-fetching patterns if you require more advanced data fetching handling. So long as it produces a CardEmbedMetadata, you can pass that to the other components that you want to use.
import { useFetchCardMetadata } from '@komo-tech/react-native-widgets';
// ... rest of your component
const { data, isLoading, isError } = useFetchCardMetadata({
embedMetaUrl: KomoCardNativeEmbedUrl
});
// ... use the data.Render a Card Cover
- The
CardCovercomponent is used to display the cover image of a Komo card. - It handles loading states, error states, and button display.
- The component requires an
onClickhandler andisLoadingstate. - The
imageUrlandimageAspectRatioprops are typically obtained from the CardEmbedMetadata.
import { CardCover } from '@komo-tech/react-native-widgets';
// ... rest of your component
<CardCover
imageUrl={metadata?.imageUrl}
imageAspectRatio={metadata?.imageAspectRatio}
isLoading={isLoading}
isError={isError}
onClick={() => doSomethingOnCoverClicked()}
metaButtonStyle={metadata?.buttonStyle}
containerStyle={{ borderRadius: 8 }}
/>;Using the Experience Modal
- The
ExperienceModalcomponent is used to display the full Komo experience in a modal overlay. - It handles loading states, error states, and communication with the embedded experience.
- The component requires an
isOpenstate andonClosehandler. - A valid
embedUrlprop is required for the experience modal to function, and this is typically obtained from the CardEmbedMetadata. - If you have forced OAuth enabled, you also need to pass through the
embedAuthUrlfrom CardEmbedMetadata.
import { ExperienceModal } from '@komo-tech/react-native-widgets';
// ... rest of your component
<ExperienceModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
embedUrl={metadata?.embedUrl}
embedAuthUrl={metadata?.embedAuthUrl}
loadingTimeoutMs={15000} // Optional: customize loading timeout
appId="my-app" // Optional: identify where the content is embedded
/>;Experience Modal example without Card Cover
- You can use whichever components you want to build your desired experience.
- For example, you can trigger the
ExperienceModalwithout rendering our CardCover.
// ... rest of your component
const { data, isLoading } = useFetchCardMetadata({
isEnabled,
embedMetaUrl: EmbedMetaUrlFromKomoPortal
});
const [modalOpen, setModalOpen] = useState(false);
// other code, e.g. some element that calls setModalOpen(true) after isLoading returns false
<ExperienceModal
isOpen={modalOpen}
onClose={() => {
setModalOpen(false);
}}
embedUrl={data?.embedUrl}
/>;Listening for events from the embedded experience
- You can listen for events from the embedded experience by using the
onWindowMessageoronKomoEventprops on theExperienceModalorKomoCardWidget. - The
onWindowMessageprop exposes anywindow.postMessageevents from the embedded experience. - The
onKomoEventprop exposes any User Interaction Events from the embedded experience.- Note: User Interaction Events will also appear in the
onWindowMessagecallback.onKomoEventis a more convenient way to listen for Komo User Interaction Events from the embedded experience.
- Note: User Interaction Events will also appear in the
<ExperienceModal
isOpen={modalOpen}
onClose={() => {
setModalOpen(false);
}}
embedUrl={data?.embedUrl}
onKomoEvent={(event) => {
console.log('Komo event received:', event);
}}
onWindowMessage={(event) => {
console.log('Window message received:', event);
}}
/>Extension Data
- The
ExperienceModalandKomoCardWidgetcomponents allow you to set extension data on the user interaction events. - The
extensionDataValuesprop is a plainRecord<string, string | number | boolean | object>object. - Make sure PII is not passed in as extension data, as it is passed directly to your tag manager integrations.
<KomoCardWidget
embedMetaUrl={KomoCardNativeEmbedUrl}
extensionDataValues={{
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. This is useful for campaign attribution, A/B testing, and analytics tracking.
Basic Usage
import { KomoCardWidget } from '@komo-tech/react-native-widgets';
<KomoCardWidget
embedMetaUrl={KomoCardNativeEmbedUrl}
queryParams={{
utm_source: 'mobile-app',
utm_medium: 'widget',
utm_campaign: 'summer-2024',
utm_content: 'hero-banner'
}}
/>UTM Tracking Example
<KomoCardWidget
embedMetaUrl={embedUrl}
queryParams={{
utm_source: 'instagram',
utm_medium: 'social',
utm_campaign: 'product-launch',
utm_term: 'keyword',
utm_content: 'story-swipe-up'
}}
/>Dynamic Campaign Tracking
import { KomoCardWidget } from '@komo-tech/react-native-widgets';
import { useRoute } from '@react-navigation/native';
function CampaignScreen() {
const route = useRoute();
const { campaignId, source } = route.params;
return (
<KomoCardWidget
embedMetaUrl={embedUrl}
queryParams={{
utm_campaign: campaignId,
utm_source: source,
utm_medium: 'app'
}}
/>
);
}User Segment Tracking
import { KomoCardWidget } from '@komo-tech/react-native-widgets';
import { useUser } from './hooks/useUser';
function ContestScreen() {
const { userSegment, subscriptionTier } = useUser();
return (
<KomoCardWidget
embedMetaUrl={embedUrl}
queryParams={{
utm_source: 'app',
utm_content: userSegment,
user_tier: subscriptionTier
}}
/>
);
}Combining with Other Props
Query parameters work alongside form prefill and extension data:
<KomoCardWidget
embedMetaUrl={embedUrl}
// Prefill form fields
formPrefillValues={{
email: user.email,
first_name: user.firstName
}}
// Add analytics data
extensionDataValues={{
user_id: user.id,
account_type: user.accountType
}}
// Track campaign source
queryParams={{
utm_source: 'app',
utm_medium: 'home-screen',
utm_campaign: 'welcome-flow'
}}
/>Using with ExperienceModal
The ExperienceModal component also supports queryParams:
import { ExperienceModal } from '@komo-tech/react-native-widgets';
import { useState } from 'react';
import { Button } from 'react-native';
function CustomModal() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<Button title="Open Contest" onPress={() => setIsOpen(true)} />
<ExperienceModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
embedUrl={metadata?.embedUrl}
queryParams={{
utm_source: 'custom-modal',
utm_medium: 'app'
}}
/>
</>
);
}Deep Link Attribution
Track users coming from deep links:
import { useEffect, useState } from 'react';
import { Linking } from 'react-native';
import { KomoCardWidget } from '@komo-tech/react-native-widgets';
function DeepLinkScreen() {
const [queryParams, setQueryParams] = useState({});
useEffect(() => {
// Parse deep link URL parameters
Linking.getInitialURL().then((url) => {
if (url) {
const urlObj = new URL(url);
const params = {};
urlObj.searchParams.forEach((value, key) => {
params[key] = value;
});
setQueryParams(params);
}
});
}, []);
return (
<KomoCardWidget
embedMetaUrl={embedUrl}
queryParams={{
...queryParams,
utm_source: 'deep-link'
}}
/>
);
}Multi-Platform Tracking
Detect and track the platform:
import { Platform } from 'react-native';
import { KomoCardWidget } from '@komo-tech/react-native-widgets';
<KomoCardWidget
embedMetaUrl={embedUrl}
queryParams={{
utm_source: 'react-native',
utm_medium: 'app',
platform: Platform.OS, // 'ios' or 'android'
app_version: DeviceInfo.getVersion()
}}
/>Technical Details
- Query parameters are added directly to the webview URL (no prefix)
- All values must be strings
- Parameters are available to analytics tools in the embedded experience
- Can be combined with
formPrefillValuesandextensionDataValues - Supports standard UTM parameters and custom parameters
Auth0 Session Transfer
- The
KomoCardWidgetcomponent supports Auth0 authentication through theauthPassthroughParamsprop. - The
ExperienceModalcomponent supports Auth0 authentication through theembedAuthUrlandauthPassthroughParamsprops.- The
embedAuthUrlis typically obtained from the CardEmbedMetadata.
- The
- Pre-requisites:
- Auth0 SSO must be configured on the Komo Hub, and “Force Embed Auth” must be enabled under Embed SDK settings on the hub.
- Pass a fresh session transfer token to the
authPassthroughParamsprop, e.g.session_transfer_token: 'ABC123'.
- With this setup, the user will be redirected to Auth0 to authenticate when the experience modal is opened, before being redirected back to the embedded experience.
- The session transfer token must be obtained immediately before opening the experience modal, since it has a short 60 second lifespan.
- Recommended: Specify
webViewProps={{ incognito: true }}to ensure user session state is cleared correctly when changing between different authenticated users.
<KomoCardWidget
embedMetaUrl={KomoCardNativeEmbedUrl}
authPassthroughParams={new URLSearchParams({
session_transfer_token: 'ABC123'
})}
webViewProps={{ incognito: true }}
/>
// or if using the ExperienceModal directly
<ExperienceModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
embedUrl={metadata?.embedUrl}
embedAuthUrl={metadata?.embedAuthUrl}
authPassthroughParams={new URLSearchParams({
session_transfer_token: 'ABC123'
})}
webViewProps={{ incognito: true }}
/>Error handling
- If the
session_transfer_tokenpassed to Auth0 is used, invalid, or expired, then the users will end up being shown the ExperienceModalerrorDisplay, which includes a built-in retry button. - If you don’t provide an
errorDisplayoverride, the retry function will just attempt to reload the experience with the current parameters and will most likely fail again. - We recommend that you provide a custom
errorDisplayso that you can handlesession_transfer_tokenregeneration before trying to load the content again.
API Reference
ButtonStyle
| Name | Type | Description | Required |
|---|---|---|---|
| text | string? | Text to display on the button | Optional |
| backgroundColor | string? | Background color of the button | Optional |
| color | string? | Text color of the button | Optional |
CardCover Props
| Name | Type | Description | Required |
|---|---|---|---|
| onClick | () => void | The callback for when the cover is clicked | Required |
| isLoading | boolean | Whether the cover is loading | Required |
| isError | boolean? | Whether the cover is in an error state | Optional |
| loader | ReactNode? | Override the default skeleton loader | Optional |
| errorDisplay | ReactNode? | Override the default error display | Optional |
| metaButtonStyle | ButtonStyle? | The button style returned from the embed metadata endpoint | Optional |
| overrideButtonStyle | StyleProp<ViewStyle>? | Override the button style | Optional |
| overrideButtonTextStyle | StyleProp<TextStyle>? | Override the button text style | Optional |
| containerStyle | StyleProp<ViewStyle>? | Override the container style | Optional |
| coverImageStyle | StyleProp<ImageStyle>? | Override the cover image style | Optional |
| hideCoverButton | boolean? | Whether to hide the cover button | Optional |
| imageUrl | string? | The url of the cover image | Optional |
| imageAspectRatio | number? | The aspect ratio of the cover image | Optional |
CardEmbedMetadata
| Name | Type | Description | Required |
|---|---|---|---|
| title | string? | The title of the card | Optional |
| imageUrl | string? | URL of the card's cover image | Optional |
| imageHeight | number? | Height of the cover image in pixels | Optional |
| imageWidth | number? | Width of the cover image in pixels | Optional |
| imageAspectRatio | number? | Aspect ratio of the cover image | Optional |
| embedUrl | string? | URL for the embedded experience | Optional |
| embedAuthUrl | string? | URL used to OAuth user before showing the embedded experience | Optional |
| buttonStyle | ButtonStyle? | Styling for the card's button | Optional |
ExperienceModal Props
| Name | Type | Description | Required |
|---|---|---|---|
| isOpen | boolean | Whether the modal is open | Required |
| onClose | () => void | Callback for when close is requested | Required |
| embedUrl | string | The URL of the embedded card experience | Required |
| modalHeader | ReactNode | Override the default modal header | Optional |
| shareClickUrl | string | Override the url that redirects a user when clicking on a share link | Optional |
| appId | string | An identifier for the embedded Komo content | Optional |
| formPrefillValues | Record<string, string> | Prefill values for the form within the experience | Optional |
| extensionDataValues | Record<string, string | number | boolean | object> | Extension data values for the experience | Optional |
| loadingIndicator | ReactNode | Override the default loading indicator | Optional |
| modalProps | ModalProps | Override the default modal props | Optional |
| loadingTimeoutMs | number | Timeout in milliseconds before showing error state. Defaults to 15000ms | Optional |
| errorDisplay | ({ onRetry }: { onRetry: () => void }) => ReactNode | Override the default error display | Optional |
| onFileDownload | WebViewProps["onFileDownload"] | Callback for when a file download is requested. Only applies to iOS. See react-native-webview docs for more details | Optional |
| onKomoEvent | (event: KomoEvent) => void | Callback for when a Komo event is raised in the embedded experience | Optional |
| onWindowMessage | (event: any) => void | Callback for when a window message is raised in the embedded experience | Optional |
| embedAuthUrl | string? | The URL of the authorization endpoint. If provided, the experience modal will first load the auth URL, then redirect to the embed URL. | Optional |
| authPassthroughParams | URLSearchParams | Passthrough parameters to add to the auth URL as query parameters. For example, an Auth0 session transfer token can be added to the auth URL. | Optional |
| webViewProps | WebViewProps | Additional props for the react-native-webview component. Only applies if the platform is not web. | Optional |
| iframeProps | IframeProps | Additional props for the iframe component. Only applies if the platform is web. | Optional |
KomoCardWidget Props
| Name | Type | Description | Required |
|---|---|---|---|
| embedMetaUrl | String | The native embed url taken from the Komo portal settings of the card to be embedded | Required |
| appId | String | Useful for the embedded Komo content to identify where it's being embedded | Optional |
| containerStyle | StyleProp<ViewStyle> | Style overrides for the container of the card cover (including both image and CTA button) | Optional |
| coverImageStyle | StyleProp<ImageStyle> | Style overrides for the image of the card cover | Optional |
| buttonStyle | StyleProp<ViewStyle> | Style overrides for the CTA button of the card cover | Optional |
| buttonTextStyle | StyleProp<TextStyle> | Style overrides for the CTA button text of the card cover | Optional |
| coverLoader | ReactNode | The loader shown while the cover is loading (defaults to a skeleton card loader) | Optional |
| coverErrorDisplay | ReactNode | Override the default error display for the cover | Optional |
| hideCoverButton | Boolean | Hide the CTA button of the cover | Optional |
| modalHeader | ReactNode | The header of the modal to render instead of the default | Optional |
| onError | (error) => void | Callback for when an error occurs during querying the embed metadata endpoint | Optional |
| onModalClose | () => void | Callback on modal close | Optional |
| onModalOpen | () => void | Callback on modal open | Optional |
| shareClickUrl | String | Override of the url that redirects a user when clicking on a share link | Optional |
| formPrefillValues | Record<string, string> | Prefill values for the form within the experience | Optional |
| extensionDataValues | Record<string, string | number | boolean | object> | Extension data values for the experience | Optional |
| onFileDownload | WebViewProps["onFileDownload"] | Callback for when a file download is requested. Only applies to iOS. See react-native-webview docs for more details | Optional |
| onKomoEvent | (event: KomoEvent) => void | Callback for when a Komo event is raised in the embedded experience | Optional |
| onWindowMessage | (event: any) => void | Callback for when a window message is raised in the embedded experience | Optional |
| authPassthroughParams | URLSearchParams | Passthrough parameters to add to the auth URL as query parameters. For example, an Auth0 session transfer token can be added to the auth URL. | Optional |
| loadingTimeoutMs | number | Timeout in milliseconds before showing error state in the modal. Defaults to 15000ms | Optional |
| modalErrorDisplay | ({ onRetry }: { onRetry: () => void }) => ReactNode | Override the default error display for the modal | Optional |
| webViewProps | WebViewProps | Additional props for the react-native-webview component. Only applies if the platform is not web. | Optional |
| iframeProps | IframeProps | Additional props for the iframe component. Only applies if the platform is web. | Optional |
KomoEvent
| Name | Type | Description | Required |
|---|---|---|---|
| eventName | string | The name of the event | Required |
| eventData | any | Object containing the event data | Required |
| extensionData | Record<string, string | number | boolean | object> | Extension data raised along with the event | Required |
useFetchCardMetadata Hook
Options
| Name | Type | Description | Required |
|---|---|---|---|
| embedMetaUrl | string | The URL of the embed metadata for the card, copied from the Komo Portal | Required |
| isEnabled | boolean | Whether the embed metadata query is enabled. Defaults to true | Optional |
| onError | (e: any) => void | Callback for when an error occurs during querying the embed metadata endpoint | Optional |
Result
| Name | Type | Description | Required |
|---|---|---|---|
| data | CardEmbedMetadata? | The embed metadata for the card | Optional |
| isLoading | boolean | Whether the embed metadata is loading | Required |
| isError | boolean | Whether the embed metadata query failed | Required |
| isSuccess | boolean | Whether the embed metadata query succeeded | Required |
| refetchAsync | () => Promise<void> | Function to refetch the embed metadata | Required |