Topic: Content Security Policy (CSP), Meta Pixel, LinkedIn Insight Tag, TikTok Pixel
In the first two articles, I explained what a Content Security Policy (CSP) is, why it often causes issues with Google Tag Manager and how to solve the basics. Maybe you’ve already implemented what was described there: Your GTM works again with a nonce, inline scripts run, and your basic tracking is sending data again.
But: Even though most things are working again, it seems the problem caused by the CSP still isn’t fully resolved. While GA4 is receiving data again, Meta Business Manager likely shows no conversions, or individual scripts triggered via custom HTML tags still fail. You may have seen an error like this during testing:
This error shows that your CSP is blocking external resources from loading. That’s absolutely intentional — injecting unauthorized scripts into your site and letting them run unnoticed in your visitor’s browser should be prevented. But you still have the problem that your tracking doesn’t work.
The key issue: Many tracking tools, especially social media pixels, only work because they load additional external scripts or resources. What helps Meta, TikTok & others make their pixels more flexible and easier to evolve is now causing trouble for you. But why exactly?
Why a Nonce or Hash Doesn’t Help Here
In the previous articles, we already learned how to make scripts run with a nonce or a hash despite CSP when they are directly in your HTML — for example, the GTM snippet itself, or simple custom HTML tags embedded through Google Tag Manager.
For some tools, that unfortunately isn’t enough. As you might imagine, the Meta Pixel does far more behind the scenes than the small snippet embedded in GTM suggests.
Meta Pixel, LinkedIn Insight Tag, TikTok Pixel and many others load additional scripts or resources after initialization — resources that are no longer part of your original HTML. For these files, neither a nonce nor a hash applies, because the browser treats them as separate network requests.
Example: In the screenshot above, an inline script with a nonce may run, but as soon as the script tries to load https://connect.facebook.net/en_US/fbevents.js, the browser checks the CSP. If that domain isn’t allowed, the load is blocked — even if the initial script block was correctly signed.
In short: Nonce and hash only solve the inline-script problem, but they fail when a tag tries to load external resources afterwards.
The Solution: Whitelisting External Sources / Allow-List
To solve this problem, there is really only one approach: Explicitly allow the blocked resources — in other words, create a “whitelist” (allow-list) for specific external domains or scripts. Depending on the provider, there are several standard domains that should be included:
- Meta Pixel: https://connect.facebook.net
- LinkedIn Insight Tag: https://snap.licdn.com
- TikTok Pixel: https://analytics.tiktok.com, https://business-api.tiktok.com
- Google Tag Manager & Analytics: https://www.googletagmanager.com, https://www.google-analytics.com
These sources need to be explicitly allowed in your site’s CSP so tracking works with CSP despite nonce/hash. Typically this is done using the script-src directive, sometimes also img-src or connect-src (depending on which type of resource the tool loads).
Note: Many vendors use different subdomains or occasionally change their scripts. Meta, for example, uses various versions of *.facebook.net. As tempting as it may be to simply allow a wildcard like *.facebook.net, I strongly advise against it, as this could unintentionally whitelist unwanted domains and undermine the purpose of your CSP. The safe approach is to start with the documented, known domains and expand your CSP only when necessary.
Reporting: Detecting and Monitoring Issues
As mentioned earlier, external tools change regularly, and there’s always a risk that a new source will be used that you haven’t whitelisted yet. CSP reporting solves this problem.
CSP reporting can also be extremely useful for testing. Sometimes different sources are nested inside one another. If your GTM snippet loads external sources that then load more external sources, it often happens that an additional required allow-entry goes unnoticed. For reporting, a Content Security Policy provides two different options:
- Content-Security-Policy-Report-Only: This version doesn’t block anything — it only reports violations directly in the browser. This is ideal for testing before activating a strict CSP that could unintentionally break your tracking.
- report-uri or (modern) report-to: With this version, the browser explicitly reports which script or resource was blocked, on which page, and when.
A typical report tells you which page was affected, which directive was violated (e.g. script-src), which domains were blocked, and includes a timestamp and browser information. With this data, it is usually no problem for an IT department to configure the CSP correctly. I recommend running several iterations, though: If a script fails to execute, the report may not catch additional external resources that the script would have tried to load.
Tip: CSP reports using report-to can even be automatically forwarded to a webhook (e.g., in Microsoft Teams). This lets you receive real-time notifications when your tracking is blocked by CSP — for example, because Meta introduced a new CDN domain.
Watch Out for Special Cases
Unfortunately, that still doesn’t cover every case. A classic example is the Meta Pixel: It doesn’t just load resources from connect.facebook.net, but depending on event, device or other conditions, it also accesses additional subdomains such as graph.facebook.com. If you haven’t allowed that domain in your CSP, certain requests remain blocked — and with them certain conversion events.
The same applies to other tools that combine multiple services, use CDNs or behave differently depending on context. Therefore it’s worth testing extensively and checking in the browser console or in reporting which domains are actually being blocked.
All clear?
If you’ve followed all three articles, your Content Security Policy should prevent security issues without breaking your tracking setup. If you still need help, I’m happy to support you at any time.