Skip to content

Commit 92d82ab

Browse files
docs: add integration guide
Install, init, consent, events, identity, CDN usage, cookies, wire format. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 27438f3 commit 92d82ab

1 file changed

Lines changed: 192 additions & 0 deletions

File tree

packages/audience/web/README.md

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# @imtbl/audience-web-sdk — Audience Web SDK
2+
3+
Explicit, typed, consent-aware event tracking and identity management for web surfaces. Part of the Immutable Audience platform.
4+
5+
## Install
6+
7+
```bash
8+
npm install @imtbl/audience-web-sdk
9+
```
10+
11+
## Quick Start
12+
13+
```typescript
14+
import { ImmutableWebSDK, AudienceEvent, IdentityProvider } from '@imtbl/audience-web-sdk';
15+
16+
const sdk = ImmutableWebSDK.init({
17+
publishableKey: 'pk_imtbl_...',
18+
environment: 'production',
19+
consent: 'anonymous',
20+
});
21+
22+
// Track a typed event
23+
sdk.track(AudienceEvent.Purchase, {
24+
currency: 'USD',
25+
value: 9.99,
26+
itemId: 'sword_01',
27+
});
28+
29+
// Track a custom event
30+
sdk.track('beta_key_redeemed', { source: 'influencer' });
31+
32+
// Page view (call on route change in SPAs)
33+
sdk.page();
34+
```
35+
36+
## Initialisation
37+
38+
```typescript
39+
const sdk = ImmutableWebSDK.init({
40+
publishableKey: 'pk_imtbl_...', // Required — from Immutable Hub
41+
environment: 'production', // 'dev' | 'sandbox' | 'production'
42+
consent: 'none', // 'none' | 'anonymous' | 'full' (default: 'none')
43+
consentSource: 'CookieBannerV2', // Identifies the consent source (default: 'WebSDK')
44+
trackPageViews: false, // Auto-fire page() on SPA route changes (default: false)
45+
debug: false, // Log all events to console (default: false)
46+
cookieDomain: '.studio.com', // Cross-subdomain cookie sharing (optional)
47+
flushInterval: 5000, // Queue flush interval in ms (default: 5000)
48+
flushSize: 20, // Queue flush size threshold (default: 20)
49+
});
50+
```
51+
52+
## Consent
53+
54+
The SDK defaults to `none` — no events are collected until consent is explicitly set.
55+
56+
```typescript
57+
sdk.setConsent('anonymous'); // Anonymous tracking (no PII)
58+
sdk.setConsent('full'); // Full tracking (PII via identify)
59+
sdk.setConsent('none'); // Stop tracking, purge queue, clear cookies
60+
```
61+
62+
Consent is:
63+
- **Persisted locally** via `_imtbl_consent` cookie (shared with the pixel)
64+
- **Synced server-side** via `PUT /v1/audience/tracking-consent`
65+
66+
| Level | Behaviour |
67+
|-------|-----------|
68+
| `none` | SDK is inert. No events collected. Queue purged on downgrade. |
69+
| `anonymous` | Events collected with anonymous ID only. `identify()` calls are discarded. |
70+
| `full` | Full collection. `identify()` sends. `userId` included on events. |
71+
72+
**On downgrade to `none`:** queue purged, `imtbl_anon_id` and `_imtbl_sid` cookies cleared.
73+
**On downgrade from `full` to `anonymous`:** identify messages purged, `userId` stripped from queued events.
74+
75+
## Event Tracking
76+
77+
### Typed Events
78+
79+
```typescript
80+
sdk.track(AudienceEvent.SignUp, { method: 'google' });
81+
sdk.track(AudienceEvent.SignIn, { method: 'passport' });
82+
sdk.track(AudienceEvent.Purchase, { currency: 'USD', value: 9.99 });
83+
sdk.track(AudienceEvent.WishlistAdd, { gameId: 'game_123', source: 'landing_page' });
84+
sdk.track(AudienceEvent.WishlistRemove, { gameId: 'game_123' });
85+
sdk.track(AudienceEvent.SessionStart, {});
86+
sdk.track(AudienceEvent.SessionEnd, { duration: 1800 });
87+
sdk.track(AudienceEvent.LevelReached, { level: 5, characterClass: 'warrior' });
88+
sdk.track(AudienceEvent.Spend, { currency: 'gold', value: 100 });
89+
sdk.track(AudienceEvent.TutorialComplete, { stepNumber: 3 });
90+
```
91+
92+
### Custom Events
93+
94+
```typescript
95+
sdk.track('checkout_started', { cartValue: 49.99, itemCount: 3 });
96+
sdk.track('discord_joined');
97+
```
98+
99+
## Page Tracking
100+
101+
```typescript
102+
// Explicit page view
103+
sdk.page();
104+
sdk.page({ section: 'shop', category: 'weapons' });
105+
```
106+
107+
For SPAs, enable auto-tracking to fire `page()` on every route change:
108+
109+
```typescript
110+
const sdk = ImmutableWebSDK.init({
111+
publishableKey: 'pk_imtbl_...',
112+
environment: 'production',
113+
consent: 'anonymous',
114+
trackPageViews: true, // Detects pushState, replaceState, popstate
115+
});
116+
```
117+
118+
Attribution context (UTMs, click IDs, referrer, landing page) is automatically attached to the first page view.
119+
120+
## Identity
121+
122+
```typescript
123+
// Identify a known user (requires full consent)
124+
sdk.identify('user@example.com', IdentityProvider.Email);
125+
sdk.identify('76561198012345', IdentityProvider.Steam);
126+
sdk.identify('passport_sub_abc', IdentityProvider.Passport, {
127+
email: 'user@example.com',
128+
name: 'Player One',
129+
});
130+
131+
// Link two identities (same player, different providers)
132+
sdk.alias(
133+
{ uid: '76561198012345', provider: IdentityProvider.Steam },
134+
{ uid: 'user@example.com', provider: IdentityProvider.Email },
135+
);
136+
137+
// Reset on logout (new anonymous ID, clears userId)
138+
sdk.reset();
139+
```
140+
141+
**Providers:** `Passport`, `Steam`, `Epic`, `Google`, `Apple`, `Discord`, `Email`, `Custom`
142+
143+
## Queue & Lifecycle
144+
145+
```typescript
146+
// Force flush all queued events
147+
await sdk.flush();
148+
149+
// Stop the SDK (flushes remaining events, tears down listeners)
150+
sdk.shutdown();
151+
```
152+
153+
Events are batched and flushed every 5 seconds or when 20 messages accumulate. On page unload (`visibilitychange` / `pagehide`), remaining events are flushed via `fetch` with `keepalive: true`.
154+
155+
## CDN Usage
156+
157+
For sites without a bundler:
158+
159+
```html
160+
<script src="https://cdn.immutable.com/web-sdk/v1/imtbl-web.js"></script>
161+
<script>
162+
var sdk = window.ImmutableWebSDK.init({
163+
publishableKey: 'pk_imtbl_...',
164+
environment: 'production',
165+
consent: 'anonymous',
166+
});
167+
168+
sdk.track('signup_started');
169+
sdk.identify('user@example.com', 'email');
170+
</script>
171+
```
172+
173+
## Cookies
174+
175+
All cookies are first-party, `SameSite=Lax`, `Secure` on HTTPS, and shared with the pixel:
176+
177+
| Cookie | Lifetime | Purpose |
178+
|--------|----------|---------|
179+
| `imtbl_anon_id` | 2 years | Anonymous device ID |
180+
| `_imtbl_sid` | 30 min (rolling) | Session continuity |
181+
| `_imtbl_consent` | 1 year | Consent state |
182+
183+
## Wire Format
184+
185+
Events are sent to `POST /v1/audience/messages` with the `x-immutable-publishable-key` header. All messages include `surface: 'web'` and follow the backend OpenAPI spec.
186+
187+
## Bundle Size
188+
189+
| Bundle | Size (gzipped) |
190+
|--------|---------------|
191+
| npm (ESM, tree-shaken) | ~3.6 KB |
192+
| CDN (IIFE, self-contained) | ~4.0 KB |

0 commit comments

Comments
 (0)