# JavaScript SDK reference > The complete public API of oakdata-js: init options, event capture, identity, super properties, groups, consent, and getters. Source: https://oakdata.co/docs/sdk/reference --- 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: | Name | Type | Description | | --- | --- | --- | | `api_host` | string | Base 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](https://oakdata.co/docs/sdk/proxy). | | `autocapture` | boolean | Autocapture clicks, form submits, input changes, and copies. Default `true`. See [autocapture](https://oakdata.co/docs/sdk/autocapture). | | `capture_pageview` | boolean | Automatically fire `$pageview` on load and on every client-side route change. Default `true`. | | `capture_inputs` | boolean | Include input and form-field *values* in autocapture events (passwords are never captured). Default `false` - only field names and whether they were filled. | | `outbound` | boolean | Fire `$outbound_click` when a link to another domain is clicked. Default `true`. | | `declarative` | boolean | Honor `data-oak-event` / `data-oak-prop-*` attributes for markup-only event tracking. Default `true`. See [autocapture](https://oakdata.co/docs/sdk/autocapture). | | `session_timeout_ms` | number | Inactivity window before a new session starts. Default `1800000` (30 minutes). | | `respect_dnt` | boolean | Honor the browser's Do Not Track signal. When `true` and DNT is enabled, the tracker disables itself entirely. Default `false`. | | `property_denylist` | string[] | Property keys stripped from every event before it's sent - useful for scrubbing PII or noisy fields. Default `[]`. | | `before_send` | fn \| 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) => void | Called once, after the tracker is fully wired up. | | `debug` | boolean | Log 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](https://oakdata.co/docs/quickstart/script), 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](https://oakdata.co/docs/concepts/identity) 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; `setOnce` only 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-out** so 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 | Name | Type | Description | | --- | --- | --- | | `oak.getDistinctId()` | string \| null | The current distinct id - the identified user id once identify() has run, otherwise the anonymous id. null before init(). | | `oak.getSessionId()` | string \| null | The current [session](https://oakdata.co/docs/concepts/sessions) 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: | Name | Type | Description | | --- | --- | --- | | `$pageview` | auto | Page load + SPA route change. | | `$click` | auto | Any click, with the resolved actionable element. | | `$rage_click` | auto | Three or more rapid clicks in the same spot. | | `$dead_click` | auto | A click that produced no DOM change or navigation. | | `$outbound_click` | auto | A click on a link to another host. | | `$form_submit` | auto | A form submission (password fields excluded). | | `$input_change` | auto | An input/select/textarea value change (value masked by default). | | `$copy` | auto | Text copied to the clipboard. | See [autocapture & data attributes](https://oakdata.co/docs/sdk/autocapture) for opting elements in or out, and [events & properties](https://oakdata.co/docs/concepts/events) 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. | Name | Type | Description | | --- | --- | --- | | `$web_vital` | auto | A Core Web Vital reading - `LCP`, `INP`, or `CLS` - reported as it's finalized for the page. | | `$error` | auto | An uncaught JavaScript error, with its message, source, and stack. | | `$unhandled_rejection` | auto | A promise rejection with no handler. | | `$performance / $paint` | auto | Navigation and paint timing for the page, captured at pageview time. | | `$long_task` | auto | A main-thread task long enough to block interaction. | | `$page_leave` | auto | Fired when the visitor leaves the page, closing out engagement time. | Errored sessions are flagged in the [sessions](https://oakdata.co/docs/api/rest) and [replay](https://oakdata.co/docs/concepts/replay-privacy) lists, so you can jump from “something broke” to the exact recording.