feat(analytics): gate GA4/GTM behind Google Consent Mode v2#1360
Merged
Conversation
Fold cookie-consent behavior into the custom docusaurus-plugin-gtm rather
than adopting a third-party plugin, so the consent signaling and the GTM
loader are emitted from a single injectHtmlTags call. This guarantees the
`consent default = denied` script runs before GTM loads by array order,
independent of plugin registration order.
- docusaurus-plugin-gtm: inject Consent Mode v2 defaults (all denied except
security_storage), replay stored choice from localStorage, and set
ads_data_redaction, all before the GTM loader. Prod-only, unchanged
otherwise. Adds storageKey/waitForUpdate options.
- src/components/CookieConsent: SSR-safe bottom banner (Accept all / Reject
optional) plus a shared consent helper that writes localStorage and fires
gtag('consent','update') with the category -> Google signal mapping.
- src/theme/Root.js: render the banner globally.
Verified against a production build: compiled HTML emits the consent
default script before the GTM loader.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Visit the preview URL for this PR (updated for commit 9235c08): https://pan-dev-f1b58--pr1360-nsi6124w.web.app (expires Tue, 28 Jul 2026 17:32:44 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: 9359a9fa100d5fdb082f75280473a90b1f96eb51 |
BlogCard scrapes content_html for a card image and injects it via innerHTML, so Medium-hosted images and the medium.com/_/stat tracking pixel get requested by the browser and set third-party cookies before consent. feed2json.js now downloads each post's hero image into static/img/blog-feed/ (gitignored, regenerated at build), points thumbnail at the local copy, and strips all remote <img> tags (including the stat pixel) from content_html. The client no longer requests anything off medium.com, so those cookies are never set — independent of consent. On download failure the thumbnail is left unset and BlogCard falls back to the local stock image. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the localStorage key coupling between the GTM head script and the CookieConsent banner explicit in one place, rather than relying on both sides defaulting to the same string. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
sserrata
marked this pull request as ready for review
July 21, 2026 17:33
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 a GDPR-style cookie consent banner and gates GA4/GTM behind Google Consent Mode v2, by folding the behavior of
docusaurus-plugin-cookie-consentinto our owndocusaurus-plugin-gtminstead of adopting the third-party package.Co-locating the consent signaling and the GTM loader in a single
injectHtmlTagscall means theconsent default = deniedscript is guaranteed to run before GTM loads (by array order), independent of plugin registration order — which is the fragile part of wiring the two as separate plugins.Changes
docusaurus-plugin-gtm/index.js— injects Consent Mode v2 defaults (all denied exceptsecurity_storage), replays the stored choice fromlocalStorage, and setsads_data_redaction, all before the GTM loader. Prod-only, otherwise unchanged. New options:storageKey,waitForUpdate.src/components/CookieConsent/— SSR-safe bottom banner (Accept all / Reject optional) plus a shared helper (consent.js) that writeslocalStorageand firesgtag('consent','update', …)using the category → Google signal mapping.src/theme/Root.js— renders the banner globally.Category → Google signal mapping
analytics_storagead_storage,ad_user_data,ad_personalizationfunctionality_storage,personalization_storageVerification
PRODUCTS_INCLUDE=contributingproduction build succeeds; compiledbuild/index.htmlcontainsconsent","defaultbeforegtm.js.Follow-ups before/after merge
paloaltonetworks.com/legal-notices/privacy. Swap if there's a preferred URL.analytics_storageautomatically under Consent Mode; configure EU region behavior / ping modeling in theGTM-PLXD79Ncontainer as desired.🤖 Generated with Claude Code