Skip to content

feat(docs): wire Google Analytics into the published docs site - #1482

Merged
igorls merged 1 commit into
developfrom
feat/docs-ga-wiring
May 12, 2026
Merged

feat(docs): wire Google Analytics into the published docs site#1482
igorls merged 1 commit into
developfrom
feat/docs-ga-wiring

Conversation

@igorls

@igorls igorls commented May 12, 2026

Copy link
Copy Markdown
Member

Summary

  • Pass MEMPALACE_DOCS_GA_ID (set as a repo Variable) from the deploy workflow into the VitePress build, so the published site at mempalaceofficial.com actually emits the gtag tags. Today the conditional in config.mts exists but the env var was never injected, so GA shipped as dead code.
  • Harden the gtag snippet: encodeURIComponent on the script URL and JSON.stringify for the inline gtag('config', ...) call, so a malformed value can't break the page.

The privacy/local-first guarantees in CLAUDE.md apply to the Python product, not the marketing/docs site, so analytics on the public site is in scope.

Test plan

  • Confirm the MEMPALACE_DOCS_GA_ID repo Variable is set in Settings → Secrets and variables → Actions → Variables.
  • Merge to develop and let the Deploy Docs workflow run.
  • View source on https://mempalaceofficial.com — expect two new <script> tags pointing at googletagmanager.com/gtag/js?id=G-... and the inline gtag('config', ...).
  • Confirm a hit shows up in the GA4 Realtime view.
  • Sanity check: if the Variable is ever unset, the build still succeeds and emits no GA tags (existing behavior, preserved).

…ppet

Pass the GA Measurement ID from the GitHub Actions repo variable into the
docs build so the published site at mempalaceofficial.com actually emits
the gtag tags. Also escape the ID via encodeURIComponent / JSON.stringify
so a malformed value can't break the page.
Copilot AI review requested due to automatic review settings May 12, 2026 21:52
@igorls
igorls requested a review from milla-jovovich as a code owner May 12, 2026 21:52
@igorls
igorls merged commit 35a0633 into develop May 12, 2026
8 checks passed

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates the VitePress configuration to properly encode and stringify the Google Analytics ID in the generated script tags. Review feedback points out that the necessary environment variable mapping in the GitHub Actions workflow is missing, which would prevent the ID from being available during the build process. Additionally, a potential XSS vulnerability was identified because JSON.stringify does not escape the HTML closing script tag, and a suggestion was provided to escape the character to harden the implementation.

Comment on lines +33 to +34
['script', { async: '', src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(gaId)}` }],
['script', {}, `window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', ${JSON.stringify(gaId)});`],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The pull request description mentions passing MEMPALACE_DOCS_GA_ID from the deploy workflow, but the necessary changes to the GitHub Actions workflow files (typically located in .github/workflows/) are not included in this PR. \n\nIn GitHub Actions, repository variables are not automatically injected into the environment of run steps. To ensure the analytics ID is available during the VitePress build, you must explicitly map it in your workflow file:\n\nyaml\n- name: Build Docs\n run: npm run docs:build\n env:\n MEMPALACE_DOCS_GA_ID: ${{ vars.MEMPALACE_DOCS_GA_ID }}\n\n\nWithout this, gaId will remain undefined in the production build, and the Google Analytics tags will not be rendered.

['script', { async: '', src: `https://www.googletagmanager.com/gtag/js?id=${gaId}` }],
['script', {}, `window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', '${gaId}');`],
['script', { async: '', src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(gaId)}` }],
['script', {}, `window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', ${JSON.stringify(gaId)});`],

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

security-medium medium

While using JSON.stringify is a good improvement for handling quotes and special characters, it does not escape the HTML closing script tag </script>. If the environment variable were to contain this sequence, it could prematurely terminate the script block and lead to a Cross-Site Scripting (XSS) vulnerability. To fully harden the snippet as intended in the PR description, consider escaping the < character.

        ['script', {}, `window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', ${JSON.stringify(gaId).replace(/</g, '\\u003c')});`],

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Wires the Google Analytics measurement ID from the GitHub Pages deploy workflow into the VitePress build so the published docs site can conditionally emit GA/gtag tags, and hardens the generated script tags against malformed IDs.

Changes:

  • Pass MEMPALACE_DOCS_GA_ID from GitHub Actions repo Variables into the docs build step.
  • Update the VitePress head GA snippet to URL-encode the ID in the loader URL and to safely embed the ID in the inline gtag('config', ...) call.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
website/.vitepress/config.mts Safens GA script URL composition and inline config emission when MEMPALACE_DOCS_GA_ID is present.
.github/workflows/deploy-docs.yml Injects MEMPALACE_DOCS_GA_ID into the docs build environment so GA tags can be emitted at build time.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 32 to +34
...(gaId ? [
['script', { async: '', src: `https://www.googletagmanager.com/gtag/js?id=${gaId}` }],
['script', {}, `window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', '${gaId}');`],
['script', { async: '', src: `https://www.googletagmanager.com/gtag/js?id=${encodeURIComponent(gaId)}` }],
['script', {}, `window.dataLayer = window.dataLayer || [];\nfunction gtag(){dataLayer.push(arguments);}\ngtag('js', new Date());\ngtag('config', ${JSON.stringify(gaId)});`],
@igorls igorls added this to the v3.3.6 milestone May 15, 2026
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.

2 participants