Browser SDK for AI-interpretable event tracking and retention
npm install @bricksworks/sdkBrowser SDK for AI-interpretable event tracking and session recording.


- Click Tracking - Capture user clicks with element fingerprinting
- Form Tracking - Track form submissions (without field values for privacy)
- Navigation Tracking - Monitor page navigation including SPA transitions
- Session Recording - Record DOM state for replay
- Exception Capture - Track unhandled errors and promise rejections
- Network Error Capture - Monitor failed HTTP requests (4xx, 5xx, network failures)
- Rage Click Detection - Detect frustrated rapid clicking on the same element
- Dead Click Detection - Find broken UI elements that don't respond to clicks
- Element Fingerprinting - Reliable element identification in minified React apps
- React Integration - First-class React provider and hooks
- Privacy-First - No field values captured by default
``bash`
npm install @bricksworks/sdkor
pnpm add @bricksworks/sdkor
yarn add @bricksworks/sdk
`typescript
import { createBricks } from '@bricksworks/sdk';
const sdk = createBricks({
apiKey: 'your-workspace-api-key',
});
sdk.start();
// After user logs in, identify them
sdk.identify('user-123', {
email: 'user@example.com',
name: 'John Doe',
});
`
That's it! The SDK automatically tracks clicks, forms, navigation, and records sessions.
Important: Call identify() after your user logs in to link their session to their identity. This enables personalized AI insights and cross-session tracking.
`typescript
// Basic identification with user ID and traits
sdk.identify('user-123', {
email: 'user@example.com',
name: 'John Doe',
});
// With additional business context
sdk.identify('user-123', {
email: 'user@example.com',
name: 'John Doe',
plan: 'pro',
company: 'Acme Inc',
role: 'admin',
});
// Anonymous traits (no user ID)
sdk.identify({
email: 'visitor@example.com',
});
`
- After login - As soon as you know who the user is
- After signup - Link the new user to their browsing session
- On page load - If user is already authenticated, identify them immediately
`typescript
// Example: React login flow
async function handleLogin(credentials) {
const user = await api.login(credentials);
// Identify user after successful login
sdk.identify(user.id, {
email: user.email,
name: user.name,
plan: user.subscription.plan,
});
}
`
`typescript
import { createBricks } from '@bricksworks/sdk';
const sdk = createBricks({
apiKey: 'your-workspace-api-key',
});
sdk.start();
// Identify user after login
sdk.identify({
externalId: 'user-123',
email: 'user@example.com',
plan: 'pro',
});
// Complete session when user finishes (e.g., checkout complete)
await sdk.complete();
`
For React applications, use the provider and hook for a more idiomatic experience:
`tsx
import { BricksProvider } from '@bricksworks/sdk/react';
import { ENDPOINTS } from '@bricksworks/sdk';
function App() {
return (
endpoint={ENDPOINTS.local} // optional, defaults to production
debug={true} // optional
>
);
}
`
`tsx
import { useBricks } from '@bricksworks/sdk/react';
function UserProfile({ userId }) {
const bricks = useBricks();
useEffect(() => {
bricks.identify({ externalId: userId });
}, [userId]);
return
$3
| Prop | Type | Default | Description |
|------|------|---------|-------------|
|
apiKey | string | required | Your workspace API key |
| endpoint | string | production | Backend URL |
| debug | boolean | false | Enable debug logging |
| compression | boolean | true | Gzip compress payloads |
| sessionTimeout | number | 30 min | Session timeout in ms |
| plugins | object | all enabled | Plugin configuration |
| onError | function | - | Error callback |
| fallback | ReactNode | - | Error boundary fallback |$3
- React 16.8+ (hooks support required)
- React is an optional peer dependency (not required for vanilla JS usage)
$3
The React provider is client-only. For SSR frameworks like Next.js:
`tsx
// Next.js App Router - mark as client component
'use client';import { BricksProvider } from '@bricksworks/sdk/react';
export function Providers({ children }) {
return (
{children}
);
}
``tsx
// Next.js Pages Router - use dynamic import
import dynamic from 'next/dynamic';const BricksProvider = dynamic(
() => import('@bricksworks/sdk/react').then((mod) => mod.BricksProvider),
{ ssr: false }
);
`Configuration
$3
| Option | Type | Default | Description |
|--------|------|---------|-------------|
|
apiKey | string | required | Your workspace API key |
| endpoint | string | production | Backend URL (use ENDPOINTS.local for dev) |
| debug | boolean | false | Enable debug logging to console |
| compression | boolean | true | Gzip compress payloads |
| sessionTimeout | number | 30 min | Session timeout in milliseconds |$3
`typescript
import { createBricks, ENDPOINTS } from '@bricksworks/sdk';// Production (default)
createBricks({ apiKey: '...' });
// Local development
createBricks({
apiKey: '...',
endpoint: ENDPOINTS.local,
});
`Plugins
All plugins are enabled by default. You can disable or configure individual plugins:
`typescript
const sdk = createBricks({
apiKey: 'your-api-key',
plugins: {
// Disable a plugin
recording: false, // Configure a plugin
deadClick: {
waitTimeMs: 3000,
ignoreSelectors: ['.no-dead-click'],
},
},
});
`$3
| Plugin | Description | Default |
|--------|-------------|---------|
|
recording | Session recording with rrweb | enabled |
| clickCapture | Click event tracking | enabled |
| formCapture | Form submission tracking | enabled |
| navigationCapture | Page navigation tracking | enabled |
| exceptionCapture | Unhandled error tracking | enabled |
| networkErrorCapture | Failed HTTP request tracking | enabled |
| rageClick | Rapid click detection | enabled |
| deadClick | Unresponsive element detection | enabled |
| performance | Performance metrics | enabled |$3
####
recording`typescript
plugins: {
recording: {
blockSelector: '.sensitive', // CSS selector for elements to block
maskInputSelector: 'input[type="password"]',
maskAllInputs: true, // Mask all input values (default: true)
},
}
`####
deadClickDetects clicks on interactive elements (buttons, links, etc.) that don't cause any DOM changes within a timeout period. Uses MutationObserver to watch for DOM mutations after clicks.
`typescript
plugins: {
deadClick: {
waitTimeMs: 2500, // Time to wait for DOM mutation (default: 2500ms)
ignoreSelectors: ['.external'], // CSS selectors to ignore
},
}
`How it works:
1. User clicks an interactive element (button, link, element with
role="button", etc.)
2. SDK watches for any DOM changes using MutationObserver
3. If no changes occur within waitTimeMs, it's flagged as a dead click
4. Links that navigate away and clicks with modifier keys (Ctrl, etc.) are ignored####
rageClickDetects rapid, frustrated clicking on the same element.
`typescript
plugins: {
rageClick: {
clickThreshold: 3, // Clicks needed to trigger (default: 3)
timeWindowMs: 1000, // Time window in ms (default: 1000)
radiusPixels: 30, // Max distance between clicks (default: 30)
},
}
`####
networkErrorCaptureTracks failed HTTP requests from both fetch and XMLHttpRequest.
`typescript
plugins: {
networkErrorCapture: {
urlPatterns: ['/api/'], // Only track URLs matching these patterns
minStatus: 400, // Minimum status code to capture (default: 400)
captureNetworkFailures: true, // Capture network failures (default: true)
},
}
`####
exceptionCaptureTracks unhandled errors and promise rejections.
`typescript
plugins: {
exceptionCapture: {
captureUnhandledErrors: true, // Capture window.onerror (default: true)
captureUnhandledRejections: true, // Capture unhandledrejection (default: true)
},
}
`SDK Methods
$3
Start capturing events.
`typescript
sdk.start();
`$3
Stop capturing events.
`typescript
sdk.stop();
`$3
Identify the current user. Call after login.
`typescript
sdk.identify({
externalId: 'user-123', // Your user ID
email: 'user@example.com',
name: 'John Doe',
plan: 'pro',
company: 'Acme Inc',
});// Or just traits without externalId
sdk.identify({ email: 'user@example.com' });
`$3
Force send any buffered events immediately.
`typescript
await sdk.flush();
`$3
Complete the session and notify the backend. Call when the user completes their journey (e.g., after checkout).
`typescript
await sdk.complete();
`$3
Start a new session. Returns the new session ID.
`typescript
const newSessionId = sdk.resetSession();
`$3
Get the current session ID.
`typescript
const sessionId = sdk.getSessionId();
`$3
Completely destroy the SDK and release all resources.
`typescript
sdk.destroy();
`Element Fingerprinting
The SDK uses multi-layer element identification to reliably track elements even in minified React applications:
1. Data attributes (priority):
data-testid, data-analytics-id
2. ARIA: aria-label, aria-labelledby
3. Semantics: id, name, href, type
4. Content: element text
5. Structure: DOM pathTip: Add
data-testid attributes to important elements for the most reliable tracking:`html
`TypeScript Support
Full TypeScript support with exported types:
`typescript
import type { BricksConfig, BricksInstance } from '@bricksworks/sdk';// React types
import type { BricksProviderProps, BricksContextValue } from '@bricksworks/sdk/react';
``- Chrome 80+
- Firefox 78+
- Safari 14+
- Edge 80+
~150KB gzipped (includes session recording capabilities)
MIT