Content-Security-Policy
The directives the widget script needs if your site sends a Content-Security-Policy header. A blocked widget either doesn't appear or appears unstyled.
# The minimum for a page with a live oddsmatcher on it Content-Security-Policy: script-src 'self' https://oddsrelay.io; style-src 'self' 'unsafe-inline'; connect-src 'self' https://api.oddsrelay.io; # Calculator-only pages need no connect-src entry for us: # the calculators make no network request at all. # # 'unsafe-inline' only matters on engines without adoptedStyleSheets. # Current browsers use a constructed stylesheet, which CSP does not check.
Directives
| Directive | Why |
|---|---|
| script-srchttps://oddsrelay.io · Required | The bundle itself. One file, one origin, loaded once per page however many widgets are on it. |
| style-src'unsafe-inline' · Legacy browsers only | Only on older browsers without constructed stylesheets. Current browsers don't check it, so you can leave it out; on the older ones a policy without it leaves the widget rendered but completely unstyled. If your policy uses a nonce, 'unsafe-inline' is ignored: add the widget's style through style-src-elem 'unsafe-inline' or contact us. Nothing leaks out of the shadow root, so the permission cannot touch your page. |
| connect-srchttps://api.oddsrelay.io · Live board only | Only the oddsmatcher calls the feed, and it calls it from the visitor's browser directly. The calculators make no network request at all, so a calculator-only page needs nothing here. |
Not needed: img-src, font-src, frame-src and 'unsafe-eval'. The script loads no images, fonts or iframes and never evaluates code.
Symptoms and fixes
| What you see | Cause and fix |
|---|---|
| The widget renders, but unstyled: stacked plain text, no card, no table.Console: Refused to apply inline style because it violates the following Content Security Policy directive: "style-src …" | An engine without adoptedStyleSheets fell back to a <style> element, and your policy blocks it. Add 'unsafe-inline' to style-src. If you use a nonce-based policy, the nonce disables the 'unsafe-inline' fallback, so add the widget's style through style-src-elem 'unsafe-inline' or contact us before shipping. |
| Nothing renders at all. The host div stays empty and no error appears.Console: Refused to load the script 'https://oddsrelay.io/widgets/…' because it violates … "script-src …" | The bundle was never allowed to load. Add https://oddsrelay.io to script-src. If there is no console error at all, the script was probably blocked by a consent manager instead, not by CSP. |
| The board shows its reconnecting or empty state permanently. Calculators are fine.Console: Refused to connect to 'https://api.oddsrelay.io/…' because it violates … "connect-src …" | Only the live board calls the feed; the calculators never do, which is why they look unaffected. Add https://api.oddsrelay.io to connect-src. |
| A JavaScript error appears in your monitoring as the bare string "Script error." with no message or stack.Console: Script error. | The script tag lost its crossorigin="anonymous" attribute, so the browser reports the error opaquely. Restore crossorigin="anonymous" on the script tag. The bundle is served with Access-Control-Allow-Origin: *, so it costs nothing. |
A widget that renders nothing with no console message at all is usually not a CSP problem: see consent managers and install and troubleshooting.