cd ..
$ cat csp-google-analytics-guide.md

CSP and Google Analytics: A Guide to Not Blocking Yourself

Why your Google Analytics data might be zero despite the tag being installed — and how to fix Content Security Policy conflicts with GA4 and Google Ads.

decong20772026/07/133 min read

You added the Google Analytics tag. You see it loading in the Network tab. But your dashboard shows zero users. Sound familiar?

The Problem

This was my browser console:

Refused to connect to 'https://analytics.google.com/g/collect'
because it violates the Content Security Policy directive:
"connect-src 'self' https://www.google-analytics.com https://www.google.com"

I had a CSP (Content Security Policy) header that allowed google-analytics.com, but GA4 was trying to send data to analytics.google.com — a different domain.

Why This Happens

Google Analytics 4 (the newer gtag.js) uses multiple endpoints for data collection:

Endpoint Used for
www.google-analytics.com/g/collect Universal Analytics (UA)
analytics.google.com/g/collect GA4 (the modern version)
www.googletagmanager.com GTM script loading

If your CSP only allows the first one, GA4 data silently fails.

The Fix

Add https://analytics.google.com to your connect-src directive:

Content-Security-Policy:
  default-src 'self';
  connect-src 'self'
    https://www.google-analytics.com
    https://www.google.com
    https://analytics.google.com;    ← This one
  ...

Bonus: Google Ads Image Tracking

If you also use Google Ads, you might see another error:

Refused to load image from 'https://www.google.com.tw/ads/ga-audiences'
because of img-src restriction

This is Google's audience tracking. The image request can come from any localized Google domain (.com.tw, .co.jp, .de, etc.). The fix is to add https://*.google.com to your img-src:

img-src 'self' blob: data: https://*.google.com;

Full Example (Next.js)

In next.config.mjs:

const nextConfig = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: [
              "default-src 'self'",
              "script-src 'self' 'unsafe-inline' https://www.googletagmanager.com",
              "style-src 'self' 'unsafe-inline'",
              "img-src 'self' blob: data: https://*.google.com",
              "font-src 'self'",
              "connect-src 'self' https://www.google-analytics.com https://www.google.com https://analytics.google.com",
              "object-src 'none'",
              "base-uri 'self'",
              "form-action 'self'",
              "frame-ancestors 'none'",
            ].join('; '),
          },
        ],
      },
    ];
  },
};

How to Debug CSP Issues

  1. Open Chrome DevTools → Console. CSP violations show as clear error messages with the violated directive
  2. Each error tells you exactly which URL was blocked and which directive caused it
  3. Temporarily remove the CSP header in dev mode to confirm the data flow works
  4. Use the report-uri or report-to directive to collect violations programmatically

Does CSP Affect Googlebot?

No. Googlebot does not execute JavaScript in a way that is subject to CSP. The raw HTML content is indexed fine. But CSP does affect GA4 data collection from real users, which means you get zero analytics data.

Summary

Directive Why you need it
connect-src + analytics.google.com GA4 data collection
img-src + *.google.com Google Ads audience tracking
script-src + googletagmanager.com Loading gtag.js

If your GA4 dashboard shows zero data but the tag is installed, check your CSP. It took me an afternoon to find this — hopefully this saves you the same.

$ echo "EOF"

评论交流