There are two standard ways to configure CSP:
Content Security Policy (CSP) allows you to restrict how resources such as JavaScript, CSS, or pretty much anything that the browser loads. To set CSP, you can send is as HTTP header or set it in HTML as a meta tag.
- Specify an allowlist of domains that can inject their resources on the page.
- Specify a random nonce, with which resources on the page must be marked in order to load. This approach is known as strict CSP.
Some useful links
- https://github.com/helmetjs/helmet - Express middleware for more than CSP
Values of CSP directive
unsafe-inline
Enables inline scripts in the page, potentially insecure if a script can be injected to the page.
nonce-<base64-random-string>
Used to secure inline scripts without usage of
unsafe-inline
.Once having nonce in the CSP, browsers will ignore additional
unsafe-inline
and will force nonce
for all the inline scriptsCSP and GTM
Once you start using nonce, you have to inject the nonce to the initialization code of GTM and even use the "nonce-aware" implementation of the script. If you do it, GTM will add nonce to all the tags it loads. The only problem is with Custom HTML!.
When you use Custom HTML, you have to inject the nonce to scripts in the HTML yourself. To do it, you need to create a GTM variable and store the nonce to it. The best way to do it is via DOM variable:

It takes
nonce
from data-nonce
atribute of a html tag with id gtmScriptTag
. We use data-nonce
because some browsers turn nonce to any empty string. That tag is likely to be the script on the page initializing GTM:Now we need to pass the nonce value to the Custom HTML. If we name the GTM variable
nonce
, it would look like this:
It is important to mention two things:
- if you create a new script in the Custom HTML, you have to pass the nonce to it, see code
c.nonce = "{{ nonce }}"
- you have to change
Support method document.write
to make whole thing work properly.