Skip to content

fix(telemetry): add cookie fallback to getDistinctId for identity resolution#1203

Closed
everettbu wants to merge 2 commits into
masterfrom
sean/growth-616-fix-posthog-identity-resolution
Closed

fix(telemetry): add cookie fallback to getDistinctId for identity resolution#1203
everettbu wants to merge 2 commits into
masterfrom
sean/growth-616-fix-posthog-identity-resolution

Conversation

@everettbu

Copy link
Copy Markdown

Mirror of supabase/supabase#42535
Original author: seanoliver


Summary

Fixes the PostHog identity resolution break that was causing ~43% of Google Ads signups to lose attribution.

  • When PostHog SDK isn't initialized yet (e.g., immediately after OAuth redirect), getDistinctId() now falls back to parsing the distinct_id from the PostHog cookie
  • This ensures the anonymous session (which captures UTM/gclid params on ad click) gets properly aliased to the user ID on signup

Problem

There's a ~10,500 user gap between Google Ads reported signups (24.3K) and our internal attribution data (13.8K) for Nov 30, 2025 – Feb 2, 2026. IP address matching analysis confirmed 69% of this gap is recoverable by fixing identity resolution.

The root cause: after OAuth redirect, getDistinctId() returned undefined because PostHog SDK wasn't initialized yet, so the identify call didn't include anonymous_id, and no alias was created.

Changes

packages/common/posthog-client.ts

  • Modified getDistinctId() to fall back to cookie parsing when SDK isn't initialized
  • Added getDistinctIdFromCookie() private method to parse distinct_id from PostHog's ph_* cookie

Testing

  1. Land on /sign-in?gclid=test123&utm_source=google
  2. Grab the distinct_id from PostHog cookie:
    const phCookie = document.cookie.split(';').find(c => c.trim().startsWith('ph_'))
    const phData = JSON.parse(decodeURIComponent(phCookie.split('=')[1]))
    console.log('Pre-OAuth distinct_id:', phData.distinct_id)
  3. Complete OAuth sign-in flow
  4. Check Network tab for POST /platform/telemetry/identify
  5. Verify anonymous_id in request payload matches the pre-OAuth distinct_id

Note on reproducing the race condition locally

The bug is caused by a race condition where PostHog SDK isn't initialized by the time useTelemetryIdentify runs after OAuth. This is difficult to reliably reproduce locally because:

  • PostHog loads early in the app bundle
  • OAuth redirect (to GitHub/Google and back) gives PostHog time to initialize
  • Local network is fast

You can try throttling to "Slow 3G" in DevTools Network tab, but even then PostHog often initializes in time. The race condition depends on multiple factors: user connection speed, PostHog CDN latency, OAuth provider response time, browser caching, etc.

This is a safe, defensive change - when PostHog IS initialized (the common case), behavior is unchanged. The cookie fallback only activates when the SDK isn't ready yet.

Validating in production

We'll know the fix is working after 1-2 weeks by monitoring:

  • PostHog alias creation rate (should increase)
  • Google Ads attribution gap (should decrease from ~43% to ~30%)

Linear

Fixes GROWTH-616

Summary by CodeRabbit

  • Bug Fixes
    • Improved reliability of user identification in analytics tracking by adding fallback mechanisms and enhanced error handling. The system now gracefully handles edge cases while maintaining consistent user tracking throughout the application.

…olution

When PostHog SDK isn't initialized yet (e.g., immediately after OAuth
redirect), getDistinctId() now falls back to parsing the distinct_id
from the PostHog cookie instead of returning undefined.

This fixes the identity resolution break that was causing ~43% of Google
Ads signups to not be attributed correctly. The anonymous PostHog session
(which captures UTM/gclid params on ad click) will now be properly aliased
to the user ID on signup, even when the SDK hasn't fully loaded.

Fixes GROWTH-616
Address CodeRabbit feedback:
- Use substring instead of split('=')[1] to handle '=' in cookie value
- Match exact cookie name ph_<apiKey>_posthog instead of any ph_ prefix
@everettbu

Copy link
Copy Markdown
Author

Upstream PR was closed or merged. Code is synced via branch mirror.

@everettbu everettbu closed this Feb 6, 2026
@everettbu everettbu deleted the sean/growth-616-fix-posthog-identity-resolution branch February 6, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants