@nveal/browser
@nveal/browser
A lightweight, privacy-first session recording SDK for web applications. Capture user sessions and replay them for debugging, analytics, and user experience research.
Getting Your SDK Key
You need an SDK key to use this package. Sign up at nveal.com to create a project and get your API key.
Installation
npm
npm install @nveal/browseryarn
yarn add @nveal/browserpnpm
pnpm add @nveal/browserCDN (Script Tag)
<script src="https://cdn.nveal.com/v1/nveal.js"></script>Quick Start
ES Modules (React, Vue, Svelte, Angular, etc.)
import { nveal } from '@nveal/browser';
nveal.init({
apiKey: 'YOUR_SDK_KEY', // Get yours at nveal.com
metadata: { userId: 'user-123', orderId: 'order-456' },
});Script Tag
<script src="https://cdn.nveal.com/v1/nveal.js"></script>
<script>
Nveal.init({
apiKey: 'YOUR_SDK_KEY',
metadata: { userId: 'user-123' },
});
</script>Configuration
Pass a configuration object to nveal.init(). Only apiKey is required — everything else has sensible defaults.
Full Configuration Reference
| Option | Type | Default | Description |
|---|---|---|---|
apiKey |
string |
required | Your Nveal SDK key from nveal.com |
apiBaseUrl |
string |
Nveal service URL | Custom API base URL |
metadata |
Record<string, string | number | boolean> |
{} |
Custom metadata attached to the session |
recordCanvas |
boolean |
false |
Record <canvas> elements |
recordConsole |
boolean |
false |
Record console logs (log, warn, error, etc.) |
maskAllInputs |
boolean |
true |
Mask all input field values in the recording |
maskAllText |
boolean |
false |
Mask all visible text content |
maskPII |
boolean |
true |
Auto-block PII-sensitive fields (passwords, credit cards, SSNs) |
blockSelector |
string |
— | CSS selector for elements to block (content hidden, structure preserved) |
ignoreSelector |
string |
— | CSS selector for elements to completely exclude |
sampling |
SamplingConfig |
— | Fine-grained event sampling (see Sampling) |
eventBatchSize |
number |
50 |
Number of events per batch before sending |
batchInterval |
number |
5000 |
Flush interval in milliseconds |
idleTimeoutMs |
number |
300000 (5 min) |
Pause flushing after this period of inactivity |
idleBufferCap |
number |
500 |
Max buffered events during idle (oldest dropped first) |
sessionTimeoutMs |
number |
1800000 (30 min) |
Start a new session after this inactivity period |
onReady |
() => void |
— | Callback when recording starts |
onError |
(error: Error) => void |
— | Callback when an error occurs |
Example: Full Configuration
import { nveal } from '@nveal/browser';
nveal.init({
apiKey: 'YOUR_SDK_KEY',
// Metadata
metadata: { userId: 'user-123', plan: 'pro' },
// Recording options
recordCanvas: true,
recordConsole: true,
// Privacy
maskAllInputs: true,
maskPII: true,
blockSelector: '.sensitive-data',
ignoreSelector: '.do-not-record',
// Performance
eventBatchSize: 30,
batchInterval: 3000,
idleTimeoutMs: 300000,
// Sampling
sampling: {
mousemove: 50,
scroll: 150,
input: 'last',
},
// Callbacks
onReady: () => console.log('Nveal recording started'),
onError: (err) => console.error('Nveal error:', err),
});API Reference
nveal.init(config)
Initialize and start recording. Validates the SDK key with the Nveal service before recording begins.
await nveal.init({
apiKey: 'YOUR_SDK_KEY',
metadata: { userId: 'user-123' },
onReady: () => console.log('Recording started'),
});nveal.stop()
Stop recording and flush any remaining buffered events to the server.
await nveal.stop();nveal.setMetadata(key, value)
Add or update session metadata at runtime. Useful for attaching information that becomes available after init (e.g., after login).
nveal.setMetadata('orderId', 'order-789');
nveal.setMetadata('checkoutStep', 3);nveal.getSessionKey()
Returns the current session key, or null if not recording.
const sessionKey = nveal.getSessionKey();
console.log('Session:', sessionKey);nveal.isActive()
Check whether a recording session is currently active.
if (nveal.isActive()) {
console.log('Recording is running');
}nveal.addCustomEvent(tag, payload)
Emit a custom event that will be captured in the recording timeline. Use this to capture non-DOM events like alerts, confirms, toasts, or application-level actions.
// Capture an alert before showing it
nveal.addCustomEvent('browser-alert', { message: 'Payment confirmed!' });
alert('Payment confirmed!');
// Capture a custom application event
nveal.addCustomEvent('checkout-step', { step: 3, total: 99.99 });During replay, listen for these events using rrweb's custom-event listener:
replayer.on('custom-event', (event) => {
if (event.data.tag === 'browser-alert') {
showMockAlert(event.data.payload.message);
}
});Sampling Configuration
Reduce event volume for better performance on high-traffic pages:
nveal.init({
apiKey: 'YOUR_SDK_KEY',
sampling: {
mousemove: 50, // Throttle mouse movements to 50ms intervals
scroll: 150, // Throttle scroll events to 150ms
input: 'last', // Only record final input value (not every keystroke)
media: 500, // Throttle media interaction events
mouseInteraction: {
Click: true, // Record clicks
DblClick: true, // Record double-clicks
MouseDown: false, // Skip mouse-down events
MouseUp: false, // Skip mouse-up events
Focus: true, // Record focus changes
Blur: true, // Record blur events
TouchStart: true, // Record touch start
TouchEnd: true, // Record touch end
},
},
});Privacy & PII Protection
Nveal ships with privacy-first defaults. No configuration needed for basic protection.
Default Behavior
- All input fields are masked (
maskAllInputs: true) — form values are replaced with*characters in the recording. - PII auto-blocking is enabled (
maskPII: true) — fields matching common sensitive patterns (passwords, credit card numbers, SSNs, etc.) are completely blocked from the recording.
Customizing Privacy Settings
nveal.init({
apiKey: 'YOUR_SDK_KEY',
// Input masking
maskAllInputs: true, // Mask all form field values
maskAllText: false, // Keep visible text readable
// PII protection
maskPII: true, // Auto-block sensitive fields
// Element-level control
blockSelector: '.sensitive-data', // Block specific elements (placeholder shown)
ignoreSelector: '.do-not-record', // Completely exclude elements from recording
});Using CSS Selectors
You can also use HTML attributes to control recording per-element:
<!-- This element will be blocked (replaced with placeholder) -->
<div class="sensitive-data">Credit card details here</div>
<!-- This element will be completely ignored -->
<div class="do-not-record">Internal admin controls</div>Idle Detection
The SDK automatically detects user inactivity and pauses event flushing to save bandwidth. Events continue to be buffered locally and are sent when the user returns.
| Option | Default | Description |
|---|---|---|
idleTimeoutMs |
300000 (5 min) |
Pause flushing after this idle period |
idleBufferCap |
500 |
Max events to buffer during idle (oldest dropped first) |
sessionTimeoutMs |
1800000 (30 min) |
Start a new session after prolonged inactivity |
During replay, idle periods appear as fast-forwarded time gaps — the session timeline stays clean and focused on actual user activity.
TypeScript Support
Full TypeScript type definitions are included out of the box. Import types directly:
import type { NvealConfig, SamplingConfig } from '@nveal/browser';
const config: NvealConfig = {
apiKey: 'YOUR_SDK_KEY',
recordCanvas: true,
};Browser Compatibility
The SDK targets ES2020 and works in all modern browsers:
| Browser | Minimum Version |
|---|---|
| Chrome | 80+ |
| Firefox | 78+ |
| Safari | 14+ |
| Edge | 80+ |
Bundle Formats
| Format | File | Use Case |
|---|---|---|
| ESM | dist/index.esm.js |
Modern bundlers (Vite, Webpack 5, Rollup) |
| CJS | dist/index.cjs.js |
Node.js / CommonJS environments |
| UMD | dist/nveal.umd.js |
Script tags, CDN usage |
Development
# Install dependencies
npm install
# Build all formats (ESM, CJS, UMD)
npm run build
# Watch mode for development
npm run dev
# Type check
npm run typecheckChangelog
See CHANGELOG.md for a detailed history of changes.
License
Copyright (c) 2026 Nveal. All rights reserved. This is proprietary software.