Note: This blog post was written with the help of AI tools and reviewed by the author to ensure quality and accuracy.

Keep Dev Traffic Out of Analytics in Astro


The Problem with Running Everything in Development

You’re working on your blog locally, testing changes, clicking through your own site, and having a great time building. Meanwhile, your Google Analytics dashboard is filling up with dev traffic that skews your real visitor metrics. Or worse—you accidentally click your own AdSense ads a few times, and Google’s fraud detection flags your account.

Sound familiar? This is a surprisingly common oversight, but it’s easily preventable.

Why This Matters

Analytics Pollution

Every time you refresh the page during development, you’re adding noise to your analytics data. Real visitors’ behavior becomes harder to track when mixed with your own testing sessions.

Ad Fraud Detection

Google takes ad clicks seriously. Clicking your own ads—whether intentional or accidental during testing—can trigger fraud detection algorithms and put your AdSense account at risk.

Unnecessary Network Requests

Third-party scripts add latency and bandwidth. In development, there’s no reason to load these dependencies when you’re focused on building features.

The Solution: Environment-Based Conditionals

If you’re using Astro, you have a built-in way to detect your build environment using import.meta.env.PROD. This flag is true during production builds and false during development.

Before: Always Loaded

---
// BaseHead.astro
---

<!-- Google Analytics - Always loads, even in dev! -->
<script is:inline src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
<script is:inline>
  window.dataLayer = window.dataLayer || [];
  function gtag() {
    dataLayer.push(arguments);
  }
  gtag("js", new Date());
  gtag("config", "G-XXXXXXXXXX");
</script>

<!-- Google AdSense - Always loads, even in dev! -->
<script
  is:inline
  async
  src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXXXXXXX"
  crossorigin="anonymous"></script>

After: Production Only

---
// BaseHead.astro
---

<!-- Google Analytics - Only in production -->
{import.meta.env.PROD && (
  <>
    <script is:inline src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXXXXX"></script>
    <script is:inline>
      window.dataLayer = window.dataLayer || [];
      function gtag() {
        dataLayer.push(arguments);
      }
      gtag("js", new Date());
      gtag("config", "G-XXXXXXXXXX");
    </script>
  </>
)}

<!-- Google AdSense - Only in production -->
{import.meta.env.PROD && (
  <script
    is:inline
    async
    src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXXXXXXX"
    crossorigin="anonymous"></script>
)}

How It Works

When you run astro dev, the development server builds with import.meta.env.PROD = false. The conditional expressions {import.meta.env.PROD && (...)} evaluate to false, and the scripts don’t render at all.

When you run astro build, the production build uses import.meta.env.PROD = true. The conditionals evaluate to true, and the scripts are included in your final HTML.

Key Benefits

Clean Analytics — Only real visitor data in your dashboards
Fraud Protection — Zero risk of accidental ad clicks triggering detection
Faster Dev — Fewer network requests means snappier local development
Build-Time Detection — Zero runtime overhead; this is all compiled away
No Extra Config — Uses Astro’s native environment detection

Beyond Google: Apply This Pattern Everywhere

This approach works for any third-party script you want to gate behind a production build:

{import.meta.env.PROD && (
  <>
    <!-- Sentry error tracking -->
    <script src="https://browser.sentry-cdn.com/..."></script>

    <!-- Custom analytics service -->
    <script src="https://analytics.example.com/track.js"></script>

    <!-- Heatmap/session replay tools -->
    <script src="https://sessionreplay.example.com/record.js"></script>
  </>
)}

Any performance monitoring, user tracking, or promotional script can be safely gated this way.

Verification

After making these changes, you can verify they’re working:

Check your dev build:

npm run dev
# Open DevTools → Network tab
# Look for googletagmanager.com requests
# ✓ They shouldn't appear

Check your production build:

npm run build
# Open dist/index.html in a text editor
# Search for "googletagmanager"
# ✓ It should be there

Conclusion

Conditionally loading external scripts is a small change with big benefits. It keeps your analytics clean, protects your ad accounts from fraud detection, and speeds up your development workflow. Best of all, Astro makes it trivial to implement with built-in environment detection.

If you’re not already doing this, add it to your next deployment. Your analytics dashboard will thank you. 📊