@sonderhq/sdk
v0.1.3
Published
Sonder browser SDK: semantic autocapture, friction primitives (rage/dead clicks), and friction-time state probes. Masked at the edge, run-length encoded, no pixels or DOM capture.
Maintainers
Readme
@sonderhq/sdk
The browser SDK for Sonder — Sentry for UX friction. It captures a compact, human-readable semantic ribbon of what users did ("clicked Save changes in Billing"), detects friction primitives (rage clicks, dead clicks, error clicks), and on friction only, records a small state probe of what the user actually saw on screen (visible error text, spinner, empty list, disabled button). No pixels, no DOM dumps, no session video.
Everything is masked at the edge: emails, phone numbers, card numbers, SSNs, and input values never leave the browser in the clear. Consecutive repeats are run-length encoded before transport, so a click storm is one event with a count.
Quickstart
The fastest path is the wizard — it detects your framework, injects the provider, and verifies events arrive:
npx sonder-init <write_key>Or install manually:
npm install @sonderhq/sdkimport { initSonder } from "@sonderhq/sdk";
initSonder({
writeKey: "snd_pk_your_write_key",
buildId: import.meta.env.VITE_SONDER_BUILD_ID // release stamping, optional
});That is the whole integration. Autocapture is on by default; there is nothing to instrument. Custom events are optional sharpeners, never a prerequisite:
window.sonder?.track("checkout_completed", { plan: "team" });
window.sonder?.identify("user-123", { plan: "trial" });React
import { SonderProvider } from "@sonderhq/sdk/react";
export function App({ children }) {
return (
<SonderProvider writeKey="snd_pk_your_write_key">
{children}
</SonderProvider>
);
}Next.js (App Router)
// app/sonder-provider.tsx
"use client";
import { SonderProvider } from "@sonderhq/sdk/next";
export function SonderClientProvider({ children }) {
return (
<SonderProvider writeKey="snd_pk_your_write_key">
{children}
</SonderProvider>
);
}Wrap {children} in your root layout with <SonderClientProvider>.
npx sonder-init does both edits for you.
Options
| Option | Default | What it does |
| --- | --- | --- |
| writeKey | required | Workspace write key (client-safe, write-only). |
| ingestUrl | Sonder cloud | Collector endpoint; point at your own region/proxy. |
| buildId | sonder-js@<version> | Release stamp; lets Sonder mark issues resolved/regressed per deploy. |
| flushIntervalMs | 5000 | Batch flush cadence. |
| maxBatchSize | 25 | Flush early when the buffer reaches this size. |
| sampleRate | 1 | Fraction of events kept (0–1). |
| autoCapture | true | Set false to send only explicit track calls. |
What is collected — and what is not
Collected: element labels/roles/selectors/sections, parametrized routes
(/settings/:id, never raw ids), friction events with a structured state probe,
and event counts. Not collected: input values, raw HTML, screenshots, pixel or
DOM recordings, mousemove/scroll streams. Masking runs in the SDK and again
server-side. Mark anything extra with data-sonder-mask to force-mask it, or
data-sonder-name to give an element a stable label.
