ADR 0005: PostHog (EU instance) as cross-surface product analytics
- Status: โ Accepted
- Date: 2026-04-25
- Deciders: Akshay Sarode
- Tags: analytics, gdpr, frontend, infrastructure
Contextโ
Until April 2026, AceSense had only Firebase Analytics wired (consent-mode v2, behind a cookie-consent banner). That covers compliant pageview/event capture but is weak on:
- Funnel analysis across surfaces. Firebase Analytics does not natively tie a marketing-site visit to a Flutter-app sign-in to a video upload to a Pro plan purchase under one identity.
- Session debugging. No session-replay-style debugging for product issues.
- Self-serve product analytics. Filtering, cohorts, and feature-flag scaffolding are not the strong suit of Google Analytics 4.
We needed a single tool that:
- Identifies a user once, then ties their journey across acesense.io โ app.acesense.io โ admin.acesense.io.
- Hosts data in the EU so we don't add transfer-out scope to our DPIA / Schrems-II posture.
- Has a Flutter SDK so the journey extends into the iOS + Android apps natively, not just the web.
- Has a Docusaurus-friendly setup so docs.acesense.io can also report.
Options consideredโ
Option A โ PostHog (EU instance)โ
- Pros:
- First-class EU host (
eu.i.posthog.com) โ Frankfurt-region, no SCCs needed. - Official
@posthog/react,posthog-js, andposthog_flutterSDKs (the last cross-platform). - Autocapture by default; opt-in session replay; built-in feature flags + experiments if we ever want them.
- Open source / self-hostable as an exit ramp if we ever need it.
- First-class EU host (
- Cons:
- Adds a vendor + cost line.
- Bundle size:
posthog-jsis ~50KB gz; non-trivial but acceptable for a marketing site.
- Cost: Free tier covers 1M events / month โ comfortably more than we'll generate in 2026.
Option B โ Mixpanelโ
- Pros: Mature funnels, strong user-cohort analysis.
- Cons: EU residency requires the higher pricing tier; no Flutter SDK as polished as posthog_flutter; no SSG-friendly client-only mode for Docusaurus that we trust.
- Cost: Free tier exists but EU residency starts paid.
Option C โ Plausible / Umamiโ
- Pros: Privacy-first, very lightweight.
- Cons: No identified-user funnels, no Flutter SDK, no session-replay path. Solves only the lightweight pageview question, not the full cross-surface job.
- Cost: Plausible: $9/mo upwards. Umami: self-hosted free.
Option D โ Stay on Firebase Analytics onlyโ
- Pros: Already wired, GDPR-compliant via consent mode v2.
- Cons: Doesn't solve cross-surface identity, no session replay, GA4 query UX is weak.
- Cost: Free.
Decisionโ
We will adopt PostHog on the EU instance as the cross-surface product analytics tool. We keep Firebase Analytics in parallel because (a) it's already wired, (b) it gives us Google Ads parity if we ever run paid, and (c) GA4's strict consent-mode integration is useful as a fallback when PostHog is consent-blocked.
The same project token (phc_zRE93mnโฆ) is wired into all six surfaces:
acesense-landing(React) โ autocapture on, no session recording (SEO surface).acesense-launchpad(React) โ autocapture on, default behaviour.acesense-admin(React) โ autocapture on, no session recording (internal tool).acesense-annotate(Tauri desktop) โ explicit-event-only, no autocapture, no session recording.acesense-docs(Docusaurus) โ client-only module, autocapture on, no session recording.acesense-frontend(Flutter) โposthog_flutter4.10+, application lifecycle events captured.
Consequencesโ
Positiveโ
- A single funnel ties marketing-site visitor โ Flutter-app user โ paying customer.
- EU instance keeps all event data in Frankfurt-region โ no SCC/Schrems-II overhead.
- Same identity surface for future feature flags / experiments without picking another vendor.
Negativeโ
- One more vendor in the data-processor list. Updated DPA + sub-processor public list to include PostHog Inc. (Schrems-compliant via EU instance).
- Bundle-size cost: ~50KB gz on the marketing site. Mitigated by code-splitting; impact on LCP is sub-50ms on a 4G connection.
- Two analytics tools running in parallel (PostHog + Firebase Analytics) โ small duplication of pageview signal. Cost: zero; mental tax: small.
Neutralโ
- The token is public-by-design (same posture as Firebase web API keys). Repo
.env.exampledocuments this for future contributors. - We do not rely on PostHog for compliance-grade audit logs. Those go to Cloud Logging.
Follow-up actionsโ
- Wire
@posthog/reactin landing, launchpad, admin, annotate. - Wire
posthog-jsclientModule in Docusaurus. - Wire
posthog_flutterin the Flutter app. - Same EU host + project token across all six.
- Update reference/analytics when we add
posthog.identify(...)calls inside the Flutter auth flow. - Add PostHog to the public sub-processor list under
compliance/sub-processors(next compliance-doc revision). - Couple PostHog initialization to the existing Firebase consent-mode v2 banner so it only initializes after analytics consent is granted.
- Decide whether to enable session replay on the Flutter app (off today). Tied to a separate UX-research need.
Referencesโ
- PostHog EU instance: eu.posthog.com
- PostHog Flutter SDK:
posthog_flutter - Related: reference/analytics, reference/seo-discovery
Was this page helpful?