Documentation overview

Website SDK

One script tag connects your website to The AI CMO: visits, conversions, and revenue flow into your warehouse, journeys can react to what people do on your site, and website messages from Journeys render on your pages.

Install

In the app, open your account menu and choose Website SDK. Add your site by domain and you get a snippet to paste before </head>:

<!-- The AI CMO -->
<script async src="https://theaicmo.com/sdk/v1/tracker.js"></script>
<script>
  window.AICMO = window.AICMO || [];
  AICMO.push(['init', { siteId: 'lpo_your_site_id' }]);
</script>

That's the whole install. The script loads asynchronously and cannot block or break your page – even if analytics is unreachable, your site is unaffected.

To confirm it works, visit your site once, then refresh the Website SDK page. Each site shows "Receiving data – last event" with a timestamp once the first event lands, and the page banner switches to "SDK installed and receiving data".

What is tracked automatically

With no further code, the SDK captures pageviews (including single-page app navigation), visitors and sessions, and campaign attribution from tracked links and UTM parameters. Everything else – your business moments, conversions, revenue, identity – you declare explicitly with the calls below, so your analytics contains what you decided matters, not noise.

Session recording, heatmaps, and automatic click capture are switched off by design: they multiply event volume without adding decisions, and they are the first thing a privacy review flags.

Everything the SDK sends lands in your warehouse with an sdk_ prefix on the event type, attributed to the visitor and – once they identify – to the person.

Included analytics volume

Visitor analytics is included with your plan: up to 1M events a month on Assistant, 5M on Manager, 20M on CMO. Conversions, identity, custom events, journeys, and revenue tracking are never counted against this – it meters only the behavioral layer (pageviews and sessions).

If a site outgrows its plan's volume, nothing breaks and nothing is lost silently: visitor analytics switches to sampling (1 in 10 visitors), you get an alert, and full detail returns when volume drops or the plan grows. First-party data – conversions, revenue, journey events – is never sampled.

The API

Call methods through the queue, which is safe to use before the script has loaded:

AICMO.push(['method', ...arguments]);
MethodWhat it does
init({ siteId, consent? })Starts the SDK. Pass consent: 'pending' to wait for a consent banner.
track(eventName, properties)Sends a custom business event – see below.
identify(idOrEmail)Tells the SDK who the visitor is – an email or your own customer ID.
trackConversion(type, { value, currency, email })Records a conversion with revenue.
trackPageView()Manual pageview, for cases the automatic tracking can't see.
optIn() / optOut()Grant or withdraw consent at runtime.
consentStatus()Returns granted, denied, or pending.

Custom events

Custom events are how your site's own business moments – a deposit, a booking, a quote request – reach the platform:

AICMO.push(['track', 'deposit', { value: 250, currency: 'USD' }]);

Or with zero JavaScript, declaratively on any element:

<button data-aicmo-event="deposit_click" data-aicmo-value="50">Deposit</button>

Two rules to know:

  • Event keys must be registered first in Data → Events, and use lowercase letters, numbers, and underscores. Events with unregistered keys are not stored – but the Events tab shows keys it has seen so you can register them with one click.
  • In the warehouse the event lands as sdk_<key> (a registered deposit becomes sdk_deposit), and a journey with the matching custom-event trigger enrolls the person the next time the engine polls – within about a minute.

You can also define no-code capture rules in Data → Events: a CSS selector or URL match that fires an event without touching your site's code, reading the value from the page or a cookie.

Identifying people

Anonymous visitors get a random visitor ID. The moment you know who they are, tell the SDK:

AICMO.push(['identify', 'jane@acme.com']);   // email
AICMO.push(['identify', 'player-48213']);    // or your customer ID

Identification is what connects website behavior to a real customer: their events join their profile, journeys can enroll them, and person-targeted website messages can reach them. If your site already sets a login cookie, configure it as the identity cookie in Data → Events and the SDK identifies people automatically – no code change.

Revenue

Send revenue either through a conversion or on a custom event:

AICMO.push(['trackConversion', 'signup', { value: 49, email: 'jane@acme.com' }]);
AICMO.push(['track', 'deposit', { value: 250, currency: 'USD' }]);

The value becomes the event's amount in your warehouse, and feeds journey goals, revenue reporting, and What's Working.

Website messages

When a journey publishes a website message, the SDK renders it on your site – as a banner, card, or modal – styled to the message, isolated from your page's CSS, and shown at most once per day per message. Person-targeted messages appear only to the identified person they were written for. Impressions, clicks, and dismissals are tracked automatically and feed the journey's performance numbers.

The inbox

Messages can persist in an on-site inbox instead of – or alongside – the one-shot popup. When a visitor has inbox messages, the SDK shows a small launcher in the corner with an unread badge; opening it lists their messages, newest first, and marks them read. Visitors with no messages never see the launcher at all.

Three things put messages there: the journey Website step (choose "Popup + inbox" or "Inbox only" on the step), promos – when a promo with a customer message is credited to someone, that message lands in their inbox automatically, with its terms attached – and the Inbox page (sidebar), where you manage the whole channel: see each message's reads, who it targets, where it came from, end it early, or compose a new one – with an image and a button if you like – for every visitor or one person. The Inbox page also documents the two public endpoints for rendering the same inbox natively inside your own logged-in UI instead of the SDK widget.

Personalization

The SDK can change what your site says per visitor. Mark an element with data-aicmo-slot="hero-title" (or give a CSS selector on the rule), then create rules under Audience → Audiences → Personalization: what to show, and who sees it – everyone, or one of your saved audiences. Higher-priority rules win; identified visitors on your exclusion lists are never personalized. Variants are plain text by default; HTML variants exist behind a per-site switch you have to turn on deliberately.

Rules can target devices – all, mobile (phones and tablets), or desktop – so the shorter headline shows only where screens are small.

Rules apply on page load and on navigation in single-page apps. Applied elements carry a data-aicmo-personalized attribute so your team can see what changed and why.

Each rule reports how often it applied and, for identified visitors, the revenue those people generated after first seeing it – the rule's row under Personalization reads both, so a rule is never a guess.

A/B testing a rule

When creating a rule you can switch on A/B test this change: write a second version, choose the split (say 50/50), and set a holdout – a slice of visitors who keep seeing your original page but still count as exposed. Every visitor lands in the same arm on every visit, and the rule's row then reads revenue per arm – A vs B vs holdout – with the leader highlighted. The holdout answers the question that matters: does the change beat doing nothing?

Customers who are inside a journey with a control group are left out of rule A/B tests automatically – they see your original content and are not counted. One person is never part of two experiments at once, so journey uplift numbers and rule test numbers both stay honest.

Web push notifications

Turn browsers into a push channel – no third-party push provider needed. Browser subscriptions are off by default: nothing is offered or collected from visitors until you switch them on for the site (Website SDK page → Web push notifications). Once on, two steps:

  1. Host a one-line service worker at your site root, saved as /aicmo-sw.js (browsers require this file to live on your own domain):

    importScripts('https://theaicmo.com/sdk/v1/push-sw.js');
    
  2. Call AICMO.registerPush() from your own button – for example an "enable notifications" toggle in your account area. Browsers punish permission prompts the visitor didn't ask for, so the SDK never prompts on its own.

That's it. Subscribed browsers become reachable by the Push step in Journeys. Subscriptions are matched to the person once you identify them – someone who subscribes anonymously and logs in later becomes addressable automatically. AICMO.unregisterPush() removes this browser's subscription.

This is mobile push without an app: on Android phones, notifications arrive like any app's – even with the browser closed. On iPhone they arrive once the visitor has added your site to their home screen (Apple requires your site to ship a web app manifest for that). Desktop Chrome, Edge, and Firefox work everywhere. Blacklists and self-exclusion are enforced before every send.

Mobile apps (React Native)

Your React Native app gets the same three things through @aicmo/react-native – no dependencies, and no third-party push provider:

  • Events and identityidentify, track, and trackConversion land in your warehouse exactly like the website SDK's.
  • Push, delivered directly – upload your Firebase service account on the Website SDK page (verified live, stored encrypted) and The AI CMO sends notifications straight through your own Firebase project: Android natively, iOS via Firebase's APNs integration. Your app passes its FCM token with registerPushToken, and the Push step in Journeys reaches the device – matched to the person after identify.

The package README walks through setup for bare React Native and Expo. Blacklists and self-exclusion are enforced before every send, on this route like every other.

Survey pages

Your hosted survey pages can carry your site's SDK too: in a survey's Fill page & branding → Tracking section, pick the site and survey visits land in your analytics, with a survey_completed event fired on submit. GA4 and Meta Pixel IDs are supported there as well – IDs only, never scripts. Owner previews are never tracked.

  • Consent gating: start with consent: 'pending' and call optIn() when the visitor accepts. Until then, nothing runs. An optOut() is remembered and the SDK stays silent on future visits.
  • Do Not Track is respected by default.
  • The SDK sets no cookies. Visitor state lives in localStorage on your own domain. It only reads cookies you explicitly configure for identity or value capture.
  • Session recordings mask every input field by default.