Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.immutable.com/llms.txt

Use this file to discover all available pages before exploring further.

The Web SDK is currently in alpha. APIs and behavior may change between releases.
Who is this for? Web developers building web games, marketing sites, or SPAs who need explicit event tracking, user identity, or SPA support. Works with any framework (React, Next.js, Svelte, vanilla JS).
The Immutable Web SDK is a typed package for tracking player behavior as part of the Immutable attribution system. UTM parameters, click IDs, and referrer data are captured automatically, connecting ad campaigns to the players they drove. Session lifecycle (session_start, session_end) is handled automatically. Page views are tracked by calling page() on each route change, and in-game moments like progressions, purchases, and sign-ups are triggered by your code. All events flow to the same pipeline as the Tracking Pixel, Unity SDK, and REST API.

What You Need

Installation

npm install @imtbl/audience

Quick Start

1

Initialize the SDK

import { Audience, AudienceEvents, IdentityType } from '@imtbl/audience';

const audience = Audience.init({
  publishableKey: 'YOUR_PUBLISHABLE_KEY',
});
Consent defaults to 'none'. The SDK won’t track anything until you explicitly set a consent level.
2

Set consent

The SDK uses a three-tier consent model ('none', 'anonymous', 'full'). The SDK does not provide a consent UI. Build your own cookie banner or privacy prompt, then call setConsent with the appropriate level when the user responds.
// User accepts anonymous tracking
audience.setConsent('anonymous');

// User logs in and accepts full tracking
audience.setConsent('full');
At 'anonymous', page views and events are tracked but identify() and alias() calls are dropped. At 'full', all methods are available. See the Data Dictionary for what is collected at each level.
3

Track page views

Call page() on each route change. The first call in each session includes attribution parameters.
audience.page();
4

Track events

Log player actions with track(). The SDK ships with predefined events for common player actions (purchases, sign-ups, progression, wishlist actions, and more) that give you typed properties and autocomplete. You can also pass any custom event string.
// Predefined event — typed properties
audience.track(AudienceEvents.SIGN_UP, { method: 'email' });
audience.track(AudienceEvents.PURCHASE, { currency: 'USD', value: 9.99 });

// Custom event — any properties
audience.track('tutorial_complete', { stepCount: 5 });
5

Identify users

Identifies the player by associating their userId with their activity and traits. Call at login or account connection. Requires 'full' consent.
audience.identify('player-123', IdentityType.Passport, {
  email: 'user@example.com',
});
6

Clean up on exit

Flushes the queue and sends a session_end event (if consent is above 'none').
audience.shutdown();

Complete Example

import { Audience, AudienceEvents, IdentityType } from '@imtbl/audience';

// 1. Initialize
const audience = Audience.init({
  publishableKey: 'YOUR_PUBLISHABLE_KEY',
});

// 2. Set consent after cookie banner
audience.setConsent('anonymous');

// 3. Track page views on route changes
audience.page();

// 4. Track player actions
audience.track(AudienceEvents.PURCHASE, { currency: 'USD', value: 9.99 });

// 5. Identify after login (requires 'full' consent)
audience.setConsent('full');
audience.identify('player-123', IdentityType.Passport, { email: 'user@example.com' });

// 6. Clean up on exit
audience.shutdown();

Verify the Integration

Initialize with debug: true to see SDK activity in the browser console:
const audience = Audience.init({
  publishableKey: 'YOUR_PUBLISHABLE_KEY',
  debug: true,
});
  1. Console: Look for log entries showing session_start, page, and any track() calls
  2. Network tab: Look for POST requests to https://api.immutable.com (or https://api.sandbox.immutable.com if you’re using a test key). Events flush every 5 seconds or when 20 events accumulate
Remove debug: true before deploying to production.

Content Security Policy

If your site enforces a Content-Security-Policy header, add the event endpoint so the SDK can deliver events:
connect-src: https://api.immutable.com
If you load the SDK from Immutable’s CDN, also add the script host:
script-src: https://cdn.immutable.com
If you install the SDK as a package dependency (npm/yarn/pnpm), only connect-src is required. The CDN directive is only needed for the <script>-tag installation.
For nonce-based CSP (CDN install only), add the nonce attribute to your inline <script> tag. The nonce covers the inline code only. The CDN-loaded script is authorized by the script-src directive above.
<script src="https://cdn.immutable.com/audience/v1/imtbl.js"></script>
<script nonce="YOUR_NONCE">
  var audience = ImmutableAudience.init({ publishableKey: 'YOUR_PUBLISHABLE_KEY' });
  audience.setConsent('anonymous');
  audience.page();
</script>

API Reference

Creates and returns an Audience instance. Call once when your app loads to set up tracking.
ParameterTypeRequiredDefaultDescription
publishableKeystringYesAPI key from Hub (starts with pk_imapik- for production, pk_imapik-test- for sandbox)
consent'none' | 'anonymous' | 'full'No'none'Initial consent level
debugbooleanNofalseLog SDK activity to the browser console
cookieDomainstringNoCurrent domainShare cookies across subdomains (e.g. '.studio.com'). The Tracking Pixel uses domain for this same setting.
flushIntervalnumberNo5000How often the queue flushes, in milliseconds
flushSizenumberNo20Number of queued messages that triggers a flush
baseUrlstringNoImmutable APIOverride the default API base URL
onError(err: AudienceError) => voidNoundefinedCallback for flush and consent sync failures
const audience = Audience.init({
  publishableKey: 'YOUR_PUBLISHABLE_KEY',
  consent: 'none',
  debug: true,
  cookieDomain: '.studio.com',
  onError: (err) => console.error(err.code, err.message),
});
Controls what the SDK is allowed to collect. Call when the user accepts or changes their cookie preferences. Takes effect immediately, no page reload needed. See the Data Dictionary for consent levels and downgrade behavior.
// Upgrade after cookie banner
audience.setConsent('anonymous');

// Downgrade — stops tracking, clears cookies
audience.setConsent('none');
Checks whether a consent level allows tracking. Returns true when level is 'anonymous' or 'full'. Use before calling track() or page() when you need to guard behavior based on the current consent level, for example when conditionally showing a tracking-dependent UI element.
ParameterTypeDescription
level'none' | 'anonymous' | 'full'The consent level to check
import { canTrack } from '@imtbl/audience';

if (canTrack(currentConsentLevel)) {
  // safe to call track() and page()
}
Checks whether a consent level allows player identification. Returns true when level is 'full'. Use before calling identify() or alias() when you need to guard identity-dependent logic, for example to only prompt a player to link accounts when consent allows it.
ParameterTypeDescription
level'none' | 'anonymous' | 'full'The consent level to check
import { canIdentify } from '@imtbl/audience';

if (canIdentify(currentConsentLevel)) {
  // safe to call identify() and alias()
}
Records a page view. Call on every route change to track which pages players visit and in what order. The first call in each session includes attribution parameters.
ParameterTypeDescription
propertiesRecord<string, unknown>Optional custom properties
Requires: 'anonymous' or 'full' consent. Calls at 'none' are silently dropped.
Records a player action. Call when a player does something you want to measure, such as a purchase, sign-up, level completion, or any custom action. Predefined events give you typed properties with autocomplete.
ParameterTypeDescription
eventstringAn AudienceEvents value (e.g. AudienceEvents.PURCHASE) or any custom string
propertiesRecord<string, unknown>Event properties. Required for predefined events that have required fields (e.g. purchase), optional otherwise.
Requires: 'anonymous' or 'full' consent. Calls at 'none' are silently dropped.
// Predefined event — typed properties
audience.track(AudienceEvents.PURCHASE, { currency: 'USD', value: 9.99, itemName: 'Sword' });

// Custom event — any properties
audience.track('tutorial_complete', { stepCount: 5 });
Associates the player’s userId with their activity and traits. Call at login or account connection.
ParameterTypeDescription
idstringThe player’s identifier in that provider
identityTypeIdentityTypeWhich provider the ID comes from (see table below)
traitsobjectOptional. email, name, or custom key-value pairs
Requires: 'full' consent.
audience.identify('player-456', IdentityType.Passport, {
  email: 'user@example.com',
});
Identity types:
ValueProvider
'passport'Immutable Passport
'steam'Steam
'epic'Epic Games
'google'Google
'apple'Apple
'discord'Discord
'email'Email address
'custom'Custom identity system
Links two account IDs that belong to the same player. Call when a player connects a second account with a different provider, for example a player previously identified via Steam who later links a Passport account.
ParameterTypeDescription
from{ id: string, identityType: IdentityType }The account being linked
to{ id: string, identityType: IdentityType }The player’s main account
Requires: 'full' consent.
audience.alias(
  { id: 'steam-user-789', identityType: IdentityType.Steam },
  { id: 'player-456', identityType: IdentityType.Passport },
);
Wipes the current player’s identity and starts a fresh anonymous session. Call when a player logs out so the next player on the same device isn’t mixed up.
audience.reset();
Sends all queued events to the server immediately. Call when you need events delivered right now instead of waiting for the next automatic flush. Returns a Promise that resolves when the batch is sent.
await audience.flush();
Sends any remaining events and shuts down the SDK. Call when the app unmounts or the page is about to unload. Fires a session_end event if consent is above 'none'.

Event Delivery

  • Events are batched and flushed every 5 seconds or when 20 events accumulate (configurable via flushInterval and flushSize)
  • On page unload (navigate away, close tab), the queue flushes remaining events so they are not lost

FAQ

Yes, they’re complementary, not alternatives. The Tracking Pixel handles passive capture (page views, attribution, form submissions, outbound clicks) with no code beyond a snippet. The Web SDK handles explicit events, user identity, and SPA route tracking. Use both on the same site if you need passive and custom tracking. All events flow to the same pipeline. See the Data Dictionary for the full per-event schema.
Chrome 80+, Firefox 78+, Safari 14+, Edge 80+.
Erasure is a server-side operation. Call DELETE /v1/audience/data from your backend with the user’s userId or anonymousId. See Deleting User Data in the REST API docs for the full request shape.On the client side, call reset() after the erasure is accepted. This clears the user’s identity, wipes the event queue, and generates a fresh anonymous ID so the next session is not linked to the erased user:
audience.reset();

Next Steps

Attribution

How tracking data powers player attribution and Hub reports

Data Dictionary

Full reference of event schemas and consent levels

Tracking Pixel

Passive tracking snippet for marketing sites and landing pages

Unity SDK

In-game tracking for Unity desktop builds

REST API

Send events from your backend or game server

API Keys

Manage your publishable and secret keys