# Browser SDK

> Complete reference for the TraceKit browser SDK. Automatic error capture, breadcrumb tracking, and distributed tracing for any JavaScript application.

- Canonical: https://tracekit.dev/docs/frontend/browser-sdk

## Quick Start

Install the package and initialize the SDK in your application entry point.

```bash
npm install @tracekit/browser
```

```ts
import { init, captureException } from '@tracekit/browser';

init({
  apiKey: 'your-api-key',
  release: '1.0.0',
  environment: 'production',
});

try {
  riskyOperation();
} catch (err) {
  captureException(err as Error);
}
```

Calling `init()` automatically captures uncaught errors, unhandled promise rejections, console errors, network requests, DOM interactions, and navigation changes as breadcrumbs. Read on for configuration and advanced usage.

For browser pageviews and goals, see [Analytics setup](/docs/analytics).

## Live visitor presence

Browser `0.3.0` sends live presence when analytics is enabled.
It sends the first signal after initialization.
It then sends one signal every 27 to 33 seconds while the page is visible.
SPA navigation updates the current page without starting a new visitor session.
Hidden pages stop regular signals and send one hidden-state update.

Presence uses a tab identifier in `sessionStorage`.
The SDK does not request browser location access.
Set `enabled: false` until your consent policy permits analytics collection.
Disabled clients create no presence storage, timers, channels, or requests.

See [Live Analytics](/docs/analytics/live) for the online count and visitor globe.

## Configuration Reference

Pass a `TracekitBrowserConfig` object to `init()`. Only `apiKey` is required.

### Annotated Configuration

```ts
init({
  // Required
  apiKey: 'your-api-key',

  // Identity & environment
  release: '1.0.0',                    // undefined by default
  environment: 'production',            // default: 'production'
  serviceName: 'my-app',               // default: 'browser-app'

  // Sampling & control
  sampleRate: 1.0,                      // 0.0-1.0, default: 1.0
  enabled: true,                        // default: true
  debug: false,                         // default: false

  // Data limits
  maxBreadcrumbs: 100,                  // default: 100

  // Endpoint
  endpoint: 'https://app.tracekit.dev', // default

  // Distributed tracing
  tracePropagationTargets: [            // default: [] (same-origin only)
    'https://api.example.com',
  ],

  // Event filtering
  beforeSend: (event) => {
    if (event.message?.includes('ResizeObserver')) return null;
    return event;
  },

  // Addon integrations (e.g., session replay)
  addons: [],

  // Integration toggles (all default: true)
  integrations: {
    globalError: true,    // window.onerror + unhandledrejection
    console: true,        // console.* breadcrumbs
    fetch: true,          // fetch() breadcrumbs + traceparent
    xhr: true,            // XHR breadcrumbs + traceparent
    dom: true,            // click event breadcrumbs
    navigation: true,     // pushState/popState breadcrumbs
  },
});
```

### Options Reference

| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `apiKey` | string | required | Your TraceKit project API key. |
| `release` | string | undefined | Release version. Maps to service.version in OTLP. Required for release tracking and source map resolution. |
| `environment` | string | `"production"` | Deployment environment name for dashboard filtering. |
| `sampleRate` | number | 1.0 | Error event sample rate from 0.0 (none) to 1.0 (all). |
| `enabled` | boolean | true | Master switch to enable/disable the SDK entirely. |
| `debug` | boolean | false | Enable verbose console logging for SDK internals. |
| `serviceName` | string | `"browser-app"` | Service name for OTLP resource attributes. |
| `maxBreadcrumbs` | number | 100 | Maximum breadcrumbs to buffer. Oldest are dropped when full. |
| `endpoint` | string | `"https://app.tracekit.dev"` | TraceKit ingest endpoint. Override for self-hosted. |
| `tracePropagationTargets` | (string \| RegExp)[] | [] | URL patterns for distributed tracing. Matching requests receive a traceparent header. |
| `beforeSend` | (event) => event \| null | undefined | Callback to modify or filter events. Return null to drop. |
| `addons` | Integration[] | [] | Additional integrations like session replay. |
| `integrations` | object | all true | Toggle built-in integrations. See table below. |

### Integration Toggles

All built-in integrations default to `true`. Disable individual integrations by setting them to `false`.

| Toggle | Default | What It Does |
| --- | --- | --- |
| `globalError` | true | Captures window.onerror and unhandledrejection events. |
| `console` | true | Records console.error and console.warn as breadcrumbs. |
| `fetch` | true | Records fetch() as breadcrumbs and injects traceparent headers. |
| `xhr` | true | Records XMLHttpRequest as breadcrumbs and injects traceparent headers. |
| `dom` | true | Records click events on interactive elements as breadcrumbs. |
| `navigation` | true | Records pushState/popState navigation as breadcrumbs. |

## API Reference

All functions are exported from `@tracekit/browser`. The SDK must be initialized with `init()` before calling other functions.

### `init(config: TracekitBrowserConfig): void`

Initialize the SDK. Must be called once, as early as possible in your application entry point. Creates the singleton client, installs integrations, and begins capturing errors.

```ts
import { init } from '@tracekit/browser';
init({ apiKey: 'your-api-key', release: '1.0.0' });
```

### `captureException(error: Error, context?: Record): string`

Manually capture an error. Returns the event ID (UUID). The optional context parameter merges extra data into the event.

```ts
import { captureException } from '@tracekit/browser';

try {
  JSON.parse(invalidJson);
} catch (err) {
  const eventId = captureException(err as Error, { input: invalidJson });
  console.log('Reported as:', eventId);
}
```

### `captureMessage(message: string, level?: SeverityLevel): string`

Send a message event. Returns the event ID. Default level is "info". Use for non-error events you want to track.

```ts
import { captureMessage } from '@tracekit/browser';

captureMessage('User completed onboarding', 'info');
captureMessage('Payment retry limit exceeded', 'warning');
```

### `setUser(user: UserContext | null): void`

Set or clear the current user context. User data is attached to all subsequent events. Pass null to clear on logout.

```ts
import { setUser } from '@tracekit/browser';

// After login
setUser({ id: 'user-123', email: 'alice@example.com', username: 'alice' });

// On logout
setUser(null);
```

### `setTag(key: string, value: string): void`

Set a tag on the current scope. Tags are indexed and searchable in the dashboard. Attached as span attributes.

```ts
import { setTag } from '@tracekit/browser';

setTag('tenant', 'acme-corp');
setTag('feature_flag', 'new-checkout-v2');
```

### `setExtra(key: string, value: any): void`

Set extra data on the current scope. Extra data is not indexed but provides additional debug context.

```ts
import { setExtra } from '@tracekit/browser';

setExtra('cart_items', 3);
setExtra('last_action', 'add_to_cart');
```

### `addBreadcrumb(crumb: Breadcrumb): void`

Manually add a breadcrumb. Breadcrumbs are included with the next error event to provide context about what happened.

```ts
import { addBreadcrumb } from '@tracekit/browser';

addBreadcrumb({
  type: 'user',
  category: 'auth',
  message: 'User logged in',
  level: 'info',
  data: { method: 'oauth', provider: 'github' },
});
```

### `getClient(): BrowserClient | null`

Get the underlying BrowserClient singleton. Returns null if the SDK has not been initialized. Use for advanced scenarios.

```ts
import { getClient } from '@tracekit/browser';

const client = getClient();
if (client) {
  console.log('SDK initialized');
}
```

## Types

All types are exported from `@tracekit/browser` for use in your TypeScript code.

### BrowserEvent

| Field | Type | Description |
| --- | --- | --- |
| `type` | string | Event type: "exception" or "message" |
| `message` | string | Error message or custom message text |
| `stackTrace` | string? | Raw stack trace string |
| `frames` | StackFrame[]? | Parsed stack frames with filename, function, line, column |
| `debugId` | string? | Debug ID for source map resolution |
| `level` | SeverityLevel | Event severity level |
| `timestamp` | number | Event timestamp in milliseconds |
| `handled` | boolean | Whether the error was caught by application code |

### Breadcrumb

| Field | Type | Description |
| --- | --- | --- |
| `type` | string | Breadcrumb type: "http", "navigation", "ui", "user", "console", "error" |
| `category` | string | Category for grouping: "fetch", "xhr", "click", "console", etc. |
| `message` | string? | Optional human-readable description |
| `level` | SeverityLevel | Breadcrumb severity |
| `timestamp` | number | Timestamp in milliseconds |
| `data` | Record? | Arbitrary data payload (URL, status code, element selector, etc.) |

### UserContext

| Field | Type | Description |
| --- | --- | --- |
| `id` | string? | Unique user identifier |
| `email` | string? | User email address |
| `username` | string? | Display name or username |

### SeverityLevel

A union type for event severity:

```ts
type SeverityLevel = 'fatal' | 'error' | 'warning' | 'info' | 'debug';
```

### StackFrame

| Field | Type | Description |
| --- | --- | --- |
| `filename` | string | Source file path or URL |
| `function` | string | Function name at this frame |
| `lineno` | number? | Line number (1-based) |
| `colno` | number? | Column number (1-based) |

### Integration

| Field | Type | Description |
| --- | --- | --- |
| `name` | string | Unique integration identifier |
| `install` | (client) => void | Called when the SDK initializes |
| `teardown` | (() => void)? | Optional cleanup on SDK shutdown |

## Usage Examples

### Setting user context after login

```ts
import { setUser } from '@tracekit/browser';

async function handleLogin(email: string, password: string) {
  const user = await authService.login(email, password);
  setUser({
    id: user.id,
    email: user.email,
    username: user.displayName,
  });
}

function handleLogout() {
  authService.logout();
  setUser(null);
}
```

### Adding custom breadcrumbs

```ts
import { addBreadcrumb } from '@tracekit/browser';

function addToCart(product: Product) {
  cart.add(product);
  addBreadcrumb({
    type: 'user',
    category: 'cart',
    message: 'Added item to cart',
    level: 'info',
    data: { productId: product.id, price: product.price },
  });
}
```

### Filtering events with beforeSend

```ts
import { init } from '@tracekit/browser';

init({
  apiKey: 'your-api-key',
  beforeSend: (event) => {
    // Drop noisy ResizeObserver errors
    if (event.message?.includes('ResizeObserver')) return null;
    // Drop errors from browser extensions
    if (event.stackTrace?.includes('chrome-extension://')) return null;
    // Scrub sensitive data
    if (event.message?.includes('password')) {
      event.message = '[REDACTED]';
    }
    return event;
  },
});
```

### Configuring distributed tracing

```ts
import { init } from '@tracekit/browser';

init({
  apiKey: 'your-api-key',
  tracePropagationTargets: [
    'https://api.example.com',         // Exact match
    'https://auth.example.com',        // Another backend
    /^https:\/\/.*\.example\.com/,     // Regex: all subdomains
  ],
});
// Fetch requests to matching URLs receive a traceparent header.
// Your backend reads this header to link frontend and backend traces.
```

### Using with session replay

```ts
import { init } from '@tracekit/browser';
import { replayIntegration } from '@tracekit/replay';

const replay = replayIntegration({
  sessionSampleRate: 0.1,   // Record 10% of sessions
  errorSampleRate: 1.0,     // Always record sessions with errors
});

init({
  apiKey: 'your-api-key',
  release: '1.0.0',
  addons: [replay],
});
```

See the [Session Replay documentation](/docs/frontend/session-replay) for full configuration options.

## Troubleshooting

### CORS errors with tracePropagationTargets

Your backend CORS configuration must accept the `traceparent` header.

```ts
// Express.js example:
app.use(cors({
  origin: 'https://your-app.com',
  allowedHeaders: ['Content-Type', 'Authorization', 'traceparent', 'tracestate'],
}));
```

### beforeSend not filtering events

The callback must return `null` to drop events. Returning `undefined` (no return statement) still sends the event. Always include a final `return event;` for events you want to keep.

### Events not appearing in dashboard

Check these causes: (1) `sampleRate` below 1.0 drops events. (2) `enabled: false` disables the SDK. (3) `beforeSend` returning null. (4) Invalid API key. Enable `debug: true` to see SDK logs.

### Integration toggle effects

Disabling `globalError` stops automatic error capture; you must call `captureException()` manually. Disabling `fetch` or `xhr` stops both breadcrumb recording and traceparent injection.

### Debug mode for development

Enable debug mode to log all SDK activity to the browser console.

```ts
init({
  apiKey: 'your-api-key',
  debug: process.env.NODE_ENV === 'development',
});
```

## Complete Example

A real-world setup showing all major features together.

```ts
import {
  init,
  captureException,
  captureMessage,
  setUser,
  setTag,
  setExtra,
  addBreadcrumb,
} from '@tracekit/browser';
import { replayIntegration } from '@tracekit/replay';

// 1. Initialize with full configuration
const replay = replayIntegration({
  sessionSampleRate: 0.1,
  errorSampleRate: 1.0,
});

init({
  apiKey: process.env.TRACEKIT_API_KEY!,
  release: process.env.APP_VERSION || '0.0.0',
  environment: process.env.NODE_ENV || 'production',
  serviceName: 'my-frontend',
  tracePropagationTargets: [
    'https://api.myapp.com',
    /^https:\/\/.*\.myapp\.com/,
  ],
  beforeSend: (event) => {
    if (event.message?.includes('ResizeObserver')) return null;
    if (event.stackTrace?.includes('chrome-extension://')) return null;
    return event;
  },
  addons: [replay],
});

// 2. Set user context after authentication
async function onLogin(credentials: { email: string; password: string }) {
  const user = await api.login(credentials);
  setUser({ id: user.id, email: user.email, username: user.name });
  setTag('plan', user.plan);
  setExtra('signup_date', user.createdAt);
  addBreadcrumb({
    type: 'user',
    category: 'auth',
    message: 'User logged in',
    level: 'info',
  });
  captureMessage('User login successful', 'info');
}

// 3. Manual error capture with context
async function loadDashboard() {
  try {
    const data = await api.fetchDashboard();
    renderDashboard(data);
  } catch (err) {
    captureException(err as Error, {
      component: 'Dashboard',
      retryCount: 0,
    });
    showErrorFallback();
  }
}
```
