Unity

Note: This SDK is currently in beta. Please report any issues on GitHub.

This is the official PostHog SDK for Unity. It uses an internal queue to make calls fast and non-blocking. It also batches requests and flushes asynchronously, making it perfect to use in any part of your Unity game or application.

PostHog Unity SDK supports Windows, Mac, Linux, iOS, Android, and WebGL platforms.

Installation

PostHog is available for Unity via the Unity Package Manager.

Requirements

  • Unity 2021.3 LTS or later
  • .NET Standard 2.1 API Compatibility Level

Via Unity Package Manager (Git URL)

  1. Open Window > Package Manager
  2. Click the + button and select Add package from git URL
  3. Enter: https://github.com/PostHog/posthog-unity.git?path=com.posthog.unity

Via local package

  1. Clone or download the posthog-unity repository
  2. Open Window > Package Manager
  3. Click the + button and select Add package from disk
  4. Navigate to com.posthog.unity/package.json

Configuration

There are two ways to configure PostHog in Unity:

The easiest way to configure PostHog is through the Unity Inspector:

  1. Go to Edit > Project Settings > PostHog (this creates a settings asset if one doesn't exist)
  2. Enter your API Key and select your Host (US or EU Cloud)
  3. Configure other options as needed

The settings asset is created at Assets/Resources/PostHogSettings.asset. PostHog automatically initializes when your game starts using these settings.

You can also create the settings asset manually via Assets > Create > PostHog > Settings in Resources.

Tip: Click Test Connection in the Inspector to verify your API key is valid.

Option 2: Code-based initialization

For more control, initialize PostHog in your game's startup script:

C#
using PostHog;
using UnityEngine;
public class GameManager : MonoBehaviour
{
void Start()
{
PostHog.Setup(new PostHogConfig
{
ApiKey = "<ph_project_api_key>",
Host = "https://us.i.posthog.com" // usually 'https://us.i.posthog.com' or 'https://eu.i.posthog.com'
});
}
}

Note: If you use code-based initialization, remove any PostHogSettings.asset from your Resources folder to avoid double initialization.

Configuration options

All options below can be set via the Unity Inspector or in code:

C#
PostHog.Setup(new PostHogConfig
{
// Required
ApiKey = "<ph_project_api_key>",
// Optional
Host = "https://us.i.posthog.com", // PostHog instance URL (default: https://us.i.posthog.com)
FlushAt = 20, // Events before auto-flush (default: 20)
FlushIntervalSeconds = 30, // Seconds between flushes (default: 30)
MaxQueueSize = 1000, // Max queued events (default: 1000)
MaxBatchSize = 50, // Max events per request (default: 50)
CaptureApplicationLifecycleEvents = true, // Auto-capture app lifecycle events (default: true)
CaptureExceptions = true, // Auto-capture unhandled exceptions (default: true)
PersonProfiles = PersonProfiles.IdentifiedOnly, // When to create person profiles
PreloadFeatureFlags = true, // Fetch flags on init (default: true)
SendFeatureFlagEvent = true, // Track flag usage (default: true)
LogLevel = PostHogLogLevel.Warning // Log verbosity (default: Warning)
});

Capturing events

You can send custom events using capture:

C#
PostHog.Capture("user_signed_up");

Tip: We recommend using a [object] [verb] format for your event names, where [object] is the entity that the behavior relates to, and [verb] is the behavior itself. For example, project created, user signed up, or invite sent.

Setting event properties

Optionally, you can include additional information with the event by including a properties object:

C#
PostHog.Capture("user_signed_up", new Dictionary<string, object>
{
{ "login_type", "email" },
{ "is_free_trial", true }
});

Capturing screen views

Track screen views to understand user navigation through your game:

C#
PostHog.Screen("Main Menu");
// With additional properties
PostHog.Screen("Level Select", new Dictionary<string, object>
{
{ "unlocked_levels", 5 }
});

Identifying users

We highly recommend reading our section on Identifying users to better understand how to correctly use this method.

When a user logs in, you can associate their events with their identity by calling IdentifyAsync:

C#
using PostHog;
using System.Collections.Generic;
await PostHog.IdentifyAsync("user_123", new Dictionary<string, object>
{
{ "email", "user@example.com" },
{ "name", "Max Hedgehog" },
{ "plan", "premium" }
});

Reset on logout

When a user logs out, call ResetAsync to clear the current user's identity and generate a new anonymous distinct ID:

C#
await PostHog.ResetAsync();

Anonymous vs identified events

PostHog captures two types of events: anonymous and identified

Identified events enable you to attribute events to specific users, and attach person properties. They're best suited for logged-in users.

Scenarios where you want to capture identified events are:

  • Tracking logged-in users in B2B and B2C SaaS apps
  • Doing user segmented product analysis
  • Growth and marketing teams wanting to analyze the complete conversion lifecycle

Anonymous events are events without individually identifiable data. They're best suited for web analytics or apps where users aren't logged in.

Scenarios where you want to capture anonymous events are:

  • Tracking a marketing website
  • Content-focused sites
  • B2C apps where users don't sign up or log in

Under the hood, the key difference between identified and anonymous events is that for identified events we create a person profile for the user, whereas for anonymous events we do not.

Important: Due to the reduced cost of processing them, anonymous events can be up to 4x cheaper than identified ones, so we recommended you only capture identified events when needed.

Controlling person profiles

By default, the SDK captures identified events. To control whether events create person profiles, configure PersonProfiles during initialization:

C#
PostHog.Setup(new PostHogConfig
{
ApiKey = "<ph_project_api_key>",
Host = "https://us.i.posthog.com",
PersonProfiles = PersonProfiles.IdentifiedOnly // Only create profiles on identify
});

Available options:

  • PersonProfiles.IdentifiedOnly (default) - Only creates person profiles when Identify is called
  • PersonProfiles.Always - Creates person profiles for all events
  • PersonProfiles.Never - Never creates person profiles (anonymous events only)

Super properties

Super properties are properties associated with events that are set once and then sent with every Capture call.

They are set using Register, which takes a key and value, and they persist across sessions.

C#
// Register a super property
PostHog.Register("app_version", "1.2.3");
PostHog.Register("platform", "iOS");

This ensures that every event sent by the user will include these properties.

Removing super properties

Super properties are persisted across sessions so you have to explicitly remove them if they are no longer relevant:

C#
PostHog.Unregister("app_version");

If you are doing this as part of a user logging out you can instead simply use PostHog.ResetAsync() which takes care of clearing all stored super properties and more.

Group analytics

Group analytics allows you to associate the events for that person's session with a group (e.g. teams, organizations, etc.). Read the Group Analytics guide for more information.

Note: This is a paid feature and is not available on the open-source or free cloud plan. Learn more on the pricing page.

  • Associate events with a group:
C#
PostHog.Group("company", "company_id_in_your_db");
  • Associate events with a group AND update group properties:
C#
PostHog.Group("company", "company_id_in_your_db", new Dictionary<string, object>
{
{ "name", "Acme Inc" },
{ "plan", "enterprise" },
{ "employees", 100 }
});

The name is a special property which is used in the PostHog UI for the name of the group. If you don't specify a name property, the group ID will be used instead.

Feature flags

PostHog's feature flags enable you to safely deploy and roll back new features as well as target specific users and groups with them.

Boolean feature flags

C#
if (PostHog.IsFeatureEnabled("flag-key"))
{
// Do something differently for this user
}

Multivariate feature flags

C#
var flag = PostHog.GetFeatureFlag("flag-key");
if (flag.IsEnabled)
{
string variant = flag.GetVariant("control"); // "control" is the default value
if (variant == "variant-key") // Replace with your variant key
{
// Do something for this variant
}
}

Feature flag payloads

Access payloads through the feature flag object:

C#
// Define your payload class (must use [Serializable] and public fields for JsonUtility)
[Serializable]
public class CheckoutConfig
{
public string theme;
public int maxItems;
public bool showBanner;
}
// Get flag and access payload
var flag = PostHog.GetFeatureFlag("checkout-config");
if (flag.IsEnabled)
{
var config = flag.GetPayload<CheckoutConfig>();
Debug.Log($"Theme: {config.theme}, Max items: {config.maxItems}");
}
// For dynamic/nested payloads, use PostHogJson
var payload = flag.GetPayloadJson();
string theme = payload["theme"].GetString("light");
int maxItems = payload["settings"]["maxItems"].GetInt(10);

Ensuring flags are loaded before usage

Every time a user opens the app, we send a request in the background to fetch the feature flags that apply to that user. We store those flags in storage.

This means that for most screens, the feature flags are available immediately – except for the first time a user visits.

To be notified when flags are loaded:

C#
// Via callback during setup
PostHog.Setup(new PostHogConfig
{
ApiKey = "<ph_project_api_key>",
OnFeatureFlagsLoaded = () => Debug.Log("Flags ready!")
});
// Or via event
PostHog.OnFeatureFlagsLoaded += () => UpdateUI();

Reloading feature flags

Feature flag values are cached. If something has changed with your user and you'd like to refetch their flag values, call:

C#
await PostHog.ReloadFeatureFlagsAsync();

Overriding server properties for flags

You can set properties used for flag evaluation:

C#
// Set person properties for targeting
PostHog.SetPersonPropertiesForFlags(new Dictionary<string, object>
{
{ "plan", "premium" },
{ "beta_user", true }
});
// Set group properties for targeting
PostHog.SetGroupPropertiesForFlags("company", new Dictionary<string, object>
{
{ "size", "enterprise" }
});
// Reset properties
PostHog.ResetPersonPropertiesForFlags();
PostHog.ResetGroupPropertiesForFlags();

Experiments (A/B tests)

Since experiments use feature flags, the code for running an experiment is very similar to the feature flags code:

C#
var flag = PostHog.GetFeatureFlag("experiment-feature-flag-key");
if (flag.GetVariant("control") == "variant-name")
{
// Do something for this variant
}

It's also possible to run experiments without using feature flags.

Error tracking

The Unity SDK automatically captures unhandled exceptions and sends them to PostHog. This is enabled by default.

Manual exception capture

For handled exceptions that you want to report:

C#
try
{
// Risky operation
}
catch (Exception e)
{
PostHog.CaptureException(e);
// Handle the error gracefully
}
// With additional properties
PostHog.CaptureException(e, new Dictionary<string, object>
{
{ "context", "checkout_flow" },
{ "item_count", 5 }
});

Configuration

C#
PostHog.Setup(new PostHogConfig
{
ApiKey = "<ph_project_api_key>",
// Exception tracking options
CaptureExceptions = true, // Enable automatic capture (default: true)
ExceptionDebounceIntervalMs = 1000, // Min ms between captures (default: 1000)
CaptureExceptionsInEditor = true // Capture in Unity Editor (default: true)
});

Disabling error tracking

C#
PostHog.Setup(new PostHogConfig
{
ApiKey = "<ph_project_api_key>",
CaptureExceptions = false // Disable automatic exception capture
});

Application lifecycle events

When CaptureApplicationLifecycleEvents is enabled (default: true), these events are captured automatically:

  • Application Installed - First launch
  • Application Updated - Version changed
  • Application Opened - App foregrounded
  • Application Backgrounded - App backgrounded

Opt out of data capture

For GDPR compliance, you can disable data collection at any time:

C#
// Opt out (stops all tracking, clears queue)
PostHog.OptOut();
// Opt back in
PostHog.OptIn();
// Check status
if (PostHog.IsOptedOut)
{
// Show consent dialog
}

Debug mode

If you're not seeing the expected events being captured or feature flags being evaluated, enable debug mode to see what's happening:

C#
PostHog.Setup(new PostHogConfig
{
ApiKey = "<ph_project_api_key>",
Host = "https://us.i.posthog.com",
LogLevel = PostHogLogLevel.Debug
});

Available log levels: None, Error, Warning, Info, Debug

Manual flush

Force send all queued events immediately:

C#
PostHog.Flush();

Shutdown

Clean up when your app exits:

C#
void OnApplicationQuit()
{
PostHog.Shutdown();
}

Note: The SDK automatically flushes on app quit, so explicit shutdown is optional.

Platform support

PlatformSupport
Windows/Mac/LinuxFull
iOSFull
AndroidFull
WebGLWith limitations*
ConsolesUntested

*WebGL uses PlayerPrefs for storage (limited size) and is subject to CORS restrictions.

Troubleshooting

Events not appearing in PostHog

  1. Check your API key is correct
  2. Verify the host URL matches your PostHog instance (e.g., https://us.i.posthog.com or https://eu.i.posthog.com)
  3. Set LogLevel = PostHogLogLevel.Debug to see detailed logs
  4. Ensure you're not opted out (PostHog.IsOptedOut)

WebGL issues

  • Ensure your PostHog instance allows CORS from your domain
  • WebGL has limited storage - consider reducing MaxQueueSize

Demo

Check out Hedgehog Game, a sample Unity game that demonstrates how to integrate PostHog analytics.

Community questions

Was this page useful?

Questions about this page? or post a community question.