Repository navigation
feat(web): add PostHog analytics - #114
Merged
Merged
Conversation
Capture pageviews (including App Router navigations), identify Supabase users, reset on sign-out, and send a signed_up event on account creation. Events go through a same-origin /ingest rewrite to PostHog US cloud. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
This pull request has been ignored for the connected project Preview Branches by Supabase. |
Supabase signUp also succeeds for an existing unconfirmed email by resending the confirmation, which returned the real user and fired a second signed_up. Skip users whose confirmation was sent a minute or more after creation. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds PostHog product analytics to the Next.js web app in
apps/web(the captuto.com site). PostHog was not set up anywhere in the repo before this.posthog-jsis started from a client component (components/providers/PostHogAnalytics.tsx) in the root layout. The setup code is inlib/analytics/posthog.ts.capture_pageview: 'history_change', so App Router client navigations are captured as$pageview, not just full page loads. Autocapture and the other SDK defaults are unchanged.onAuthStateChange:INITIAL_SESSION,SIGNED_INandUSER_UPDATED→posthog.identify(user.id, { email, name }).namecomes fromuser_metadata.full_nameornameand is only sent when present.SIGNED_OUT→posthog.reset(). This covers every sign-out path (sidebar, header, password reset, account deletion), because they all go through the shared browser Supabase client.signed_up: captured on/signupaftersupabase.auth.signUpsucceeds, right after identifying the new user. It is only sent for accounts that were just created:/ingest/static/*and/ingest/array/*tohttps://us-assets.i.posthog.comand/ingest/*tohttps://us.i.posthog.com.ui_hostishttps://us.posthog.com.skipTrailingSlashRedirect: trueis set because PostHog's API paths use trailing slashes. This setting applies to the whole app, so URLs with a trailing slash are no longer redirected.Env vars
NEXT_PUBLIC_POSTHOG_KEYNODE_ENV=production), falls back to the public "Captuto" project key. In dev and test, nothing is sent unless this is set.NEXT_PUBLIC_POSTHOG_HOST/ingest(the same-origin proxy above)Both are documented in
apps/web/.env.example. No secrets are added. The fallback is the public client key only.Verification
pnpm install --frozen-lockfile: passpnpm lint: pass, no warningspnpm type-check: passpnpm test:run: pass (web: 405 tests, extension: 71, skills: 7). New tests are inapps/web/lib/analytics/posthog.test.ts.next build(with placeholder Supabase env): pass./scripts/dev-start.sh --local, withNEXT_PUBLIC_POSTHOG_KEYset and PostHog's event endpoints mocked:$pageview, plus a$pageviewon the client-side navigation from/to/login. Config, flags and surveys requests went through/ingest.$identifyandsigned_up. The PostHogdistinct_idbecame the Supabase user id. Re-checked after the dedupe fix.distinct_id. Sign-in sent$identify. Reloading kept the identified state without sending another$identify.NEXT_PUBLIC_POSTHOG_KEYunset in local dev, there were no/ingestrequests and no PostHog cookie.HeadlessChromeuser agent andnavigator.webdriver), so the browser checks used a desktop Chrome user agent with automation flags turned off.CI
36ac5cfReview Gate
review-code-dev(deep, frontend): no P0, P1 or P2 findings. One P3 was fixed:signed_upcould fire twice when the same unconfirmed email signed up again.Risk
skipTrailingSlashRedirectapplies to the whole app. Pages, middleware auth checks and security headers still apply to URLs with a trailing slash.Human Review Notes
ph_*cookie for every visitor.🤖 Generated with Claude Code