@sumidata/browser
| Install | |
|---|---|
npm install @sumidata/browser |
|
| Latest Version: | 0.10.0 |
| License: | Proprietary |
| Last Updated: | Oct 1, 2026 |
| Links: | npm |
@sumidata/browser
Session replay, console/error capture, and product events for the browser. Same SDK that ships
on the CDN <script> tag — packaged for Next.js, Vite, Nuxt, and any bundler/CSP-strict setup.
Install
npm install @sumidata/browser
Quickstart
import Sumidata from '@sumidata/browser'
Sumidata.init({ projectId: 'YOUR_PROJECT_ID' }) // starts recording
That is enough to get a replay in your dashboard. CommonJS:
const Sumidata = require('@sumidata/browser')
Sumidata.init({ projectId: 'YOUR_PROJECT_ID' })
Call
init()in the browser only. It toucheswindow/document, so in SSR frameworks run it client-side (see the framework guides below). Importing the package on the server is safe; callinginit()on the server is not.
Configuration
Sumidata.init(config):
| Option | Type | Default | Notes |
|---|---|---|---|
projectId |
string |
— | Required. Your Sumidata project id (a UUID). |
apiUrl |
string |
https://api.sumidata.io |
Base URL of the Sumidata API the SDK sends to. |
flushInterval |
number |
10000 |
Batch flush interval, ms. |
masking |
'fieldsOnly' | 'fieldsAndLabels' | 'dangerouslyNoMask' |
'fieldsOnly' |
Input masking level. |
captureNetworkBodies |
boolean |
true |
Capture request/response bodies of network calls. |
autocapture |
'on' | 'off' | boolean |
'on' |
Automatic interaction events. |
chat |
'true' | 'false' | boolean |
false |
Site chat widget. Does not appear with the package: the chat bundle reads its config from the CDN loader and, without it, logs [Sumidata] Chat: no config found. For the widget use the CDN snippet with data-chat="true". |
sdkUrl |
string |
— | URL of sumidata.js, e.g. https://sdk.sumidata.io/sumidata.js. The heatmap page-capture bundle is loaded from the same place; without it page capture for heatmaps is off. |
API
| Method | Purpose |
|---|---|
init(config) |
Start the session and recording. Returns a Promise. |
identify(userId) |
Link the session to a user; rotates the session on user change. |
event(name, properties?) |
Track a product event. |
purchase(order) |
Record an order (0.10.0 or later). See Purchases. |
identifyExperiment([{ id, variant }]) |
Register A/B assignments (idempotent). |
reset() |
Clear identity and start a fresh session (call on logout). |
getSessionId() |
Current session id, or null. A new session can start at any time — read it when you send it, don't cache it at page load. |
shutdown() |
Stop recording and flush. |
push(method, args?) |
Command form: push('event', ['plan_selected']) is the same as event('plan_selected'). Takes identify, event, purchase, identifyExperiment, reset. |
Sumidata.identify('user-42')
Sumidata.event('plan_selected', { plan: 'pro' })
Purchases
Record each order with purchase() (SDK 0.10.0 or later), once, when the order is placed:
Sumidata.purchase({
orderId: 'ord-1001',
totalAmount: 100,
currency: 'USD',
items: [
{ productId: 'shirt', productName: 'Shirt', quantity: 1, unitPrice: 40 },
{ productId: 'shoes', productName: 'Shoes', quantity: 1, unitPrice: 60 },
],
})
The SDK sends the order at once, in its own request, together with your project, the visitor's
device and session (so the order is linked to the session and its replay) and the buyer. The
buyer is the id you passed to identify(); an externalUserId on the order names a different
buyer and wins. A call made before init() resolves waits in the SDK queue. With the CDN
<script> snippet use the command form — it also waits if the SDK has not loaded yet. The wait
needs the queue line that opens the install snippet; check that your page has it before the loader
tag, or a call made before the SDK loads throws in your code:
<script>
window.Sumidata = window.Sumidata || { push: function(m, a) { (this.q = this.q || []).push([m, a]) } };
</script>
Then:
window.Sumidata.push('purchase', [{
orderId: 'ord-1002',
totalAmount: 40,
currency: 'USD',
items: [{ productId: 'shirt', productName: 'Shirt', quantity: 1, unitPrice: 40 }],
}])
| Field | Type | Notes |
|---|---|---|
orderId |
string | number |
Required, non-empty. 1001 and '1001' are the same order. |
totalAmount |
number |
What the buyer paid, after discount. |
currency |
string |
ISO 4217, e.g. USD. |
discountAmount |
number |
|
couponCode |
string |
|
isPrimarySale |
boolean |
|
timestamp |
number |
Epoch ms. Default: the moment of the call. |
items |
array |
Products: productId (required, non-empty string), productName, productCategory, quantity (whole, from 1, default 1), unitPrice (from 0, default 0). |
externalUserId |
string |
The buyer. Overrides identify(). |
utmSource … utmContent |
string |
Campaign. Empty ones are filled from the buyer's latest campaign, otherwise the device's. |
purchase() returns nothing and never throws. A recorded order is silent; anything else is logged
to the console with the [Sumidata] prefix:
| Console message | Meaning |
|---|---|
Purchase not sent: orderId must be a non-empty string or a number / Purchase not sent: purchase() expects an order object |
Nothing was sent. |
Purchase <id> was already recorded — not counted again |
The project already has this orderId — a reload of the thank-you page is safe. A stored order cannot be corrected by resending. |
Purchase <id> rejected — <field>: <reason> |
The server refused the order, e.g. product fields at the order level instead of items[]. |
Purchase <id>: <n> item(s) dropped: <reason> |
The order was recorded without the invalid products. |
Purchase <id> not accepted — the project's monthly session quota is used up |
Nothing was stored. |
Purchase <id> not delivered — call purchase() again to resend |
The browser reported the request as failed. The SDK does not resend on its own. A page that navigates away right after the call can log this too, while its request still delivers the order — calling again then reports it as already recorded. |
Call purchase() once per order: two calls with the same orderId at the same moment can both be
stored. There is no way to delete a single order — send test orders to a separate project.
event() cannot record a purchase: it moves every property into the event payload, so an
orderId sent through it never counts.
Orders sent from your backend still go to POST https://api.sumidata.io/sdk/ingest — field reference, limits and response
shapes: sumidata.io/docs/conversions/server-ingest.
Every method is error-isolated: a failure inside the SDK is logged with a [Sumidata] prefix and
never throws into your application.
Framework guides
- Next.js (App Router)
- Vite / React
- Nuxt
- Google Tag Manager
Version History
| Version | Released | License |
|---|---|---|
| 0.10.0 | Proprietary | |
| 0.7.0 | Proprietary | |
| 0.3.1 | Proprietary | |
| 0.3.0 |