

The browser SDK (`@sazabi/browser`) instruments a web frontend and sends telemetry to Sazabi. It captures errors, navigation, clicks, network calls, and console output, and lets you emit custom events and logs. It authenticates with a **public key**, which is write-only and safe to ship in your bundle.

For server-side reads and writes against the API, use the [TypeScript SDK](/reference/sdk) with a secret key instead.

## Install [#install]

```bash
npm install @sazabi/browser
```

## Initialize [#initialize]

Import the `register` entrypoint first — before any other import — so the SDK installs its instrumentation before other code captures the native `fetch`, `XMLHttpRequest`, or history APIs. Then call `init`:

```ts filename="app-entry.ts"
import "@sazabi/browser/register";
import { init } from "@sazabi/browser";

init({
  intakeUrl: import.meta.env.VITE_SAZABI_INTAKE_URL,
  serviceName: "my-web-app",
});
```

`init` is idempotent. `init` options:

| Option            | Required | Purpose                                                                                                                                                                                                                                            |
| ----------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `intakeUrl`       | Yes      | Your log source's intake URL, from [**Settings > Log streams**](https://app.sazabi.com/settings/log-source-providers) (or `sazabi log-sources create sazabi_browser_sdk`). It embeds a write-only public key, so it is safe to ship in the bundle. |
| `publicKey`       | No       | Only needed when `intakeUrl` points at a proxy you run that carries no key.                                                                                                                                                                        |
| `serviceName`     | Yes      | Logical name of the frontend app. Stamped on every event.                                                                                                                                                                                          |
| `serviceVersion`  | No       | App version (for example a git SHA).                                                                                                                                                                                                               |
| `environment`     | No       | Deployment environment, such as `production`.                                                                                                                                                                                                      |
| `network`         | No       | Network-capture and trace-context options.                                                                                                                                                                                                         |
| `console`         | No       | Console-capture options (defaults to `error` and `warn`).                                                                                                                                                                                          |
| `input`           | No       | Field-interaction capture options (never captures values).                                                                                                                                                                                         |
| `pointer`         | No       | Pointer-episode options: `capture`, `sampleIntervalMs` (default 1000), `partialIntervalMs` (default 10000).                                                                                                                                        |
| `consent`         | No       | A function returning a boolean or promise; capture stays dormant until it resolves `true`.                                                                                                                                                         |
| `flushIntervalMs` | No       | Batch flush cadence.                                                                                                                                                                                                                               |
| `maxQueuedEvents` | No       | Maximum buffered events before the oldest are dropped.                                                                                                                                                                                             |

Get the public key from [**Settings > Public keys**](https://app.sazabi.com/settings/api). Never use a secret key in the browser.

## Identify and reset [#identify-and-reset]

```ts
import { identify, reset } from "@sazabi/browser";

// After sign-in:
identify("user_123", { plan: "pro" });

// On sign-out:
reset();
```

`identify` attaches a client-asserted user identity (and optional traits) to subsequent events. `reset` clears the identity and rotates the session so a shared device does not thread activity into the previous user's timeline.

## Custom events and logs [#custom-events-and-logs]

```ts
import { addEvent, log } from "@sazabi/browser";

addEvent("checkout_started", { cartValue: 42 });
log("WARN", "cache lookup failed", { requestId: "req_9" });
```

`addEvent(name, attributes?)` emits a custom event into the session stream. `log(severity, message, metadata?)` emits an application log line with session context; `severity` is one of `DEBUG`, `INFO`, `WARN`, or `ERROR`.

## Flush and shutdown [#flush-and-shutdown]

```ts
import { flush, shutdown } from "@sazabi/browser";

await flush(); // Force-send queued events now.
await shutdown(); // Flush, then remove all instrumentation.
```

`flush` sends any queued events immediately. `shutdown` flushes and removes the SDK's instrumentation, reversing `init` and the `register` import.

## What the SDK captures automatically [#what-the-sdk-captures-automatically]

After `init`, the SDK captures, with session context attached:

* **Errors** — uncaught exceptions and unhandled promise rejections, with stack traces.
* **Navigation** — page loads and single-page-app route changes.
* **Pointer episodes** — one event per mouse, touch, or pen contact, from down to up, with coordinates, distance, duration, pressure, concurrent contacts, and a once-per-second path sample. Long contacts emit partial events every ten seconds. When the browser takes over a contact, such as a touch scroll, the event ends at that point with `app.pointer.ended_by: cancel`.
* **Clicks** — taps derived from pointer episodes, plus keyboard and script clicks, by privacy-safe selector and label. It also flags rapid repeat clicks and clicks with no response.
* **Input interactions** — one event per field engagement (by field label). It never captures keystrokes or values.
* **Network calls** — `fetch` and `XMLHttpRequest` calls with method, status, and duration. By default it injects a W3C `traceparent` header on same-origin requests so frontend and backend telemetry correlate.
* **Console** — mirrors `console.error` and `console.warn` by default (the original console output is untouched).
* **Lifecycle** — the tab going to the background and coming back.

The SDK never captures request or response bodies, input values, or keystrokes. Mark an element subtree with `data-sazabi-mask` to suppress its text capture.

## Further reading [#further-reading]

<Cards>
  <Card title="Instrument your frontend" href="/guides/instrument/frontend" description="The guide to instrumenting a web frontend." />

  <Card title="Public keys" href="/guides/administer/keys" description="Manage the public key the SDK uses." />
</Cards>
