Real User Monitoring

Track what your users actually experience. Sessions, Web Vitals, errors, clicks, and optional session replay.

Installation

Terminal
npm install vident-browser

Quick Start

Quick Start
import { createVidentBrowser } from 'vident-browser'

const vident = createVidentBrowser({
apiKey: 'vd_...',
appName: 'my-app',
})

// Identify users (optional)
vident.setUser('user-123', { plan: 'pro', company: 'Acme' })

// Track custom events
vident.trackEvent('checkout_started', { cartValue: 99.99 })

Configuration

Full Config
createVidentBrowser({
// Required
apiKey: 'vd_...',

// Optional
appName: 'my-app',              // Identifies your app
sampleRate: 1,                   // 0-1, default 1 (100%)

// Auto-tracking (all true by default)
trackPageViews: true,            // SPA navigation included
trackClicks: true,               // Interactive elements
trackVitals: true,               // Core Web Vitals
trackErrors: true,               // Unhandled errors
trackResources: true,            // Fetch/XHR timing

// Session storage
sessionStorage: 'cookie',        // 'cookie' | 'sessionStorage'

// Distributed tracing
tracing: { ... },

// Session replay
replay: { ... },
})

What's Tracked Automatically

Page Views

Tracked on initial load and SPA navigation (pushState, replaceState, popstate).

Clicks

Tracked on interactive elements: buttons, links, inputs, and elements with role="button".

Core Web Vitals

All six metrics sent once per session:

| Metric | What it measures | |--------|------------------| | LCP | Largest Contentful Paint - loading performance | | FID | First Input Delay - interactivity (legacy) | | INP | Interaction to Next Paint - responsiveness | | CLS | Cumulative Layout Shift - visual stability | | TTFB | Time to First Byte - server response | | FCP | First Contentful Paint - perceived speed |

Errors

Unhandled errors and promise rejections captured with stack traces.

HTTP Resources

Fetch and XHR requests tracked with timing and status codes.

Dashboard Features

Once data flows in, the Vident dashboard gives you:

  • Errors — Auto-grouped by stack trace with affected sessions
  • Sessions — Filterable session list with replay, searchable by user or event
  • Users — User profiles with session history, error counts, and device info
  • Events — Custom event explorer with trends and property breakdowns
  • Funnels — URL-based conversion funnels with step-by-step drop-off
  • Web Vitals — LCP, CLS, INP per page with geographic and device segmentation

Manual Tracking

Manual Tracking
// Custom events
vident.trackEvent('purchase_completed', {
orderId: 'abc-123',
total: 149.99,
items: 3,
})

// Manual page views (usually auto-tracked)
vident.trackPageView('/custom-route')

// Manual error capture with trace correlation
vident.trackError(new Error('Payment failed'), {
requestId: 'req-456',
traceId: 'abc123def456',
})

User Identification

User Identification
// Set user with ID only
vident.setUser('user-123')

// Set user with traits
vident.setUser('user-123', {
email: '[email protected]',
plan: 'enterprise',
company: 'Acme Corp',
})

Session Storage Modes

Storage Modes
// Cookie mode (default) - survives OAuth redirects
createVidentBrowser({
apiKey: 'vd_...',
sessionStorage: 'cookie',
})

// sessionStorage mode - tab-isolated, no cookie consent needed
createVidentBrowser({
apiKey: 'vd_...',
sessionStorage: 'sessionStorage',
})

Cookie mode: Session survives page refreshes and OAuth redirects. Uses SameSite=Lax.

sessionStorage mode: Isolated per tab. Cleared when tab closes. No cookies written.

Distributed Tracing

Connect frontend requests to backend traces.

Distributed Tracing
createVidentBrowser({
apiKey: 'vd_...',
tracing: {
  enabled: true,                 // default
  traceFetch: true,              // Trace fetch requests
  traceXHR: true,                // Trace XHR requests
  propagateToOrigins: [
    /\.mycompany\.com$/,        // Same root domain (default)
    'api.partner.com',           // Explicit allowlist
  ],
},
})

Automatically injects W3C traceparent headers to allowlisted origins.

Session Replay

Record user sessions for debugging. Privacy-first with configurable masking.

Session Replay
createVidentBrowser({
apiKey: 'vd_...',
replay: {
  enabled: true,
  sampleRate: 0.1,               // 10% of sessions uploaded
  onErrorSampleRate: 1.0,        // 100% when error occurs
  privacyMode: 'strict',         // 'strict' | 'balanced' | 'permissive'
},
})

Privacy Modes

| Mode | Text | Inputs | Use case | |------|------|--------|----------| | strict | Masked | Masked | Default, GDPR-safe | | balanced | Visible | Masked | Better context | | permissive | Visible | Visible | Internal tools only |

HTML Privacy Attributes

Privacy Attributes
<!-- Block element entirely -->
<div data-vd-block>Sensitive content</div>

<!-- Mask text with asterisks -->
<span data-vd-mask>[email protected]</span>

<!-- Show content even in strict mode -->
<p data-vd-unmask>Public announcement</p>

Force Upload for VIP Users

Force Upload
// Always capture replay for important users
if (user.plan === 'enterprise') {
vident.forceReplayUpload()
}

Framework Integration

Next.js

Next.js App Router
// next.config.ts
import { withVident } from 'vident-browser/next'
export default withVident({})

// app/providers.tsx — initialize the SDK
'use client'
import { createVidentBrowser } from 'vident-browser'
import { useEffect } from 'react'

let vident: ReturnType<typeof createVidentBrowser> | null = null

export function RumProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
  if (!vident) {
    vident = createVidentBrowser({
      apiKey: process.env.NEXT_PUBLIC_VIDENT_API_KEY!,
    })
  }
}, [])
return children
}

// app/layout.tsx
import { RumProvider } from './providers'

export default function RootLayout({ children }) {
return (
  <html>
    <body>
      <RumProvider>{children}</RumProvider>
    </body>
  </html>
)
}

Script Tag

Script Tag
<script type="module">
import { createVidentBrowser } from 'https://esm.sh/vident-browser'

window.vident = createVidentBrowser({
  apiKey: 'vd_...',
  appName: 'my-site',
})
</script>

API Reference

Client Methods

| Method | Description | |--------|-------------| | trackEvent(name, props?) | Track custom event | | trackPageView(url?) | Manual page view | | trackError(error, opts?) | Manual error capture | | setUser(id, traits?) | Identify user | | getSessionId() | Get current session ID | | forceReplayUpload() | Force replay upload | | stopReplay() | Stop replay recording |

Session Functions

Session Functions
import { getSessionId, endSession } from 'vident-browser'

// Get current session ID (or null if expired)
const sessionId = getSessionId()

// Manually end session (starts new one on next event)
endSession()

Sampling

Sampling
createVidentBrowser({
apiKey: 'vd_...',
sampleRate: 0.5,  // Only 50% of sessions tracked
})

When sampled out, the client returns a no-op implementation with zero overhead.