Script examples

Working code for the common cases: tag manager, advertising pixels, cookie banner, conversion events, and scripts scoped to selected campaigns.

5 min read

Working code for the cases that come up most. Copy one, change the identifiers, and hand it to whoever adds it in OmniLab. This page is for whoever writes the script.

Where the script runs

Organisation scripts run in the consumer-facing OmniLab Pages runtime, not inside OmniLab Studio. Before active scripts run, OmniLab initialises window.omnilab and can expose both group data and basic contact data to the page.

Values commonly available to organisation scripts
window.omnilab?.contact?.externalId
window.omnilab?.contact?.email
window.omnilab?.group
window.omnilab?.group?.configuration?.variables
window.omnilab?.group?.uniqueKey
window.location.pathname

Contact values are available only when the participant is already known in that flow.

Your code must contain real script tags

OmniLab expects the script code field to contain one or more valid <script>...</script> blocks. Inline scripts and external script loaders are both supported.

Inline script example
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: "omnilab_view",
  organisation_key: window.omnilab?.group?.uniqueKey,
  page: window.location.pathname,
});
</script>
External script example
<script async src="https://www.googletagmanager.com/gtm.js?id=GTM-AB12C3D"></script>

Context and trigger behaviour

SettingWhat it means
ALLRun in both iframe and non-iframe OmniLab Pages
IFRAME_ONLYRun only when OmniLab is embedded
NON_IFRAME_ONLYRun only when OmniLab Pages is standalone
VISITLoad during the normal page visit
REGISTRATIONHold the script for the registration stage

If the current trigger is REGISTRATION, OmniLab still keeps the other active scripts available and adds the registration-targeted scripts for that stage. In practice, use a separate REGISTRATION script for conversion events instead of overloading the base page-view script.

Safe use cases

  • Analytics loaders such as GTM, a pixel base tag, or a dataLayer bootstrap
  • Per-organisation behaviour based on window.omnilab.group.configuration.variables
  • Lightweight event pushes on visit or registration
  • Minor DOM enhancements that do not depend on fragile selectors or block interaction
Page-view script using organisation variables
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: "omnilab_view",
  organisation_key: window.omnilab?.group?.uniqueKey,
  country: window.omnilab?.group?.configuration?.variables?.country,
  locale: window.omnilab?.group?.configuration?.variables?.locale || "en_US",
  page: window.location.pathname,
  surface: "OmniLab Pages",
});
</script>
Registration-only conversion event
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: "registration_complete",
  external_id: window.omnilab?.contact?.externalId,
  email: window.omnilab?.contact?.email,
  organisation_key: window.omnilab?.group?.uniqueKey,
});
</script>

What to avoid

  • Replacing or overriding OmniLab business logic
  • Blocking synchronous work that delays page load or prevents participation
  • Fragile DOM rewrites that depend on unstable class names or layout details
  • Collecting extra personal data without a clear legal basis and review
  • Large client-side libraries that are not essential to the participant journey

A broken script can break every embedded experience

Because these scripts execute in OmniLab Pages, one bad script can affect live campaigns. Keep them small, test them in staging, and give admins a rollback plan before production.

Local testing workflow

  1. Build and review the script in a staging environment.
  2. Test both iframe and non-iframe delivery if the script depends on the container.
  3. If the trigger is REGISTRATION, complete a full registration flow and inspect the browser console and network panel.
  4. After admins save the script, publish the affected campaign again before you validate the live experience.

Handoff to admins

When you hand a script to an admin, provide:

  • the script name
  • the intended context (ALL, IFRAME_ONLY, or NON_IFRAME_ONLY)
  • the intended trigger (VISIT or REGISTRATION)
  • whether the script should start active or inactive
  • a rollback instruction and a staging test result

Complete example scripts

Google Tag Manager base loader

Use this when your team wants GTM available before firing additional events.

Google Tag Manager loader
<script>
(function (w, d, s, l, i) {
  w[l] = w[l] || [];
  w[l].push({
    'gtm.start': new Date().getTime(),
    event: 'gtm.js',
  });
  var f = d.getElementsByTagName(s)[0],
    j = d.createElement(s),
    dl = l != 'dataLayer' ? '&l=' + l : '';
  j.async = true;
  j.src = 'https://www.googletagmanager.com/gtm.js?id=' + i + dl;
  f.parentNode.insertBefore(j, f);
})(window, document, 'script', 'dataLayer', 'GTM-AB12C3D');
</script>

Page-view event with organisation variables

Page-view dataLayer push
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: 'view_page',
  country: window.omnilab?.group?.configuration?.variables?.country,
  region: window.omnilab?.group?.configuration?.variables?.region,
  language:
    window.omnilab?.group?.configuration?.variables?.centerLanguage || 'English',
  locale:
    window.omnilab?.group?.configuration?.variables?.locale || 'en_US',
  page: window.location.pathname,
  page_type: 'Experience',
  organisation_key: window.omnilab?.group?.uniqueKey?.toUpperCase(),
  surface: 'OmniLab Pages',
});
</script>

Registration event with dataLayer.push

Use this when you want to emit a conversion-style event after registration.

Registration dataLayer push
<script>
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: 'registration_complete',
  organisation_key: window.omnilab?.group?.uniqueKey?.toUpperCase(),
  country: window.omnilab?.group?.configuration?.variables?.country,
  locale:
    window.omnilab?.group?.configuration?.variables?.locale || 'en_US',
  page: window.location.pathname,
  registration_status: 'complete',
});
</script>

Meta Pixel registration trigger

Use this pattern when the base Meta Pixel is already present and you only need to fire an event from OmniLab Pages.

Meta Pixel registration event
<script>
if (typeof window.fbq === 'function') {
  window.fbq('track', 'CompleteRegistration', {
    organisation_key: window.omnilab?.group?.uniqueKey,
    country: window.omnilab?.group?.configuration?.variables?.country,
    locale:
      window.omnilab?.group?.configuration?.variables?.locale || 'en_US',
    page: window.location.pathname,
  });
}
</script>

Kiosk idle signal, scoped to selected campaigns

Use this when kiosk campaigns need to reset themselves after a visitor walks away. It is also the reference pattern for any script that must run on some campaigns but not others: the allowlist is a substring match against the full URL, and a campaign public link works as an entry.

Idle detection for kiosk campaigns
<script>
(function () {
  const TRIGGER_STRINGS = ['summer-experience-kiosk', 'back-to-school-2026-kiosk'];

  const shouldActivate = TRIGGER_STRINGS.some((trigger) =>
    window.location.href.includes(trigger)
  );
  if (!shouldActivate) return;

  const IDLE_TIMEOUT = 10000;
  let timer;

  function sendIdle() {
    window.parent.postMessage({ type: 'omnilab:idle', timestamp: Date.now() }, '*');
    reset();
  }

  function reset() {
    clearTimeout(timer);
    timer = setTimeout(sendIdle, IDLE_TIMEOUT);
  }

  ['click', 'mousedown', 'mousemove', 'keydown', 'scroll', 'touchstart', 'touchmove'].forEach(
    (e) => document.addEventListener(e, reset, { passive: true })
  );

  reset();
})();
</script>

Install it as IFRAME_ONLY on the VISIT trigger, and hand the admin the list of campaigns it covers alongside the code — that list has to grow every time a new kiosk campaign launches. The signal repeats every 10 seconds while the screen stays idle. Acting on it is the kiosk application's job, not yours — this script's responsibility ends at the postMessage. Kiosk integration has the receiving contract to hand to whoever builds the kiosk.

Advertising pixels

Dropping your ad platform's pixel here is what lets it see campaign traffic — so you can build a lookalike audience from people who engaged, and exclude people who already converted.

Meta Pixel base loader
<script>
!function(f,b,e,v,n,t,s){if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};if(!f._fbq)f._fbq=n;
n.push=n;n.loaded=!0;n.version='2.0';n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];s.parentNode.insertBefore(t,s)}(window,
document,'script','https://connect.facebook.net/en_US/fbevents.js');
fbq('init', '<YOUR-PIXEL-ID>');
fbq('track', 'PageView');
</script>

Google Ads and TikTok follow the same shape: paste the base tag the platform gives you, on the page-load trigger. Fire the conversion event from a separate registration-triggered script rather than adding conditionals to the base tag.

If you already run a tag manager, load the container instead and manage the pixels inside it — one script in OmniLab, all your tags managed where your team already manages them.

Load your own consent tool exactly as you do on your website, on the page-load trigger:

Consent tool loader
<script src="https://cdn.example-consent-tool.com/loader.js" data-site-id="<YOUR-SITE-ID>"></script>

Then make your other scripts wait for its answer rather than firing regardless. Most consent tools expose a callback or a global you can check — follow that tool's documentation, and test the refuse path, not just the accept path.

Test what happens when someone refuses

The accept path almost always works. The refuse path is where tags fire anyway, and it is the one that carries regulatory risk. Refuse consent and confirm your pixels stay silent.

Reading organisation variables in your script

Only two paths are guaranteed to exist for every organisation:

What you want to readVariable pathExample result
Organisation keywindow.omnilab?.group?.uniqueKeyparis-centre
Current page pathwindow.location.pathname/summer-experience

window.omnilab?.group?.configuration?.variables is a free-form key/value store: an admin can create any key with any name under Organisation settings, and none are seeded for you. country, locale, and region in the examples above are keys one organisation chose to configure — not built-in fields every organisation has. Confirm with whoever configures the organisation which keys actually exist before you reference them, and always add a fallback for a key that might be missing, for example variables?.locale || 'en_US'.

centerLanguage is not a real key

The centerLanguage path used in some examples on this page is illustrative only — it doesn't exist unless an admin creates a variable with that exact name. Reading an unconfigured key returns undefined, so always check with your admin first, or fall back to a literal default.

Keep analytics payloads generic

Prefer organisation, locale, page, and event context unless your measurement design truly requires more. If a destination expects transformed or filtered values, apply that logic inside your script before pushing it.

On this page