|
| 1 | +# @imtbl/pixel — Immutable Tracking Pixel |
| 2 | + |
| 3 | +A drop-in JavaScript snippet that captures device signals, page views, and attribution data for Immutable's events pipeline. Zero configuration beyond a publishable key. |
| 4 | + |
| 5 | +## Quick Start |
| 6 | + |
| 7 | +Paste this snippet into your site's `<head>` tag: |
| 8 | + |
| 9 | +```html |
| 10 | +<script> |
| 11 | +(function(){ |
| 12 | +var w=window,i="__imtbl"; |
| 13 | +w[i]=w[i]||[]; |
| 14 | +w[i].push(["init",{"key":"YOUR_PUBLISHABLE_KEY"}]); |
| 15 | +var s=document.createElement("script");s.async=1; |
| 16 | +s.src="https://cdn.immutable.com/pixel/v1/imtbl.js"; |
| 17 | +document.head.appendChild(s); |
| 18 | +})(); |
| 19 | +</script> |
| 20 | +``` |
| 21 | + |
| 22 | +Replace `YOUR_PUBLISHABLE_KEY` with your project's publishable key. |
| 23 | + |
| 24 | +The script loads asynchronously and does not block page rendering. The default consent level is `none` — the pixel loads but does not collect until consent is explicitly set (see [Consent Modes](#consent-modes)). To start collecting anonymous device signals immediately, add `"consent":"anonymous"` to the init object. |
| 25 | + |
| 26 | +## Consent Modes |
| 27 | + |
| 28 | +The `consent` option controls what the pixel collects. **Default is `none`** (no events fire until consent is set). |
| 29 | + |
| 30 | +| Level | What's collected | Cookies set | Use case | |
| 31 | +|-------|-----------------|-------------|----------| |
| 32 | +| `none` | Nothing — pixel loads but is inert | None | Before consent banner interaction | |
| 33 | +| `anonymous` | Device signals, attribution, page views, form submissions, link clicks (no PII) | `imtbl_anon_id`, `_imtbl_sid` | Anonymous analytics without PII | |
| 34 | +| `full` | Everything in `anonymous` + user identity (email hash, userId) | `imtbl_anon_id`, `_imtbl_sid` | After explicit user consent | |
| 35 | + |
| 36 | +### Updating consent at runtime |
| 37 | + |
| 38 | +```javascript |
| 39 | +// After cookie banner interaction — upgrade to full |
| 40 | +window.__imtbl.push(['consent', 'full']); |
| 41 | + |
| 42 | +// Or downgrade (purges PII from queue) |
| 43 | +window.__imtbl.push(['consent', 'none']); |
| 44 | +``` |
| 45 | + |
| 46 | +## Auto-Tracked Events |
| 47 | + |
| 48 | +All events fire automatically with no instrumentation required. |
| 49 | + |
| 50 | +| Event | When it fires | Key properties | |
| 51 | +|-------|--------------|----------------| |
| 52 | +| `page` | Every page load | UTMs, click IDs (`gclid`, `fbclid`, `ttclid`, `msclkid`, `dclid`, `li_fat_id`), `referral_code`, `landing_page` | |
| 53 | +| `session_start` | New session (no active `_imtbl_sid` cookie) | `sessionId` | |
| 54 | +| `session_end` | Page unload (`visibilitychange` / `pagehide`) | `sessionId`, `duration` (seconds) | |
| 55 | +| `form_submitted` | HTML form submission | `formAction`, `formId`, `formName`, `fieldNames`. `emailHash` at `full` consent only. | |
| 56 | +| `link_clicked` | Outbound link click (external domains only) | `linkUrl`, `linkText`, `elementId`, `outbound: true` | |
| 57 | + |
| 58 | +### Disabling specific auto-capture |
| 59 | + |
| 60 | +```html |
| 61 | +<script> |
| 62 | +(function(){ |
| 63 | +var w=window,i="__imtbl"; |
| 64 | +w[i]=w[i]||[]; |
| 65 | +w[i].push(["init",{ |
| 66 | + "key":"YOUR_KEY", |
| 67 | + "consent":"anonymous", |
| 68 | + "autocapture":{"forms":false,"clicks":true} |
| 69 | +}]); |
| 70 | +var s=document.createElement("script");s.async=1; |
| 71 | +s.src="https://cdn.immutable.com/pixel/v1/imtbl.js"; |
| 72 | +document.head.appendChild(s); |
| 73 | +})(); |
| 74 | +</script> |
| 75 | +``` |
| 76 | + |
| 77 | +## Identity (Optional) |
| 78 | + |
| 79 | +For sites with user accounts, identify known users at `full` consent: |
| 80 | + |
| 81 | +```javascript |
| 82 | +window.__imtbl.push(['identify', 'user-123', 'passport', { email: 'player@example.com' }]); |
| 83 | +``` |
| 84 | + |
| 85 | +Note: traits passed via `identify` are sent as-is. Email values are only automatically SHA-256 hashed when captured from form submissions via auto-capture (see [Auto-Tracked Events](#auto-tracked-events)). If you pass an email in identify traits, hash it yourself before calling identify if that is required for your use case. |
| 86 | + |
| 87 | +## Cookies |
| 88 | + |
| 89 | +| Cookie | Lifetime | Purpose | |
| 90 | +|--------|----------|---------| |
| 91 | +| `imtbl_anon_id` | 2 years | Anonymous device ID (shared with web SDK) | |
| 92 | +| `_imtbl_sid` | 30 minutes (rolling) | Session ID — resets on inactivity | |
| 93 | + |
| 94 | +Both cookies are first-party (`SameSite=Lax`, `Secure` on HTTPS). |
| 95 | + |
| 96 | +## Content Security Policy (CSP) |
| 97 | + |
| 98 | +If your site uses a Content-Security-Policy header, add these origins to the relevant directives: |
| 99 | + |
| 100 | +``` |
| 101 | +script-src ... https://cdn.immutable.com; |
| 102 | +connect-src ... https://api.immutable.com; |
| 103 | +``` |
| 104 | + |
| 105 | +These must be added alongside your existing policy values, not replace them. |
| 106 | + |
| 107 | +For nonce-based CSP, add the nonce to the inline `<script>` tag in the snippet: |
| 108 | + |
| 109 | +```html |
| 110 | +<script nonce="YOUR_NONCE"> |
| 111 | +(function(){ |
| 112 | +var w=window,i="__imtbl"; |
| 113 | +w[i]=w[i]||[]; |
| 114 | +w[i].push(["init",{"key":"YOUR_KEY","consent":"anonymous"}]); |
| 115 | +var s=document.createElement("script");s.async=1; |
| 116 | +s.src="https://cdn.immutable.com/pixel/v1/imtbl.js"; |
| 117 | +document.head.appendChild(s); |
| 118 | +})(); |
| 119 | +</script> |
| 120 | +``` |
| 121 | + |
| 122 | +Note: the nonce covers the inline snippet only. The CDN-loaded script (`imtbl.js`) is covered by the `script-src https://cdn.immutable.com` directive. |
| 123 | + |
| 124 | +## Browser Support |
| 125 | + |
| 126 | +| Browser | Minimum Version | |
| 127 | +|---------|----------------| |
| 128 | +| Chrome | 80+ | |
| 129 | +| Firefox | 78+ | |
| 130 | +| Safari | 14+ | |
| 131 | +| Edge | 80+ | |
| 132 | + |
| 133 | +## Game Page Integration |
| 134 | + |
| 135 | +The Game Page uses the pixel with `consent: 'anonymous'` (no PII, device signals only): |
| 136 | + |
| 137 | +```html |
| 138 | +<script> |
| 139 | +(function(){ |
| 140 | +var w=window,i="__imtbl"; |
| 141 | +w[i]=w[i]||[]; |
| 142 | +w[i].push(["init",{"key":"GAME_PAGE_PUBLISHABLE_KEY","consent":"anonymous"}]); |
| 143 | +var s=document.createElement("script");s.async=1; |
| 144 | +s.src="https://cdn.immutable.com/pixel/v1/imtbl.js"; |
| 145 | +document.head.appendChild(s); |
| 146 | +})(); |
| 147 | +</script> |
| 148 | +``` |
| 149 | + |
| 150 | +### Validation Checklist |
| 151 | + |
| 152 | +After installing on Game Page, verify: |
| 153 | + |
| 154 | +- [ ] Snippet is in `<head>` and does not block rendering (async load confirmed) |
| 155 | +- [ ] Page load impact under 50ms (measure with Lighthouse) |
| 156 | +- [ ] `PageMessage` events visible in events pipeline with `surface: 'pixel'` |
| 157 | +- [ ] Attribution context (UTMs, referrer) correctly captured on campaign-linked visits |
| 158 | +- [ ] Session cookie (`_imtbl_sid`) set and rolling on navigation |
| 159 | +- [ ] Anonymous ID cookie (`imtbl_anon_id`) set with 2-year expiry |
| 160 | +- [ ] No console errors across Chrome 80+, Firefox 78+, Safari 14+, Edge 80+ |
| 161 | +- [ ] CSP (if any) allows `script-src cdn.immutable.com` and `connect-src api.immutable.com` |
| 162 | +- [ ] 100% of events pass backend schema validation (check rejected count in API logs) |
| 163 | +- [ ] Event volume within expected range — no duplicate events, no runaway listeners |
| 164 | +- [ ] Monitor for 24 hours post-deployment before clearing for external rollout |
| 165 | + |
| 166 | +### Browser Compatibility Matrix |
| 167 | + |
| 168 | +| Check | Chrome 80+ | Firefox 78+ | Safari 14+ | Edge 80+ | |
| 169 | +|-------|-----------|-------------|------------|---------| |
| 170 | +| Pixel loads (no network errors) | | | | | |
| 171 | +| `page` event fires (POST 200 in Network tab) | | | | | |
| 172 | +| `surface: 'pixel'` in request body | | | | | |
| 173 | +| `_imtbl_sid` cookie set (30min expiry) | | | | | |
| 174 | +| `imtbl_anon_id` cookie set (2yr expiry) | | | | | |
| 175 | +| UTM params captured in properties | | | | | |
| 176 | +| `form_submitted` fires on form submit | | | | | |
| 177 | +| `link_clicked` fires on outbound click | | | | | |
| 178 | +| No console errors | | | | | |
0 commit comments