Reference — Content-Security-Policy for the LoudPixel pixel
The exact CSP directives the LoudPixel attribution pixel needs, including a SHA-256 hash for the inline queue stub so you never need 'unsafe-inline'.
If your site sends a Content-Security-Policy header, the pixel needs three directives. Without them the browser blocks it silently — your pages look fine, the console shows a CSP violation, and your dashboard shows zero events forever.
The short version
script-src https://loudpixel.ai 'sha256-FMheJwvj8IrbXYYNzgQaXAhWC3JNf4Zm8jpCl80/3FY=';
connect-src https://loudpixel.ai;
img-src https://loudpixel.ai;Add these to your existing directives — do not replace them. CSP directives are allowlists, so append the values above to whatever you already have on each line.
What each one is for
| Directive | Why the pixel needs it |
|---|---|
script-src https://loudpixel.ai | loads /t.js |
script-src 'sha256-…' | allows the one inline stub in the install snippet |
connect-src https://loudpixel.ai | sendBeacon / fetch to /api/v1/track/pixel and /track/pixel/goal — this is how events actually reach us |
img-src https://loudpixel.ai | only if you use the /p.gif image fallback (email, AMP, RSS) |
connect-src is the one people miss. Allow the script but not the connection and the pixel loads, runs, and every event it sends is blocked — the most confusing possible failure, because nothing on the page looks wrong.
The pixel needs nothing else: no cookies, no localStorage, no style-src, no frame-src, no 'unsafe-eval'.
Why there is a hash
The install snippet is two lines, and the first is inline:
<script>window.lp=window.lp||{};window.lp.track=window.lp.track||function(){(window.lp.q=window.lp.q||[]).push(arguments)};</script>
<script async src="https://loudpixel.ai/t.js?domain=yourdomain.com"></script>That stub exists so lp.track('checkout', …) on your thank-you page works even before the async script has finished loading — it queues the call and the pixel replays it on arrival. Without it, that call throws ReferenceError: lp is not defined on exactly the page where your money is.
Being inline, it needs one of three things under CSP: 'unsafe-inline', a nonce, or a hash. The hash above is the SHA-256 of that exact stub text, so you can keep a strict policy. The hash covers the bytes between the tags exactly — if you reformat the stub, add whitespace, or change a character, the hash no longer matches and the browser blocks it. Copy it verbatim, or use a nonce instead:
<script nonce="YOUR_REQUEST_NONCE">window.lp=window.lp||{};window.lp.track=window.lp.track||function(){(window.lp.q=window.lp.q||[]).push(arguments)};</script>If your page never calls lp.track(), drop the stub entirely and you need no hash, no nonce, and no 'unsafe-inline' — just the script-src, connect-src and img-src origins.
If you proxy the pixel from your own domain
Customers who serve /t.js from their own origin (for ad-blocker resistance) pass ?api=/api/v1, which makes every request same-origin. In that case you need no LoudPixel origin at all — 'self' covers it.
Checking it worked
Open DevTools on a page that has the pixel:
- Console — a blocked pixel says so explicitly: "Refused to load the script" or "Refused to connect", naming the directive that blocked it. That message names your fix.
- Network — you should see
t.jsreturn 200, then aPOSTto/api/v1/track/pixelshortly after. The POST is the one that matters; a 200 ont.jsalone proves nothing.
Report-only first, if you prefer
Content-Security-Policy-Report-Only applies the same rules and blocks nothing, so you can add the pixel, watch for violations for a day, and only then move the directives to the enforcing header.
Reference — Conversions API (CAPI) signing
Send server-side conversions (e.g. a Stripe webhook) to LoudPixel with an HMAC signature so they feed AI-search revenue attribution.
What is llms.txt
The one file that tells AI engines what your business is, in the words you choose — and how LoudPixel writes and serves it for you.