JavaScript SDK reference

The complete public API of oakdata-js: init options, event capture, identity, super properties, groups, consent, and getters.

Everything below lives on the default export of oakdata-js. Import it once and call methods anywhere - calls made before init() are queued and replayed, so ordering never matters.

import
ts
import oak from 'oakdata-js'

oak.init(key, options)

Boots the tracker. Call it once with your project key. Returns the live API instance (also stored on window.oak), or null during SSR / prerender. Calling init twice is a no-op - the first call wins.

init
ts
oak.init(process.env.NEXT_PUBLIC_OAK_KEY!, {
  api_host: process.env.NEXT_PUBLIC_OAK_HOST,
})

The options object accepts:

OptionTypeDescription
api_hoststringBase URL events are sent to. Defaults to the current origin - set it to https://oakdata.co, or to your own subdomain when using the managed reverse proxy.
autocapturebooleanAutocapture clicks, form submits, input changes, and copies. Default true. See autocapture.
capture_pageviewbooleanAutomatically fire $pageview on load and on every client-side route change. Default true.
capture_inputsbooleanInclude input and form-field values in autocapture events (passwords are never captured). Default false - only field names and whether they were filled.
outboundbooleanFire $outbound_click when a link to another domain is clicked. Default true.
declarativebooleanHonor data-oak-event / data-oak-prop-* attributes for markup-only event tracking. Default true. See autocapture.
session_timeout_msnumberInactivity window before a new session starts. Default 1800000 (30 minutes).
respect_dntbooleanHonor the browser's Do Not Track signal. When true and DNT is enabled, the tracker disables itself entirely. Default false.
property_denyliststring[]Property keys stripped from every event before it's sent - useful for scrubbing PII or noisy fields. Default [].
before_sendfn | fn[]A hook (or array of hooks) run on each event just before it's queued. Return the event to send it, or null/false to drop it. Hooks run in order; the first to drop wins.
loaded(oak) => voidCalled once, after the tracker is fully wired up.
debugbooleanLog internal activity to the console. Default false.

before_send example

Drop events from a noisy path and redact a property:

before_send
ts
oak.init(KEY, {
  before_send: (event) => {
    if (event.context.page.path.startsWith('/admin')) return null
    if (event.properties.email) event.properties.email = '[redacted]'
    return event
  },
})

Content Security Policy

If your site sends a Content-Security-Policy header, allow your api_host in connect-src - or the browser silently blocks every event:

CSP
text
connect-src 'self' https://oakdata.co;

If you load the SDK from a CDN via a script tag, also allow that origin in script-src (e.g. https://esm.sh or https://cdn.jsdelivr.net). The npm install needs no script-src change.

Capturing events

oak.capture(name, properties?)

Records a custom event. oak.track() is an exact alias. Names are free-form strings; properties are any JSON-serializable object.

capture
ts
oak.capture('signup_completed', { plan: 'pro', seats: 5 })

oak.page(properties?)

Manually records a $pageview. Rarely needed - with capture_pageview on (the default), pageviews fire automatically. Use it for virtual pageviews, e.g. a modal you treat as a screen.

page
ts
oak.page({ section: 'onboarding' })

Identity

See identity resolution for how anonymous and identified activity are stitched together.

oak.identify(userId, traits?)

Links the current anonymous visitor to a known user id, merging their prior anonymous activity into the identified profile. Optionally pass traits to set in the same call. Afterwards, getDistinctId() returns the user id.

identify
ts
oak.identify('user_8f3a', { email: 'sam@acme.com', plan: 'pro' })

oak.alias(newId)

Records an alias linking the current distinct id to newId and switches the stored id to it. Use it to merge two ids you control - for example, tying a server-generated id to the browser's anonymous id.

alias
ts
oak.alias('user_8f3a')

oak.set(traits)  /  oak.setOnce(traits)

Sets persistent traits on the current person. set overwrites existing keys; setOnceonly writes keys that aren't already present - good for first-touch attributes like signup date.

set
ts
oak.set({ plan: 'enterprise' })
oak.setOnce({ first_seen_plan: 'free', signup_source: 'docs' })

Super properties

Super properties are merged into every subsequent event and persisted in local storage, so they survive reloads.

oak.register(props)  /  oak.unregister(key)

register
ts
oak.register({ app_version: '2.4.0', workspace: 'acme' })
oak.unregister('workspace')

Groups

oak.group(type, id, traits?)

Associates the current person with a group - an account, company, or any other entity many users share. Subsequent events carry the group association.

group
ts
oak.group('company', 'acme-co', { name: 'Acme', plan: 'enterprise' })

Consent & lifecycle

oak.reset()

Clears all stored ids, traits, super properties, groups, and the queued event buffer, then generates a fresh anonymous id. Call it on sign-outso the next visitor on a shared device isn't attributed to the previous user.

reset
ts
oak.reset()

oak.opt_out()  /  oak.opt_in()

opt_out() stops all sending, clears the pending queue, and persists the choice across reloads. opt_in() re-enables tracking. Use these to back a consent banner.

consent
ts
if (userDeclinedAnalytics) oak.opt_out()
else oak.opt_in()

oak.flush(useBeacon?)

Sends queued events immediately instead of waiting for the next batch. Returns a promise. Pass true to use navigator.sendBeacon, which survives page unload (the SDK already does this internally on pagehide).

flush
ts
await oak.flush()

Getters

MethodTypeDescription
oak.getDistinctId()string | nullThe current distinct id - the identified user id once identify() has run, otherwise the anonymous id. null before init().
oak.getSessionId()string | nullThe current session id. null before init().

The instance returned by oak.init() (and window.oak after boot) also exposes getFirstTouch() and getLastTouch() for first- and last-touch attribution.

Autocaptured events

With autocapture and capture_pageview on, the SDK emits these without any code from you:

EventTypeDescription
$pageviewautoPage load + SPA route change.
$clickautoAny click, with the resolved actionable element.
$rage_clickautoThree or more rapid clicks in the same spot.
$dead_clickautoA click that produced no DOM change or navigation.
$outbound_clickautoA click on a link to another host.
$form_submitautoA form submission (password fields excluded).
$input_changeautoAn input/select/textarea value change (value masked by default).
$copyautoText copied to the clipboard.

See autocapture & data attributes for opting elements in or out, and events & properties for the properties attached to every event.

Performance & error events

The SDK also watches page performance and uncaught errors out of the box - no setup, and independent of autocapture. A slipped Core Web Vital or an error spiking on one route shows up right alongside behavioural data.

EventTypeDescription
$web_vitalautoA Core Web Vital reading - LCP, INP, or CLS- reported as it's finalized for the page.
$errorautoAn uncaught JavaScript error, with its message, source, and stack.
$unhandled_rejectionautoA promise rejection with no handler.
$performance / $paintautoNavigation and paint timing for the page, captured at pageview time.
$long_taskautoA main-thread task long enough to block interaction.
$page_leaveautoFired when the visitor leaves the page, closing out engagement time.

Errored sessions are flagged in the sessions and replaylists, so you can jump from “something broke” to the exact recording.