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.
What You Need
- An Immutable Hub account with a project (get started here)
- A publishable key from your project settings (API keys guide)
- A target build platform of Windows or macOS. Linux is not supported yet. Mobile and console are out of scope.
- A Unity project on a supported version:
- A Unity project using Mono or IL2CPP as the scripting backend (both are fully supported)
Installation
Install the package via Unity Package Manager using a Git URL.- In Unity, open Window → Package Manager.
- Click the + button in the top-left, then Add package from git URL….
- Paste the URL below and click Add:
Packages/manifest.json directly.
Quick Start
Initialize the SDK at boot
ImmutableAudience.Init once at game launch. You can mark a static method with [RuntimeInitializeOnLoadMethod] to have Unity call it before any scene loads.Set consent
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.Track events
ImmutableAudience.Track to log a player action. The SDK ships with predefined events for common player actions and accepts any custom event string.Identify users
Full consent.Complete Example
Verify the Integration
After Init, the SDK exposes its state through read-only properties onImmutableAudience. Log them to confirm a healthy install:
OnError callback in your AudienceConfig to surface failures (see Error Handling):
| Property | Healthy value |
|---|---|
Initialized | true |
AnonymousId | non-null GUID |
SessionId | non-null GUID once session_start has fired |
QueueSize | 1 immediately after a Track call, then 0 once flushed |
| Unity Console | no SDK warnings, no OnError invocations |
API Reference
All methods are static onImmutable.Audience.ImmutableAudience and are safe to call from any thread after Init returns.
Init(AudienceConfig)
Init(AudienceConfig)
ArgumentNullException if config is null, and ArgumentException if PublishableKey is empty.AudienceConfig fields:| Field | Type | Required | Default | Description |
|---|---|---|---|---|
PublishableKey | string | Yes | (none) | API key from Hub. Keys starting with pk_imapik-test- route to the sandbox environment. All other keys route to production. |
BaseUrl | string? | No | (auto from key) | Override the API base URL. Leave null to use the key-based default routing. |
Consent | ConsentLevel | No | None | Initial consent level. The SDK collects nothing until this is Anonymous or higher. |
DistributionPlatform | string? | No | null | The platform the build is shipping on. Init normalizes this to lowercase, so case at the call site does not matter. Use DistributionPlatforms.* constants for the standard values (see below). |
Debug | bool | No | false | Enable SDK warnings via UnityEngine.Debug.Log. Disable in release builds. |
FlushIntervalSeconds | int | No | 5 | How often pending events are flushed to the backend. |
FlushSize | int | No | 20 | Flush as soon as this many events are queued. |
OnError | Action<AudienceError>? | No | null | Callback fired on errors. Runs on a background thread. Marshal to the main thread before touching Unity APIs. AudienceError.Code is one of FlushFailed, ValidationRejected, ConsentSyncFailed, NetworkError, ConsentPersistFailed (see Error Handling for descriptions). |
PersistentDataPath | string? | No | (auto from Unity) | Directory for the SDK identity, consent, and queued-event files. The Unity integration fills this in from Application.persistentDataPath. |
PackageVersion | string | No | SDK package version | Library version sent on every message. Override only if you need to report a different version (e.g. wrapping the SDK in your own package). |
ShutdownFlushTimeoutMs | int | No | 2000 | Maximum time Shutdown waits for the final flush. |
Distribution platforms
DistributionPlatform is a free-form string sent in the distributionPlatform property of the game_launch event. Init lowercases the value before it goes on the wire. Use the DistributionPlatforms constants when one matches:| Constant | Value |
|---|---|
DistributionPlatforms.Steam | "steam" |
DistributionPlatforms.Epic | "epic" |
DistributionPlatforms.GOG | "gog" |
DistributionPlatforms.Itch | "itch" |
DistributionPlatforms.Standalone | "standalone" |
SetConsent(ConsentLevel level)
SetConsent(ConsentLevel level)
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.OnError with AudienceErrorCode.ConsentSyncFailed but do not affect local state.Track(IEvent)
Track(IEvent)
| Parameter | Type | Description |
|---|---|---|
evt | IEvent | The typed event instance. Null events are dropped with a log warning. |
Anonymous or Full consent. Calls at None are silently dropped.Track(string eventName, Dictionary<string, object>? properties)
Track(string eventName, Dictionary<string, object>? properties)
Track(IEvent) for predefined events. Property values can be any JSON-serializable primitive or string. Strings are truncated at 256 characters.| Parameter | Type | Description |
|---|---|---|
eventName | string | Required, non-empty. The custom event name. Null or empty values are dropped with a log warning. |
properties | Dictionary<string, object>? | Optional. Event properties. Defaults to null. |
Anonymous or Full consent.Identify(string userId, IdentityType identityType, Dictionary? traits = null)
Identify(string userId, IdentityType identityType, Dictionary? traits = null)
IdentityType.Custom for providers not in the enum.| Parameter | Type | Description |
|---|---|---|
userId | string | Required, non-empty. The player’s identifier in the chosen provider. The SDK silently drops calls with null or empty userId (a Debug.LogWarning is emitted) so a missing ID does not crash the game. Gate calls on a populated value during development. |
identityType | IdentityType | Required. Which provider the ID comes from (see table below). |
traits | Dictionary<string, object>? | Optional. Custom user traits (e.g. personaName). Defaults to null. |
Full consent. Calls at lower levels are dropped with a log warning.| Value | Provider |
|---|---|
IdentityType.Passport | Immutable Passport |
IdentityType.Steam | Steam |
IdentityType.Epic | Epic Games |
IdentityType.Google | |
IdentityType.Apple | Apple |
IdentityType.Discord | Discord |
IdentityType.Email | Email address |
IdentityType.Custom | Custom identity system |
Alias(string fromId, IdentityType fromType, string toId, IdentityType toType)
Alias(string fromId, IdentityType fromType, string toId, IdentityType toType)
| Parameter | Type | Description |
|---|---|---|
fromId | string | Required, non-empty. The account being linked. |
fromType | IdentityType | Required. The provider for fromId. |
toId | string | Required, non-empty. The player’s main account. |
toType | IdentityType | Required. The provider for toId. |
Full consent. Both fromType and toType are required for data-deletion matching.Reset()
Reset()
DeleteData(string? userId = null)
DeleteData(string? userId = null)
Task you can await for acknowledgement, or discard for fire-and-forget.| Parameter | Type | Description |
|---|---|---|
userId | string? | Optional. The known user ID to target. When omitted (or null), the current anonymous ID is used. |
Reset on the client so the next session isn’t linked to the deleted user. See the REST API for the request shape.FlushAsync()
FlushAsync()
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.Shutdown()
Shutdown()
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.Diagnostic getters
Diagnostic getters
CanTrack or CanIdentify helpers, so read CurrentConsent and compare against ConsentLevel.Anonymous or ConsentLevel.Full instead), or watch the queue size during development.| Property | Type | Description |
|---|---|---|
Initialized | bool | True between Init() and Shutdown() |
CurrentConsent | ConsentLevel | The current consent level |
UserId | string? | Set by the most recent Identify call. Null before Identify, after Reset, or when consent is below Full. |
AnonymousId | string? | Persistent ID separate from UserId and SessionId. Null while consent is None. |
SessionId | string? | The current session’s GUID. Null while consent is None. |
QueueSize | int | Number of unsent events (memory + disk) |
Event Delivery
- Events are batched and flushed every 5 seconds or when 20 events accumulate. Configure via the
FlushIntervalSecondsandFlushSizefields onAudienceConfig(seeInit). Application.quittingtriggers a final flush capped atShutdownFlushTimeoutMs(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 anOnError callback when configuring Init to observe them.
AudienceError.Code is one of:
| Code | Description |
|---|---|
FlushFailed | An event batch failed to flush. Either a local storage read error (batch dropped) or a non-2xx, non-4xx server response (typically 5xx). On 5xx, the batch is retained and retried with exponential backoff. |
ValidationRejected | The server rejected an event batch with a 4xx status. The batch was dropped. Retrying will not help (typically a malformed payload). |
ConsentSyncFailed | Failed to sync a consent change to the backend. The local consent level has already been applied. The server-side audit log may be out of date. |
NetworkError | A network call failed (exception, timeout, or non-2xx response on data deletion). Event batches are retained for retry. Data-delete requests are not retried automatically. |
ConsentPersistFailed | Failed to persist the consent level to disk. The in-memory level still applies but reverts on next launch. |
FAQ
Is Linux supported?
Is Linux supported?
Which scripting backends are supported?
Which scripting backends are supported?
Does the SDK work in the Editor?
Does the SDK work in the Editor?
pk_imapik-test-...) during development to keep dev events out of production reporting.What happens if I call Track before consent is set?
What happens if I call Track before consent is set?
SetConsent(ConsentLevel.Anonymous) (or higher) runs, subsequent Track calls flow normally. To verify state during development, read ImmutableAudience.CurrentConsent or the other diagnostic getters.Can I use the Unity SDK alongside the Web SDK or Tracking Pixel?
Can I use the Unity SDK alongside the Web SDK or Tracking Pixel?
How do I handle a GDPR erasure request?
How do I handle a GDPR erasure request?
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.Where does the SDK store its data?
Where does the SDK store its data?
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.