Skip to main content

Analytics Surfaces

The repository audit found PostHog wired into three web surfaces: landing, launchpad, and docs. Admin, annotate, and the Flutter frontend do not currently contain a PostHog SDK or initialization path.

Current wiringโ€‹

SurfaceInitializationConsent/session behaviorIdentity
Landinglazy @posthog/react provider using Vite env valuesexplicit analytics opt-in; SDK is not imported before consent; replay disabledanonymous only
Launchpad@posthog/react provider using Vite env valuesloads for authorized users when configured; replay disabledanonymous only
DocsDocusaurus client module using customFieldsloads after the private site hydrates; replay disabledanonymous only
Adminnot wiredn/an/a
Annotatenot wiredn/an/a
Flutter frontendnot wiredn/an/a

All three configured surfaces use the EU ingest host https://eu.i.posthog.com. A PostHog project token is a client-side project identifier, not a secret; administrative credentials must never be embedded in a bundle.

The landing page is strict opt-in:

  1. getConsentPreferences() reads the saved cookie choice.
  2. Without analytics: true, DeferredPostHogProvider renders children without importing the PostHog React SDK.
  3. Firebase Analytics follows the same decision and is dynamically imported only after opt-in.
  4. cookieConsentUpdated mounts analytics after a grant. Withdrawal unmounts PostHog and makes trackEvent reject future Firebase events.

Tests in acesense-landing/src/firebase.test.ts and the landing entry/provider tests pin the no-consent path. The HTML preconnect hints do not initialize an analytics SDK or send an event, but they still reveal the destination to the browser; revisit them if policy requires zero pre-consent connection hints.

Private surfacesโ€‹

Launchpad and docs are available only after the server-side admin session gate. They currently collect anonymous page/navigation analytics without a separate cookie preference. Both disable session recording so confidential fundraising and internal documentation content is not replayed to PostHog.

If policy requires consent for workforce/internal analytics, add the same opt-in gate used by landing or remove analytics from these surfaces. That is a product/legal decision and is not implied by the current code.

No cross-surface identity todayโ€‹

Sharing a project token does not by itself join a person across devices or applications. None of the three wired surfaces calls posthog.identify, and the Flutter app is not wired, so the earlier claimed web โ†’ app person journey does not exist.

Before adding identity:

  • document the purpose and lawful basis;
  • avoid sending email or other direct identifiers unless approved;
  • define reset behavior on sign-out/shared devices;
  • test aliasing and duplicate-person behavior;
  • update the privacy notice and deletion/export path.

CSP and network policyโ€‹

The private docs and launchpad servers use request nonces for every HTML script and style element. Their CSP allowlists exact PostHog ingest/asset origins, exact Firebase Auth API origins, the Firebase auth frame, and same-origin assets. Script attributes and wildcard subdomains are not allowed. Launchpad's replay setting also avoids loading the recorder for confidential pages.

Verificationโ€‹

Run repository checks first:

cd acesense-landing
pnpm test
pnpm build

cd ../acesense-launchpad
pnpm lint
pnpm test
pnpm build:hosting
pnpm --dir functions test

cd ../acesense-docs/website
pnpm test
cd ../functions
pnpm test

Then verify from a clean browser profile:

  1. Landing before consent: no PostHog/Firebase Analytics SDK request or event.
  2. Landing after opt-in: expected EU ingest request appears.
  3. Landing after withdrawal: no new analytics events.
  4. Docs/launchpad as a non-admin: no private bundle is served.
  5. Docs/launchpad as an admin: pageview requests use the EU host and no replay recorder loads.

Provider dashboards and live network traces are external sources. Repository code can establish intended configuration, not whether production received an event or applied a specific retention setting.