Installing the widget
One script tag, what it costs, and how to confirm it is live.
The tag
<script async src="https://your-app/w.js" data-wq-key="wq_a7k9vd9pnw5imawe"></script>Put it before </body> on every page you want reportable. async matters: the
widget must never delay your page.
The key is public. It is embedded in a script tag on a website — treat it as an identifier, not a secret. What stops it being abused is allowed origins.
If a tag attribute is awkward in your setup, the key can ride on the URL instead:
<script async src="https://your-app/w.js?k=wq_a7k9vd9pnw5imawe"></script>What it costs your visitors
| File | Size | When it loads |
|---|---|---|
w.js | 8.4 kB gzip | On page load, async |
w-shot.js | 11 kB gzip | Only once someone starts a report |
The screenshot renderer and the selector generator live in the second file. A visitor who never reports a bug never downloads them.
For scale: a common performance budget is 170 kB of compressed JavaScript for a whole page on mobile. The widget is about 5% of that, and it is off the critical path.
Confirming it is live
The widget calls home once on boot to fetch its configuration. That first call is also the install check: the project's install page flips to ✓ Installed with a timestamp. Reload the page after deploying the tag.
If it stays on "Waiting for the first page load":
- Look for
w.jsin the Network tab. A 404 means thesrcis wrong. - A 404 from
/api/ingest/<key>means the key does not match a project. - Check the tag is actually in the deployed HTML, not just in your local build.
Single-page apps
Nothing to do. The widget reads location.href when a report is sent, so React
Router, Next.js and friends record whichever route the reporter was on.
One thing to know: the error prompt offers each failure once per route, not once per page load — an SPA never reloads, so "once per load" would mean once per session.
Content Security Policy
If your site sends a CSP, the widget needs three things:
script-src https://your-app;
connect-src https://your-app;
img-src data:;img-src data: is for the screenshot: it is built in the browser as a data URL
before being uploaded. Without it, reports still send, just without images.
Errors thrown before the widget loads
Because the tag is async, an error thrown in the first moments of page load can
happen before the capture buffers are installed. Those are not recorded. Every
error after boot is.