Common issues
Fixes for the problems integrators hit most often when embedding the widget.
This page collects the issues we see most often and how to resolve them. Each fix is something you can check from the host page without contacting support. If none of these match, see Contact & support.
The widget doesn't appear
The script loads but nothing renders. Work through these in order:
- Check the target element exists. The widget mounts into the element matched by
data-target(default#inboard). Make sure a<div id="inboard"></div>is present in the DOM before the widget initialises. If you inject the placeholder later, callInboard.init()yourself once it's in the DOM. - Check the embed key. A typo or a key from a different environment produces an
embed_key_not_founderror. Confirm the key on the project page matches thedata-embed-keyvalue exactly. - Open the console. The widget logs a single grouped error if it can't mount. A
404oninboard-widget.jsmeans the scriptsrcis wrong; a CORS orconnect-srcerror points at Content Security Policy. - Confirm the script actually ran. If you load the script with
deferbut inject it dynamically,deferis ignored — the widget may try to mount before the DOM is ready. UseInboard.init()explicitly in that case.
Wrong platform detected
The widget guesses the installer's platform from the page, and sometimes guesses wrong (for example, a headless storefront that doesn't look like Shopify).
- Force the platform with
data-platform="shopify"(or the relevant slug) on the script tag, orplatform: "shopify"inInboard.init(). This skips auto-detection entirely. - Let the installer choose. If you can't know the platform ahead of time, leave detection on — the widget always offers a platform picker as a fallback so the installer can correct it themselves.
- See Multi-platform support for how detection ranks candidates.
Variables aren't filling in
You passed data-variables but the guide still shows empty placeholders.
- Check the JSON is valid.
data-variablesmust be a valid JSON string — mismatched quotes are the usual culprit. Single-quote the attribute and double-quote the JSON:data-variables='{"domain":"acme.com"}'. - Check the names match. Variable names are case-sensitive and must match the names defined in the dashboard exactly (the
{{name}}tokens). - Secrets are never echoed back. A variable defined as
secretis substituted into the rendered guide in the browser and never sent to our servers — so it won't appear in any network response. That's expected. See Variable handling.
Verification keeps failing
An installer completes a step but the verification check reports failure.
- DNS and HTTP checks have propagation lag. A DNS record or newly deployed snippet can take minutes to become visible to our checkers. The widget retries automatically; the installer can also re-run the check manually.
- The check may be too strict. If installers reliably complete a step but the automated check fails, switch that step to self-report in the dashboard. See the verification methods in Configuration.
- Confirm the target is publicly reachable. Server-side checks (
POST /v1/verify) run from our infrastructure, so a staging URL behind auth or an internal hostname will always fail.
Styles look wrong or clash with my site
The widget renders inside a Shadow DOM, so your page CSS cannot leak in and the widget's CSS cannot leak out.
- If the widget looks unstyled, your CSP may be blocking its stylesheet — allow
style-src 'unsafe-inline'(see CSP). - To change colours, radius, or fonts, set theme tokens via
data-stylerather than writing CSS against the widget's internals — see Custom styling.
Getting 429 Too Many Requests
You're over the per-key rate limit. Limits are listed in the API reference. Respect the Retry-After header and back off — the widget does this automatically, so this usually only appears when calling the API directly.
Still stuck?
Grab the requestId from the failing response (every API error includes one) and include it when you reach out — it lets us find the exact request in our logs.