Skip to content

2026-07-19 — PostHog integration: replay + flags + surveys adopted, feedback pill shipped

posthog-integration (Phases 1–5 code-complete; PostHog-dashboard smokes tracked in the plan) adds the user-behavior layer for launch. Dash0 is untouched — PostHog records what the human did, Dash0 what the system did, correlated by the browser OTel service.instance.id.

What shipped:

  • Session replay + analytics (posthog-js in apps/poker): first-party /ingest reverse-proxy (adblock-resistant), identified by users.id at Privy sign-in, masking targets secrets only (wallet addresses recordable by decision). skipTrailingSlashRedirect: true app-wide as a consequence.
  • Feature flags, fail-closed on both sides: useFeatureFlag (client, UI-only, no first-paint flicker) + game-server isFlagEnabled (posthog-node local evaluation — needs BOTH the phc_ project key and the phx_ personal key). Every key lives in a FLAG_DEFAULTS registry with a named default; PostHog down → current behavior, never undefined. Flags are the rollout/targeting layer; game_settings stays the kill-switch layer.
  • The feedback pill (the custom piece): a brat-styled one-tap affordance on every poker page (signed-in + feedback_pill_enabled only). Auto-attaches route, tableId, OTel session/trace ids, the last ≤10 ErrorRouter-routed coded errors (new ring buffer inside routeError), build sha, viewport, and the PostHog replay URL → POST /feedback on game-server (JWT-only identity, zod-capped, rejected loud) → the new user_feedback table (migration 0098) → best-effort bounded-retry Slack push to the Dash0-alerts channel. A Slack outage never fails a submission; a failed submit preserves the typed text and offers retry.
  • Surveys: moment-triggered only — the first is post-first-cash-out, on the new cash_out_completed event (fired once per withdraw intent at the confirmed transition). One question, dismissible, ≥14-day suppression. No timer modals, ever.
  • Spans: ui.feedback.submit (client) + feedback.received (server), both telemetry-contract-registered.

Current-state pages: User Feedback & Feature Flags, Environment variables (the optional-with-loud-WARN var class). Decision record: .indusk/planning/posthog-integration/adr.md (docs decision page lands at retrospective).