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
- Generate a nonce per response on the server. Never reuse a value across responses.
- Add it to the policy in
script-src-elemand to the container snippet. - Add base hosts. For the container, the guide lists
https://www.googletagmanager.comfor scripts and images, and that host plushttps://www.google.comfor connections. - 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.
- Allow Preview mode only where needed. The guide lists extra hosts for the preview tool, for example
tagmanager.google.comfor scripts and styles. - 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
| Symptom | Likely cause |
|---|---|
| Container does not load | Nonce missing or different from the policy |
| Some tags silent | A host they need is not in connect-src or img-src |
| Variables return undefined | Custom JavaScript variable with no unsafe-eval |
| Works on one page only | Policy set per template, not globally |
| Cached pages break | A 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.