Advanced

Content Security Policy

Configure CSP headers for pages using the FanID Widget.

If your site uses a strict Content Security Policy (CSP), you may need to adjust it for the FanID Widget. CSP rules must allow your tenant domain — whichever URL you passed to baseUrl.

Required directives

When loading from unpkg CDN

Content-Security-Policy:
  script-src 'self' https://unpkg.com;
  style-src 'self' https://unpkg.com 'unsafe-inline';
  connect-src 'self' https://your-org.fanid.co;
  img-src 'self' https://your-org.fanid.co data:;

When self-hosting or bundling

Content-Security-Policy:
  script-src 'self';
  style-src 'self' 'unsafe-inline';
  connect-src 'self' https://your-org.fanid.co;
  img-src 'self' https://your-org.fanid.co data:;

Replace https://your-org.fanid.co with the exact baseUrl you pass to FanIDWidget.init(). If you use a custom domain (e.g. https://fans.your-site.com), substitute that instead.

Directive breakdown

DirectiveRequired forValue
script-srcLoading the widget scriptCDN domain or 'self' if self-hosted
style-srcWidget panel CSS + injected gate styles'unsafe-inline' required for injected <style> tag
connect-srcAPI calls to your FanID tenantThe exact baseUrl (e.g. https://your-org.fanid.co)
img-srcOrganization logo in overlaysSame as connect-src

connect-src covers both transports — bearer-mode requests that send an Authorization header (the normal case for any page not served from the tenant host) and cookie-mode requests with credentials: 'include'. The browser does not require 'Authorization' to be listed anywhere in CSP; custom request headers are governed by CORS, not CSP. If your tenant runs on a different origin than baseUrl suggests (e.g. behind a custom domain), allowlist that origin in connect-src and img-src instead.

CORS request headers

The Authorization header used in bearer transport is added automatically by the widget. Your tenant's CORS configuration (managed by FanID) already lists Authorization and Content-Type as allowed request headers — nothing extra is required from you. If you front the tenant with your own reverse proxy or WAF, make sure that proxy preserves both headers on /api/subscriber/* requests.

Request telemetry and CSP

Every API request the widget sends carries widget_version and widget_transport query parameters (see Cross-Domain Setup). No CSP directive is needed for them. CSP source expressions match scheme, host, port, and path — never the query string — so a connect-src entry that already allows your tenant origin allows these requests unchanged.

What can break them is infrastructure, not policy: if you front your tenant with a reverse proxy, CDN, or WAF, make sure it does not strip unknown query parameters from /api/subscriber/*.

'unsafe-inline' for styles

The gated content overlay injects a <style> tag into <head> with randomized CSS class names. This requires 'unsafe-inline' in style-src. The injected styles only affect elements with the generated random class names and do not conflict with your existing stylesheets.

Troubleshooting

If the widget fails silently, check your browser console for CSP violation reports. Common issues:

  • Blocked API calls: Add your tenant baseUrl to connect-src
  • Missing logo: Add your tenant baseUrl to img-src
  • Invisible overlay: Add 'unsafe-inline' to style-src
  • Authorization header stripped: a custom proxy in front of the tenant may be dropping the header — verify the bearer reaches /api/subscriber/me end-to-end
Copyright © 2026