Embedding and WebView integration

Technical reference for embedding OmniLab in a web page, mobile WebView, or custom domain — with HTML, JavaScript, and React Native examples.

This guide covers the technical implementation for all embedded OmniLab delivery modes: manual iframe, JavaScript player tag, native WebView (React Native and other platforms), and custom domain delegation via DNS.

See the business-facing overviews at:


Embed-ready URLs

All embedded delivery modes start from the same OmniLab URL patterns:

Use caseURL pattern
Campaign landing pagehttps://experience.example.com/<campaign-public-link>?embedded=1
Direct touchpointhttps://experience.example.com/<campaign-public-link>?c=<touchpoint-id>&embedded=1
Space-specific launchhttps://experience.example.com/<campaign-public-link>?s=<space-id>&embedded=1
Variant or languageAppend &v=<variant-id> or &l=<language> as needed

Always add embedded=1 when loading in an iframe or WebView. This flag tells OmniLab to run in an embedded context and adjusts layout and navigation accordingly.


Manual iframe

Minimal example

Manual iframe
<iframe
  id="omnilab-embed"
  src="https://experience.example.com/<campaign-public-link>?c=<touchpoint-id>&embedded=1"
  title="OmniLab campaign"
  loading="lazy"
  allow="camera; microphone; geolocation"
  style="width:100%;min-height:900px;border:0;overflow:hidden"
></iframe>

Adjust the allow attribute to match the permissions the experience requires. Camera, microphone, and geolocation are only needed when the experience uses scanning, media capture, or location-aware flows.

Automatic height resize

OmniLab pages send postMessage resize events. Listen for them on the parent page so the iframe height follows content instead of showing an internal scrollbar.

Parent page resize listener
<script>
  window.addEventListener("message", (event) => {
    const data = event.data;

    if (data?.type !== "resize" || data?.target !== "body") return;

    const iframe = document.querySelector("#omnilab-embed");
    if (iframe && typeof data?.data?.height === "number") {
      iframe.style.height = data.data.height + "px";
    }
  });
</script>

Other postMessage events

OmniLab can also emit modal lifecycle events that your wrapper may want to participate in:

Event typeWhen it fires
resizeContent height changes
open-modalA modal is about to open inside the experience
close-modalA modal has closed
ready-to-open-modalThe modal is ready to animate in
ready-to-close-modalThe modal is ready to animate out

To log all messages during development:

Debug: log all OmniLab messages
window.addEventListener("message", (event) => {
  console.log("OmniLab message", event.origin, event.data);
});

JavaScript player tag

Use the OmniLab JavaScript player tag when a single host page must load different campaigns based on the current page URL.

Container + OmniLab player tag
<div id="omnilab-container"></div>

<script>
  (function (b, o, n, u, s) {
    var a, t;
    a = b.createElement(u);
    a.async = 1;
    a.src = s;
    t = b.getElementsByTagName(u)[0];
    t.parentNode.insertBefore(a, t);
    o[n] = o[n] || [];
  })(document, window, "_om_async", "script", "https://<omnilab-script-host>/omplayer.js");

  _om_async.push([
    "init",
    {
      domain: "experience.example.com",
      targetId: "omnilab-container",
      queryParam: "id",
    },
  ]);
</script>

With that setup, the host page URL drives which OmniLab experience loads:

  • Simple campaign: https://www.example.com/promo?id=summer-campaign
  • With touchpoint: https://www.example.com/promo?id=summer-campaign%3Fc%3D<touchpoint-id>%26embedded%3D1

The value in id is the path after the OmniLab domain. URL-encode any nested query string before publishing the link. If your deployment uses a specific script host URL, use that instead of the placeholder above.


React Native WebView

Installation

npm install react-native-webview

Minimal example

OmniLab in a React Native WebView
import React from "react";
import { WebView } from "react-native-webview";

export default function OmniLabWebView() {
  return (
    <WebView
      source={{
        uri: "https://experience.example.com/<campaign-public-link>?c=<touchpoint-id>&embedded=1",
      }}
      style={{ flex: 1 }}
      javaScriptEnabled
    />
  );
}

Use a campaign landing page URL when the app should show multiple experiences, or a direct touchpoint URL to launch one specific experience immediately.

React Native requirements

  • Enable JavaScript (javaScriptEnabled={true}).
  • Grant camera, microphone, geolocation, and file permissions when the experience needs them.
  • Use a full-screen or edge-to-edge container (flex: 1).
  • If the host app must react to OmniLab events, confirm that the WebView bridge supports postMessage.
  • Test virtual keyboard behaviour when the experience includes forms or sign-in steps.

Native iOS and Android guidance

  • Use the platform's standard WebView component or a maintained wrapper library.
  • Enable JavaScript.
  • Forward device permission prompts (camera, microphone, geolocation) to the WebView.
  • Test portrait and landscape layouts on real target devices.
  • Verify app backgrounding, resume, and network loss do not break the participant flow.
  • If the wrapper needs to react to postMessage events, validate the bridge in staging before shipping.

Custom domain delegation (DNS setup)

Overview

A delegated custom domain lets OmniLab experiences run under your own branded subdomain (for example experience.example.com) instead of the default OmniLab-hosted domain.

DNS record to create

Your DNS team creates a CNAME record pointing the chosen subdomain to the OmniLab endpoint:

Record typeNameValue
CNAMEexperience (your chosen subdomain)OmniLab endpoint provided by your Customer Success Manager

If your DNS provider does not support CNAME at the apex (root domain), use a subdomain such as experience.example.com rather than trying to delegate example.com itself.

TTL considerations

Set the TTL (time-to-live) on the DNS record to a low value (300–600 seconds) before the switch so propagation is faster if you need to roll back. After the domain is stable, you can raise the TTL.

SSL certificate

OmniLab provisions an SSL certificate automatically once the DNS record is verified. Allow up to 15–30 minutes after DNS propagation for the certificate to become active. During this window, browsers may show a temporary certificate warning.

Propagation time

DNS changes can take up to 48 hours to propagate globally, depending on your provider and the existing TTL on the record. Plan the domain delegation well before your go-live date.

Typical embedding model

SurfaceExample
Host websitehttps://www.example.com/promo
Embedded OmniLab sourcehttps://experience.example.com/summer-campaign?embedded=1

Go-live checklist

  • Custom subdomain approved and DNS record created.
  • DNS propagation verified (use a DNS checker tool).
  • SSL certificate active (no certificate warning in browser).
  • Standalone OmniLab URL working on the new hostname.
  • Embedded page tested: layout, permissions, cookies, redirects.
  • Existing QR codes and media placements updated to the new hostname.

Delivery best practices

  • Let the iframe fill available width; avoid a fixed narrow desktop width.
  • Start with a generous minimum height (min-height: 900px), then let the resize listener set the final height.
  • Test sign-in steps, camera permissions, redirects, and mobile layout inside the real host page.
  • If the host page uses sticky headers or constrained containers, test touchpoints that open drawers, forms, keyboards, or camera prompts.
  • Keep secrets and API tokens on your backend — never in the kiosk page or WebView bundle.

Was this helpful?

Optional comments help us improve this page for future authors and readers.

On this page