Skip to main content
The Unity SDK is currently in alpha. APIs and behavior may change between releases.
Who is this for? Unity engineers building games on Windows (64-bit), macOS, Linux (64-bit), iOS, or Android who want typed in-game tracking, identity, and offline-safe queuing.
The Immutable Unity SDK instruments the in-game layer of the player journey as part of the Immutable attribution system, connecting the campaigns and referral links that drove players to your game with their actual in-game behavior. Session lifecycle and a launch event are captured automatically. In-game moments like progressions, purchases, and milestones are triggered by your code.

What You Need

Mobile builds targeting iOS or Android with attribution signals require additional setup. See Mobile.

Installation

Install the package via Unity Package Manager using a Git URL.
  1. In Unity, open Window → Package Manager.
  2. Click the + button in the top-left, then Add package from git URL….
  3. Paste the URL below and click Add:
The package appears in your project as Immutable Audience under Packages in the Project window. To update to a newer release, edit the version tag in Packages/manifest.json directly.

Quick Start

Prefer learning from a running project? A working Unity sample lives at unity-immutable-sdk/examples/audience. Clone the repository, set your publishable key, and run.
1

Initialize the SDK at boot

Call ImmutableAudience.Init once at game launch. You can mark a static method with [RuntimeInitializeOnLoadMethod] to have Unity call it before any scene loads.
Consent defaults to ConsentLevel.None, which suppresses all tracking. The example above sets Anonymous directly so events flow immediately. For an in-game privacy prompt, see the next step.
2

Set consent

The SDK uses a three-tier consent model (None, Anonymous, Full). The default is None. The SDK does not collect anything until you explicitly raise it. The SDK does not provide a consent UI. Build your own in-game prompt and call SetConsent when the player responds.
SetConsent takes effect immediately. Lowering the level purges queued events the new level no longer permits. See the Data Dictionary for what each level collects.
3

Track events

Use ImmutableAudience.Track to log a player action. The SDK ships with predefined events for common player actions and accepts any custom event string.
4

Identify users

Identifies the player by associating their userId with their in-game activity and traits. Call at login or account connection. Requires Full consent.
5

Clean up on exit

Called automatically on Application.quitting. For manual teardown:

Complete Example

Verify the Integration

After Init, the SDK exposes its state through read-only properties on ImmutableAudience. Log them to confirm a healthy install:
Pair with an OnError callback in your AudienceConfig to surface failures (see Error Handling):
A healthy install:

Mobile

Mobile adds opt-in device-level attribution signals for iOS and Android.

Attribution opt-in

Two gates must both be set before any mobile attribution data ships: Setting AUDIENCE_MOBILE_ATTRIBUTION does three things: adds the AD_ID manifest permission on Android, compiles in native attribution code, and switches the iOS privacy manifest to the tracking variant (NSPrivacyTracking = true). If neither gate is set, the build ships without attribution code: no AD_ID manifest permission, no native tracking, and NSPrivacyTracking = false in the iOS privacy manifest.

Platform setup

1. Create a Mobile Build Settings assetThe iOS build post-processors need a NSUserTrackingUsageDescription string. Apple rejects builds that omit this key. Create the asset once per Unity project:
  1. Assets → Create → Immutable Audience → Mobile Build Settings
  2. Set Tracking Usage Description to a specific description of what you collect and why. Apple rejects generic copy.
2. Request App Tracking Transparency (ATT) authorizationCall RequestTrackingAuthorizationAsync at a contextually appropriate moment. The IDFA, when authorized, ships automatically in the next game_launch. A tracking_authorization_changed event fires on any subsequent status transition.ATT requires iOS 14+. On iOS 13 the call resolves to NotDetermined and IDFA is unavailable. All other SDK features work normally.
Privacy manifest (automatic)No action required. The SDK ships a PrivacyInfo.xcprivacy that Unity merges into the generated Xcode project. The post-processor selects the correct variant based on the AUDIENCE_MOBILE_ATTRIBUTION define:No Required Reason APIs are used by the SDK. NSPrivacyAccessedAPITypes in the manifest reflects Unity engine internals only.

API Reference

All methods are static on Immutable.Audience.ImmutableAudience and are safe to call from any thread after Init returns.
Starts the SDK. Call once at game launch (see the Quick Start). Subsequent calls are ignored with a warning.Throws ArgumentNullException if config is null, and ArgumentException if PublishableKey is empty.
AudienceConfig fields:

Distribution platforms

DistributionPlatform is a free-form string sent in the distribution_platform property of the game_launch event. Init lowercases the value before it goes on the wire. Use the DistributionPlatforms constants when one matches:If you ship on a platform not in this list, pass the lowercase short name as a string.
Changes the consent level. Pass ConsentLevel.None, ConsentLevel.Anonymous, or ConsentLevel.Full. Takes effect immediately. Lowering the level purges queued events that the new level no longer permits. Lowering to None also clears the anonymous ID.
The new level is persisted to disk so it survives the next launch. The SDK also notifies the backend asynchronously for audit logging. Failures fire OnError with AudienceErrorCode.ConsentSyncFailed but do not affect local state.
Sends a predefined event. See the Data Dictionary for available event classes and their schemas.Requires: Anonymous or Full consent. Calls at None are silently dropped.
Sends a custom event with arbitrary properties. No validation runs on this overload. Prefer Track(IEvent) for predefined events. Property values can be any JSON-serializable primitive or string. Strings are truncated at 256 characters.Requires: Anonymous or Full consent.
Associates the player’s userId with their in-game activity and traits. Call at login or account connection. Use IdentityType.Custom for providers not in the enum.Requires: Full consent. Calls at lower levels are dropped with a log warning.
Identity types:Auto-collection on Steam and EpicWhen DistributionPlatform is "steam" or "epic" and consent is Full at Init, the SDK calls Identify for you. The platform session must already be active when Init runs:Auto-collection runs once at Init. If your consent flow starts below Full, call Identify manually when the player grants full consent. If your game also has its own backend user ID, link it with Alias rather than calling Identify again.
Links two user IDs that belong to the same player. Call when a player connects a second account (e.g. a player with an internal game account ID later signs in via Steam).Requires: Full consent. Both fromType and toType are required for data-deletion matching.
Wipes the current player’s identity, generates a fresh anonymous ID, and discards queued events (memory and disk) so the next player on the device isn’t attributed to the previous one. Call when a player logs out. Reset does not change the consent level, so studios using an explicit consent prompt should also call SetConsent(ConsentLevel.None) at logout if the next player should start unconsented.To send queued events before they’re discarded:
Asks the backend to erase the player’s data. Returns a Task you can await for acknowledgement, or discard for fire-and-forget.
Erasure is server-side. After the request is accepted, also call Reset on the client so the next session isn’t linked to the deleted user. See the REST API for the request shape.
Sends all queued events to the server immediately. Returns a Task that completes when the queue is empty or a backoff window prevents further sends. Call before Reset (which discards queued events) or Shutdown (which is capped at ShutdownFlushTimeoutMs) if you want every pending event delivered first. When calling FlushAsync in a logout flow, pass a CancellationToken with a deadline so the call does not hang if the network is unavailable at logout time, for example new CancellationTokenSource(TimeSpan.FromSeconds(5)).Token.
Flushes any pending events (capped at ShutdownFlushTimeoutMs, default 2 seconds) and stops the SDK. Called automatically on Application.quitting. You do not need to call it yourself unless you want to control the flush timing or reinitialize with new config.
Shows the iOS App Tracking Transparency prompt and returns the user’s decision. The prompt appears once per app install; subsequent calls return the cached status without showing the prompt again.On non-iOS platforms, iOS 13, or before the SDK is initialized, resolves to NotDetermined.Requires: AUDIENCE_MOBILE_ATTRIBUTION define + EnableMobileAttribution = true.
Call at a moment when the value exchange is clear to the player. Apple’s HIG forbids prompting on cold launch. After the user responds, the SDK fires tracking_authorization_changed if the status differs from the previously stored value.
Read-only properties for inspecting SDK state. Use these to verify the SDK is initialized, gate UI elements that depend on consent state (the Unity SDK does not currently ship dedicated CanTrack or CanIdentify helpers, so read CurrentConsent and compare against ConsentLevel.Anonymous or ConsentLevel.Full instead), or watch the queue size during development.

Event Delivery

  • Events are batched and flushed every 5 seconds or when 20 events accumulate. Configure via the FlushIntervalSeconds and FlushSize fields on AudienceConfig (see Init).
  • Application.quitting triggers a final flush capped at ShutdownFlushTimeoutMs (default 2 seconds).
  • Events not flushed before quit are persisted to disk and shipped on the next launch. Events older than 30 days are discarded.

Error Handling

Flushes run on a background thread with automatic retries. Most failures don’t surface to your code. Pass an OnError callback when configuring Init to observe them. AudienceError.Code is one of:

FAQ

Both Mono and IL2CPP are fully supported. Choose either in Edit → Project Settings → Player → Other Settings → Scripting Backend.
Yes. Init, Track, session lifecycle, and flush all work in Play Mode and Edit Mode test runners. Events fired in the Editor reach the same pipeline as builds. Set TestMode = true in your AudienceConfig during development to mark events as test traffic and keep them separate from production data in analytics.
Yes. Unity captures in-game actions, and the Web SDK covers web games, marketing sites, and single-page apps. All events flow to the same pipeline. See the Data Dictionary for the full per-event schema.
Erasure is server-side. From your backend, call DELETE /v1/audience/data with the user’s userId or anonymousId. See Deleting User Data for the request shape. From inside the game, call ImmutableAudience.DeleteData(userId) and then ImmutableAudience.Reset() so subsequent activity isn’t linked to the erased user.
Auto-collection fires at Init when consent is Full and the platform session is already active (Steam running, or EOS initialized and the player logged in). If consent is below Full at Init, or the platform session is not active yet, the SDK does not auto-identify. Call Identify yourself once the player grants full consent.
Under Application.persistentDataPath in a folder named imtbl_audience. The folder contains the anonymous ID, the persisted consent level, and any queued events that haven’t been flushed yet. Deleting it resets the SDK’s local state on next launch.
Call Identify with the same userId on both surfaces at login. Events from both sessions are attributed to that player automatically, no Alias call needed.Alias is only needed when the same player uses different provider IDs on different surfaces. For example, if the player is identified as a Steam user in-game but later links a Passport account, call Alias to tell the backend they are the same person. See Identity Stitching in the Data Dictionary.

Next Steps

Sample app

Working Unity project with Init, consent, Track, and Identify wired up

Attribution

How tracking data powers player attribution and Hub reports

Data Dictionary

Full reference of event schemas and consent levels

Web SDK

Typed SDK for web games, marketing sites, and SPAs

REST API

Send events from your backend or game server

Conversion Postbacks

Send attributed conversions back to ad networks to improve campaign optimisation

API Keys

Manage your publishable and secret keys