Skip to content

Add Google Analytics 4 to both sites (env-var driven)#12

Merged
radinhamidi merged 1 commit intochore/site-seofrom
chore/google-analytics
Apr 30, 2026
Merged

Add Google Analytics 4 to both sites (env-var driven)#12
radinhamidi merged 1 commit intochore/site-seofrom
chore/google-analytics

Conversation

@radinhamidi
Copy link
Copy Markdown
Member

Summary

Adds GA4 (gtag.js) to both `querygym.com` and `leaderboard.querygym.com`. The measurement ID isn't hardcoded — each Cloudflare Pages project sets its own ID via the dashboard's Environment variables pane:

CF Pages project Env var Value
`querygym-site` `PUBLIC_GA_MEASUREMENT_ID` your G-XXXXXXXXXX
`querygym-leaderboard` `PUBLIC_GA_MEASUREMENT_ID` your G-YYYYYYYYYY (separate property/stream)

If the env var is unset (local dev, fork PRs, preview branches without prod env), nothing renders — no analytics requests fire. Keeps dev environments silent.

How it works

  • New shared component `web/shared/components/GoogleAnalytics.astro`
  • Reads `import.meta.env.PUBLIC_GA_MEASUREMENT_ID` at build time (Astro inlines `PUBLIC_*` into the static output).
  • Renders the standard gtag.js script + a small inline config call.
  • Wired into both Default layouts.

The inline config script is built as a string and emitted via `set:html` so Astro doesn't try to parse JS function-body curly braces as JSX expressions.

Stacked on #11

This PR is based on `chore/site-seo` (PR #11). Merge order:

  1. Merge Add SEO surface to querygym.com + restore home-page logo #11 first (SEO surface + logo fix).
  2. Then re-target this PR's base to `main` (GitHub does this automatically) and merge.

After #11 merges this PR's diff will narrow to just the three GA-related files.

Test plan

  • No env var: build succeeds; `grep googletagmanager dist/index.html` returns 0 on both sites.
  • `PUBLIC_GA_MEASUREMENT_ID=G-TEST123ABC pnpm -F @qg/site build`: gtag.js script with the test ID renders in ``.
  • Same for the leaderboard.
  • CF Pages env vars set in dashboard before re-deploy.
  • After deploy: GA4 Realtime report shows traffic from `querygym.com` and `leaderboard.querygym.com`.

Privacy notes

  • GA4's default IP anonymization is in effect.
  • No consent banner here. If EU traffic becomes a real concern, add a Cookie-banner component (or migrate to Cloudflare Web Analytics, which doesn't require consent).

🤖 Generated with Claude Code

New shared component @qg/shared/components/GoogleAnalytics.astro
reads `PUBLIC_GA_MEASUREMENT_ID` at build time. Astro inlines
PUBLIC_* env vars into the static output, so each Cloudflare Pages
project sets its own ID via "Environment variables":

  querygym-site         → PUBLIC_GA_MEASUREMENT_ID = G-XXXXXXXXXX
  querygym-leaderboard  → PUBLIC_GA_MEASUREMENT_ID = G-YYYYYYYYYY

Component renders nothing if the env var is unset — keeps `pnpm dev`,
preview branches, and forks silent (no analytics traffic from dev or
contributor environments).

Wired into both layouts:
- web/site/src/layouts/Default.astro
- reproducibility/site/src/layouts/Default.astro

The inline config script is built as a string and emitted via
set:html so Astro doesn't try to parse JS function-body curly braces
as JSX expressions.

No consent banner. GA4's default IP anonymization applies; add a
banner if EU traffic becomes a real concern.

Verified locally: with env var set, gtag.js + config render in <head>
on both sites; without it, zero googletagmanager references in the
output.

Stacked on top of #11 (chore/site-seo). Once #11 merges, this PR's
diff will narrow to just the GA bits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@radinhamidi radinhamidi merged commit a24ca57 into chore/site-seo Apr 30, 2026
3 checks passed
@radinhamidi radinhamidi deleted the chore/google-analytics branch April 30, 2026 05:20
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