Csp
To load asset.js and allow beacons under a Content Security Policy, add statelessid.com to script-src and connect-src. Both directives are required.
The two directives you need
script-src controls which origins are allowed to provide executable scripts. Add https://statelessid.com to script-src so the browser is permitted to download and execute asset.js.
connect-src controls which origins are allowed to receive fetch or XMLHttpRequest connections. Add https://statelessid.com to connect-src so the browser is permitted to send the beacon. Both directives are required. A policy that allows script-src but not connect-src will load the script successfully and then silently fail to count visits when the beacon is blocked.
Adding to an existing policy
If your CSP already exists as a header or meta tag, find the script-src and connect-src directives and append https://statelessid.com to each. No wildcard is needed. No subdomain is needed. The canonical domain statelessid.com covers both the script file at /asset.js and the beacon endpoint.
A minimal addition to a policy that already allows 'self' looks like: script-src 'self' https://statelessid.com; connect-src 'self' https://statelessid.com. Place these alongside your existing allowed origins.
No unsafe-inline or unsafe-eval needed
asset.js does not use eval, new Function, document.write, or inline event handlers. Adding it to your policy does not require weakening the policy with unsafe-inline or unsafe-eval. The script operates within a strict CSP without needing those escape hatches.
If your policy currently uses unsafe-inline or unsafe-eval for other scripts, adding statelessid.com to your allowlist does not change that. If you are tightening a policy and removing those directives, asset.js does not reintroduce the need for them.
Nonce-based policies
Some sites use a per-request nonce on script-src instead of a domain allowlist. In that pattern, the server generates a random value per request, adds it to the CSP header as script-src 'nonce-RANDOM_VALUE', and injects that same nonce into each trusted script tag.
To use this pattern with asset.js, inject the per-request nonce into the asset.js script tag: <script src="https://statelessid.com/asset.js" data-k="YOUR_KEY" defer nonce="RANDOM_VALUE"></script>. Alternatively, add https://statelessid.com as a trusted domain alongside the nonce, which allows the external script without needing the nonce on that tag. The connect-src allowlist addition is the same either way.
Troubleshooting
If asset.js loads but no visits appear in the dashboard, check the browser console for a CSP violation on the beacon request. The error message names the blocked URL and the directive that blocked it. The blocked URL will be a statelessid.com endpoint. Adding statelessid.com to connect-src and reloading the page resolves this.
If both directives are set and you still see CSP violations, check whether your site has multiple CSP headers or a meta tag that overrides the header. Each CSP header is evaluated independently and all must allow the resource. Also check whether a default-src without statelessid.com is narrowing the effective policy on directives you have not set explicitly — script-src and connect-src override default-src when set, but if either is absent, default-src applies.
If you are using a report-only CSP header during testing, violations appear in the console and in your report endpoint but do not block requests. Switch to the enforced header (Content-Security-Policy without -Report-Only) to see which requests are blocked in practice before deploying.