Skip to content

Add the European Cookiebot consent stack to documentation - #525

Merged
emrberk merged 15 commits into
mainfrom
docs/cookie-consent
Aug 31, 2026
Merged

Add the European Cookiebot consent stack to documentation#525
emrberk merged 15 commits into
mainfrom
docs/cookie-consent

Conversation

@emrberk

@emrberk emrberk commented Aug 25, 2026

Copy link
Copy Markdown
Member

What

Applies the same Europe-only consent architecture as questdb/questdb.io#2979 to every documentation page:

  1. Cookiebot is the consent authority — the documentation site uses the same European domain group as questdb.com.
  2. PostHog follows statistics consent — unanswered or rejected statistics consent uses native cookieless mode; accepted statistics consent and visitors outside the banner distribution use cookie-based analytics.
  3. Google Ads follows marketing consent — a client-side consent callback loads the Google tag only after Cookiebot grants marketing consent. No Google request is made while marketing is unanswered or rejected.
  4. Global Privacy Control — GPC prevents Google Ads from loading in every region and does not alter PostHog behavior.
  5. Persistent Cookie settings — the footer control lets visitors review or change their choices.
  6. Shared implementation — the Docusaurus consent plugin keeps identifiers, event handling, and behavior aligned with the main website.

There is no US/CCPA implementation in this PR.

The PR also removes unused Subscribe and YouTubeEmbed components that contained legacy, ungated PostHog calls.

Consent behavior

Context PostHog Google Ads
European banner unanswered or fully rejected Cookieless Blocked
Statistics accepted Cookie-based Unchanged
Marketing accepted Unchanged Enabled unless GPC is active
Outside banner distribution Cookie-based Enabled unless GPC is active
GPC active in any region Unchanged Blocked

Implementation notes

  • Cookiebot events synchronize both analytics mode and advertising eligibility.
  • The Google loader is idempotent and creates its script outside the framework-managed tree.
  • The generated HTML contains no Cookiebot-managed marketing script node.
  • Production build and consent-state tests pass.

Required deploy step

Production documentation currently receives PostHog through Netlify snippet injection. After merge, remove that snippet from:

Site configuration → Build & deploy → Post processing → Snippet injection

Leaving both implementations enabled risks duplicate initialization and preserves a path outside the repository consent logic.

/docs is served same-origin under questdb.com, so the Cookiebot consent
cookie and banner are shared with the main site; this adds the same
load-bearing script order to every page's head: Consent Mode v2 defaults
(all denied), the Cookiebot CMP in manual blocking mode, a bridge event,
then PostHog and the Google Ads tag.

PostHog previously reached these pages through Netlify's snippet injection,
invisible in this repo and ungated — session replay and cookies for every
visitor regardless of consent. It now initializes here instead, with
cookieless_mode 'on_reject' and an opt-in/opt-out gate driven by the
consent state: statistics consent means full capture, anything else means
cookieless. The snippet is byte-identical to the one production serves
today. The Netlify snippet injection must be removed when this deploys,
or PostHog initializes twice.

The footer gains a "Cookie settings" link that reopens the banner — the
consent withdrawal path, and the opt-out mechanism for visitors whose
region never showed a banner.

Subscribe and YouTubeEmbed are deleted: neither is imported, registered in
MDXComponents, nor referenced by any document, and both carried PostHog
calls that predate this gating.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

🤖 Component Converter Reminder

A component in src/components/ or src/theme/ was modified in this pull request.

We are creating markdown correspondents of every path (e.g. questdb.com/docs/quick-start/ → questdb.com/docs/quick-start.md) for LLM consumption.
If the component usage is shadowing useful content, it may need a converter for markdown output in convert-components.js.

Quick Check

  • Content component (code, tables, data) → Add converter if not exists
  • UI/visual component (styling, buttons, decorative) → No converter needed

💡 This is a friendly reminder, not a blocker. Ignore if not applicable.

@github-actions

github-actions Bot commented Aug 25, 2026

Copy link
Copy Markdown

🚀 Build success!

Latest successful preview: https://preview-525--questdb-documentation.netlify.app/docs/

Commit SHA: 47675e6

📦 Build generates a preview & updates the link on each commit.

emrberk and others added 3 commits August 25, 2026 13:16
- uc.js is now async: it was a render-blocking third-party script second in
  head on an SEO-critical site. Safe because the PostHog gate falls back to
  the persisted opt-in state when Cookiebot has not answered yet.
- The gate keys on Cookiebot.hasResponse rather than the consent object,
  which exists (undecided) from the moment uc.js runs.
- wait_for_update raised to 2000ms to match the main site.
- Footer hides "Cookie settings" until Cookiebot exists.
- theme/Input and utils/emailPattern removed: orphaned by the Subscribe
  deletion, zero remaining references.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Same bridge as questdb.io (see its commit for the full reasoning): honors
Global Privacy Control over implied consent with denial after Cookiebot's
granted update, redaction restore, prefix-enumerated ad-cookie expiry, a
watchdog for the iframe-gated granted window, silent-wipe recovery via
CookiebotOnDialogDisplay, and an always-fresh broadcast snapshot. Explicit
choices are never overridden.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Comment thread src/internals/ssr.template.js Outdated
@emrberk
emrberk force-pushed the docs/cookie-consent branch from 8af86e7 to 469e52e Compare August 25, 2026 15:01
emrberk and others added 7 commits August 25, 2026 19:07
Termination check runs before the denial so a throwing denyAds cannot
keep the interval alive, and the watchdog re-arms on Cookiebot events
so a late-arriving uc.js still gets a full watch window.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The .gitleaksignore fingerprint pins a branch commit SHA, which stops
matching after the squash merge and would turn main red on the push
scan. The inline gitleaks:allow is SHA-independent; the fingerprint
entry stays so the PR range scan of the original commit passes too.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@emrberk emrberk changed the title Add the cookie consent stack and gate PostHog on it Add the European Cookiebot consent stack to documentation Aug 26, 2026
@githubwei
githubwei enabled auto-merge (squash) August 31, 2026 16:21
@emrberk
emrberk disabled auto-merge August 31, 2026 17:02
@emrberk
emrberk merged commit 666fb21 into main Aug 31, 2026
4 checks passed
@emrberk
emrberk deleted the docs/cookie-consent branch August 31, 2026 17:03
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