Documentation

Browsonic SDK Documentation

Real-time error and event capture for JavaScript applications. The @browsonic/sdk package is the canonical surface — framework adapters (React, Vue, Svelte, Angular, Next.js, Astro, Remix) wrap it without changing the wire format.

Last updated:

Introduction

Browsonic SDK is a lightweight, zero-dependency JavaScript library that automatically captures frontend errors and anomalies in real time. It is published on the public npm registry as @browsonic/sdk under the Apache 2.0 licence.

What it captures

Console errors
console.error, warn, info
Unhandled exceptions
window.onerror events
Promise rejections
Unhandled promise rejections
Network failures
HTTP 4xx / 5xx responses

Key features

FeatureDescription
Zero dependenciesNo external libraries required.
Automatic collectionIntercepts console, errors, and fetch automatically.
Smart batchingGroups events and flushes at a configurable interval.
DeduplicationPrevents duplicates via fingerprinting.
Offline supportPersists the queue to localStorage when offline.
Privacy firstAutomatic redaction of sensitive keys.
Circuit breakerAuto-disables on repeated internal errors.

Installation

Install with your preferred package manager.

npm

Terminal window
npm install @browsonic/sdk

pnpm

Terminal window
pnpm add @browsonic/sdk

yarn

Terminal window
yarn add @browsonic/sdk

Quick Start

Get up and running in under two minutes.

Basic setup

import { Browsonic } from '@browsonic/sdk';
const sdk = new Browsonic();
sdk.init({
apiEndpoint: 'https://api.browsonic.com',
appKey: 'your-app-key',
apiKey: 'sk_live_…', // mint in dashboard (required when trackPageViews is on, which is the default)
});
// That's it. Errors are now captured automatically.

React integration

src/main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Browsonic } from '@browsonic/sdk';
import App from './App';
const sdk = new Browsonic();
sdk.init({
apiEndpoint: import.meta.env.VITE_BROWSONIC_API,
appKey: import.meta.env.VITE_BROWSONIC_APP_KEY,
apiKey: import.meta.env.VITE_BROWSONIC_API_KEY,
environment: import.meta.env.MODE,
clientVersion: import.meta.env.VITE_GIT_SHA,
debug: import.meta.env.DEV,
});
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
);

Framework-specific adapters (@browsonic/react, @browsonic/vue, @browsonic/svelte, @browsonic/angular, @browsonic/nextjs, @browsonic/astro, @browsonic/remix) add router instrumentation and navigation breadcrumbs on top of the core SDK. See the integration guide for framework-specific wiring.

Configuration

Every option accepted by init(), grouped by purpose.

Required

ParameterTypeDescription
apiEndpointstringBase URL of your Browsonic API.
appKeystringApplication identifier for multi-tenant routing.
apiKeystringTenant API key — sent as X-API-KEY. Required when trackPageViews is on (the default).

Environment & release

ParameterTypeDefaultDescription
environmentstring"production"Environment name.
clientVersionstring | nullnullClient version tag (surfaced as Versions in the dashboard).
debugbooleanfalseVerbose console logging.

Batching & transport

ParameterTypeDefaultDescription
flushIntervalMsnumber10000Interval between batch sends (ms).
maxBatchSizenumber25Maximum events per batch.
maxPayloadBytesnumber51200Maximum batch payload size (bytes; sized to stay under the 64 KB sendBeacon ceiling).

Event capture

ParameterTypeDefaultDescription
captureLevelsEventLevel[]["error"]Console levels to capture.
cooldownMsnumber60000Dedup time window (ms).

Queue & persistence

ParameterTypeDefaultDescription
maxQueueSizenumber200Maximum events held in memory.
persistQueuebooleanfalseSave queue to localStorage across reloads.

Ignore rules

ParameterTypeDefaultDescription
ignoreExtensionsbooleantrueAuto-ignore browser extension errors.
ignoreScriptErrorsbooleantrueIgnore cross-origin "Script error" messages.
ignorePatternsstring[][]Stack trace patterns to ignore.
ignoreMessagesstring[][]Error message patterns to ignore.
ignoreUrlsstring[][]URL patterns to ignore errors from.

Complete example

import { COMMON_THIRD_PARTY_PATTERNS } from '@browsonic/sdk';
sdk.init({
// Required
apiEndpoint: 'https://api.browsonic.com',
appKey: 'my-production-app',
apiKey: 'sk_live_…',
// Environment
environment: 'production',
clientVersion: 'v2.1.0',
debug: false,
// Batching
flushIntervalMs: 10000,
maxBatchSize: 25,
// Deduplication
cooldownMs: 60000,
// Capture
captureLevels: ['warn', 'error'],
// Queue
maxQueueSize: 300,
persistQueue: true,
// Privacy
redactKeys: ['token', 'password', 'secret'],
// Ignore Rules (filter noise)
ignoreExtensions: true,
ignoreScriptErrors: true,
ignorePatterns: COMMON_THIRD_PARTY_PATTERNS,
ignoreMessages: ['ResizeObserver loop'],
});

API Reference

All methods available on the SDK instance.

captureMessage(message, level?)

Capture a message manually. level defaults to info.

sdk.captureMessage('User completed checkout', 'info');
sdk.captureMessage('Payment failed', 'error');

captureError(error)

Capture an Error instance manually.

try {
await riskyOperation();
} catch (error) {
sdk.captureError(error as Error);
}

setUser(user) · clearUser()

Attach a user context to all subsequent events. Sensitive keys (token / password / secret / auth) are redacted before transport.

sdk.setUser({
id: 'user-123',
email: 'user@example.com',
plan: 'premium',
});
// On logout
sdk.clearUser();

addMetadata(key, value) · removeMetadata(key) · clearMetadata()

Attach custom key/value pairs to every subsequent event.

sdk.addMetadata('feature', 'checkout');
sdk.addMetadata('cartValue', 99.99);
sdk.addMetadata('isNewUser', true);
sdk.removeMetadata('feature');
sdk.clearMetadata();

Lifecycle: flush(), pause(), resume(), destroy()

MethodDescription
flush()Force immediate flush of queued events. Returns a Promise.
pause() / resume()Pause and resume event collection without losing the in-memory queue.
destroy()Destroy the SDK and release all listeners and timers.
getState()Returns 'uninitialized' | 'initializing' | 'running' | 'paused' | 'destroyed'.
getPendingCount()Number of events currently queued for transport.

Event Types

Built-in event types captured by the SDK.

TypeLevelSourceDescription
console_debuginfoconsole.debug()Debug log (verb preserved on telemetry).
console_infoinfoconsole.info()Informational log.
console_warnwarnconsole.warn()Warning log.
console_errorerrorconsole.error()Error log.
errorerrorwindow.onerrorUnhandled exception.
fatalfatalmanualCapture-on-purpose fatal report.
unhandledrejectionerrorPromise rejectionUnhandled promise rejection.
network_errorwarn / errorfetch() / XHRHTTP 4xx / 5xx response.

Wire format

interface BrowsonicEvent {
eventId: string; // Unique UUID
timestamp: string; // ISO 8601
type: EventType;
level: EventLevel;
message: string;
stack?: string | null;
context: EventContext; // url, referrer, pageAge
telemetry?: Timeline; // events leading up to error
metadata?: MetadataEntry[];
}
interface EventBatch {
batchId: string;
timestamp: string;
appKey: string;
environment: string;
clientVersion?: string;
sessionId: string;
sessionContext: SessionContext;
user?: UserContext;
events: BrowsonicEvent[];
}

Telemetry Timeline

Chronological events leading up to each error — the debugging context that turns a stack trace into a story.

Categories

Console
console.log, warn, error calls.
Network
Fetch & XMLHttpRequest requests.
Navigation
SPA route changes (History API).
Visitor
User clicks & inputs (privacy-safe).

How it works

  1. The SDK collects events in a ring buffer (FIFO, configurable size).
  2. When an error fires, the last N events ship with the error payload.
  3. The dashboard renders the timeline in the Timeline tab of each event.
  4. It answers the only question that matters: what happened right before this error?

Configuration

sdk.init({
apiEndpoint: 'https://api.browsonic.com',
appKey: 'my-app',
apiKey: 'sk_live_…',
// Telemetry Timeline
maxTelemetryEntries: 50, // ring buffer size (default 20)
includeTelemetry: true, // attach with errors (default true)
// Network telemetry
captureXHR: true,
networkTelemetry: true,
// Navigation
trackNavigation: true,
// Visitor (see Visitor Tracking)
trackVisitor: false, // OFF by default for privacy
});

Visitor Tracking

Track user interactions (clicks, inputs) in a privacy-safe manner.

Privacy-first design

Visitor tracking is off by default. When you enable it, actual input values are never stored — only patterns and lengths. Password fields are skipped entirely.

What is collected

DataExamplePurpose
Element tagbutton, inputIdentify element type.
Element text"Submit Order"Human-readable identification.
Element IDsubmit-btnIdentify specific element.
CSS classesbtn primaryDebugging context.
Input typeemail, textUnderstand input purpose.
Value length16Know input size without content.
Value patternemail, numericUnderstand input format.

What is never collected

  • Actual input values (e.g. "john@example.com").
  • Password field content — completely skipped.
  • Credit card numbers.
  • Any typed text content.

Configuration

sdk.init({
trackVisitor: true,
visitor: {
click: true, // track click events
input: true, // track input events
inputThrottleMs: 500, // throttle (default 500 ms)
},
});

Privacy & Security

How Browsonic handles sensitive data and what compliance posture you inherit by default.

Data collection summary

Data typeCollectedHow it is stored
Error messages✅ YesFull text.
Stack traces✅ YesFull text.
Console logs✅ YesFull text (telemetry).
Network URLs✅ YesFull URL — no body / headers.
User clicks⚠️ OptionalElement info only.
User inputs⚠️ OptionalPattern + length only.
Input values❌ NeverN/A.
Passwords❌ NeverCompletely skipped.

Privacy-safe defaults

SettingDefaultDescription
trackVisitorfalseVisitor tracking off by default.
trackNavigationtrueURL changes only, no user data.
networkTelemetrytrueURLs only — no request / response bodies.
captureAsyncStackfalsePerformance opt-in feature.

Automatic redaction

These keys are automatically redacted in localStorage, sessionStorage, cookies, and user context:

const DEFAULT_REDACT_KEYS = [
'token', 'password', 'authorization',
'secret', 'key', 'credential', 'auth',
];
sdk.init({
redactKeys: [
...DEFAULT_REDACT_KEYS,
'ssn',
'creditCard',
'bankAccount',
],
redactCookieNames: ['session_id', 'csrf_token'],
});

Pattern-based redaction

In addition to key-based redaction, the SDK scans free-text values (error messages, telemetry payloads, captured network metadata) and replaces matches with [REDACTED]:

PatternWhat it catches
Emailname@host.tld tokens anywhere in a value.
JWTeyJ… three-segment Base64 tokens.
Credit card12–19 digit runs (with optional spaces / hyphens).
Opaque secret32-char-or-longer continuous [A-Za-z0-9_-] tokens.

HTTP header filtering

Network telemetry captures only headers on an explicit allowlist — everything else is dropped. A hard blocklist (authorization, cookie, set-cookie, token, api-key, password, …) is dropped even if a user tries to add it to the allowlist. Header values are also passed through pattern redaction as defense in depth.

Compliance

GDPR
Data minimization (patterns, not values). Purpose limitation (debugging only). Consent-based tracking (off by default).
CCPA
Transparent data collection. Opt-out via configuration. No sale of personal data.

For the full security policy, see SECURITY.md on GitHub.

Troubleshooting

Common issues and how to resolve them.

SDK not capturing events

  1. Check initialization — sdk.getState() should return "running".
  2. Enable debug mode: sdk.updateConfig({ debug: true }).
  3. Verify captureLevels includes the event type you expect.

Events not reaching the server

  1. Check pending count — sdk.getPendingCount().
  2. Force flush — await sdk.flush().
  3. Verify apiEndpoint is correct and CORS is configured.
  4. Check the Network tab for 4xx / 5xx responses.

High event volume

  1. Increase cooldown — cooldownMs: 300000 (5 minutes).
  2. Reduce capture levels — captureLevels: ['error'].
  3. Increase flush interval — flushIntervalMs: 60000.