Docs

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.

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).