How do I configure a strict Content Security Policy so GTM (and its Custom HTML tags) still runs?
GTM needs script-src to allow googletagmanager.com for the loader itself, plus either unsafe-inline or a per-request nonce for the inline snippet and any Custom HTML tags, and connect-src/img-src entries for whichever destinations your tags actually call. A strict CSP with none of these silently blocks GTM at the browser level with no error visible in GTM Preview - only in the browser console.
Why this happens
Content Security Policy is enforced by the browser before any of GTM's own JavaScript runs, so a blocked script never reaches the point where GTM Preview could report anything about it - Preview simply never connects, or connects and shows nothing firing, because the container script itself was refused. This looks identical to several other "GTM Preview shows nothing" problems but has a completely different fix: the evidence is in the browser console (a CSP violation report), not in GTM.
Fix it
- Open the browser console on the live page (not Preview) and look for "Refused to load the script... because it violates the following Content Security Policy directive" - this confirms CSP is the cause and names the exact directive.
- Add
https://www.googletagmanager.comtoscript-srcat minimum, since that is where the container script (gtm.js) loads from. - For the inline dataLayer bootstrap snippet and any Custom HTML tags with inline scripts, add either
'unsafe-inline'(weaker, easiest) or generate a per-request nonce and add it to your own GTM snippet's script tag - GTM propagates that same nonce to tags it injects. - Add the actual destinations your tags call to
connect-srcandimg-src: commonlyhttps://www.google-analytics.com,https://*.google-analytics.com,https://analytics.google.com,https://www.facebook.com,https://connect.facebook.net- the exact list depends on which tags are actually configured in your container. - If you cannot use unsafe-inline or thread a nonce through every request, consider
strict-dynamiccombined with a nonce on the bootstrap script, letting it dynamically load further scripts without whitelisting every downstream domain individually.
How to verify it worked
Reload the live page with the Network tab open and filter for "googletagmanager." A successful load shows gtm.js with a 200 status and no red CSP error in the Console tab. Then open GTM Preview against the same URL - if CSP was the blocker, Preview now connects and shows tags evaluating where it previously showed nothing at all.
Still stuck after working through this?
Send us what you are seeing in Preview and the Network tab. We trace GTM containers for a living and can usually tell you what is actually happening in one look.
Ask a GTM Engineer