This reference documents @umap360/sdk-web 1.5.x. See
Installation to add it to your app.
The client
The package's default export is a singleton client — import it once and call its methods anywhere:
import umap360 from '@umap360/sdk-web';
// The named export `umap360` is the same instance. `Client` is the class, if you
// ever need to construct your own.All public types (UMAPConfig, UserTraits, EventProperties, EventContext,
…) are exported for TypeScript users, alongside advanced utilities —
maskUrlQueryParams, DEFAULT_MASK_QUERY_PARAMS, and MASK_PLACEHOLDER (the
URL-redaction helpers), plus Storage, ContextBuilder, EventQueue, and the
ID/fingerprint generators.
Every tracking method throws if called before init().
init()
umap360.init(config: UMAPConfig): void;Initialises the SDK. writeKey and apiHost are required; everything else has a
default. init() is idempotent — a second call is a no-op. It throws if
writeKey or apiHost is missing, or if apiHost is a non-HTTPS production host.
Configuration
| Option | Type | Default | Description |
|---|---|---|---|
writeKey | string | — | Required. Your uk_live_ write key. |
apiHost | string | — | Required. Edge-function base URL; the SDK appends eventPath. |
eventPath | string | '/v1-batch' | Path appended to apiHost for the events POST. Set '' to POST directly to apiHost. |
consentPath | string | '/v1-consent' | Path appended to apiHost for consent records. |
flushAt | number | 20 | Send once this many events are queued. |
flushInterval | number | 10000 | Send queued events after this many milliseconds. |
maxRetries | number | 3 | Retry attempts after the first failed send (up to 4 total). 0 = a single attempt. Only 5xx/network errors are retried. |
sessionTimeout | number | 30 | Session idle timeout, in minutes. |
trackPages | boolean | true | Auto-track pageviews, including SPA route changes. |
trackClicks | boolean | false | Auto-track clicks on links and buttons. |
captureLinkQueryParams | boolean | false | Keep the query + hash of an auto-tracked link's URL. Off = origin + path only (tokens/OTPs stripped). |
maskQueryParams | string[] | [] | Extra param keys to redact in captured URLs, on top of the built-in denylist. |
enableFingerprinting | boolean | false | Compute a device fingerprint. Off by default (DPDP/GDPR); gate it behind consent. |
respectDNT | boolean | false | Disable the SDK when the browser sends Do Not Track. |
respectGPC | boolean | true | Disable the SDK when the browser asserts Global Privacy Control. |
consentMode | 'advisory' | 'enforced' | 'advisory' | 'enforced' makes consent.deny('analytics') actually stop capture. |
storagePrefix | string | 'umap360_' | localStorage key prefix. |
debug | boolean | false | Verbose console logging. |
onError | (error, droppedEvents) => void | — | Called when events are permanently dropped (a 4xx rejection, or queue-cap eviction). |
Identity & event methods
Each method optionally takes a callback: (error?, response?) => void that fires
once the event's batch is delivered (or rejected). On success, response is the
ingestion result, e.g. { success: true, processed: 1, failed: 0 }.
identify()
umap360.identify(userId: string, traits?: UserTraits, callback?): void;Associates the current visitor with a known user ID and merges traits (e.g.
email, name, plan). The ID and traits are persisted, so the user stays
identified across reloads. A missing or sentinel ID (e.g. '', 'null',
'[object Object]') is rejected via the callback instead of being sent.
umap360.identify('user_8f2c', { email: 'ada@example.com', plan: 'pro' });track()
umap360.track(event: string, properties?: EventProperties, callback?): void;Records a custom event with arbitrary properties.
umap360.track('Order Completed', { order_id: 'ORD-456', total: 4999 });page()
umap360.page(name?: string, properties?: PageProperties, callback?): void;
umap360.page(properties?: PageProperties, callback?): void;Records a pageview. title, url, path, referrer, and search are
auto-filled from the current document (sensitive query/hash values
redacted) and can be overridden via properties. With
trackPages on (the default) this fires automatically — call it manually only
for views the SDK can't detect.
screen()
umap360.screen(name: string, properties?: ScreenProperties, callback?): void;The mobile-web equivalent of page(), for app-style screen views. name is
required.
alias()
umap360.alias(userId: string, previousId?: string, callback?): void;Links two distinct identities — its previousId (distinct from the current
userId/anonymousId) is folded into the userId profile by a real server-side
merge. For the common anonymous→known case, prefer identify (same anonymousId
- a
userId); a self-alias is handled by ordinary resolution.previousIddefaults to the current user ID, or the anonymous ID if none. An illegaluserId/previousIdis rejected via the callback rather than sent. See Identity stitching.
group()
umap360.group(groupId: string, traits?: Record<string, unknown>, callback?): void;Associates the current user with an account, company, or workspace.
reset()
umap360.reset(): void;Clears the current identity (call it on logout): it drops the user ID and traits, mints a fresh anonymous ID, starts a new session, and clears the prior identity's referrer chain, device fingerprint, and stored attribution (UTMs + click IDs) so nothing leaks to the next user on a shared device.
Utility methods
| Method | Returns | Description |
|---|---|---|
getAnonymousId() | string | The current anonymous ID (anon_<uuid>). |
getUserId() | string | null | The current user ID, or null if not identified. |
flush(callback?) | Promise<void> | Send all queued events immediately. |
ready() | Promise<void> | Resolves once async init (e.g. fingerprint) has settled. Await it before a flush() right after init(). |
setEnabled(enabled) | void | Master switch. Disabling clears the queue and drops further events. |
isEnabled() | boolean | Whether capture is currently enabled. |
setDebug(debug) | void | Toggle verbose logging at runtime. |
use(plugin) | void | Register a plugin. |
Consent
The consent namespace records per-purpose consent decisions. Decisions are
written to localStorage immediately (so checks are synchronous and work
offline) and sent best-effort to the /v1-consent
endpoint for a server-side audit trail —
which records decisions but does not yet enforce them at ingestion.
umap360.consent.grant('analytics');
umap360.consent.deny('analytics');
if (umap360.consent.hasConsent('analytics')) {
umap360.track('Newsletter Signup');
}| Method | Description |
|---|---|
grant(purpose) | Record consent for a purpose. |
deny(purpose) | Record a denial for a purpose. |
hasConsent(purpose) | Synchronously read the latest local decision (boolean). |
showBanner(config?) | Reserved for a built-in banner. |
Advisory vs enforced (the consentMode option):
'advisory'(default) — decisions are recorded and queryable viahasConsent(), but the SDK does not auto-suppress tracking. You decide what to gate.'enforced'—deny('analytics')additionally disables capture (clears the queue and drops future events);grant('analytics')re-enables it. A denial recorded in a previous session is honoured on the nextinit().
In enforced mode, grant('analytics') re-enables capture unconditionally, so
it overrides a manual setEnabled(false). A Do Not Track / GPC opt-out is not
liftable this way — those gates run during init(), before the consent namespace
exists — so don't treat setEnabled(false) as a consent-proof kill switch.
showBanner() has no built-in UI yet
consent.showBanner() is a stub — there is no bundled banner component in
1.5.x. Render your own consent UI and call grant() / deny() from it.
Fingerprinting is the one purpose enforced regardless of consentMode: a
fingerprint is only attached when hasConsent('fingerprinting') is true, and the
server strips it otherwise.
Automatic data collection
- Pageviews (
trackPages, default on) — the first pageview plus SPA route changes (the SDK wrapshistory.pushState/replaceStateand listens forpopstate). - Clicks (
trackClicks, opt-in) — captureselement_type,element_text,element_id,element_class, andlink_urlfor links/buttons. Sensitive fields (password/email/tel/card/OTP) and bare card/SSN text are omitted. Adddata-umap-no-captureto an element (or any ancestor) to skip it, anddata-umap-track="My Event"to name the emitted event. - Context — every event carries an enriched
contextobject:page,campaign(UTMs + click IDs likegclid/fbclid),device,browser,os,screen,network,session,locale/timezone, and (when enabled)fingerprint. See Event ingestion for the full wire shape. - Cross-domain identity — if a visitor arrives with a
?aid=<anonymous_id>query param and has no ID stored on this origin yet, the SDK adopts it, so the same anonymous identity carries across your domains. The value must be a validanon_<uuid>(the formgetAnonymousId()returns) or it is ignored.
Privacy & security
- HTTPS enforced —
init()throws on a non-HTTPS productionapiHost. - GPC honoured by default (
respectGPC: true) and DNT opt-in (respectDNT) — when the browser asserts either signal,init()disables the SDK. - URL redaction — the values of sensitive params (
token,access_token,refresh_token,password,secret,otp,code,email,api_key,session,signature, and more) are replaced with<redacted>in capturedurl/search/referrer— in both the query string and the#fragment— whileutm_*and click IDs are preserved. Extend the denylist withmaskQueryParams. - Fingerprinting is off by default and, when enabled, is gated by
consent.hasConsent('fingerprinting').
Delivery: batching & retries
- Events are queued and sent when
flushAt(20) is reached or everyflushInterval(10s);flush()forces a send. - The in-memory queue is capped at 100 events — on overflow the oldest are
evicted and reported to
onError. - A
4xxresponse is permanent: those events are dropped, passed toonError, and logged — this includes429, so the SDK does not honourRetry-Afteror retry rate-limited requests today (only the server emitsRetry-After; see Errors & rate limits). A5xxor network error is retried with jittered exponential backoff (1s base, capped at 30s) up tomaxRetries. - Queued events are persisted across reloads (7-day TTL) and de-duplicated across browser tabs.
- The server rejects a
trackevent whose name exceeds 200 characters (event name too long); very large property payloads are warn-only, not rejected — see Event volume.
Plugins
use(plugin) registers a plugin to hook the event pipeline:
umap360.use({
name: 'redact-emails',
beforeTrack(event) {
// return null to drop the event, or a modified event to forward it
return event;
},
});Hooks that fire:
| Hook | Signature | When |
|---|---|---|
initialize | (client) => void | On use() if already initialised, otherwise during init(). |
beforeTrack | (event) => event | null | Before each event is queued; return null to drop it. |
onIdentify | (userId, traits) => void | After identify(). |
onReset | () => void | After reset(). |
afterTrack is declared but not wired
The UMAPPlugin type also declares an afterTrack hook, but the SDK does not
invoke it in 1.5.x — registering one has no effect today. Use beforeTrack.
How methods map to the REST API
Every method emits an event with a type on POST /v1-batch — the same contract
as the REST API:
| Method | Event type |
|---|---|
track() | track |
identify() | identify |
page() | page |
screen() | screen |
alias() | alias |
group() | group |
So whether you use the SDK or call the endpoint directly, your event model is the same.
Last updated 2026-06-09