MenuScript blocked by CSP

Troubleshooting

Script blocked by CSP

The exact Content-Security-Policy lines ProductLense needs, the hash for the inline queue stub, and the extra entries for proxied setups.

If your site sends a Content-Security-Policy header, the browser blocks anything the policy does not allow. When it blocks ProductLense, the console shows a message such as Refused to load the script 'https://api.productlense.app/a.js' because it violates the following Content Security Policy directive, and the Network tab shows the request as blocked.

The lines to add

ProductLense needs two things: loading the script, and sending events to the same origin.

Text
script-src 'self' https://api.productlense.app 'sha256-QAzHnEuzZp5XrZOqqqgzRNwN4NNwWRVKhMNT7BOq49o=';
connect-src 'self' https://api.productlense.app;
  • https://api.productlense.app in script-src allows a.js.
  • The sha256- hash allows the inline queue stub exactly as written in the install snippet: window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}. If you change one character or add whitespace inside the tag, the hash no longer matches. If you do not use the stub, leave the hash out.
  • connect-src allows the event requests to /api/e, and the visitor id request to /api/vid used by cross-domain links and checkout tracking.

Add these values to your existing directives. Do not add a second script-src: when a directive appears twice, browsers use only the first.

With a nonce instead of a hash

If your framework adds a nonce to inline scripts, give the stub the nonce and keep https://api.productlense.app in script-src:

HTML
<script nonce="{{ csp_nonce }}">window.productlense=window.productlense||function(){(window.productlense.q=window.productlense.q||[]).push(arguments)}</script>
<script defer data-site="SITE_ID" src="https://api.productlense.app/a.js"></script>

With 'strict-dynamic' in your policy, host allowlists are ignored; give the ProductLense tag the nonce too.

When the script is proxied

If you serve the script from your own domain and send events through it (see the proxy guides), 'self' covers both and https://api.productlense.app can be removed. If you serve only the script and keep data-api="https://api.productlense.app", keep https://api.productlense.app in connect-src.

Check it works

  1. Reload the page with the developer tools open. The console shows no CSP violation that mentions ProductLense.
  2. The Network tab shows a.js with status 200 and a POST to /api/e with status 204.
  3. Your visit appears on the Live page in the ProductLense dashboard.

    ↑ ↓ to move, Enter to open