Content Security Policy
The SDK uses no eval, no new Function, no inline styles and no inline event handlers. It loads
plugins by inserting <script> elements from the same origin as the core script.
With the first-party proxy (recommended)
Everything is same-origin:
script-src 'self' 'sha256-3BpoD12D7JyjxG9yVW9HjNqDaPmrAvEXCCdcuxFSs/4=';
connect-src 'self';Without a proxy
Add the API origin:
script-src 'self' https://api.3x.example 'sha256-3BpoD12D7JyjxG9yVW9HjNqDaPmrAvEXCCdcuxFSs/4=';
connect-src 'self' https://api.3x.example;The inline stub
The hash above is the SHA-256 of the exact one-line queue stub:
<script>window.x3=window.x3||function(){(window.x3q=window.x3q||[]).push(arguments)}</script>Any whitespace change changes the hash. Alternatives:
- Nonces: add
nonce="…"to both tags. In Next.js,<X3Analytics nonce={nonce} />; on dynamically rendered pages Next applies the request nonce from your CSP header automatically. - No stub: drop the first line if you never call
x3(…)before the script has loaded – the npm package needs no stub at all.
strict-dynamic
With 'strict-dynamic', plugins load because they are inserted by the trusted (nonced or hashed)
core script.
Shopify and iframes
The SDK does nothing inside iframes. On Shopify checkout pages use a custom web pixel with
@3x-engine/sdk/pixel (Shopify).