A bug report button on your site does one thing well: it catches problems at the moment users hit them, on the page where they hit them, instead of hoping someone digs up your support email later. This guide walks through adding one with BugDump — from the one-line setup to the configuration options that matter in production.
Option 1: the script tag (recommended)
Add one line to your HTML, ideally near the end of the head or body:
<script src="https://bugdump.com/sdk/latest.js" async data-api-key="your-api-key"></script>
That's the entire integration. The data-api-key attribute triggers auto-initialization — no JavaScript to write, no build step, no framework adapter. A floating bug button appears in the corner of every page the tag is on.
The async attribute matters: it keeps the SDK from blocking page parsing or DOMContentLoaded. The widget initializes as soon as the script arrives, but your page never waits for it. The entry script is around 118 KB (about 28 KB gzipped); heavier pieces like the DOM-screenshot library and the session replay module are separate chunks that load only when actually used, so pages that never need them never download them.
Because the widget lives in a Shadow DOM, your site's CSS can't break it and its styles can't leak into your layout — a real concern with older embed-style widgets.
Option 2: npm
If you'd rather have the SDK as a bundled, versioned dependency:
npm install @bugdump/sdk
import { Bugdump } from '@bugdump/sdk';
const bugdump = Bugdump.init({ apiKey: 'your-api-key' });
You get full TypeScript definitions, which makes the configuration surface discoverable in your editor. This route fits apps where every third-party script goes through the bundle and dependency review.
Option 3: manual init with a command queue
For sites that load the script asynchronously but need to call the SDK immediately — before the download finishes — use the stub pattern:
<script>
window.bugdump = window.bugdump || function () {
(window.bugdump.q = window.bugdump.q || []).push(arguments);
};
</script>
<script src="https://bugdump.com/sdk/latest.js" async></script>
<script>
bugdump('init', { apiKey: 'your-api-key' });
bugdump('identify', { email: 'user@example.com' });
</script>
Until the SDK arrives, bugdump(...) queues calls; when it loads, the queue replays in order. Without the stub, an inline call would race the async download and throw. This is the same pattern analytics snippets use, and it's the right choice when init options depend on runtime state — the logged-in user, a feature flag, the page type.
Configuration worth setting on day one
The defaults are sensible, but a few options deserve a deliberate decision:
theme—'light','dark', or'auto'(follows the OS). If your app has its own theme toggle, match it.Identify your users. For apps with accounts, call
bugdump('identify', { email })after login. Reports arrive with the reporter attached, and you skip asking users to type their email into the widget.bubbleText— a dismissible teaser next to the button ("Found a bug?"). Useful during a beta, when you actively want reports; dismissal is remembered per browser.hideButton— hide the floating button and open the widget from your own UI (a "Report a problem" item in your help menu) viabugdump('open'). This keeps the page chrome clean while keeping reporting one click away.translations— override any widget string. If your product isn't in English, the report button shouldn't be either.
Filtering noise before it costs you
The widget keeps rolling buffers of console entries and network requests so every report carries recent history. On pages with chatty third-party scripts — analytics beacons, feature-flag pollers, health checks — that history fills with noise, and noise evicts signal.
Configure consoleFilter and networkFilter to drop irrelevant entries before they enter the buffers. Two benefits: the entries you care about survive until the report is sent, and third-party traffic you'd rather not store never leaves the browser. If you enable captureNetworkBodies, filtering becomes a privacy control as well as a hygiene one — decide explicitly which endpoints' bodies belong in a bug report.
Pitfalls to avoid
Don't gate the button behind a form. Every mandatory field costs reports. The description is the only thing worth requiring; environment, console, network, and replay data are collected automatically, which is the whole point.
Mind your Content-Security-Policy. A strict CSP needs the SDK's origin in
script-src— and note the SDK loads its optional chunks from the same origin, so allowing only the entry file isn't enough.If you self-host or proxy the SDK, copy all of its files, not just the entry. The entry resolves its screenshot and replay chunks relative to its own URL; serving it alone leaves those features silently broken while the rest of the widget appears to work.
Don't ship it only to production. Put the widget on staging too, with a separate project key. Your team becomes the first user of your own reporting flow, and configuration mistakes surface before real users see them.
Verifying it works
After installing, file a report yourself: click the button, take a screenshot, annotate it, and send. Then open the report in the dashboard and check that console logs, network requests, and environment data all came through — and that identify attached your account if you set it up. The whole verification takes two minutes, and it's the same experience your users will have.
From here, reports flow into a kanban board, forward to your team chat or issue tracker through integrations, and — if you connect the MCP server — become something your AI coding assistant can investigate directly.