Skip to content

fix(consent): gate PostHog analytics on CookieYes consent - #7971

Merged
ankur-arch merged 2 commits into
mainfrom
gdpr-patch
Jun 22, 2026
Merged

fix(consent): gate PostHog analytics on CookieYes consent#7971
ankur-arch merged 2 commits into
mainfrom
gdpr-patch

Conversation

@ankur-arch

@ankur-arch ankur-arch commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Problem

PostHog was initialised with capture_pageview and 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:

Tracker State
GTM ✅ Google Consent Mode v2, defaults all to denied, bridged to CookieYes
PromptWatch, Tolt type="text/plain" + data-cookieyes, inert until consent
PostHog ❌ fired before consent — fixed here

Context

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 a cookieyes-consent cookie, while the actual CookieYes integration (the GTM bridge) uses cookieyes_consent_update (underscores) + getCkyConsent(). The wrong event name likely meant the old gate never fired.

Fix

  • New shared helper packages/ui/src/lib/consent.tshasAnalyticsConsent() and onAnalyticsConsentChange(), reading the same CookieYes signals the GTM bridge already uses (one source of truth).
  • All three apps now init PostHog with 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

  • No PostHog network calls / cookies before accepting the banner
  • Accepting analytics consent starts capture; rejecting stops it
  • Returning visitor with stored consent is captured on load

Summary by CodeRabbit

Release Notes

  • New Features
    • Analytics tracking is now conditional on user consent status
    • Consent changes are detected and applied to tracking behavior in real-time

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>
@vercel

vercel Bot commented Jun 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview, Comment Jun 22, 2026 10:32am
docs Ready Ready Preview, Comment Jun 22, 2026 10:32am
eclipse Ready Ready Preview, Comment Jun 22, 2026 10:32am
site Ready Ready Preview, Comment Jun 22, 2026 10:32am

Request Review

@coderabbitai

coderabbitai Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 998e3bc8-4efb-455b-a430-e54c044a98f7

📥 Commits

Reviewing files that changed from the base of the PR and between 0da9dae and 0a1e14a.

📒 Files selected for processing (4)
  • apps/blog/src/instrumentation-client.ts
  • apps/docs/src/instrumentation-client.ts
  • apps/site/src/instrumentation-client.ts
  • packages/ui/src/lib/consent.ts

Walkthrough

A new consent.ts module is added to the UI package, exporting hasAnalyticsConsent() and onAnalyticsConsentChange() backed by the CookieYes getCkyConsent browser API. All three apps (blog, docs, site) then update their PostHog instrumentation clients to default to opt-out, conditionally opt in on load, and react to live consent changes.

Changes

PostHog CookieYes Consent Gating

Layer / File(s) Summary
Consent utility module
packages/ui/src/lib/consent.ts
Introduces the CkyConsent type, Window.getCkyConsent global augmentation, hasAnalyticsConsent() (with SSR/exception safety), and onAnalyticsConsentChange() (listening to cookieyes_consent_update and cookieyes_banner_load DOM events, SSR-safe).
PostHog consent wiring across all apps
apps/blog/src/instrumentation-client.ts, apps/docs/src/instrumentation-client.ts, apps/site/src/instrumentation-client.ts
Each app's PostHog init gains opt_out_capturing_by_default: true, a conditional opt_in_capturing() call inside loaded when hasAnalyticsConsent() is truthy, and an onAnalyticsConsentChange subscription that toggles capturing on or off at runtime.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • prisma/web#7965: Adds the GTM side of the same CookieYes consent bridge, sharing the window.getCkyConsent API and the same cookieyes_consent_update/cookieyes_banner_load event pattern that consent.ts is built on.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(consent): gate PostHog analytics on CookieYes consent' accurately and concisely summarizes the main change—adding consent-gating to PostHog analytics tracking across three applications using CookieYes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@argos-ci

argos-ci Bot commented Jun 22, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Jun 22, 2026, 10:38 AM

@ankur-arch
ankur-arch merged commit 3c7bb0e into main Jun 22, 2026
10 of 16 checks passed
@ankur-arch
ankur-arch deleted the gdpr-patch branch June 22, 2026 10:29
ankur-arch added a commit that referenced this pull request Aug 12, 2026
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>
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.

1 participant