> ## 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.

# Data Dictionary

> Complete reference of data collected and event schemas across the Web SDK, Unity SDK, and REST API

<Warning>
  The Web SDK, Unity SDK, and REST API are currently in **alpha**. The data collected and event schemas may change between releases.
</Warning>

Full reference of data collected and event schemas for the [Web SDK](/docs/products/audience/analytics/web-sdk), [Unity SDK](/docs/products/audience/analytics/unity-sdk), and [REST API](/docs/products/audience/analytics/rest-api), and the data forwarded externally by [Conversion Postbacks](/docs/products/attribution/postbacks/overview). Use it to understand what each integration sends, when it sends it, and what properties each event carries. Also useful for privacy reviews, legal assessments, and technical audits.

## Cookies

First-party cookies only. No third-party cookies are created.

The Unity SDK does not use cookies. It persists `AnonymousId` and queued events to native local storage instead.

<AccordionGroup>
  <Accordion title={<>imtbl_anon_id <Badge color="surface" shape="pill">Web SDK</Badge></>}>
    Persistent anonymous device identifier (UUID v4).

    | Property | Value |
    | - | - |
    | Lifetime | 2 years |
    | Scope | First-party, current hostname |
    | Attributes | `SameSite=Lax`, `Secure` on HTTPS |
  </Accordion>

  <Accordion title={<>_imtbl_sid <Badge color="surface" shape="pill">Web SDK</Badge></>}>
    Session continuity across page loads. Refreshed on each tracking call. Expires after 30 minutes of inactivity.

    | Property | Value |
    | - | - |
    | Lifetime | 30 minutes (rolling) |
    | Scope | First-party, current hostname |
    | Attributes | `SameSite=Lax`, `Secure` on HTTPS |
  </Accordion>

  <Accordion title={<>_ga <Badge color="surface" shape="pill">Web SDK</Badge></>}>
    Google Analytics client ID. Read-only. The Web SDK reads this cookie for cross-platform identity stitching but does not write it.

    | Property | Value |
    | - | - |
    | Source | Google Analytics |
  </Accordion>

  <Accordion title={<>_fbc <Badge color="surface" shape="pill">Web SDK</Badge></>}>
    Facebook click ID. Read-only. The Web SDK reads this cookie for cross-platform identity stitching but does not write it.

    | Property | Value |
    | - | - |
    | Source | Meta (Facebook) |
  </Accordion>

  <Accordion title={<>_fbp <Badge color="surface" shape="pill">Web SDK</Badge></>}>
    Facebook browser ID. Read-only. The Web SDK reads this cookie for cross-platform identity stitching but does not write it.

    | Property | Value |
    | - | - |
    | Source | Meta (Facebook) |
  </Accordion>
</AccordionGroup>

## Auto-Tracked

Signals collected and events fired by the integration without any studio code.

### Device Fingerprint Signals

These signals are collected automatically when consent is `anonymous` or `full`.

<Tabs>
  <Tab title="Web SDK">
    | Signal | Source | Example |
    | - | - | - |
    | User agent | `navigator.userAgent` | `Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...` |
    | Screen resolution | `screen.width` × `screen.height` | `1920×1080` |
    | Timezone | `Intl.DateTimeFormat().resolvedOptions().timeZone` | `America/New_York` |
    | Browser language | `navigator.language` | `en-US` |
    | IP address | Server-side from request headers | Raw IP stored for geo enrichment |
  </Tab>

  <Tab title="Unity SDK">
    The Unity SDK collects a different fingerprint set (CPU, GPU, RAM, OS family, Unity version, screen DPI, device model) and emits it once per session as part of [`game_launch`](#auto-tracked-events) rather than on every event.
  </Tab>
</Tabs>

### Attribution Signals

The Web SDK collects these URL-based signals. Mobile Unity builds with attribution enabled collect a separate set of device-level signals. Desktop Unity builds collect none.

<Tabs>
  <Tab title="Web SDK">
    The Web SDK attaches them to the first `page()` call and the `sign_up` and `link_clicked` events.

    | Signal | Source | Example |
    | - | - | - |
    | UTM parameters | URL query string | `utm_source`, `utm_medium`, `utm_campaign`, `utm_term`, `utm_content` |
    | Google click ID | URL query string | `gclid` |
    | Meta click ID | URL query string | `fbclid` |
    | TikTok click ID | URL query string | `ttclid` |
    | Reddit click ID | URL query string | `rdt_cid` |
    | Microsoft click ID | URL query string | `msclkid` |
    | Display & Video 360 click ID | URL query string | `dclid` |
    | LinkedIn click ID | URL query string | `li_fat_id` |
    | X click ID | URL query string | `twclid` |
    | Referrer | `document.referrer` | The referring page URL |
    | Landing page | `window.location.href` (first page in session) | Entry point URL |
    | Referral code | URL query string | `referral_code`: a custom parameter you add to campaign links (e.g. `?referral_code=influencer-abc`) to track referral sources |
  </Tab>

  <Tab title="Unity SDK">
    Desktop builds do not collect URL-based attribution signals. The closest analogue is the studio-supplied `distribution_platform` property on [`game_launch`](#auto-tracked-events).

    Mobile [attribution builds](/docs/products/audience/analytics/unity-sdk#mobile) (`AUDIENCE_MOBILE_ATTRIBUTION` + `EnableMobileAttribution = true`) ship additional signals with `game_launch`.

    **iOS**

    | Property | Type | Consent | Description |
    | - | - | - | - |
    | `att_status` | `string` | `Anonymous`+ | ATT authorization status: `notDetermined`, `restricted`, `denied`, or `authorized`. |
    | `idfa` | `string` | `Full` | Advertising identifier. Present only when ATT status is `authorized` and consent is `Full`. |
    | `skan_registered` | `boolean` | `Anonymous`+ | `true` on the launch where SKAdNetwork first-install registration fires. Omitted on subsequent launches. |

    **Android**

    | Property | Type | Consent | Description |
    | - | - | - | - |
    | `gaid` | `string` | `Full` | Google Advertising ID. Omitted when `gaid_limit_ad_tracking` is `true`. Available from the second launch onwards. |
    | `gaid_limit_ad_tracking` | `boolean` | `Anonymous`+ | Whether the user has opted out of ad personalization. Available from the second launch onwards. |
  </Tab>
</Tabs>

### Auto-Tracked Events

Events fired by the integration without studio code. Title badges indicate which integrations emit each event. Trigger conditions and per-integration property differences are described inside the accordion.

<AccordionGroup>
  <Accordion title={<>game_launch <Badge color="surface" shape="pill">Unity SDK</Badge></>}>
    Player launched the game. The Unity SDK fires this automatically at `Init` when consent permits tracking. The Web SDK and REST API do not currently emit this event.

    **Event name:** `game_launch`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `platform` | `string` | No | OS or mobile platform the game is running on. One of `'Windows'`, `'macOS'`, `'Linux'`, `'iOS'`, `'Android'`. |
    | `is_editor` | `boolean` | No | `true` when the game is running inside the Unity Editor; `false` for shipped builds. Use this to filter dev runs out of production analytics. |
    | `version` | `string` | No | Game version string |
    | `build_guid` | `string` | No | Unity build GUID |
    | `unity_version` | `string` | No | Unity version the build was made with |
    | `os_family` | `string` | No | Host operating system family from Unity's `SystemInfo.operatingSystemFamily`. One of `'Windows'`, `'MacOSX'`, `'Linux'`, `'Other'`. |
    | `device_model` | `string` | No | Hardware model |
    | `gpu` | `string` | No | GPU name |
    | `gpu_vendor` | `string` | No | GPU vendor |
    | `cpu` | `string` | No | CPU name |
    | `cpu_cores` | `integer` | No | Number of CPU cores |
    | `ram_mb` | `integer` | No | System RAM in megabytes |
    | `screen_dpi` | `integer` | No | Display DPI (omitted when 0). |
    | `distribution_platform` | `string` | No | Value of `AudienceConfig.DistributionPlatform` (e.g. `'steam'`, `'epic'`). Omitted if not set. Studio-supplied storefront identifier. Complements the Unity-emitted `platform`, which is the OS-level player runtime. |
    | `idfv` | `string` | No | iOS only. Identifier for Vendor, a device ID scoped to your publisher. Reset when all apps from the same publisher are uninstalled. |
    | `android_id` | `string` | No | Android only. Android device unique identifier. |

    On mobile with `EnableMobileAttribution = true`, additional attribution signals are included. See [Attribution Signals](#attribution-signals) for the full set.

    **Postback forwarding:** when [Conversion Postbacks](/docs/products/attribution/postbacks/overview) are configured for the game, attributed `game_launch` events are forwarded to the configured ad network as a registration/install signal. See [Outbound Forwarding](#outbound-forwarding).

    Fired automatically by `ImmutableAudience.Init`. Studios do not call this directly. The wire payload includes the full Unity property set:

    ```json theme={null}
    {
      "type": "track",
      "eventName": "game_launch",
      "properties": {
        "platform": "Windows",
        "is_editor": false,
        "version": "1.2.0",
        "build_guid": "00000000-0000-0000-0000-000000000000",
        "unity_version": "2022.3.10f1",
        "os_family": "Windows",
        "device_model": "PC",
        "gpu": "Generic GPU",
        "gpu_vendor": "Generic",
        "cpu": "Generic CPU",
        "cpu_cores": 8,
        "ram_mb": 16384,
        "screen_dpi": 96,
        "distribution_platform": "steam"
      }
    }
    ```
  </Accordion>

  <Accordion title={<>session_start <Badge color="surface" shape="pill">Unity SDK</Badge></>}>
    Fires when a new session begins. The Unity SDK fires it on `Init`, consent upgrade from `None`, or resume after a pause longer than 30 seconds. The Web SDK does not emit this event; it attaches a `sessionId` to every message instead (see [Auto-attached metadata](#auto-attached-metadata)) and session boundaries are derived from that.

    | Property | Type | Description |
    | - | - | - |
    | `session_id` | `string` | Unity SDK only, deprecated. Use the top-level `sessionId` field instead, see [Auto-attached metadata](#auto-attached-metadata). |
  </Accordion>

  <Accordion title={<>session_end <Badge color="surface" shape="pill">Unity SDK</Badge></>}>
    Fires when a session ends. Only fires when consent is at `Anonymous` or higher. The Unity SDK fires it when `Shutdown` is called, consent is downgraded to `None`, or a session rolls due to extended pause. The Web SDK does not emit this event.

    | Property | Type | Description |
    | - | - | - |
    | `session_id` | `string` | Deprecated. Use the top-level `sessionId` field instead, see [Auto-attached metadata](#auto-attached-metadata). |
    | `duration_sec` | `number` | Engagement seconds since `session_start`, wall-clock minus accumulated pause time |
  </Accordion>

  <Accordion title={<>session_heartbeat <Badge color="surface" shape="pill">Unity SDK</Badge></>}>
    Fires every 60 seconds while the game is focused. Pause and resume reset the heartbeat clock, so wall-clock and reported engagement time can diverge.

    | Property | Type | Description |
    | - | - | - |
    | `session_id` | `string` | Deprecated. Use the top-level `sessionId` field instead, see [Auto-attached metadata](#auto-attached-metadata). |
    | `duration_sec` | `number` | Engagement seconds since `session_start`, wall-clock minus accumulated pause time |

    Used to estimate playtime per session for studios where players regularly leave the game backgrounded. The Web SDK does not emit this event.
  </Accordion>

  <Accordion title={<>tracking_authorization_changed <Badge color="surface" shape="pill">Unity SDK</Badge></>}>
    ATT authorization status changed from its previously recorded value. Does not fire on first launch. The initial state is reported by `game_launch`.

    **Requires:** `EnableMobileAttribution = true`, `Anonymous` or `Full` consent, iOS only.

    **Event name:** `tracking_authorization_changed`

    | Property | Type | Consent | Description |
    | - | - | - | - |
    | `previous_status` | `string` | `Anonymous`+ | Prior ATT status: `notDetermined`, `restricted`, `denied`, or `authorized` |
    | `new_status` | `string` | `Anonymous`+ | New ATT status |
    | `idfa` | `string` | `Full` | Present only when transitioning to `authorized` with `Full` consent |
  </Accordion>

  <Accordion title={<>install_referrer_received <Badge color="surface" shape="pill">Unity SDK</Badge></>}>
    Android Play Install Referrer captured. Fires once per install. On first launch the Play Services fetch is usually still in flight when `game_launch` fires, so the event typically arrives on the second launch.

    **Requires:** `EnableMobileAttribution = true`, `Full` consent, Android only.

    **Event name:** `install_referrer_received`

    | Property | Type | Description |
    | - | - | - |
    | `install_referrer` | `string` | Raw referrer string from Google Play (e.g. `utm_source=google-play&utm_medium=organic`) |
  </Accordion>

  <Accordion title={<>page <Badge color="surface" shape="pill">Web SDK</Badge></>}>
    Call `page()` manually on each route change.

    | Property | Type | Web SDK | Description |
    | - | - | - | - |
    | `utm_source` | `string` | Once per session | UTM source parameter from URL |
    | `utm_medium` | `string` | Once per session | UTM medium parameter from URL |
    | `utm_campaign` | `string` | Once per session | UTM campaign parameter from URL |
    | `utm_term` | `string` | Once per session | UTM term parameter from URL |
    | `utm_content` | `string` | Once per session | UTM content parameter from URL |
    | `gclid` | `string` | Once per session | Google Ads click ID |
    | `fbclid` | `string` | Once per session | Meta click ID |
    | `ttclid` | `string` | Once per session | TikTok click ID |
    | `rdt_cid` | `string` | Once per session | Reddit click ID |
    | `msclkid` | `string` | Once per session | Microsoft click ID |
    | `dclid` | `string` | Once per session | Display & Video 360 click ID |
    | `li_fat_id` | `string` | Once per session | LinkedIn click ID |
    | `twclid` | `string` | Once per session | X click ID |
    | `referrer` | `string` | Once per session | Referring page URL |
    | `landing_page` | `string` | Once per session | Entry point URL |
    | `referral_code` | `string` | Once per session | Custom referral link parameter |
    | `touchpoint_type` | `string` | Once per session | `'click'` when any click ID or UTM parameter is present |
    | `ga_client_id` | `string` | Every page | Google Analytics client ID (from `_ga` cookie) |
    | `fb_click_id` | `string` | Every page | Facebook click ID (from `_fbc` cookie) |
    | `fb_browser_id` | `string` | Every page | Facebook browser ID (from `_fbp` cookie) |
  </Accordion>

  <Accordion title={<>form_submitted <Badge color="surface" shape="pill">Web SDK</Badge></>}>
    Fires on HTML form submission. Can be disabled with `autocapture.forms: false`.

    | Property | Type | Description |
    | - | - | - |
    | `form_action` | `string` | Form action URL |
    | `form_id` | `string` | Form element ID |
    | `form_name` | `string` | Form element name |
    | `field_names` | `string[]` | Names of form fields |
    | `email_hash` | `string` | SHA-256 hashed email address (`full` consent only) |
  </Accordion>

  <Accordion title={<>scroll_depth <Badge color="surface" shape="pill">Web SDK</Badge></>}>
    Fires when the user scrolls past a depth milestone (25%, 50%, 75%, 90%, 100%). Each milestone fires at most once per page load. On above-the-fold pages (all content visible without scrolling), fires `depth: 100` with `aboveFold: true` after a 2-second dwell time to filter immediate bounces. Can be disabled with `autocapture.scroll: false`.

    | Property | Type | Description |
    | - | - | - |
    | `depth` | `integer` | Milestone reached: 25, 50, 75, 90, or 100 |
    | `aboveFold` | `boolean` | `true` on above-the-fold pages (only present when applicable) |
  </Accordion>
</AccordionGroup>

## Identity Stitching

Each integration assigns an `anonymousId` automatically when tracking begins. As a player moves through your funnel (visiting your marketing site, creating an account, launching the game), identity calls connect those anonymous sessions to a known player in attribution reports.

| Integration | How `anonymousId` is assigned |
| - | - |
| Web SDK | Reads or sets the `imtbl_anon_id` first-party cookie |
| Unity SDK | Generates a persistent GUID stored in `Application.persistentDataPath` |
| REST API | Provided by the caller in the message payload |

Call `identify()` at login to associate the player's `userId` with their activity and traits. A player who logs in on both the marketing site and in-game using the same `userId` will have both session histories attributed to the same profile, no `alias` call needed.

Call `alias()` when the same player is known by different provider IDs across surfaces, for example a player previously identified as a Steam user who later links an email account.

For exact method signatures and the full list of `IdentityType` values, see the API Reference section of the [Web SDK](/docs/products/audience/analytics/web-sdk#api-reference), [Unity SDK](/docs/products/audience/analytics/unity-sdk#api-reference), or [REST API](/docs/products/audience/analytics/rest-api#api-reference) docs.

## Predefined Events

Typed events for common player actions. These schemas apply to the [Web SDK](/docs/products/audience/analytics/web-sdk), the [Unity SDK](/docs/products/audience/analytics/unity-sdk), and the [REST API](/docs/products/audience/analytics/rest-api). Each event accordion below shows the typed call shape for every integration.

Properties are identical across integrations unless noted. Each integration also auto-attaches its own metadata to every event. See [Auto-attached metadata](#auto-attached-metadata) below.

### Event schemas

<AccordionGroup>
  <Accordion title={<>sign_up <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player created a new account.

    **Event name:** `sign_up`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `method` | `string` | No | How the player signed up (e.g. `'email'`, `'google'`, `'passport'`) |

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.SIGN_UP, { method: 'email' });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "sign_up",
          "properties": { "method": "email" }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>sign_in <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player signed in to an existing account.

    **Event name:** `sign_in`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `method` | `string` | No | Authentication method used (e.g. `'email'`, `'google'`, `'passport'`) |

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.SIGN_IN, { method: 'google' });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "sign_in",
          "properties": { "method": "google" }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>purchase <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">Unity SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player completed a purchase.

    **Event name:** `purchase`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `currency` | `string` | **Yes** | Currency code (e.g. `'USD'`, `'ETH'`) |
    | `value` | `string` | **Yes** | Total purchase value. A numeric-looking string (e.g. `'9.99'`), not a number, to avoid floating-point precision loss. Unity SDK still sends a `decimal` pending a follow-up update. |
    | `item_id` | `string` | No | Unique identifier for the item |
    | `item_name` | `string` | No | Display name of the item |
    | `quantity` | `number` | No | Number of items purchased |
    | `transaction_id` | `string` | No | Your internal transaction reference |

    **Postback forwarding:** when [Conversion Postbacks](/docs/products/attribution/postbacks/overview) are configured for the game, attributed `purchase` events (including `value` and `currency`) are forwarded to the configured ad network for ROAS optimisation. See [Outbound Forwarding](#outbound-forwarding).

    Player buys a sword for \$9.99:

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.PURCHASE, {
          currency: 'USD',
          value: '9.99',
          item_name: 'Legendary Sword',
          quantity: 1,
        });
        ```
      </Tab>

      <Tab title="Unity SDK">
        ```csharp theme={null}
        ImmutableAudience.Track(new Purchase
        {
            Currency = "USD",
            Value = 9.99m,
            ItemName = "Legendary Sword",
            Quantity = 1,
        });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "purchase",
          "properties": {
            "currency": "USD",
            "value": "9.99",
            "item_name": "Legendary Sword",
            "quantity": 1
          }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>progression <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">Unity SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player started, completed, or failed a level or stage.

    **Event name:** `progression`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `status` | `'start' \| 'complete' \| 'fail'` | **Yes** | Whether the player started, completed, or failed this segment |
    | `world` | `string` | No | Top-level grouping (e.g. `'forest'`, `'dungeon'`, `'chapter-1'`) |
    | `level` | `string` | No | Level within the world (e.g. `'3'`, `'boss'`) |
    | `stage` | `string` | No | Sub-level or checkpoint within the level |
    | `score` | `number` | No | Score achieved |
    | `duration_sec` | `number` | No | Time spent in seconds |

    Player completed level 3 of the forest world with a score of 4500 in 2 minutes:

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.PROGRESSION, {
          status: 'complete',
          world: 'forest',
          level: '3',
          score: 4500,
          duration_sec: 120,
        });
        ```
      </Tab>

      <Tab title="Unity SDK">
        ```csharp theme={null}
        ImmutableAudience.Track(new Progression
        {
            Status = ProgressionStatus.Complete,
            World = "forest",
            Level = "3",
            Score = 4500,
            DurationSec = 120,
        });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "progression",
          "properties": {
            "status": "complete",
            "world": "forest",
            "level": "3",
            "score": 4500,
            "duration_sec": 120
          }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>resource <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">Unity SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player gained or spent an in-game resource.

    **Event name:** `resource`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `flow` | `'sink' \| 'source'` | **Yes** | `'sink'` when the player spends a resource, `'source'` when they gain one |
    | `currency` | `string` | **Yes** | The resource type (e.g. `'gold'`, `'gems'`, `'energy'`) |
    | `amount` | `number` | **Yes** | Quantity gained or spent |
    | `item_type` | `string` | No | Category of the item involved (e.g. `'weapon'`, `'consumable'`) |
    | `item_id` | `string` | No | Unique identifier for the item |

    Player spends 500 gold on a weapon:

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.RESOURCE, {
          flow: 'sink',
          currency: 'gold',
          amount: 500,
          item_type: 'weapon',
          item_id: 'legendary-sword',
        });
        ```
      </Tab>

      <Tab title="Unity SDK">
        ```csharp theme={null}
        ImmutableAudience.Track(new Resource
        {
            Flow = ResourceFlow.Sink,
            Currency = "gold",
            Amount = 500,
            ItemType = "weapon",
            ItemId = "legendary-sword",
        });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "resource",
          "properties": {
            "flow": "sink",
            "currency": "gold",
            "amount": 500,
            "item_type": "weapon",
            "item_id": "legendary-sword"
          }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>achievement_unlocked <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">Unity SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player unlocked an achievement.

    **Event name:** `achievement_unlocked`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `achievement_id` | `string` | **Yes** | Unique identifier for the achievement |
    | `achievement_name` | `string` | **Yes** | Display name of the achievement |
    | `achievement_type` | `'onboarding' \| 'progression' \| 'mastery' \| 'social' \| 'collection'` | No | Category of the achievement |

    Player defeats 100 enemies and unlocks a mastery achievement:

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.ACHIEVEMENT_UNLOCKED, {
          achievement_id: 'ach_enemies_100',
          achievement_name: '100 Enemies Defeated',
          achievement_type: 'mastery',
        });
        ```
      </Tab>

      <Tab title="Unity SDK">
        ```csharp theme={null}
        ImmutableAudience.Track(new AchievementUnlocked
        {
            AchievementId = "ach_enemies_100",
            AchievementName = "100 Enemies Defeated",
            AchievementType = AchievementType.Mastery,
        });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "achievement_unlocked",
          "properties": {
            "achievement_id": "ach_enemies_100",
            "achievement_name": "100 Enemies Defeated",
            "achievement_type": "mastery"
          }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>wishlist_add / wishlist_remove <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player added or removed a game from their wishlist.

    **Event names:** `wishlist_add`, `wishlist_remove`

    **wishlist\_add:**

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `game_id` | `string` | **Yes** | Unique identifier for the game |
    | `source` | `string` | No | Where the action happened (e.g. `'store'`, `'search'`, `'recommendation'`) |
    | `platform` | `string` | No | Platform (e.g. `'steam'`, `'epic'`) |

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.WISHLIST_ADD, {
          game_id: 'game-123',
          source: 'store',
          platform: 'steam',
        });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "wishlist_add",
          "properties": { "game_id": "game-123", "source": "store", "platform": "steam" }
        }
        ```
      </Tab>
    </Tabs>

    **wishlist\_remove:**

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `game_id` | `string` | **Yes** | Unique identifier for the game |

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.WISHLIST_REMOVE, { game_id: 'game-123' });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "wishlist_remove",
          "properties": { "game_id": "game-123" }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>email_acquired <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Captured a player's email address (e.g. from a newsletter signup or waitlist form).

    **Event name:** `email_acquired`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `source` | `string` | No | Where the email was collected (e.g. `'waitlist'`, `'newsletter'`, `'checkout'`) |

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.EMAIL_ACQUIRED, { source: 'waitlist' });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "email_acquired",
          "properties": { "source": "waitlist" }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>game_page_viewed <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player viewed a game page.

    **Event name:** `game_page_viewed`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `game_id` | `string` | **Yes** | Unique identifier for the game |
    | `game_name` | `string` | No | Display name of the game |
    | `slug` | `string` | No | URL-friendly identifier (e.g. `'my-game'`) |

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.GAME_PAGE_VIEWED, {
          game_id: 'game-123',
          game_name: 'My Game',
          slug: 'my-game',
        });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "game_page_viewed",
          "properties": { "game_id": "game-123", "game_name": "My Game", "slug": "my-game" }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>link_clicked <Badge color="surface" shape="pill">Web SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player clicked a link. Fires automatically for outbound link clicks (external domains only) via auto-capture — disable with `autocapture.clicks: false` — or manually via `track()`/the REST API for links auto-capture can't see (e.g. non-anchor elements, server-rendered redirects).

    **Event name:** `link_clicked`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `url` | `string` | **Yes** | Destination URL |
    | `label` | `string` | No | Display text or label for the link |
    | `source` | `string` | No | Where the link appeared (e.g. `'navbar'`, `'footer'`, `'cta-banner'`) |
    | `element_id` | `string` | No | DOM id of the clicked element. Only set by auto-capture |
    | `outbound` | `boolean` | No | Whether the link led off-site. Only set by auto-capture |

    Auto-captured clicks also carry the session's attribution signals (`utm_*`, click IDs, `referrer`, `landing_page`, `referral_code`, `touchpoint_type`).

    <Tabs>
      <Tab title="Web SDK">
        ```typescript theme={null}
        audience.track(AudienceEvents.LINK_CLICKED, {
          url: 'https://store.steampowered.com/app/123',
          label: 'Wishlist on Steam',
          source: 'cta-banner',
        });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "link_clicked",
          "properties": {
            "url": "https://store.steampowered.com/app/123",
            "label": "Wishlist on Steam",
            "source": "cta-banner"
          }
        }
        ```
      </Tab>
    </Tabs>
  </Accordion>

  <Accordion title={<>milestone_reached <Badge color="surface" shape="pill">Unity SDK</Badge> <Badge color="surface" shape="pill">REST API</Badge></>}>
    Player reached a named milestone or achievement. Use for any named accomplishment that does not fit the start/complete/fail shape of `progression`. Covers both **one-shot** achievements (e.g. `first_boss_defeated`, `tutorial_complete`, `100_percent_completion`) and **recurring** named milestones (e.g. `character_<id>_level_<N>`, `prestige_tier_<N>`, `streak_day_<N>`, `pvp_rank_<tier>`). Parameterise `name` for the recurring case so each instance is distinguishable in analytics.

    **Event name:** `milestone_reached`

    | Property | Type | Required | Description |
    | - | - | - | - |
    | `name` | `string` | **Yes** | Milestone identifier. One-shot example: `'first_boss_defeated'`. Recurring example: `'character_aria_level_5'` |

    Player defeats the first boss:

    <Tabs>
      <Tab title="Unity SDK">
        ```csharp theme={null}
        ImmutableAudience.Track(new MilestoneReached { Name = "first_boss_defeated" });
        ```
      </Tab>

      <Tab title="REST API">
        ```json theme={null}
        {
          "type": "track",
          "eventName": "milestone_reached",
          "properties": { "name": "first_boss_defeated" }
        }
        ```
      </Tab>
    </Tabs>

    The Web SDK does not yet ship a typed equivalent. Studios on that surface can emit the same event by passing the event name directly.
  </Accordion>
</AccordionGroup>

### Auto-attached metadata

The Web SDK and Unity SDK auto-attach a shared baseline to every event, including `identify()`/`Identify()` and `alias()`/`Alias()` calls:

* A persistent anonymous device identifier (`anonymousId`)
* The current session identifier (`sessionId`)
* An integration tag identifying the SDK source
* The library identifier and version
* Locale, screen size, timezone, and user-agent string

The Web SDK additionally captures browser page context (current page URL, path, referrer, and title) on every event. The tabs below document only the integration-specific additions on top of that baseline.

The backend additionally stamps `received_at` and IP-derived geo on every event regardless of integration.

<Tabs>
  <Tab title="Web SDK">
    | Method call | Auto-attached |
    | - | - |
    | `track('sign_up', ...)`, `track('link_clicked', ...)` | [Attribution signals](#attribution-signals) from the session's first-touch snapshot |
    | every `track()` call after `identify()` (Full consent only) | `userId` |

    <Note>
      Attribution is the session's first-touch snapshot, captured at session start. A player who arrives via `?utm_source=discord`, navigates to another page, then triggers `sign_up` still carries `utm_source=discord` on that event, and `landing_page` is included.
    </Note>
  </Tab>

  <Tab title="Unity SDK">
    | Method call | Auto-attached |
    | - | - |
    | every `Track` call after `Identify` (Full consent only) | `userId` |

    The shared baseline `context` is computed once at `Init` and attached unchanged to every event, rather than reassembled per call.
  </Tab>
</Tabs>

## Consent Model

All Audience integrations use a three-tier consent model. Consent defaults to None and can be changed at any time. Changes take effect immediately. The Audience integrations do not provide a consent UI. You are responsible for building the cookie banner or privacy prompt and setting the consent level when the user makes a choice.

| Level | What it does | When to set |
| - | - | - |
| **None** | Loads but collects nothing | Before consent is given or when consent is denied |
| **Anonymous** | Tracks activity without user identity | After analytics consent |
| **Full** | Tracks everything including user identity | After full tracking consent |

Native games do not have a cookie banner. Studios typically gate the consent call on a first-launch privacy prompt or a settings menu.

### Downgrading Consent

You can downgrade consent at any time. All integrations share this core behavior:

* **Full → Anonymous:** strips player identity from queued events, removes pending `identify()` and `alias()` messages.
* **Any level → None:** purges all queued events.

<Tabs>
  <Tab title="Web SDK">
    Clears local state (cookies and identity) so no tracking artifacts remain on the device.
  </Tab>

  <Tab title="Unity SDK">
    Fires `session_end` on downgrade to `None`, then stops emitting until consent is restored. `AnonymousId` persists in native local storage across downgrades so a later upgrade resumes the same anonymous identity rather than minting a fresh one.
  </Tab>

  <Tab title="REST API">
    Consent state is the caller's responsibility. The API has no client-side state to clear on downgrade.
  </Tab>
</Tabs>

The tables below show whether each data category is collected at each consent level.

<Tabs>
  <Tab title="Web SDK">
    | Data | `'none'` | `'anonymous'` | `'full'` |
    | - | - | - | - |
    | Cookies | None | `imtbl_anon_id`, `_imtbl_sid` | `imtbl_anon_id`, `_imtbl_sid` |
    | Device fingerprint | No | Yes | Yes |
    | Attribution signals | No | Yes | Yes |
    | `page()` | No | Yes | Yes |
    | `track()` | No | Yes | Yes |
    | Outbound link clicks | No | Yes | Yes |
    | Form submissions | No | Yes (no email) | Yes (hashed email) |
    | Scroll depth milestones | No | Yes | Yes |
    | Third-party ID stitching | No | Yes | Yes |
    | `identify()` | No | No | Yes |
    | `alias()` | No | No | Yes |
  </Tab>

  <Tab title="Unity SDK">
    | Data | `None` | `Anonymous` | `Full` |
    | - | - | - | - |
    | Local storage | `AnonymousId` only | `AnonymousId`, queued events | `AnonymousId`, queued events |
    | Session events (`session_start`, `session_heartbeat`, `session_end`) | No | Yes | Yes |
    | `game_launch` (auto at `Init`) | No | Yes | Yes |
    | Device fingerprint (CPU, GPU, RAM, OS, Unity version) | No | Yes (in `game_launch`) | Yes (in `game_launch`) |
    | Custom `Track` calls | No | Yes | Yes |
    | `Identify` (player identity) | No | No | Yes |
    | IDFV, Android device ID (all mobile builds) | No | Yes (in `game_launch`) | Yes (in `game_launch`) |
    | ATT status, SKAdNetwork registration (iOS attribution builds) | No | Yes (in `game_launch`) | Yes (in `game_launch`) |
    | IDFA (iOS, attribution builds) | No | No | Yes, when ATT `authorized` |
    | GAID, Install Referrer (Android, attribution builds) | No | No | Yes, from second launch (unless user opted out of ad personalization) |
  </Tab>

  <Tab title="REST API">
    Consent is your responsibility to enforce. The API processes only what you explicitly send. See [REST API: Consent](/docs/products/audience/analytics/rest-api#consent) for the consent endpoints.
  </Tab>
</Tabs>

## Outbound Forwarding

Most data collected by Audience integrations stays within Immutable. The exception is when [Conversion Postbacks](/docs/products/attribution/postbacks/overview) are configured for a game: attributed `game_launch` and `purchase` events are forwarded server-to-server to the configured ad network (TikTok Ads, Reddit Ads).

Forwarded payloads contain only the fields each ad network requires for conversion matching:

| Forwarded field | Source |
| - | - |
| Click ID (`ttclid` for TikTok Ads, `rdt_cid` for Reddit Ads) | Captured by the Web SDK from the URL when a player arrived from a paid ad |
| Event name (mapped to the network's taxonomy) | The originating `game_launch` or `purchase` event |
| `value` and `currency` | The `purchase` event's `value` and `currency` properties |
| Hashed email (Reddit Ads only, when no click ID is present) | The player's `identify()` email, hashed with SHA-256 |

Player names, raw emails, device fingerprints, session details, and event properties beyond the table above are **not** forwarded. Only events from players at `anonymous` or `full` consent are eligible. Forwarding requires explicit per-game configuration in [Audience Hub](https://hub.immutable.com); no postbacks fire for games without an active configuration.

See [Conversion Postbacks](/docs/products/attribution/postbacks/overview) for setup, supported networks, and delivery monitoring.

## What Is Not Collected

None of the Audience integrations collect the following:

* No cross-domain tracking (first-party cookies only)
* No session replay or screen recording
* No heatmaps or mouse movement tracking
* No A/B testing or feature flags
* No impression or view-through tracking (click-through only)
* No raw email addresses (only SHA-256 hashed, only at `full` consent)

## Next Steps

<CardGroup cols={2}>
  <Card title="Attribution" icon="route" href="/docs/products/attribution/overview">
    How tracking data powers player attribution and Hub reports
  </Card>

  <Card title="Web SDK" icon="code" href="/docs/products/audience/analytics/web-sdk">
    Typed SDK for web games, marketing sites, and SPAs
  </Card>

  <Card title="Unity SDK" icon="unity" href="/docs/products/audience/analytics/unity-sdk">
    In-game tracking for Unity games on PC and mobile.
  </Card>

  <Card title="REST API" icon="server" href="/docs/products/audience/analytics/rest-api">
    Send events from your backend or game server
  </Card>

  <Card title="Conversion Postbacks" icon="share-from-square" href="/docs/products/attribution/postbacks/overview">
    Send attributed conversions back to ad networks to improve campaign optimisation
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.