[AAASM-3554] 🍪 (docs): Add GDPR cookie-consent gating to the Docusaurus site#178
Conversation
Define the head <script> source that initialises dataLayer/gtag, sets the Consent-Mode v2 default to denied for analytics + ads storage before any GA hit, and restores a stored opt-in from localStorage. Also exports the gtag.js config snippet that fires after the default is in place. Part of AAASM-3554 (node-sdk site). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Self-contained, theme-variable-driven CSS for the fixed bottom opt-in banner and its Accept/Reject buttons, with focus-visible outlines for keyboard use. Part of AAASM-3554 (node-sdk site). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Dependency-free vanilla-JS banner built with createElement + textContent (no
innerHTML, CodeQL-clean). Accept calls gtag('consent','update',
{analytics_storage:'granted'}) and persists 'granted'; Reject persists
'denied'; both hide the banner. A stored choice suppresses the banner.
Part of AAASM-3554 (node-sdk site).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Restores route-change page_view tracking lost by dropping preset-classic's gtag plugin: on client navigation it sends an updated page_path and a page_view event. Consent Mode still gates whether GA stores anything. Part of AAASM-3554 (node-sdk site). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace preset-classic's gtag option with self-managed headTags (consent default-denied -> stored opt-in restore -> gtag.js loader -> config hit) so deny-before-hit ordering is guaranteed, and register the banner + page-view tracker via clientModules. Part of AAASM-3554 (node-sdk site). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Claude Code — review result ✅ CI green — all 16 checks pass (build, coverage, module-smoke, test 18/20/22/24, CodeQL, SonarCloud). No fails to ignore. Scope vs AAASM-3554 (node-sdk Docusaurus site) — covered, with a justified design decision I reviewed and agree with. Docusaurus injects Verification (from the agent, confirmed against the diff): built Ready for approval + merge. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |



Target
Task summary:
Make the node-sdk Docusaurus docs site GDPR-compliant by adding Google Consent Mode v2 gating around the existing GA4 analytics. Analytics is denied by default and only enabled after an explicit opt-in via a lightweight cookie-consent banner. This is a fast-follow to AAASM-3552 (which added GA4) and brings the node-sdk site in line with the python-sdk mkdocs site's opt-in behaviour.
Task tickets:
Key point change (optional):
gtagoption and self-manage the gtag init viaheadTags. Docusaurus appendsconfig.headTagsafter plugin-injected head tags, so a separate consent-default entry could not be guaranteed to precede the preset'sgtag('config')hit. By owning the whole init we get a deterministic deny-before-hit order:consentDefaultScript— initdataLayer/gtag,gtag('consent','default', {...denied})foranalytics_storage/ad_storage/ad_user_data/ad_personalization, then restore a stored opt-in (localStorage['aa-analytics-consent'] === 'granted').gtag('config', 'G-6FHQKGLDE4', {anonymize_ip:true})— the first hit, now respecting the denied default.gtag('consent','update',{analytics_storage:'granted'})+ persistgranted; Reject → persistdenied; both hide the banner. A stored choice suppresses the banner. Built withcreateElement+textContent(noinnerHTML, CodeQL-clean).pnpm-lock.yamlunchanged.page_viewtracking that was previously provided by the preset gtag plugin.Effecting Scope
Affects only the standalone
website/Docusaurus project. No SDK runtime, API, or CI behaviour changes. No new npm dependency.Description
website/src/analytics/consentInit.ts— consent-default + gtag-config head script sources (Measurement ID + localStorage key shared with the banner).website/src/analytics/consentBanner.ts+consentBanner.css— vanilla-JS opt-in banner client module and its styles.website/src/analytics/gtagRouteTracker.ts— SPApage_viewtracker client module (replaces the dropped preset plugin's route tracking).website/docusaurus.config.ts— remove the presetgtagoption; addheadTags(consent-default → preconnect → gtag.js loader → config) andclientModules(tracker + banner).How to verify
cd website pnpm install --ignore-workspace pnpm buildpnpm typecheckis also clean.website/build/index.html<head>, confirm thegtag('consent','default', {...denied})+ opt-in-restore script appears before thegtag/js?id=G-6FHQKGLDE4loader and thegtag('config', ...)hit. Verified positions: consent-default 3411 < loader 3844 < config 3911.pnpm serve, open the site in a fresh profile:_ga*analytics cookies, and DevTools → Network shows the GAcollectrequest carrying the denied consent state. The banner is visible.localStorage['aa-analytics-consent'] = 'denied', still no analytics cookie; reload keeps the banner hidden.gtag('consent','update',{analytics_storage:'granted'})fires,localStorage['aa-analytics-consent'] = 'granted',_ga*cookies are now set; reload keeps the banner hidden and re-applies the granted consent before the first hit.🤖 Generated with Claude Code