Web Security

CSP for Third Party Scripts: Google Analytics, Tag Manager, and Payment Providers

The exact domains you need to allowlist for every major third party service, organized by category

SiteSecurityScore Team·15 min read·Updated Mar 1, 2026
Global network connections representing third party script integrations and external service dependencies

You built a Content Security Policy. It works great on your development server where your app only loads its own scripts. Then you deploy to production and everything breaks. Google Analytics stops collecting data. The Stripe checkout form disappears. The live chat widget vanishes. The Facebook Pixel stops firing.

The problem is that your CSP has no idea about the dozens of external services your production site depends on. Every third party script, every analytics pixel, every payment iframe, and every chat widget loads resources from external domains. If those domains are not in your policy, the browser blocks them silently.

This guide is the reference you keep open while building your CSP. It lists the exact domains you need to allowlist for every major third party service, organized by category. No guessing, no trial and error. Just the specific domains and directives each service requires.

How third party scripts interact with CSP#

A Content Security Policy is a single HTTP header your server sends with every page response. It contains a list of directives, and each directive controls which domains are allowed for a specific type of resource. Here is the basic format:

Basic CSP structure
Content-Security-Policy:
  script-src 'self' cdn.example.com;
  connect-src 'self' api.example.com;
  img-src 'self' images.example.com;
  frame-src 'self' embed.example.com

Each directive name (script-src, connect-src, img-src, frame-src) tells the browser which resource type that rule applies to. 'self' means your own domain. After that, you list the external domains that are allowed. Directives are separated by semicolons, and domains within a directive are separated by spaces.

With that in mind, here are the four ways third party scripts can trigger CSP violations:

  • Loading the script itself. The initial <script src="..."> tag loads from an external domain. If that domain is not listed in the script-src directive of your CSP, the browser blocks it.
  • Making API calls. Once loaded, the script sends data back to its servers using XHR or fetch. The connect-src directive in your CSP controls which domains the browser allows these network requests to reach.
  • Creating iframes. Payment forms and embedded widgets often run inside an iframe. The frame-src directive in your CSP decides which domains are allowed to be embedded as iframes on your page.
  • Loading additional resources. The script may load images (tracking pixels), styles, or additional scripts from other domains. Each resource type is governed by its own CSP directive: img-src for images, style-src for stylesheets, and script-src for JavaScript files.

Use strict-dynamic for script chains

Many third party scripts load additional scripts dynamically after the initial script runs. Google Tag Manager is the prime example. Adding 'strict-dynamic' to your script-src directive tells the browser that scripts loaded by a trusted script are also trusted. This dramatically reduces the number of domains you need to explicitly list.

Analytics and tracking#

Google Analytics (GA4)

Google Analytics 4 is typically loaded through Google Tag Manager, but it can also be loaded directly. Here are the domains it needs:

DirectiveDomains
script-srcwww.googletagmanager.com www.google-analytics.com
connect-srcwww.google-analytics.com analytics.google.com *.google-analytics.com *.analytics.google.com
img-srcwww.google-analytics.com www.googletagmanager.com

Google Tag Manager

Google Tag Manager is the tricky one. GTM itself loads from a known domain, but the tags it fires can load scripts from anywhere. This is where 'strict-dynamic' becomes essential.

DirectiveDomains
script-srcwww.googletagmanager.com
img-srcwww.googletagmanager.com
connect-srcwww.googletagmanager.com

GTM and inline scripts

GTM injects inline scripts for each tag it fires. Without nonces or 'strict-dynamic', these inline scripts will be blocked by your CSP. The recommended setup is: add a nonce to the initial GTM script tag and include 'strict-dynamic' in your script-src directive. This allows GTM to load all its tags without needing to list every domain individually. You will still need the domains listed above, plus the domains of any services GTM fires (GA, Ads, etc.) in the connect-src and img-src directives.

Facebook Pixel

DirectiveDomains
script-srcconnect.facebook.net
connect-srcwww.facebook.com
img-srcwww.facebook.com www.google-analytics.com
frame-srcwww.facebook.com

Hotjar

DirectiveDomains
script-srcstatic.hotjar.com script.hotjar.com
connect-src*.hotjar.com wss://*.hotjar.com
frame-srcvars.hotjar.com
img-srcstatic.hotjar.com script.hotjar.com
font-srcstatic.hotjar.com

Payment providers#

Payment providers are especially sensitive to CSP misconfigurations. If the checkout form fails to load, you lose revenue immediately. Always test payment flows thoroughly after deploying or updating your CSP.

Stripe

DirectiveDomainsPurpose
script-srcjs.stripe.comStripe.js library
frame-srcjs.stripe.com hooks.stripe.comPayment Element, 3D Secure
connect-srcapi.stripe.comAPI requests
img-src*.stripe.comCard brand logos

PayPal

DirectiveDomainsPurpose
script-srcwww.paypal.com www.paypalobjects.comPayPal SDK
frame-srcwww.paypal.com www.sandbox.paypal.comPayment buttons, checkout
connect-srcwww.paypal.com *.paypal.comAPI and eligibility calls
img-srcwww.paypalobjects.com t.paypal.comLogos, tracking pixel

Square

DirectiveDomains
script-srcjs.squareup.com js.squareupsandbox.com
frame-srcjs.squareup.com js.squareupsandbox.com
connect-srcconnect.squareup.com connect.squareupsandbox.com pci-connect.squareup.com

Customer support and engagement#

Intercom

DirectiveDomains
script-srcwidget.intercom.io js.intercomcdn.com
connect-src*.intercom.io wss://*.intercom.io uploads.intercomcdn.com
frame-srcintercom-sheets.com
img-srcstatic.intercomassets.com *.intercomcdn.com
font-srcjs.intercomcdn.com
media-srcjs.intercomcdn.com

HubSpot

DirectiveDomains
script-srcjs.hs-scripts.com js.hsforms.net js.hs-analytics.net js.hs-banner.com js.hscollectedforms.net
connect-srcapi.hubspot.com forms.hubspot.com js.hs-analytics.net
frame-srcapp.hubspot.com
img-srctrack.hubspot.com *.hsforms.com

Crisp Chat

DirectiveDomains
script-srcclient.crisp.chat
connect-srcclient.crisp.chat wss://client.relay.crisp.chat *.crisp.chat
frame-srcgame.crisp.chat
style-srcclient.crisp.chat
img-srcclient.crisp.chat image.crisp.chat storage.crisp.chat
font-srcclient.crisp.chat

Common web services#

Google Fonts

DirectiveDomains
style-srcfonts.googleapis.com
font-srcfonts.gstatic.com

Google reCAPTCHA (v2 and v3)

DirectiveDomains
script-srcwww.google.com www.gstatic.com
frame-srcwww.google.com

YouTube Embeds

DirectiveDomains
frame-srcwww.youtube.com www.youtube-nocookie.com
img-srci.ytimg.com img.youtube.com

Google Maps

DirectiveDomains
script-srcmaps.googleapis.com
frame-srcwww.google.com maps.google.com
img-srcmaps.googleapis.com maps.gstatic.com *.ggpht.com
connect-srcmaps.googleapis.com

Putting it all together: a real world example#

Here is what a CSP looks like for a typical SaaS marketing site that uses Google Tag Manager (with GA4), Stripe for payments, Intercom for support, Google Fonts, and reCAPTCHA on the contact form:

Complete CSP for a typical SaaS site
Content-Security-Policy:
  default-src 'self';
  script-src 'self' 'nonce-{value}' 'strict-dynamic'
    www.googletagmanager.com
    www.google.com www.gstatic.com
    js.stripe.com
    widget.intercom.io js.intercomcdn.com;
  style-src 'self' 'nonce-{value}'
    fonts.googleapis.com;
  font-src 'self'
    fonts.gstatic.com
    js.intercomcdn.com;
  img-src 'self' data: https:
    www.googletagmanager.com
    www.google-analytics.com
    static.intercomassets.com *.intercomcdn.com
    *.stripe.com;
  connect-src 'self'
    www.google-analytics.com analytics.google.com
    *.google-analytics.com *.analytics.google.com
    api.stripe.com
    *.intercom.io wss://*.intercom.io;
  frame-src 'self'
    www.google.com
    js.stripe.com hooks.stripe.com
    intercom-sheets.com;
  media-src 'self'
    js.intercomcdn.com;
  report-uri /api/csp-report

This is a long policy, and that is normal. Real world CSPs with multiple third party services are not short. The important thing is that every domain is explicitly listed for the specific directives it needs. No wildcards on broad domains, no unsafe-inline in script-src, and strict-dynamic handles dynamic script loading.

Best practices for managing third party scripts in CSP#

Use the most specific domain possible

Always prefer js.stripe.com over *.stripe.com and definitely over https:. Each level of specificity narrows the attack surface. Only use wildcards when a service genuinely uses unpredictable subdomains.

Separate directives properly

Do not lump everything into default-src. If Stripe only needs js.stripe.com in script-src and frame-src, do not add it to default-src where it would also apply to images, styles, and everything else.

Audit regularly

Third party services change their domains. Google has migrated analytics endpoints multiple times. Stripe has added new domains for features like 3D Secure. Check your CSP violation reports regularly and update your policy when services change their infrastructure.

Document why each domain is there

Six months from now, someone on your team will look at your CSP and wonder why hooks.stripe.com is in frame-src. Add comments to your CSP config explaining which service each domain belongs to. This makes maintenance much easier.

Remove services you no longer use

When you drop a third party service, remove its domains from your CSP. Leftover allowlisted domains from services you no longer use are an unnecessary expansion of your attack surface. Every domain in your policy is a domain that could potentially serve malicious content if compromised.

How to find domains you are missing#

Even with this reference, your site might use services not listed here. Here is how to discover what domains your CSP needs:

  • Browser DevTools Network tab. Open your site, go to the Network tab, and reload. Filter by domain to see every external domain your page contacts. Each one might need to be in your CSP.
  • CSP violation reports. Deploy your policy in Content-Security-Policy-Report-Only mode with a report-uri endpoint. The browser will tell you exactly what is being blocked and which directive caused it.
  • Run a scan. SiteSecurityScore scans your site and shows your current CSP, what it covers, and what might be missing.
  • Check the service's documentation. Many services now publish their CSP requirements. Stripe, Google, and others have documentation pages listing the exact domains their scripts use.

The bottom line#

Third party scripts are the most common reason CSP deployments fail. Not because the concept is hard, but because finding the right domains for each service is tedious and error prone. This guide gives you the starting point. Combine it with Content-Security-Policy-Report-Only mode to catch anything you missed, and you will have a production ready CSP that protects your users without breaking your integrations.

Remember that third party services change their infrastructure over time. Bookmark this page, but also keep your CSP reporting active. The combination of a good reference and real time violation data is what makes CSP manageable at scale.

Frequently asked questions#

How do I add Google Analytics to my Content Security Policy?

Add www.googletagmanager.com and www.google-analytics.com to script-src. Add www.google-analytics.com, analytics.google.com, and their wildcard variants to connect-src for data collection endpoints.

Why does Google Tag Manager need unsafe-inline in CSP?

GTM injects inline scripts for each tag it fires. The recommended solution is to use nonces with 'strict-dynamic' rather than 'unsafe-inline'. Add a nonce to the initial GTM script tag, and strict-dynamic will allow GTM to load its tags without listing every domain.

What CSP directives does Stripe require?

Stripe needs js.stripe.com in script-src, js.stripe.com and hooks.stripe.com in frame-src, and api.stripe.com in connect-src. For card brand logos, add *.stripe.com to img-src.

How do I handle third party scripts that load other scripts dynamically?

Add 'strict-dynamic' to your script-src. This tells the browser that scripts loaded by a trusted (nonced) script are also trusted. It is essential for tag managers, advertising platforms, and A/B testing tools that inject additional scripts at runtime.

Should I use wildcard domains in my CSP for third party services?

Avoid wildcards whenever possible. Using *.google.com instead of www.google-analytics.com opens your policy to any subdomain on that domain. Always use the most specific domain you can. Only use wildcards when a service genuinely uses unpredictable subdomains.

Was this helpful?
Share

Is your CSP covering all your third party scripts?

Scan your website to check if your Content Security Policy accounts for every external service you use.