Integrate a Unity game

The complete Unity path, top to bottom. Covering every platform in one document instead — that's the full guide.

1. Get a project key

Every install needs a key shaped ah_xxxxxxxx. Create one at /projects/new, or run ah projects list if the CLI is already authenticated. Do not invent a key and do not proceed without one — the SDKs disable themselves without a key.

One project covers every platform a single product ships on — website, mobile app, and game share the same key and land in the same dashboard. Use a separate project only for a separate product, so their stats stay clean.

2. Unity install

Add the UPM package to Packages/manifest.json (or Package Manager → Add package from git URL), pinned to a tag. Unity 2021.3+; pure C#, zero dependencies, no native plugins.

"com.brightmotion.agenthog": "https://github.com/AnniesAI/agenthog-unity.git?path=com.brightmotion.agenthog#v0.1.0"

Configure via a settings asset (no code): Assets → Create → AgentHog → Settings, saved as Assets/Resources/AgentHogSettings.asset with your host + key — the SDK initializes itself on startup. In a shared repo, commit that asset blank (SDK stays inert) and keep the real key in a gitignored Assets/Resources/AgentHogSettingsLocal.asset, which takes precedence. Or in code, once at startup:

AgentHog.Init(new AgentHogConfig {
    Host = "http://agenthog.io",
    ProjectKey = "ah_xxxxxxxx",   // blank key or Enabled=false → every call is a safe no-op
});

Automatic: sessions, scene loads as pageview: /scene-name, uGUI taps as click: <label>, per-screen time, device context, offline/crash carry-over. Not automatic: single-scene games should call AgentHog.Screen("/shop") on UI-panel changes, and gameplay (world-space objects, UI Toolkit) is instrumented with Capture:

AgentHog.Capture("level_complete", new Dictionary<string, object> { ["level"] = 12 });
AgentHog.Identify(traits: new Dictionary<string, object> { ["user_id"] = playerId });
AgentHog.Reset();   // sign-out: device becomes a new anonymous person

Games rarely have emails — a stable user_id trait still stitches identity. Using Singular for install attribution? Its Internal BI postbacks deliver the full verdict (network, campaign, creative, adset) server-side: generate the postback URL in project settings and call SingularSDK.SetCustomUserId(…) in the game with your own user_id (also sent via Identify) or AgentHog.AnonId — see attribution postbacks, which also covers pointing Singular at the URL directly versus relaying a copy through your own backend. Full docs: github.com/AnniesAI/agenthog-unity.

3. Event naming is a contract

The CLI, funnels, and dashboard parse these exact shapes. Autocapture already emits them; match the style when you add your own.

pageview: /pricing        click: Join the waitlist      form_submit: waitlist
input: email              scroll: 75%                   leave: /pricing
  • · Custom names are stored verbatim. Short, readable, stable — checkout_completed, not evt_CHECKOUT_v2 or a UUID.
  • · Keep varying values out of the name. capture('plan_selected', { plan: 'pro' }), never capture('plan_selected_pro') — props are queryable with --by props.plan, names baked with values are not.
  • · identify(email) is what stitches a person across devices. Call it at sign-in and after sign-up. A bare id works but will not merge across devices.
  • · Never put secrets, tokens, or full PII blobs in props — anyone with dashboard access can read them.

4. Verify before reporting success

Compiling is not evidence. Load the site or run the app, click through a few screens, then confirm data arrived:

ah events --since 24h     # fastest proof, if the CLI is authenticated
ah digest                 # sessions, sources, and top events in one report

Otherwise check the dashboard. Expect a pageview: row within seconds — the web tracker flushes every 5s or 10 queued events; React Native, Unity, and Capacitor every 10s or 20 events. Unity editor Play mode sends real events too (registered prop platform: editor).

5. Feature flags & A/B tests

Create a flag with ah flags create checkout_cta --variants control:50,b:50, then read it — the SDK assigns the variant deterministically per user and records exposure automatically (one $exposure event, plus $ff/checkout_cta on every later event, so ah funnel signup --by flag:checkout_cta just works):

AgentHog.FlagsReady(() => {                    // ruleset cached after the first launch
    string v = AgentHog.Flag("difficulty_curve");   // "control" | "b" | null
    ApplyDifficulty(v == "b" ? Curve.Gentle : Curve.Classic);  // null → code default
});
AgentHog.FlagOn("new_shop_ui");                // boolean flags → true/false

Full loop — experiments, results, verdict gates, rollout percentages, kill switch: Experiments.

6. When events are missing

Work through this before adding more instrumentation.

SymptomCause
Nothing at allThe settings asset has a blank key (the intended committed default — the real key belongs in AgentHogSettingsLocal.asset), or Init never ran. Set debugLog and watch the Console for [AgentHog] lines
Clicks named like click: BtnStart2The control has no Text/TMP child — autocapture fell back to the GameObject name. Add label text
Gameplay taps missingAutocapture covers uGUI (Canvas) only — world objects and UI Toolkit need explicit Capture
Traffic looks inflatedYou are looking at bots — aggregates exclude them by default, --all includes them

7. After integrating

Two follow-ups worth offering:

  • · Define a conversion goal so sessions get marked converted: ah goals set signup "form_submit: waitlist"
  • · Give the agent the read surface — install the ah CLI and add an AgentHog section to CLAUDE.md so future sessions query analytics instead of guessing.