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

# Browser JS

> Collect browser logs, traces, and session replay with the ClickStack browser SDK.

The ClickStack browser SDK builds on OpenTelemetry to collect browser requests, errors, and session replay. Use it to investigate frontend events alongside your backend telemetry in ClickHouse Observability.

This guide integrates:

## Install

Install the package in your frontend application:

```shell theme={null}
npm install @clickhouse/clickstack-browser
```

The package uses ES modules. npm installs its OpenTelemetry peer dependencies automatically. If your application also installs `@opentelemetry/api` directly, use version `~1.9.1` and keep a single copy; version 1.10 is outside this SDK's supported range.

## Configure your destination

> [tab] Fully managed
>
> [Beta offering](https://clickhouse.com/docs/reference/settings/beta-and-experimental-features.md#beta-features)
>
> Open **Team Settings → Data → Managed Telemetry** in your service and copy the **OTLP HTTP endpoint** and **API key**. Use the complete HTTPS endpoint, including its port, without a signal path such as `/v1/traces`.
>
> Initialize the SDK in your application's entry module:
>
> ```javascript theme={null}
> import { init } from '@clickhouse/clickstack-browser';
>
> init({
>   endpoint: 'https://YOUR_OTEL_ENDPOINT:4318',
>   apiKey: 'Bearer YOUR_INGESTION_API_KEY',
>   serviceName: 'my-frontend-app',
> });
> ```

> [tab] Self-managed
>
> Use the OTLP HTTP endpoint of your collector and its configured ingestion key. The endpoint must be reachable from your users' browsers. For collector setup, see [Ingesting with OpenTelemetry](https://clickhouse.com/docs/clickstack/observability/ingesting-data/opentelemetry.md#self-managed).
>
> ```javascript theme={null}
> import { init } from '@clickhouse/clickstack-browser';
>
> init({
>   endpoint: 'https://YOUR_COLLECTOR_HOST:4318',
>   apiKey: 'YOUR_INGESTION_API_KEY',
>   serviceName: 'my-frontend-app',
> });
> ```
>
> Use the key configured for your collector's OTLP receiver. Your collector must permit your application's origin in its HTTP receiver's CORS configuration.

Call `init` once per page load, at the top level of your entry module, such as `src/main.ts` in Vite or `instrumentation-client.ts` in Next.js. Initialization runs asynchronously; requests made immediately in the same tick may not be captured. Do not initialize in a React effect: cleanup that calls `shutdown` permanently stops telemetry for that page load.

> [!NOTE]
>
> Browser configuration is visible to anyone who loads the page, including its ingestion key. To keep the key on your server, use a same-origin endpoint such as `/otel`, omit `apiKey`, and configure your server to forward the OTLP requests with the appropriate authorization header.

## Verify ingestion

Load your application, interact with the page, make a request, and emit a console error. In ClickHouse Observability, select a recent time range and search Logs or Traces for `my-frontend-app`. Open Session replay to inspect the recorded session.

If data is missing, inspect the browser console and network requests to `/v1/traces` and `/v1/logs`. Check the endpoint, authorization header, CORS, and Content Security Policy. For self-managed deployments, confirm that your ClickStack version supports replay and the SDK's standard `session.id` attribute; receiving records alone does not confirm that sessions appear in the UI.

## Initialization options

Pass these options to `init`. Use `endpoint` for a shared collector, or provide both signal endpoints when traces and logs have separate destinations.

| Option | Default | Purpose |
| - | - | - |
| `endpoint` | Required unless both signal endpoints are set | Base OTLP HTTP URL or same-origin proxy path; the SDK appends the signal paths |
| `tracesEndpoint` | Unset | Full traces URL, used as supplied instead of the URL derived from `endpoint` |
| `logsEndpoint` | Unset | Full logs and replay URL, used as supplied instead of the URL derived from `endpoint` |
| `serviceName` | Required | Set `service.name` on all telemetry |
| `apiKey` | Unset | Value of the `authorization` header; use the format for your destination above |
| `traceOrigins` | Unset | Backend origins or regular expressions that receive trace context |
| `replay` | `true` | Record session replay; `false` keeps browser telemetry but disables replay |
| `resourceAttributes` | Unset | Additional resource attributes, including replay; `serviceName`, `serviceVersion`, and `environment` take precedence over matching keys |
| `maskAllText` | `true` | Mask text in the replay |
| `maskAllInputs` | `true` | Mask input, textarea, and select values |
| `console` | `'error'` | Capture `'error'`, `'warn'`, `'info'` (including `console.log`), or `'debug'` and more severe levels; use `false` to disable |
| `serviceVersion` | Unset | Identify your application release |
| `environment` | Unset | Set `deployment.environment.name` |
| `sanitizeUrl` | Unset | Rewrite recorded URLs, for example to remove query parameters |

For the complete API, see the [browser SDK reference](https://github.com/ClickHouse/clickstack-browser#quick-start).

## Session replay and privacy

Session replay is enabled by default. Text and input values are masked by default.

Masking does not hide checkbox states, radio states, or attributes such as link URLs and placeholders. Use the `rr-block` class to exclude sensitive elements. URL sanitization does not cover URLs inside replayed page content, stack traces, or console messages. Only capture user information permitted by your privacy policy.

To pause replay without stopping browser telemetry:

```javascript theme={null}
import { pauseReplay } from '@clickhouse/clickstack-browser';

pauseReplay();
```

When you're ready to resume recording:

```javascript theme={null}
import { resumeReplay } from '@clickhouse/clickstack-browser';

resumeReplay();
```

## Link frontend and backend traces

To connect browser requests to backend traces, add `traceOrigins` to your `init` options, replacing the example with your backend origin:

```javascript theme={null}
traceOrigins: ['https://api.example.com'],
```

Requests to the page's own origin and matching backends carry `traceparent`, `tracestate`, and `baggage`. Your backend must be instrumented to continue that context.

Cross-origin backends must allow these headers through CORS. The telemetry collector must also permit the frontend origin. If your application uses Content Security Policy, allow the collector endpoint in `connect-src`.

## Identify users and record errors

On sign-in, use `setUser` to attach user information to subsequent spans and logs:

```javascript theme={null}
import { setUser } from '@clickhouse/clickstack-browser';

setUser({ id: 'user-123', email: 'user@example.com' });
```

On sign-out, clear the user information and start a new session:

```javascript theme={null}
import { setUser, startNewSession } from '@clickhouse/clickstack-browser';

setUser(null);
startNewSession();
```

To attach application metadata to subsequent spans and logs, use `setAttributes`. Each call replaces the previous set; pass `null` to clear it:

```javascript theme={null}
import { setAttributes } from '@clickhouse/clickstack-browser';

setAttributes({ 'app.team.name': 'checkout' });
```

Uncaught errors and unhandled rejections are captured automatically. React error boundaries that report through `console.error` are also captured by default. Use `recordException` for caught errors that are not already logged; recording and logging the same error creates duplicate events:

```javascript theme={null}
import { recordException } from '@clickhouse/clickstack-browser';

try {
  await submitCheckout();
} catch (error) {
  recordException(error, { 'app.operation': 'checkout' });
  // Handle the error in your application.
}
```

Replace `submitCheckout` with the application operation you want to monitor.

## Migrating from the HyperDX browser SDK

This is not a package-name-only upgrade. `url` becomes `endpoint`, `service` becomes `serviceName`, and `tracePropagationTargets` becomes `traceOrigins`. Text and input masking now default to `true`. Replace `setGlobalAttributes` with `setUser` for user identity and `setAttributes` for application metadata. React error boundaries that report through `console.error` need no extra hook; use `recordException` when an error is not already logged.

See the [SDK migration guide](https://github.com/ClickHouse/clickstack-browser/blob/main/docs/migration.md) for removed options and attribute changes. For a script-tag installation or an application that already initializes OpenTelemetry, see the [SDK README](https://github.com/ClickHouse/clickstack-browser#readme).

If the ClickStack browser SDK causes a compatibility issue in your application, you can use the [legacy HyperDX browser SDK](https://github.com/hyperdxio/hyperdx-js/tree/main/packages/browser) while investigating it. Restore its configuration and API calls using the migration guide above; the two SDKs are not interchangeable and should not run together.
