fix(consent): gate PostHog analytics on CookieYes consent - #7971
Conversation
PostHog initialised with capture_pageview and no consent gate, so it set cookies and fired a pageview on load before the visitor interacted with the CookieYes banner — analytics tracking before consent (GDPR/ePrivacy issue). Add a shared CookieYes consent helper (packages/ui/src/lib/consent.ts) that reads the same signals as the GTM consent bridge (cookieyes_consent_update / cookieyes_banner_load events + getCkyConsent()), and use it in all three apps (docs, site, blog) to init PostHog opted-out, opting in only once analytics consent is granted and reacting to live consent changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (4)
WalkthroughA new ChangesPostHog CookieYes Consent Gating
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
|
The latest updates on your projects. Learn more about Argos notifications ↗︎
|
Since PostHog became consent-gated on CookieYes (#7971, June 22), visitors who reject analytics or never touch the banner disappear from PostHog entirely, which cut measured traffic by roughly 60% and made the top-line visitor metric unusable. This turns on PostHog's cookieless mode so those visitors are counted again without weakening the June consent behavior. - Set cookieless_mode: "on_reject" in docs/site/blog PostHog init. Together with the existing opt_out_capturing_by_default: true, visitors with no consent decision and visitors who rejected analytics are captured cookielessly: events carry the $posthog_cookieless sentinel plus $cookieless_mode: true, and PostHog's servers derive the visitor id from a salted daily hash. Nothing is stored on the device. - Bump posthog-js ^1.351.3 -> ^1.415.7. The installed 1.364.4 predates the SDK change (PostHog/posthog-js#3362, v1.369.4) that makes undecided visitors capture cookielessly, plus several cookieless fixes after it. - Make the CookieYes consent helper tri-state (granted/denied/pending) via isUserActionCompleted so a visitor who merely ignored the banner is not converted into a stored explicit opt-out before making any decision. - Re-register site_name/environment super-properties after consent transitions; the SDK resets its state on opt-in/opt-out in cookieless mode and events after the transition lost those properties otherwise. Requires "Cookieless server hash mode" enabled in PostHog project settings (Project Settings > Web analytics) before deploy, otherwise cookieless events are dropped at ingestion (verified: they currently are). Consent behavior per state, verified against a local build: - no decision yet: cookieless capture, no cookies/localStorage writes - rejected: cookieless capture, only the opt-out flag "0" stored - accepted: full PostHog analytics, unchanged from today - returning visitors: stored decision applies from init Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Problem
PostHog was initialised with
capture_pageviewand no consent gate in all three apps (docs,site,blog). On page load it set cookies/localStorage and fired a pageview before the visitor interacted with the CookieYes banner — i.e. analytics tracking before consent, a GDPR/ePrivacy issue. This was flagged via the DPO.Audit of the other trackers showed they are already compliant, so the scope here is PostHog only:
denied, bridged to CookieYestype="text/plain"+data-cookieyes, inert until consentContext
Consent-gating for PostHog previously existed but was reverted in #7884. That implementation was also buggy: it listened for
cookieyes-consent-update(hyphens) and read acookieyes-consentcookie, while the actual CookieYes integration (the GTM bridge) usescookieyes_consent_update(underscores) +getCkyConsent(). The wrong event name likely meant the old gate never fired.Fix
packages/ui/src/lib/consent.ts—hasAnalyticsConsent()andonAnalyticsConsentChange(), reading the same CookieYes signals the GTM bridge already uses (one source of truth).opt_out_capturing_by_default: true, opt in immediately for returning visitors who already consented, and opt in/out live as consent changes. No cookies or events until analytics consent is granted.Verify
Summary by CodeRabbit
Release Notes