SDK configuration
Complete reference for configuring the Sumidata JavaScript SDK. Control privacy, performance, and behaviour via data-* attributes and the runtime API.
01Basic installation
All configuration lives on the script tag as data-* attributes.
<script>
window.Sumidata = window.Sumidata || { push: function(m, a) { (this.q = this.q || []).push([m, a, Date.now()]) } };
</script>
<script
src="https://sdk.sumidata.io/loader.js"
data-project-id="YOUR_PROJECT_ID"
data-src="https://sdk.sumidata.io/sumidata.js"
async></script>Using a bundler (Vite, Vike, React, Next.js)? Install the package and call init() client-side instead - same SDK, no external script, CSP-friendly:
npm i @sumidata/browserimport Sumidata from '@sumidata/browser'
Sumidata.init({ projectId: 'YOUR_PROJECT_ID' })Sumidata.event(…), Sumidata.identify(…), Sumidata.purchase(…) - identical in effect to the push() form below. See the install guide for per-framework snippets.02Configuration options
Every option has a sensible default. Only set what you need to override.
data-project-id (required)
Your unique project identifier - a UUID - from the Dashboard (Settings → Projects).
data-project-id="YOUR_PROJECT_ID"data-src
URL of the SDK bundle the loader fetches - keep https://sdk.sumidata.io/sumidata.js from the install snippet. The chat widget and the heatmap page-capture bundle are loaded from the same place. Without the attribute the loader looks for /sumidata.js on your own site.
data-masking
Privacy masking level for session replays. Three levels:
fieldsOnly(default) - every form input value is recorded as asterisks.fieldsAndLabels- input values plus<label>text are masked. Placeholder andaria-labelattributes are not masked.dangerouslyNoMask- raw input values are recorded.
Password fields are always masked, at every level. Omitting the attribute means fieldsOnly; any other value logs a console warning and falls back to fieldsOnly.
data-masking="fieldsAndLabels"data-autocapture
Automatic event collection - pageviews, clicks, form submits, and scroll depth arrive in the dashboard without a single line of tracking code. Two values:
on(default) - the SDK sends$pageview(including SPA navigations),$autocapture_click,$autocapture_submit,$autocapture_scrolldepth milestones,$scroll_depth(the furthest depth of a pageview, sent once when the visitor navigates away or hides the tab), and$layout_signature(a page-layout fingerprint used by heatmaps) alongside your manual events.off- disables all automatic collection, including scroll depth. Manualpush('event', …)calls are unaffected.
Form field values are never collected by autocapture, in any data-masking mode. See Automatic events for the full event reference and the masking interaction.
data-autocapture="off"data-capture-network-bodies
XHR / Fetch requests are always captured (URL, method, status, timing); requests to the Sumidata API itself are skipped. This attribute controls whether request and response bodies are captured too - text bodies only, cut at 10 KB, with values under sensitive-looking keys (password, token, secret, auth, cookie, card, …) replaced by ***. Default: true; false keeps everything except the bodies.
data-capture-network-bodies="false"data-flush-interval
How often (ms) to flush buffered events, logs, and replay chunks to the server. Lower = more real-time, higher = better batching. Minimum reasonable value is 2000; below that the SDK spends more time on HTTP than on recording. Default: 10000.
POST /sdk/ingest requests - one carries events, logs, and network requests, the other carries replay chunks. When the tab is hidden, the SDK flushes immediately; on page unload it sends what is left via the Beacon API in pieces of up to 48 KB, and a replay batch larger than that is dropped.data-api-url
Base URL of the Sumidata API the SDK sends data to. Default: https://api.sumidata.io.
data-chat
Set to true to show the site chat widget; visitors' questions land in the Dashboard under Chats. The widget bundle is loaded from next to data-src. Default: off - any other value keeps the widget off. See Site chat for what visitors see and how replies reach them.
data-chat="true"03JavaScript API
push() calls are safe before the SDK has loaded - they queue until ready. getSessionId() is not queued.
Every runtime method is GTM-style: Sumidata.push('method', [arg1, arg2]). Direct calls like Sumidata.event(...) also work and are identical in effect. The full set of supported methods:
| Method | Args | Purpose |
|---|---|---|
event | [name, properties?] | Track a product event. (To record an order, use purchase.) |
purchase | [order] | Record an order, linked to the session, its replay, and the identified user. SDK 0.10.0 or later. See Conversions. |
identify | [userId] | Link the session to a stable user ID. Triggers session rotation if the user changed. |
reset | [] | Clear stored identity and rotate the session. Call on logout. |
identifyExperiment | [ [{ id, variant }, …] ] | Bind A/B variants to the current session. Sticky per session. |
Identify users
Links the current session - and every later session on this device - to your stable user ID. If a different user was previously identified on this device, the SDK automatically rotates the session to prevent history merge. Product events don't carry the user ID; orders recorded with purchase() do - an externalUserId on the order wins. Orders your server sends to POST /sdk/ingest get no user ID automatically - pass externalUserId on those yourself.
// At login
Sumidata.push('identify', ['user_123'])localStorage across tabs and OAuth redirects. A returning user is auto-identified when a new session starts - you don't need to call identify() again unless the ID changes.Reset on logout
Clears the stored user ID, rotates the session, and starts a fresh replay. Always call this on logout - otherwise the next user on the same device inherits the prior identity.
// On logout
Sumidata.push('reset', [])Track events
Fire any product event. Metadata keys with a leading underscore (_category, _feature, _surface) are extracted for AAARRR funnel tagging and do not show up in the stored payload. See Product events for the full taxonomy.
Sumidata.push('event', ['add_to_cart', {
productId: 'plan_pro_monthly',
_category: 'activation',
_feature: 'cart'
}])push('event', …) is for product events only. Revenue conversions (orderId + totalAmount) are not sent this way - every property except _category / _feature / _surface is stored in payload, so the conversion fields would never reach the conversion columns - the event is stored as an ordinary event and no error comes back. In the browser, record orders with push('purchase', [order]) instead - it waits in the queue if the SDK has not loaded yet; with the npm package, Sumidata.purchase(order) works too. The ingest API is for orders your server sends - see Conversions.Record a purchase
Send each order once, when it is placed (SDK 0.10.0 or later). The SDK sends it right away in its own request and attaches the project, the visitor's device, the session and its replay, and the identified user - an externalUserId on the order names a different buyer and wins. The call waits in the queue if the SDK has not loaded yet; a recorded order is silent, anything else is logged to the console. Fields and outcomes: Conversions.
Sumidata.push('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 }
]
}])Register A/B experiments
Bind one or more variant assignments to the current session. Sticky: the first assignment per (session, experimentId) wins. See Experiments for the integration guide.
Sumidata.push('identifyExperiment', [[
{ id: 'pricing-v3', variant: 'control' }
]])Read the session ID
Needed when your server sends an order to POST /sdk/ingest and it should be linked to the browser session and its replay, or when you register experiments from a backend feature-flag service. Orders recorded in the browser with purchase() don't need it - the SDK attaches the session and device itself. Returns null until init() has run - the ID exists before the server confirms the session. Read it right before you send: it changes when a new session starts. It is not a push() command and is not queued.
// npm package - there is no window global
import Sumidata from '@sumidata/browser'
const sessionId = Sumidata.getSessionId()// CDN snippet - the method exists only after the bundle has loaded
const sessionId = window.Sumidata?.getSessionId?.() ?? nullThere is no getter for the device ID. Read localStorage.getItem('sumidata_device_id') and send the zero UUID 00000000-0000-0000-0000-000000000000 when it returns null.
04Troubleshooting
Common issues and how to fix them.
Sessions not appearing
- Project ID mismatch - verify
data-project-idagainst the Dashboard - Ad blocker stripping the script - test in a fresh browser profile
- CSP blocking the SDK - see next section
Content Security Policy
script-src 'self' https://sdk.sumidata.io; connect-src 'self' https://api.sumidata.io;