Safeguard
Developer Tools•

How do you run Google Tag Manager under a strict CSP?

Use a per-response nonce for the container snippet, add the needed Google hosts, avoid unsafe-eval with templates, and collect reports. Steps and caveats.

Safeguard Security Team
3 min read

Put a fresh, random nonce on the inline container snippet and in your script-src-elem directive, so Tag Manager can run and pass the nonce to scripts it adds. Add only the Google hosts you use, avoid unsafe-eval by choosing templates, and collect violation reports while you tune.

What Google's guide says

Google's tag platform CSP guide recommends a nonce: an unguessable random value the server generates for each response. Add it to the script-src-elem directive and set the same value on the inline script's nonce attribute. Tag Manager then passes the nonce to scripts it adds to the page. Hashes are an alternative, and 'unsafe-inline' is described as a last resort.

Steps

  1. Generate a nonce per response on the server. Never reuse a value across responses.
  2. Add it to the policy in script-src-elem and to the container snippet.
  3. Add base hosts. For the container, the guide lists https://www.googletagmanager.com for scripts and images, and that host plus https://www.google.com for connections.
  4. Add product hosts you actually use. Analytics needs script, image, connect and frame entries. Google Ads, Floodlight and Merchant Center add their own. Google notes each Google top level domain must be listed individually, since wildcards cannot be used on the right side of a hostname.
  5. Allow Preview mode only where needed. The guide lists extra hosts for the preview tool, for example tagmanager.google.com for scripts and styles.
  6. Report, then enforce. Start in report-only. See the report-only rollout.

The unsafe-eval trap

The guide states that without 'unsafe-eval' in script-src, Custom JavaScript variables evaluate to undefined. It says to use unsafe-eval only when absolutely necessary and recommends Custom Templates as the alternative. Search your container for Custom JavaScript variables before you enforce, then replace them with templates.

Common failure modes

SymptomLikely cause
Container does not loadNonce missing or different from the policy
Some tags silentA host they need is not in connect-src or img-src
Variables return undefinedCustom JavaScript variable with no unsafe-eval
Works on one page onlyPolicy set per template, not globally
Cached pages breakA cached nonce is being reused, which also defeats the nonce

The last one is subtle. Page caching that stores one nonce for many visitors turns a nonce into a constant. Generate it per response or use hashes.

Remember what CSP can and cannot do

A CSP limits where scripts load from and where data can be sent. It does not review the tags inside a container, so a malicious tag added by a publisher can still use allowed hosts. Pair the policy with publish access limits. For comparison of nonce, hash and allow list, see CSP nonce vs hash vs allowlist.

Quick check

Do I need unsafe-inline for the container?

Google recommends a nonce instead. Unsafe-inline is the last resort.

Why do my custom variables return undefined?

Without unsafe-eval, Custom JavaScript variables evaluate to undefined. Use Custom Templates.

Where Safeguard fits

Safeguard's policies and gates can check changes to code that sets your headers, and dependency scanning covers the packages you ship. Try the free scan.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.