Skip to main content
aapp-hacks
← Back to articles
Author
app-hacks
Published
Updated
Reviewed

Astro / Google Analytics / Web Performance

Loading GA4 in Astro Only Once and Only on Production

An implementation record of initializing GA4 once in a shared head component while keeping non-production hosts out of measurement.

GA4 loading was added in commit 29d7397. Placing a tag in a component for every page risks loading it multiple times as layouts become nested or the site changes. This site uses src/components/SEOHead.astro as the single shared location, referencing the Measurement ID held in site constants only once.

Add it from the shared head only in production

SEOHead is called from the head of every public page. It adds the Google tag dynamically only when the browser hostname equals the canonical production host in the site constants. A local development server or a preview host does not meet that condition, so merely viewing a page there does not begin sending production measurement.

if (window.location.hostname === productionHost) {
  const googleTag = document.createElement('script');
  googleTag.async = true;
  googleTag.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;
  document.head.append(googleTag);
  gtag('config', measurementId);
}

The actual Measurement ID is kept in site configuration and is not copied into this article. The fact that an identifier appears in a public tag is separate from the problem of writing it in several placement points. Keeping initialization in one location and calling gtag('config', ...) once inside this condition takes priority.

How to check it and why

After npm run build, inspect the generated HTML to confirm that a production page contains one GA4 loading path. Also check that the condition does not add an external script on local and preview hostnames. Event totals in the analytics interface alone make duplicate initialization difficult to spot, so inspect generated HTML and the Network panel together.

The head is used so the same condition applies across every page, not so analytics scripts can be added to article bodies. Keeping the ID out of logs, articles, and contact submissions goes with centralizing the setting.

Common pitfalls

Without a production check, development access pollutes measurement. Adding the same tag to another component can duplicate page views and events. After a change, test production, local, and preview hosts as separate conditions.

This implementation does not fix the host at Astro build time; it checks the current hostname in the browser. The same build can therefore be delivered to development, preview, and production while loading is separated at runtime. If the canonical host changes, check the GA4 condition together with site constants, Astro’s site setting, and the canonical base.

Do not stop after inspecting one page. Confirm that fixed pages and article pages using the common layout retain the same condition.

Official documentation and related article