Plain JavaScript
Any site, any framework, no build step: one ES-module script tag. This is also the path for Vue, Angular, and Svelte until their first-class providers land.
The script tag
<!-- Before </head>. No build step required; any site, any framework. -->
<script type="module">
import { initSonder } from "https://cdn.jsdelivr.net/npm/@sonderhq/sdk@0.1/+esm";
initSonder({ writeKey: "snd_pk_your_write_key", buildId: "site@v42" });
</script>
Running npx sonder-init <write_key> in a folder with an
index.html makes these edits for you and verifies events flow.
Bundling instead? npm install @sonderhq/sdk and call
initSonder from your entry module; the package is pure ESM with zero
runtime dependencies.
Using the client
initSonder returns the client and also exposes it as
window.sonder, which is the convenient handle outside a module system:
window.sonder.track("newsletter_signup");
window.sonder.identify("user-8f31", { plan: "free" });
Getting good labels
Autocapture names elements by meaning: aria-label, then visible text,
then name/placeholder, then the associated
<label>. Two attributes give you control:
<!-- Everything inside a data-sonder-mask subtree reports [masked] as its
label, and its text never appears in state probes. -->
<section data-sonder-mask>
<h2>Account balance</h2>
<p>$12,340.55</p>
<button>Withdraw</button> <!-- captured as: click "[masked]" (button) -->
</section>
<!-- Give an unstable or icon-only control a stable, human name. -->
<button data-sonder-name="Close checkout">×</button>
data-sonder-name: a stable, human name for icon-only or generated controls.data-sonder-mask: force-mask a subtree; its text never reaches labels or state probes.
Framework roadmap
| Framework | Status |
|---|---|
| React, Next.js | shipped |
| Plain JS / any framework via script tag | shipped |
| Vue, Angular, Svelte providers | roadmap · script tag works today |
| React Native | roadmap |