Skip to content
MDView as Markdown

Google Tag Manager

Google Tag Manager is one of the most common reasons a CSP rollout stalls. The container script is inline, every tag you deploy through it can inject more script, and the set of domains involved depends on which Google products you have turned on.

Google's own guidance is clear about the order of preference: use a nonce, fall back to hashing the inline script, and treat 'unsafe-inline' as a last resort.

What Google Tag Manager gives you

  • Nonce support on the container snippet. Generate a nonce server-side for each response, put it in your script-src-elem directive, and add the matching nonce attribute to the Tag Manager script tag.
  • Hashing the inline container snippet as an alternative where you cannot generate a per-response nonce.
  • Per-product domain guidance rather than one list, because the domains differ by product: GA4 needs google-analytics.com, g.doubleclick.net and Google regional domains; Google Ads needs googleadservices.com, doubleclick.net and the syndication domains; Floodlight uses ad.doubleclick.net and advertiser-specific endpoints.
  • Custom templates, which are the safe way to extend functionality. Custom JavaScript variables require 'unsafe-eval', which Google explicitly discourages.
  • Tag Assistant for identifying blocked resources while you tune.

Sending reports to Report URI

Add the reporting directives to whatever policy you are already serving, and set the two Reporting API headers that report-to sends through. Your URLs come from the Setup page:

Content-Security-Policy-Report-Only: script-src-elem 'nonce-{random}' 'report-sha256'; report-uri https://abc123.report-uri.com/r/d/csp/reportOnly; report-to default
Reporting-Endpoints: default="https://abc123.report-uri.com/a/d/g"
Report-To: {"group":"default","max_age":31536000,"endpoints":[{"url":"https://abc123.report-uri.com/a/d/g"}],"include_subdomains":true}

'report-sha256' turns on CSP Integrity, which reports a hash of every script that loads. It goes in script-src-elem here because that directive, not script-src, governs script elements once it is present.

Your CSP reports are the fastest inventory of what your container is actually loading - including tags somebody added months ago and forgot about.

Things to watch for

  • A nonce is only a nonce if it is unguessable and regenerated for every response. A nonce baked into a cached page is worth nothing.
  • Tag Manager is a delegation of trust: anyone with publish rights in the container can add a script to your pages without touching your codebase. That is exactly the change Policy Watch and Script Watch are designed to surface.
  • Adding domains to your policy one violation at a time works, but it quietly grows an allowlist you will never prune. Review it periodically.

Official documentation

Google - Use a Content Security Policy

Start Monitoring with Report URI

Already using us for CSP? Find your CSP reporting directives on Setup, or view your CSP reports.

New to Report URI? Create an account and grab your CSP reporting directives from the Setup page.

Start your free trial