The official PostHog analytics SDK for Unity. Capture events, identify users, and track sessions in your Unity games and applications.
- Unity 2021.3 LTS or later
- .NET Standard 2.1 API Compatibility Level
- Open Window > Package Manager
- Click the + button and select "Add package from git URL"
- Enter:
https://github.com/PostHog/posthog-unity.git?path=com.posthog.unity
- Clone this repository
- Open Window > Package Manager
- Click the + button and select "Add package from disk"
- Navigate to
com.posthog.unity/package.json
using PostHog;
using System.Collections.Generic;
public class GameManager : MonoBehaviour
{
void Start()
{
// Initialize PostHog
PostHog.Setup(new PostHogConfig
{
ApiKey = "phc_your_project_api_key",
Host = "https://us.i.posthog.com" // or https://eu.i.posthog.com
});
// Capture an event
PostHog.Capture("game_started");
}
}PostHog.Setup(new PostHogConfig
{
// Required
ApiKey = "phc_...",
// Optional
Host = "https://us.i.posthog.com", // PostHog instance URL
FlushAt = 20, // Events before auto-flush
FlushIntervalSeconds = 30, // Seconds between flushes
MaxQueueSize = 1000, // Max queued events
MaxBatchSize = 50, // Max events per request
CaptureApplicationLifecycleEvents = true,
CaptureExceptions = true, // Auto-capture unhandled exceptions
SessionReplay = false, // Enable session replay (experimental)
PersonProfiles = PersonProfiles.IdentifiedOnly,
LogLevel = PostHogLogLevel.Warning
});// Simple event
PostHog.Capture("button_clicked");
// Event with properties
PostHog.Capture("level_completed", new Dictionary<string, object>
{
{ "level_id", 5 },
{ "score", 1250 },
{ "time_seconds", 45.5f }
});
// Screen view
PostHog.Screen("Main Menu");// Identify a logged-in user
await PostHog.IdentifyAsync("user_123", new Dictionary<string, object>
{
{ "email", "user@example.com" },
{ "plan", "premium" }
});
// Reset on logout (returns to anonymous)
await PostHog.ResetAsync();Associate users with companies or teams:
PostHog.Group("company", "company_123", new Dictionary<string, object>
{
{ "name", "Acme Inc" },
{ "plan", "enterprise" }
});Properties sent with every event:
// Register
PostHog.Register("app_version", "1.2.3");
PostHog.Register("platform", "iOS");
// Unregister
PostHog.Unregister("app_version");Check feature flags and run experiments:
// Get a feature flag
var flag = PostHog.GetFeatureFlag("new-checkout-flow");
// Check if enabled
if (flag.IsEnabled)
{
// Show new checkout
}
// Get variant value for multivariate flags
string variant = flag.GetVariant("control");
// Quick check without getting the flag object
if (PostHog.IsFeatureEnabled("simple-flag"))
{
// Do something
}
// Manually reload flags
await PostHog.ReloadFeatureFlagsAsync();
// Listen for flag updates
PostHog.OnFeatureFlagsLoaded += () => UpdateUI();Access payloads through the feature flag object:
// 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);Set properties used for flag evaluation:
// 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();PostHog.Setup(new PostHogConfig
{
ApiKey = "phc_...",
PreloadFeatureFlags = true, // Fetch flags on init (default: true)
SendFeatureFlagEvent = true, // Track flag usage (default: true)
SendDefaultPersonPropertiesForFlags = true, // Include device info (default: true)
OnFeatureFlagsLoaded = () => Debug.Log("Flags ready!"),
// Optional: Custom deserializer for typed payloads (e.g., Newtonsoft.Json)
PayloadDeserializer = (json, type) => JsonConvert.DeserializeObject(json, type)
});For GDPR compliance:
// Opt out (stops all tracking, clears queue)
PostHog.OptOut();
// Opt back in
PostHog.OptIn();
// Check status
if (PostHog.IsOptedOut)
{
// Show consent dialog
}Force send all queued events:
PostHog.Flush();When CaptureApplicationLifecycleEvents is enabled (default), these events are captured automatically:
Application Installed- First launchApplication Updated- Version changedApplication Opened- App foregroundedApplication Backgrounded- App backgrounded
The SDK automatically captures unhandled exceptions and sends them to PostHog as $exception events. This is enabled by default.
For handled exceptions that you want to report:
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 }
});PostHog.Setup(new PostHogConfig
{
ApiKey = "phc_...",
// 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)
});PostHog.Setup(new PostHogConfig
{
ApiKey = "phc_...",
CaptureExceptions = false // Disable automatic exception capture
});Note: Session replay is an experimental feature of this beta SDK. Performance impact varies significantly depending on your target devices and game complexity. You may need to adjust capture settings (screenshot scale, quality, throttle delay) to find the right balance for your users. We welcome your feedback—please open an issue or reach out if you encounter problems or need help tuning for your use case.
Record user sessions for replay in PostHog. Session replay captures screenshots of your game at regular intervals along with console logs and network telemetry.
PostHog.Setup(new PostHogConfig
{
ApiKey = "phc_...",
SessionReplay = true // Enable session replay
});PostHog.Setup(new PostHogConfig
{
ApiKey = "phc_...",
SessionReplay = true,
SessionReplayConfig = new PostHogSessionReplayConfig
{
// Capture settings
ThrottleDelaySeconds = 1.0f, // Min seconds between screenshots (default: 1.0)
ScreenshotQuality = 80, // JPEG quality 1-100 (default: 80)
ScreenshotScale = 0.75f, // Resolution scale 0.1-1.0 (default: 0.75)
// Telemetry
CaptureNetworkTelemetry = true, // Record HTTP request metadata (default: true)
CaptureLogs = false, // Record console logs (default: false)
MinLogLevel = SessionReplayLogLevel.Error, // Log, Warning, or Error
// Queue settings
FlushAt = 20, // Events before auto-flush (default: 20)
FlushIntervalSeconds = 30, // Seconds between flushes (default: 30)
MaxQueueSize = 100 // Max queued events (default: 100)
}
});- Screenshots are captured using async GPU readback to minimize main thread blocking
- Use
ScreenshotScaleto reduce resolution and bandwidth - Increase
ThrottleDelaySecondsif you experience performance issues - Lower
ScreenshotQualityto reduce file size
| Platform | Support |
|---|---|
| Windows/Mac/Linux | Full |
| iOS | Full |
| Android | Full |
| WebGL | With limitations* |
| Consoles | Untested |
*WebGL uses PlayerPrefs for storage (limited size) and is subject to CORS restrictions.
Clean up when your app exits:
void OnApplicationQuit()
{
PostHog.Shutdown();
}Note: The SDK automatically flushes on app quit, so explicit shutdown is optional.
- Check your API key is correct
- Verify the host URL matches your PostHog instance
- Set
LogLevel = PostHogLogLevel.Debugto see detailed logs - Ensure you're not opted out (
PostHog.IsOptedOut)
- Ensure your PostHog instance allows CORS from your domain
- WebGL has limited storage - consider reducing
MaxQueueSize
Check out Hedgehog Game, a sample Unity game that demonstrates how to integrate PostHog analytics.
MIT License - see LICENSE for details.
See CONTRIBUTING.md for development setup and guidelines.