Skip to main content

Mobile App Integration

Complete guide to embedding Komo experiences in mobile applications.
Important Note: Komo does not provide native iOS or Android SDKs. All mobile integration is done via WebViews - this is the recommended and only supported approach for embedding Komo in mobile apps.
Three WebView-based approaches available:
  • React Native SDK (recommended for React Native apps) - Uses WebView under the hood
  • Direct WebView (simplest for any platform) - Native iOS/Android WebView
  • Browser Embed SDK (for advanced hybrid apps) - WebView with JavaScript bridge

Overview

Native iOS & Android Apps

For native iOS (Swift/Objective-C) and native Android (Kotlin/Java) apps, use the Direct WebView method. Komo experiences run in a WebView component - there is no native SDK to import. Why WebViews?
  • Komo experiences are web-based and optimized for mobile browsers
  • WebViews provide full feature support without platform-specific SDKs
  • Consistent experience across all platforms
  • No app store approval delays for content updates

Three Integration Methods

MethodBest ForComplexityFeatures
React Native SDKReact Native appsLowFull feature set, pre-built components
Direct WebViewNative iOS/Android, Flutter, etc.LowestBasic embedding, minimal setup
Browser Embed SDKAdvanced WebView appsMediumAdvanced features, JavaScript bridge
Platform Guide:
  • React Native → Use React Native SDK (Method 1)
  • Native iOS (Swift) → Use Direct WebView (Method 2)
  • Native Android (Kotlin) → Use Direct WebView (Method 2)
  • Flutter → Use Direct WebView (Method 2)
  • Other frameworks → Use Direct WebView (Method 2) or Browser Embed SDK (Method 3)

Feature Comparison

FeatureReact Native SDKDirect WebViewBrowser Embed SDK
Card Covers✅ Built-in❌ Manual✅ Built-in
Form Prefilling✅ Native props⚠️ URL params✅ JavaScript API
Event Listening✅ Native callbacks❌ Limited✅ Full support
Auth0/SSO✅ Session transfer⚠️ Manual✅ Session transfer
UTM Tracking✅ Native props⚠️ URL params✅ Full support
Extension Data✅ Native props❌ No✅ JavaScript API
Custom Styling✅ Style props⚠️ Limited✅ CSS/JS

What is it?

The official @komo-tech/react-native-widgets package provides pre-built React Native components for embedding Komo cards with full feature support including form prefilling, event listening, authentication, and analytics tracking. Requirements:
  • React Native app
  • react-native-webview v13.x (peer dependency)
  • iOS 11+ / Android 5.0+

Installation

npm install @komo-tech/react-native-widgets react-native-webview
iOS Setup:
cd ios && pod install

Quick Start: KomoCardWidget

The KomoCardWidget component combines everything - metadata fetching, card cover display, and modal handling.
import { KomoCardWidget } from '@komo-tech/react-native-widgets';

function App() {
  return (
    <KomoCardWidget
      embedMetaUrl="https://your-hub.komo.site/api/cards/your-card-id/embed/meta"
      containerStyle={{ maxWidth: '80%' }}
    />
  );
}
Getting the embedMetaUrl:
  1. Go to Komo Portal → Card Settings → Embed tab
  2. Click “React Native code” in sidebar
  3. Copy “Card embed meta URL”

Form Prefilling

Pass user data to prefill forms in the embedded experience:
<KomoCardWidget
  embedMetaUrl={embedUrl}
  formPrefillValues={{
    email: user.email,
    first_name: user.firstName,
    last_name: user.lastName,
    phone: user.phoneNumber
  }}
/>
Important: Object keys must match the Unique ID of form fields in Komo.

Event Listening

Listen for user interactions and events:
<KomoCardWidget
  embedMetaUrl={embedUrl}
  onKomoEvent={(event) => {
    console.log('Komo event:', event);
    // Handle prize won, form submitted, etc.
  }}
  onWindowMessage={(message) => {
    console.log('Raw message:', message);
  }}
/>
Common Events:
  • form.submitted - User submitted a form
  • prize.won - User won a prize
  • game.completed - User completed a game
  • coupon.redeemed - User redeemed a coupon

UTM Tracking & Analytics

Track campaign attribution:
<KomoCardWidget
  embedMetaUrl={embedUrl}
  queryParams={{
    utm_source: 'mobile-app',
    utm_medium: 'home-screen',
    utm_campaign: 'summer-2024',
    utm_content: 'hero-banner'
  }}
/>
Dynamic Campaign Tracking:
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'
      }}
    />
  );
}

Extension Data

Pass custom data to analytics integrations (no PII):
<KomoCardWidget
  embedMetaUrl={embedUrl}
  extensionDataValues={{
    user_segment: 'premium',
    account_type: 'enterprise',
    custom_id: 'ABC123'
  }}
/>

Auth0 Authentication

Enable seamless authentication with Auth0:
<KomoCardWidget
  embedMetaUrl={embedUrl}
  authPassthroughParams={new URLSearchParams({
    session_transfer_token: 'ABC123' // Fresh token, 60s lifespan
  })}
  webViewProps={{ incognito: true }}
/>
Prerequisites:
  • Auth0 SSO configured on Komo Hub
  • “Force Embed Auth” enabled in Embed SDK settings
  • Session transfer token obtained immediately before opening

Advanced: Custom Implementation

Use individual components for full control:
import { 
  useFetchCardMetadata, 
  CardCover, 
  ExperienceModal 
} from '@komo-tech/react-native-widgets';
import { useState } from 'react';
import { Button } from 'react-native';

function CustomImplementation() {
  const [isModalOpen, setIsModalOpen] = useState(false);
  
  // Fetch card metadata
  const { data, isLoading, isError } = useFetchCardMetadata({
    embedMetaUrl: 'https://your-hub.komo.site/api/cards/xxx/embed/meta'
  });

  return (
    <>
      {/* Custom trigger button */}
      <Button 
        title="Open Contest" 
        onPress={() => setIsModalOpen(true)} 
      />
      
      {/* Or use CardCover component */}
      <CardCover
        imageUrl={data?.imageUrl}
        imageAspectRatio={data?.imageAspectRatio}
        isLoading={isLoading}
        onClick={() => setIsModalOpen(true)}
        metaButtonStyle={data?.buttonStyle}
      />
      
      {/* Experience Modal */}
      <ExperienceModal
        isOpen={isModalOpen}
        onClose={() => setIsModalOpen(false)}
        embedUrl={data?.embedUrl}
        embedAuthUrl={data?.embedAuthUrl}
        formPrefillValues={{ email: user.email }}
        queryParams={{ utm_source: 'custom-modal' }}
      />
    </>
  );
}

Styling & Customization

Customize the appearance:
<KomoCardWidget
  embedMetaUrl={embedUrl}
  containerStyle={{ 
    borderRadius: 12,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.25
  }}
  coverImageStyle={{ borderRadius: 8 }}
  buttonStyle={{ backgroundColor: '#FF6B6B' }}
  buttonTextStyle={{ fontSize: 18, fontWeight: 'bold' }}
/>

Error Handling

Handle loading and error states:
<KomoCardWidget
  embedMetaUrl={embedUrl}
  onError={(error) => {
    console.error('Embed failed:', error);
    // Show error UI, retry button, etc.
  }}
  coverErrorDisplay={<CustomErrorComponent />}
  modalErrorDisplay={({ onRetry }) => (
    <ErrorView onRetry={onRetry} />
  )}
/>

Method 2: Direct WebView (Simplest)

What is it?

The simplest approach - embed Komo using a standard WebView component with the site or card URL. This is the recommended approach for native iOS and Android apps (Swift, Kotlin, Java) as well as Flutter and other frameworks.
Note: There is no native iOS SDK or native Android SDK for Komo. WebView is the standard and only approach for embedding in native mobile apps.
Best for:
  • Native iOS apps (Swift/Objective-C) ← Primary use case
  • Native Android apps (Kotlin/Java) ← Primary use case
  • Flutter apps
  • Quick prototyping
  • Simple embedding needs
  • When you don’t need advanced features

React Native WebView

import { WebView } from 'react-native-webview';

function SimpleEmbed() {
  return (
    <WebView
      source={{ 
        uri: 'https://your-hub.komo.site/?card=your-card-id&singleCard=true'
      }}
      style={{ flex: 1 }}
    />
  );
}
With UTM Parameters:
<WebView
  source={{ 
    uri: 'https://your-hub.komo.site/?card=your-card-id&singleCard=true&utm_source=mobile-app&utm_medium=webview'
  }}
/>

iOS (Swift) - Native App Integration

This is the standard way to embed Komo in native iOS apps. There is no separate iOS SDK - WebView is the official integration method.
import WebKit

class ViewController: UIViewController {
    @IBOutlet weak var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let url = URL(string: "https://your-hub.komo.site/?card=your-card-id&singleCard=true")!
        let request = URLRequest(url: url)
        webView.load(request)
    }
}

Android (Kotlin) - Native App Integration

This is the standard way to embed Komo in native Android apps. There is no separate Android SDK - WebView is the official integration method.
import android.webkit.WebView
import android.webkit.WebViewClient

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val webView: WebView = findViewById(R.id.webview)
        webView.webViewClient = WebViewClient()
        webView.settings.javaScriptEnabled = true
        
        webView.loadUrl("https://your-hub.komo.site/?card=your-card-id&singleCard=true")
    }
}

Flutter

import 'package:webview_flutter/webview_flutter.dart';

class KomoEmbed extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return WebView(
      initialUrl: 'https://your-hub.komo.site/?card=your-card-id&singleCard=true',
      javascriptMode: JavascriptMode.unrestricted,
    );
  }
}

URL Structure

Single Card (Recommended):
https://your-hub.komo.site/?card=CARD_ID&singleCard=true
Full Hub:
https://your-hub.komo.site/
With Query Parameters:
https://your-hub.komo.site/?card=CARD_ID&singleCard=true&utm_source=app&utm_campaign=spring

Limitations of Direct WebView

Form prefilling - Limited to URL parameters only
Event listening - No native callback support
Auth0 session transfer - Must implement manually
Extension data - Not supported
UTM tracking - Works via URL parameters
Basic display - Full Komo experience renders

Method 3: Browser Embed SDK (Advanced)

What is it?

For advanced use cases, use the Browser Embed SDK within a WebView. Provides JavaScript API for form prefilling, event listening, and authentication - even in mobile WebViews. Best for:
  • Hybrid apps with WebView
  • Advanced WebView implementations
  • When you need JS bridge communication

Setup

Include the embed script in HTML loaded by WebView:
<!DOCTYPE html>
<html>
<head>
    <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://your-hub.komo.site/assets/embed/embed.js', 'komoEmbed');
    </script>
</head>
<body>
    <div data-komo-embed-card-cover 
         data-komo-embed='{"cardId":"YOUR_CARD_ID"}'>
    </div>
</body>
</html>

JavaScript API in WebView

Once loaded, use the komoEmbed object:
// Prefill forms
komoEmbed.setFormPrefillValues({
  email: '[email protected]',
  first_name: 'John'
});

// Listen for events
komoEmbed.listenToKomoEvents((event) => {
  console.log('Event:', event);
  // Send to native app via WebView bridge
});

// Set extension data
komoEmbed.setExtensionDataValues({
  user_id: '12345'
});

// Open programmatically
komoEmbed.openExperience({ 
  type: 'card', 
  id: 'YOUR_CARD_ID' 
});

React Native WebView with JS Bridge

import { WebView } from 'react-native-webview';
import { useRef } from 'react';

function AdvancedWebView() {
  const webViewRef = useRef(null);
  
  const html = `
    <!DOCTYPE html>
    <html>
    <head>
      <script src="https://your-hub.komo.site/assets/embed/embed.js"></script>
    </head>
    <body>
      <div id="komo-container"></div>
      <script>
        // Initialize and listen for events
        komoEmbed.listenToKomoEvents((event) => {
          // Send to React Native
          window.ReactNativeWebView.postMessage(JSON.stringify({
            type: 'komo-event',
            data: event
          }));
        });
        
        // Prefill from native app
        window.prefillForm = (values) => {
          komoEmbed.setFormPrefillValues(values);
        };
      </script>
    </body>
    </html>
  `;
  
  return (
    <WebView
      ref={webViewRef}
      source={{ html }}
      onMessage={(event) => {
        const message = JSON.parse(event.nativeEvent.data);
        if (message.type === 'komo-event') {
          console.log('Komo event:', message.data);
        }
      }}
      injectedJavaScript={`
        window.prefillForm(${JSON.stringify({ email: '[email protected]' })});
      `}
    />
  );
}

Platform-Specific Considerations

iOS

App Transport Security (ATS): Ensure your hub domain is allowed:
<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
</dict>
Safe Area Insets: Handle notches and home indicators:
<SafeAreaView style={{ flex: 1 }}>
  <KomoCardWidget embedMetaUrl={embedUrl} />
</SafeAreaView>

Android

Hardware Acceleration: Enable for smooth WebView performance:
<application android:hardwareAccelerated="true" ...>
Back Button Handling:
override fun onBackPressed() {
    if (webView.canGoBack()) {
        webView.goBack()
    } else {
        super.onBackPressed()
    }
}

Performance Tips

Optimize Loading:
  • Use single card pages (not full hub) for faster load
  • Enable caching in WebView settings
  • Preload metadata when possible
Memory Management:
  • Dispose WebViews when not visible
  • Limit concurrent embedded experiences
  • Monitor memory usage on low-end devices

Authentication & SSO

Auth0 in React Native

<KomoCardWidget
  embedMetaUrl={embedUrl}
  authPassthroughParams={new URLSearchParams({
    session_transfer_token: auth0SessionToken
  })}
  webViewProps={{ incognito: true }}
/>
Token Lifecycle:
  1. Detect user needs authentication
  2. Obtain fresh session transfer token from Auth0
  3. Pass to Komo widget
  4. Token valid for 60 seconds only

Custom Authentication

For non-Auth0 setups, use form prefilling:
<KomoCardWidget
  embedMetaUrl={embedUrl}
  formPrefillValues={{
    user_id: currentUser.id,
    auth_token: currentUser.token
  }}
/>

Testing & Debugging

Development Tips

Enable Debug Mode:
<KomoCardWidget
  embedMetaUrl={embedUrl}
  webViewProps={{
    allowsInlineMediaPlayback: true,
    mediaPlaybackRequiresUserAction: false,
    allowsAirPlayForMediaPlayback: true
  }}
/>
Console Logging:
<WebView
  onMessage={(event) => {
    console.log('WebView message:', event.nativeEvent.data);
  }}
  injectedJavaScript={`
    console.log = (function(oldLog) {
      return function(...args) {
        oldLog.apply(this, args);
        window.ReactNativeWebView.postMessage(JSON.stringify({
          type: 'console',
          data: args
        }));
      };
    })(console.log);
  `}
/>

Common Issues

White Screen:
  • Check URL is correct and accessible
  • Verify network permissions
  • Enable WebView debugging
Slow Loading:
  • Use single card mode
  • Enable WebView caching
  • Optimize images in Komo
Form Prefill Not Working:
  • Verify field Unique IDs match
  • Check data types (strings only)
  • Ensure form is loaded before prefilling
Authentication Fails:
  • Session token must be fresh (< 60s)
  • Enable incognito mode for clean sessions
  • Check Auth0 configuration in Komo

Best Practices

Do:

  • ✅ Use React Native SDK for React Native apps
  • ✅ Implement error handling and retry logic
  • ✅ Test on real devices, not just simulators
  • ✅ Handle authentication token lifecycle properly
  • ✅ Use UTM parameters for attribution
  • ✅ Optimize images in Komo for mobile
  • ✅ Test network connectivity scenarios

Don’t:

  • ❌ Hardcode authentication tokens
  • ❌ Ignore loading and error states
  • ❌ Use full hub URLs when single card will do
  • ❌ Forget to handle back button (Android)
  • ❌ Disable all WebView security features
  • ❌ Assume desktop features work on mobile

Examples by Use Case

E-commerce App

Product Page Contest:
// Show contest entry on product pages
<KomoCardWidget
  embedMetaUrl={productContestUrl}
  queryParams={{
    utm_source: 'app',
    utm_medium: 'product-page',
    utm_content: productId
  }}
  formPrefillValues={{
    product_id: productId,
    user_id: userId
  }}
/>

Event App

Live Trivia During Event:
// Full-screen trivia experience
<ExperienceModal
  isOpen={triviaOpen}
  onClose={() => setTriviaOpen(false)}
  embedUrl={triviaEmbedUrl}
  queryParams={{
    utm_source: 'event-app',
    utm_campaign: eventId
  }}
  onKomoEvent={(event) => {
    if (event.eventName === 'game.completed') {
      showLeaderboard();
    }
  }}
/>

Loyalty App

Points Redemption:
// Allow users to redeem points
<KomoCardWidget
  embedMetaUrl={redemptionCardUrl}
  extensionDataValues={{
    points_balance: user.points,
    tier_level: user.tier
  }}
  onKomoEvent={(event) => {
    if (event.eventName === 'coupon.redeemed') {
      refreshUserPoints();
    }
  }}
/>


Need Help? Contact [email protected] for mobile integration assistance.