Content Security Policy (CSP)
UpdatedIf you enforce a Content Security Policy (CSP) on your website, you need to add directives that let the JavaScript client load and communicate with Customer.io. This page shows the required directives.
A Content Security Policy (CSP) is a standard that helps you control the resources that a web browser can load on your page. If you enforce a CSP on your website, you need to allow the domains that our JavaScript client communicates with.
If you’re using our legacy JavaScript snippet, where calls use the _cio prefix, see the legacy CSP page instead.
Standard directives
Use nonce-based authorization
If your CSP uses nonce-based authorization, you can add a nonce to the JavaScript client snippet instead of allowing entire domains in script-src. This provides a stricter security model because it authorizes specific script elements rather than entire domains.
Add the nonce attribute to the snippet’s <script> tag, matching the nonce value in your CSP header:
<script nonce="your-random-nonce-value">
// Your JavaScript client snippet code here
</script>
Your CSP header should include the matching nonce:
script-src 'nonce-your-random-nonce-value' cdp.customer.io;
You still need to allow cdp.customer.io in script-src because the snippet dynamically loads additional scripts from this domain.
Package-based installations
If you installed the JavaScript client as a package—for example, @customerio/cdp-analytics-browser—rather than using the snippet, you don’t need to allow cdp.customer.io in script-src. The library bundles into your app code. You still need the connect-src directives so the library can send data to Customer.io.
connect-src cdp.customer.io *.api.gist.build *.cloud.gist.build;
frame-src renderer.gist.build code.gist.build;
style-src 'unsafe-inline';
Custom proxy setups
If you’ve set up a custom proxy to route requests through your own domain, replace the Customer.io domains in your CSP with your proxy domain. For example, if your proxy domain is analytics.example.com:
script-src analytics.example.com;
connect-src analytics.example.com *.api.gist.build *.cloud.gist.build;
Glossary of directives
Some of these directives are required for in-app messaging, which includes features like inbox messages, web-based microsurveys, and so on. If you don’t use these features, you can exclude the relevant directives.
| Directive | Host | Description |
|---|---|---|
script-src | cdp.customer.io | The host for the JavaScript client. The snippet loads the library and integration bundles from this domain. |
connect-src | cdp.customer.io | Required for sending tracking data—identify, track, and page calls—and loading integration settings. |
connect-src | *.api.gist.build, *.cloud.gist.build | Required for in-app messaging. We use these domains for message queues and real-time updates. You can exclude these if you don’t send in-app messages. |
frame-src | renderer.gist.build, code.gist.build | Required for rendering in-app messages in iframes. You can exclude these if you don’t send in-app messages. |
style-src | 'unsafe-inline' | Required because the in-app messaging infrastructure injects inline <style> blocks to position and display messages. You can exclude this if you don’t send in-app messages. |
Frequently asked questions
Do you need unsafe-inline or unsafe-eval in script-src?
No! Unlike our legacy JavaScript snippet, the JavaScript client loads as an external script. You don’t need unsafe-inline or unsafe-eval in your script-src directive. This is one of the benefits of upgrading from the legacy snippet.
Can you exclude in-app messaging directives?
Yes. If you don’t send in-app messages (including inbox messages, microsurveys, and so on), you can remove all gist domains from your CSP:
*.api.gist.buildand*.cloud.gist.buildfromconnect-srcrenderer.gist.buildandcode.gist.buildfromframe-src'unsafe-inline'fromstyle-src
