SDKs / Browser capture agent

Browser capture agent

One script tag captures console, network timing and user steps — and transmits nothing until a report is triggered.

Requires Any modern browserPackage capture.js (script tag)Source on GitHub →

Before you start

Where your InsightRecorder runs
The base URL every call goes to — http://localhost:8080 when you are running it locally, your own hostname otherwise.
A capture token
Settings → Integrations. It goes in your page source and is public by design, like an error-tracker DSN: it permits submitting a capture and nothing else. Do not reuse a server API key here.
  1. 01

    Add the script tag

    Both tags, in this order: redact.js is what masks PII in the browser before anything is transmitted. Your capture token is on Settings → Integrations — public by design, like an error-tracker DSN.

    <script src="https://api.insightrecorder.example.com/static/js/redact.js"></script>
    <script
      src="https://api.insightrecorder.example.com/static/js/capture.js"
      data-token="YOUR_CAPTURE_TOKEN"
      data-auto="error">
    </script>
  2. 02

    Trigger a report

    From your own "Report a bug" button. The buffered console, network and steps go with it. Severity defaults to P2.

    const ack = await insightRecorder.report("Checkout breaks after clicking Buy");
    // -> { id: "0192…", ref: "BUG-7F3A2C" }
    
    await insightRecorder.report("Payment API down", "P0");
  3. 03

    Auto-report uncaught errors (optional)

    data-auto="error" files a report on an uncaught error or unhandled rejection, with the session that led to it already attached.

    <script src="…/capture.js" data-token="…" data-auto="error"></script>
  4. 04

    Tune the rolling buffer (optional)

    The agent keeps only a rolling in-memory window of recent console/network — nothing is stored before a report. data-buffer-minutes sets that window (default 3; 0 keeps the count cap only), so a long-lived tab carries just the run-up to the bug.

    <script src="…/capture.js" data-token="…" data-buffer-minutes="3"></script>
  5. 05

    Verify it is working

    Load a page carrying both tags and file a report from the browser console. A ref comes back synchronously, so you know it reached the server instead of hoping it did.

    // In devtools, on a page with the agent loaded:
    await insightRecorder.report("insightrecorder smoke test");
    // -> { id: "0192…", ref: "BUG-7F3A2C" }

    Then look for the line at /app/logs and the report at /app/bugs.

    If nothing shows up

    No ref, and a network error in devtools? The capture token is wrong, or the page's origin cannot reach the server. A 429 means the per-IP capture rate limit (10 burst, 1/s) is tripping — expected if you re-run this in a loop.

Before you ship

  • Send never blocks: a full queue drops and counts (shipper.Dropped()).
  • Delivery failures are silent unless you set WithErrorHandler — a logging SDK that logs its own failures recurses.
  • Request bodies, headers, cookies and query strings are never captured.
  • Already on OpenTelemetry? Point an OTLP exporter at /api/logs/otlp instead; the SDK exists for the panic→bug workflow, which OTel does not cover.
PROMPT Install the Browser capture agent SDK with an AI agent
Raw .md

Paste this into a coding agent running inside your project, or point the agent at /docs/prompts/javascript directly. It is self-contained: the agent needs no prior knowledge of InsightRecorder.

# Install and wire the InsightRecorder capture SDK (browser)

Paste this into a coding agent (Claude Code, Cursor, …) running inside your web
application's repository. It is written to be self-contained — the agent needs
no prior knowledge of InsightRecorder.

---

You are working in a web application. Install and wire the InsightRecorder browser
capture SDK so users can report bugs that arrive with real context (console
output, network timing, and the steps that led to the failure) instead of a
screenshot and a sentence.

**Context you need:**

- The SDK is a single vanilla-JS file served by the InsightRecorder deployment at
  `<INSIGHTRECORDER_URL>/static/js/capture.js`. There is **no npm package, no build
  step, and no framework requirement**.
- It is configured entirely through `data-` attributes on the script tag.
- `data-token` is a **capture token** found in the InsightRecorder UI under
  *Settings → Integrations*. It is public by design — like an error-tracker
  DSN — and grants nothing beyond submitting a capture. It is **not** an API
  key and must not be confused with one.

**Steps:**

1. Add the script tag to the application's root HTML document — the one shared
   by every page (`index.html`, the base layout/template, or the framework's
   document component, e.g. `app/layout.tsx`, `_document.tsx`,
   `application.html.erb`, `base.html`). Add it once, not per page:

   ```html
   <script src="https://<INSIGHTRECORDER_URL>/static/js/redact.js"></script>
   <script
     src="https://<INSIGHTRECORDER_URL>/static/js/capture.js"
     data-token="<CAPTURE_TOKEN>"
     data-auto="error"
   ></script>
   ```

   - **Both tags, in this order.** `redact.js` is what masks PII in the browser
     before anything is transmitted. Omitting it does not disable redaction —
     the agent falls back to its strict built-in policy — but it does mean the
     workspace's configured rules never reach the page.

   - `data-auto="error"` makes uncaught errors and unhandled promise
     rejections report themselves automatically. Omit the attribute if you want
     manual reporting only.
   - `data-endpoint` is optional; it defaults to the script's own origin.

2. Put `<INSIGHTRECORDER_URL>` and `<CAPTURE_TOKEN>` in this project's existing
   environment/config mechanism rather than hard-coding them, and interpolate
   them in the template the way this repo already does for other public
   values. If the framework distinguishes public from server-only variables
   (`NEXT_PUBLIC_`, `VITE_`, …), use the **public** prefix — this value is
   meant to reach the browser.

3. Add a "Report a bug" affordance wherever this application already puts
   secondary user actions (a footer link, a help menu, a support widget). Wire
   it to:

   ```js
   const ack = await window.insightRecorder.report("short description of the problem");
   // ack -> { id, ref }  e.g. ref "BUG-7F3A2C" — show it to the user
   ```

   Optionally pass a severity as the second argument: `"P0"`, `"P1"`, `"P2"`
   (default), or `"P3"`.

4. If this application has a Content-Security-Policy, add the InsightRecorder origin
   to both `script-src` (to load the file) and `connect-src` (the agent POSTs
   the report there). Do not add `unsafe-inline` — it is not needed.

**Rules — do not violate these:**

- Do **not** add the script tag more than once per page load.
- Do **not** attempt to capture or forward form values, passwords, tokens, or
  request bodies. The agent deliberately never reads input/textarea values and
  never captures network bodies or headers — preserve that. Everything
  submitted is additionally PII-redacted server-side.
- Do **not** treat the capture token as a secret to be hidden, and equally do
  **not** substitute an API key (`crk_…`) for it: they are different
  credentials with different powers.
- Do **not** vendor a copy of `capture.js` or `redact.js` into this repository. Load them from
  the InsightRecorder deployment so it stays current.

**Verify before you finish:**

1. The application builds and runs.
2. Open a page, run `window.insightRecorder.report("smoke test")` in the browser
   console, and confirm it resolves with an object containing `id` and `ref`.
3. Confirm the bug appears in InsightRecorder under `/app/bugs`, and that its
   console/network timeline is populated.
4. If you set `data-auto="error"`, trigger a deliberate uncaught error and
   confirm a second report arrives.
5. Report what you changed and where the script tag lives.

If anything is ambiguous — which file is the shared document, how public
config is exposed, whether a CSP exists — inspect the repository and follow
what is already there.