> ## Documentation Index
> Fetch the complete documentation index at: https://docs.outlit.ai/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Outlit is the product that monitors customers and completes approved customer work. The customer context interfaces are the API, CLI, MCP server, and skills. Canonical references on this site: /api-reference/introduction for API concepts and authentication, /openapi.json for the public API contract, /cli/overview for the CLI, /ai-integrations/mcp for MCP. Prefer the `outlit` CLI or MCP tools for agent tasks; cite page sources when answering.

# npm package

> Install the Outlit Browser SDK with npm for explicit tracking configuration.

The Outlit Browser SDK records landing URLs, browser referrers, UTM parameters, and anonymous site activity. Identify the same browser visitor with an email when it becomes available to connect that history to later product events and conversions.

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install --save @outlit/browser
  ```

  ```bash pnpm theme={null}
  pnpm add @outlit/browser
  ```

  ```bash yarn theme={null}
  yarn add @outlit/browser
  ```

  ```bash bun theme={null}
  bun add @outlit/browser
  ```
</CodeGroup>

## Initialization

Initialize the tracker once at app startup, typically in your entry point:

```typescript theme={null}
import outlit from '@outlit/browser'

outlit.init({
  publicKey: 'pk_your_public_key',
  // Optional configuration
  trackPageviews: true,
  trackForms: true,
  trackEngagement: true,
  flushInterval: 5000, // ms
})
```

### Configuration options

<ParamField path="publicKey" type="string" required>
  Your organization's public key from [**Settings → Website Visitors**](https://app.outlit.ai/settings/workspace/website-visitors).
</ParamField>

<ParamField path="apiHost" type="string" default="https://app.outlit.ai">
  The API endpoint for sending events. Override for self-hosted or proxy setups.
</ParamField>

<ParamField path="trackPageviews" type="boolean" default="true">
  Automatically track pageviews on navigation.
</ParamField>

<ParamField path="trackForms" type="boolean" default="true">
  Automatically capture form submissions.
</ParamField>

<ParamField path="formFieldDenylist" type="string[]">
  Additional field names to exclude from form capture.
</ParamField>

<ParamField path="flushInterval" type="number" default="5000">
  How often to send batched events (in milliseconds).
</ParamField>

<ParamField path="autoTrack" type="boolean | &#x22;auto&#x22;" default="&#x22;auto&#x22;">
  Controls when tracking starts. `"auto"` (default) asks the Outlit edge endpoint whether the visitor's region requires opt-in consent: tracking enables automatically outside the EEA, UK, and Switzerland, and stays off in those regions or when the region can't be determined. The check fails closed — on a network error or timeout, tracking stays off. `true` enables tracking immediately on init; `false` waits for `enableTracking()`. A persisted opt-in or opt-out decision always takes precedence, and nothing is written to cookies or localStorage until tracking is enabled.
</ParamField>

<ParamField path="autoIdentify" type="boolean" default="true">
  Automatically identify users when they submit forms containing an email field. Extracts email and name using field name heuristics. Set to `false` to call `identify()` manually. See [Auto-identify](/concepts/identity-resolution#auto-identify) for details.
</ParamField>

<ParamField path="trackEngagement" type="boolean" default="true">
  Track engagement metrics (active time on page). Emits engagement events on page exit and SPA navigation capturing how long users actively engaged with each page.
</ParamField>

<ParamField path="idleTimeout" type="number" default="30000">
  Idle timeout in milliseconds for engagement tracking. After this period of no user interaction, the user is considered idle and active time stops accumulating.
</ParamField>

<ParamField path="trackCalendarEmbeds" type="boolean" default="true">
  Track booking events from calendar embeds (Cal.com, Calendly). Fires a calendar event when bookings are detected.
</ParamField>

## Consent management

The default `autoTrack: "auto"` mode already keeps tracking off for visitors in the EEA, UK, and Switzerland (or when the region is unknown). Have your consent management platform call `enableTracking()` when the user accepts — that call is what records opt-in consent.

To wait for `enableTracking()` instead — unless a previous opt-in is already stored — initialize with `autoTrack: false`:

```typescript theme={null}
import outlit from '@outlit/browser'

// Initialize with tracking off until consent
outlit.init({
  publicKey: 'pk_your_public_key',
  autoTrack: false, // Don't track until consent
})

// When user accepts cookies/tracking
function onConsentAccepted() {
  outlit.enableTracking()
}

// When user declines
function onConsentDeclined() {
  outlit.disableTracking()
}
```

### Check tracking status

```typescript theme={null}
import { isTrackingEnabled } from '@outlit/browser'

if (isTrackingEnabled()) {
  console.log('Tracking is active')
}
```

## API reference

### `outlit.init(options)`

Initialize the tracker. Must be called before other methods.

```typescript theme={null}
import outlit from '@outlit/browser'

outlit.init({ publicKey: 'pk_xxx' })
```

### `outlit.track(eventName, properties?)`

Track a custom event.

```typescript theme={null}
outlit.track('feature_used', {
  feature: 'export',
  format: 'csv',
  rowCount: 1500
})
```

<ParamField path="eventName" type="string" required>
  A descriptive name for the event. Use `snake_case`.
</ParamField>

<ParamField path="properties" type="Record<string, string | number | boolean | null>">
  Additional data to attach to the event.
</ParamField>

### `outlit.identify(options)`

Identify the current visitor. Links their anonymous history to a known profile.

```typescript theme={null}
outlit.identify({
  email: 'jane@acme.com',
  userId: 'usr_12345',
  customerId: 'cust_123', // Your app's account/workspace/customer ID
  traits: {
    name: 'Jane Doe',
    role: 'Engineering Manager',
  },
  customerTraits: {
    plan: 'enterprise'
  }
})
```

<ParamField path="email" type="string">
  The visitor's email address. Primary identifier.
</ParamField>

<ParamField path="userId" type="string">
  Your internal user ID (from Supabase, Auth0, etc.).
</ParamField>

<ParamField path="traits" type="Record<string, string | number | boolean | null>">
  Additional properties about the user.
</ParamField>

<ParamField path="customerId" type="string">
  Your system-owned customer/account/workspace ID. Send this when the visitor belongs to a known account.
</ParamField>

<ParamField path="customerTraits" type="Record<string, string | number | boolean | null>">
  Additional properties about the customer/account profile.
</ParamField>

### `outlit.setUser(identity)`

Set the current user identity. Ideal for SPA applications where you know the user's identity after authentication. Can be called before tracking is enabled—the identity is queued and applied when `enableTracking()` is called.

```typescript theme={null}
// After user logs in
outlit.setUser({
  email: 'jane@acme.com',
  userId: 'usr_12345',
  customerId: 'cust_123', // Your app's account/workspace/customer ID
  traits: {
    name: 'Jane Doe',
  },
  customerTraits: {
    plan: 'pro'
  }
})
```

<Info>
  Both `setUser()` and `identify()` link the visitor to a known profile. The difference is `setUser()` can be called before tracking is enabled (identity is queued), while `identify()` requires tracking to be enabled first.
</Info>

### `outlit.clearUser()`

Clear the current user identity. Call this when the user logs out.

```typescript theme={null}
// On logout
outlit.clearUser()
```

### Activation event

Track your value milestone as an ordinary event once it succeeds:

```typescript theme={null}
outlit.track('onboarding_completed', { flow: 'onboarding', step: 'completed' })
```

Choose this event as your activation event in Outlit. The first matching event records activation once for each eligible resolved person and company, independently. Billing status comes from verified integrations such as Stripe. See [Customer journey](/concepts/customer-journey).

### `outlit.getInstance()`

Get the singleton tracker instance.

```typescript theme={null}
const tracker = outlit.getInstance()
const visitorId = tracker.getVisitorId()
```

### `outlit.enableTracking()`

Enable tracking after consent. This is the call a consent tool makes to grant opt-in — it's only needed when `autoTrack: false` was set, or when `autoTrack: "auto"` resolved to a region that requires consent.

```typescript theme={null}
import outlit, { enableTracking } from '@outlit/browser'

// Initialize with autoTrack: false
outlit.init({ publicKey: 'pk_xxx', autoTrack: false })

// Later, after consent
enableTracking()
// or
outlit.enableTracking()
```

### `outlit.disableTracking()`

Disable tracking and flush any pending events. Use this when a user declines or revokes consent.

```typescript theme={null}
// When user declines or revokes consent
outlit.disableTracking()
```

### `outlit.isTrackingEnabled()`

Check if tracking is currently enabled.

```typescript theme={null}
import { isTrackingEnabled } from '@outlit/browser'

if (isTrackingEnabled()) {
  // Tracking is active
}
```

## TypeScript support

The package is written in TypeScript and includes full type definitions:

```typescript theme={null}
import outlit, {
  type OutlitOptions,
  type BrowserTrackOptions,
  type BrowserIdentifyOptions,
  type UserIdentity,
} from '@outlit/browser'

// Full type safety
outlit.init({
  publicKey: 'pk_xxx',
  trackPageviews: true,
})

outlit.track('purchase_completed', {
  orderId: 'ord_123',
  amount: 99.99,
  currency: 'USD',
})
```

## Framework examples

### Next.js (App Router)

```tsx theme={null}
// app/providers.tsx
'use client'

import { useEffect } from 'react'
import outlit from '@outlit/browser'

export function OutlitInit() {
  useEffect(() => {
    outlit.init({ publicKey: process.env.NEXT_PUBLIC_OUTLIT_KEY! })
  }, [])

  return null
}

// app/layout.tsx
import { OutlitInit } from './providers'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <OutlitInit />
        {children}
      </body>
    </html>
  )
}
```

### Vue.js

```typescript theme={null}
// main.ts
import { createApp } from 'vue'
import App from './App.vue'
import outlit from '@outlit/browser'

outlit.init({ publicKey: import.meta.env.VITE_OUTLIT_KEY })

createApp(App).mount('#app')
```

```vue theme={null}
<!-- Component.vue -->
<script setup>
import outlit from '@outlit/browser'

function handleClick() {
  outlit.track('button_clicked', { id: 'cta' })
}
</script>
```

### Svelte

```typescript theme={null}
// +layout.ts
import outlit from '@outlit/browser'

outlit.init({ publicKey: import.meta.env.VITE_OUTLIT_KEY })
```

```svelte theme={null}
<!-- Component.svelte -->
<script>
import outlit from '@outlit/browser'

function handleClick() {
  outlit.track('button_clicked', { id: 'cta' })
}
</script>
```

## Advanced usage

### Manual flush

Force immediate sending of queued events:

```typescript theme={null}
await outlit.getInstance().flush()
```

### Shutdown

Shut down gracefully the tracker (flushes remaining events):

```typescript theme={null}
await outlit.getInstance().shutdown()
```

### Access visitor ID

Get the current visitor's ID for server-side correlation (returns `null` until tracking is enabled):

```typescript theme={null}
const visitorId = outlit.getInstance().getVisitorId()

// Send to your backend
fetch('/api/correlate', {
  body: JSON.stringify({ visitorId, data: '...' })
})
```

## Engagement tracking

Engagement tracking captures how long users actively spend on each page. It's enabled by default and works automatically.

### How it works

* **Active time** is tracked when the page is visible and the user is interacting (mouse movement, clicks, scrolling, typing)
* **Idle detection** pauses active time after 30 seconds of no interaction (configurable via `idleTimeout`)
* **Engagement events** are automatically sent when the user navigates to a new page or leaves the site

### Engagement data

Each engagement event includes:

| Property | Description |
| - | - |
| `activeTimeMs` | Time in milliseconds the user was actively engaged |
| `totalTimeMs` | Total wall-clock time on the page |
| `sessionId` | Session ID for grouping page views |

### Disabling engagement tracking

```typescript theme={null}
outlit.init({
  publicKey: 'pk_xxx',
  trackEngagement: false, // Disable engagement tracking
})
```

## Next steps

<CardGroup cols={2}>
  <Card title="React integration" icon="react" href="/tracking/browser/react">
    Use the React provider and hooks
  </Card>

  <Card title="Server-side tracking" icon="server" href="/tracking/server/nodejs">
    Track events from your backend
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.