Documentation
Everything you need to install, configure, and get the most out of Webrec.
Quick Start
Get your first session recording in under two minutes.
npm install webrec-sdkimport { WebRec } from 'webrec-sdk';
WebRec.init({
apiKey: 'wr_your_project_key',
});
// Optional: identify logged-in users
WebRec.identify(user.id, {
name: user.name,
email: user.email,
});That’s it. Sessions will appear in your dashboard within seconds. Your API key is available in Project Settings → API Keys.
Installation
Package Manager
npm install webrec-sdk
# or with yarn
yarn add webrec-sdk
# or with pnpm
pnpm add webrec-sdkThen import and initialize in your application entry point:
import { WebRec } from 'webrec-sdk';
WebRec.init({
apiKey: 'wr_your_project_key',
});Script Tag
For sites without a bundler, load the SDK directly:
<script src="https://api.webrec.app/v1/webrec.min.js"></script>
<script>
WebRec.init({ apiKey: 'wr_your_project_key' });
</script>CDN
You can also load from a public CDN:
<!-- Via unpkg -->
<script src="https://unpkg.com/webrec-sdk@latest/dist/webrec.umd.js"></script>
<!-- Via jsdelivr -->
<script src="https://cdn.jsdelivr.net/npm/webrec-sdk/dist/webrec.umd.js"></script>Framework Guides
React / Next.js
Initialize once in a top-level component or layout. Use useEffect to ensure it only runs client-side.
'use client';
import { useEffect } from 'react';
import { WebRec } from 'webrec-sdk';
export function WebrecProvider({ children }: { children: React.ReactNode }) {
useEffect(() => {
WebRec.init({ apiKey: 'wr_your_project_key' });
return () => WebRec.destroy();
}, []);
return <>{children}</>;
}_app.tsx inside a useEffect.Vue / Nuxt
import { WebRec } from 'webrec-sdk';
export default defineNuxtPlugin(() => {
WebRec.init({ apiKey: 'wr_your_project_key' });
});For Vue 3 without Nuxt, call WebRec.init() in your main.ts after createApp().
Svelte / SvelteKit
<script>
import { onMount } from 'svelte';
import { WebRec } from 'webrec-sdk';
onMount(() => {
WebRec.init({ apiKey: 'wr_your_project_key' });
return () => WebRec.destroy();
});
</script>
<slot />Angular
import { Component, OnInit, OnDestroy } from '@angular/core';
import { WebRec } from 'webrec-sdk';
@Component({ selector: 'app-root', templateUrl: './app.component.html' })
export class AppComponent implements OnInit, OnDestroy {
ngOnInit() {
WebRec.init({ apiKey: 'wr_your_project_key' });
}
ngOnDestroy() {
WebRec.destroy();
}
}WordPress
Download the pre-configured plugin from your Project Settings → Installation → WordPress tab. It comes with your API key baked in — just upload and activate.
Or add this to your theme’s functions.php:
function webrec_tracking_script() {
echo '<script src="https://api.webrec.app/v1/webrec.min.js"></script>';
echo '<script>WebRec.init({ apiKey: "wr_your_project_key" });</script>';
}
add_action('wp_head', 'webrec_tracking_script');The WordPress plugin includes additional features:
- Automatic user identification — logged-in WordPress users are identified with their name, email, and role
- Admin exclusion — skip recording for admin users (enabled by default)
- Settings page — configure privacy options under Settings → Webrec
- Caching compatible — works with WP Super Cache, W3 Total Cache, and other caching plugins
Google Tag Manager
Add Webrec via Google Tag Manager in 4 steps:
- In GTM, go to Tags → New
- Choose Custom HTML as the tag type
- Paste the code below
- Set the trigger to All Pages, save, and publish
<script src="https://api.webrec.app/v1/webrec.min.js"></script>
<script>
WebRec.init({
apiKey: 'wr_your_project_key',
maskAllInputs: true,
respectDoNotTrack: true,
});
</script>User Identification via Data Layer
<script>
// Read user data from GTM data layer
var userId = {{DL - User ID}};
var userName = {{DL - User Name}};
var userEmail = {{DL - User Email}};
if (userId && window.WebRec) {
WebRec.identify(userId, {
name: userName,
email: userEmail,
});
}
</script>Shopify
Add Webrec to your Shopify store by editing your theme code:
- In Shopify admin, go to Online Store → Themes
- Click … → Edit code on your active theme
- Open
layout/theme.liquid - Paste this just before the closing
</head>tag
<script src="https://api.webrec.app/v1/webrec.min.js"></script>
<script>
WebRec.init({
apiKey: 'wr_your_project_key',
maskAllInputs: true,
});
{% if customer %}
WebRec.identify('{{ customer.id }}', {
name: '{{ customer.name }}',
email: '{{ customer.email }}',
});
{% endif %}
</script>This works with all Shopify themes including Dawn, and is compatible with Shopify’s Online Store 2.0.
Webflow
Add Webrec to your Webflow site in two steps:
- Go to Project Settings → Custom Code
- Paste this in the Head Code section
<script src="https://api.webrec.app/v1/webrec.min.js"></script>
<script>
WebRec.init({
apiKey: 'wr_your_project_key',
maskAllInputs: true,
respectDoNotTrack: true,
});
</script>Click Save, then Publish your site. Recording starts on all pages automatically.
Squarespace
Add Webrec to your Squarespace site:
- Go to Settings → Advanced → Code Injection
- Paste this in the Header section
- Click Save
<script src="https://api.webrec.app/v1/webrec.min.js"></script>
<script>
WebRec.init({
apiKey: 'wr_your_project_key',
maskAllInputs: true,
respectDoNotTrack: true,
});
</script>Works on all pages automatically. Compatible with all Squarespace templates (7.0 and 7.1).
Wix
Add Webrec to your Wix site:
- Go to Settings → Custom Code (or Tracking & Analytics)
- Click + Add Custom Code
- Paste the code below
- Set placement to Head and apply to All pages
- Click Apply
<script src="https://api.webrec.app/v1/webrec.min.js"></script>
<script>
WebRec.init({
apiKey: 'wr_your_project_key',
maskAllInputs: true,
respectDoNotTrack: true,
});
</script>Works on all pages automatically. If you use Wix Members, you can identify users with a Velo code snippet.
Framer
Add Webrec to your Framer site:
- Go to Site Settings → General → Custom Code
- Paste this in the Head section
- Publish your site
<script src="https://api.webrec.app/v1/webrec.min.js"></script>
<script>
WebRec.init({
apiKey: 'wr_your_project_key',
maskAllInputs: true,
});
</script>Ghost
Add Webrec to your Ghost blog:
- Go to Settings → Code Injection
- Paste this in the Site Header section
- Click Save
<script src="https://api.webrec.app/v1/webrec.min.js"></script>
<script>
WebRec.init({
apiKey: 'wr_your_project_key',
maskAllInputs: true,
});
</script>Configuration
Pass configuration to WebRec.init(). Only apiKey is required.
| Option | Default | Description |
|---|---|---|
apiKey | (required) | Your project API key (starts with wr_) |
endpoint | 'https://api.webrec.app/v1' | API endpoint URL. Change for proxy setups. |
sampleRate | 100 | Percentage of sessions to record (0–100) |
maskAllInputs | true | Mask all form input values by default |
respectDoNotTrack | true | Honour the browser Do Not Track setting |
captureNetwork | true | Record fetch/XHR requests |
captureConsole | true | Capture console output (log, warn, error) |
captureErrors | true | Track uncaught JS errors and promise rejections |
recordCanvas | false | Record canvas/WebGL elements (higher CPU) |
collectFonts | true | Collect page fonts for accurate replay |
sessionTimeout | 1800000 | Inactivity timeout before new session (ms) |
batchSize | 50 | Events per batch before flush |
flushInterval | 5000 | Batch flush interval (ms) |
maxQueueSize | 2000 | Max events in memory before oldest eviction |
maxRetries | 3 | Retry attempts for failed network flushes |
minSessionDuration | 0 | Discard sessions shorter than N seconds |
minTimeOnPage | 0 | Delay recording until user is on page for N ms |
startDelay | 0 | Delay in ms before recording starts after init |
blockClass | 'wr-block' | CSS class to exclude elements from recording |
ignoreClass | 'wr-ignore' | CSS class to stop recording element changes |
blockSelector | '' | CSS selector to exclude elements |
ignoreSelector | '' | CSS selector to stop recording |
ignoreUrls | [] | Regex patterns — skip recording on matching URLs |
allowUrls | [] | If set, only record matching URL patterns |
debug | false | Enable verbose console logging from the SDK |
Sampling Sub-config
WebRec.init({
apiKey: '...',
sampling: {
mousemove: 50, // Throttle mouse events to every 50ms (false to disable)
scroll: 150, // Throttle scroll events to every 150ms
input: 'last', // 'last' = only final value, 'all' = every keystroke
},
});Privacy Sub-config
WebRec.init({
apiKey: '...',
privacy: {
maskInputs: true, // Mask email/tel inputs
maskTextContent: false, // Replace ALL text with asterisks
blockSelectors: [], // CSS selectors to block entirely
ignoreSelectors: [], // CSS selectors to ignore changes on
},
});API Methods
| Method | Description |
|---|---|
WebRec.init(config) | Initialize recording with configuration |
WebRec.identify(userId, traits?) | Link the session to a known user |
WebRec.group(groupId, traits?) | Associate user with an organization/company |
WebRec.track(event, properties?) | Send a custom business event |
WebRec.stop() | Pause recording (events are not captured) |
WebRec.start() | Resume recording after stop() |
WebRec.destroy() | Full teardown — removes all listeners, allows re-init |
WebRec.getSessionId() | Returns the current session ID (or null) |
WebRec.getSessionUrl() | Returns a direct link to this session in the dashboard |
WebRec.isRecording() | Returns true if actively recording |
User Identification
Call identify() after your user logs in to link sessions to real users. Traits persist across page loads via localStorage.
WebRec.identify('user-123', {
name: 'Jane Doe',
email: 'jane@example.com',
plan: 'pro', // custom property
company: 'Acme Corp', // custom property
});When you identify a user, Webrec automatically back-fills all previous anonymous sessions from that browser, so you get a complete history.
Organization Tracking
Associate users with their company or team using group(). This enables organization-level analytics, filtering sessions by company, and tracking properties like plan or MRR.
WebRec.group('org-456', {
name: 'Acme Corp',
domain: 'acme.com',
plan: 'enterprise',
mrr: 15000,
industry: 'SaaS',
employeeCount: 250,
});Call group() after identify() — typically on login or when the user’s organization context is known. The group association persists across page loads via localStorage.
Organization Properties
Any key-value pairs passed to group() (beyond name and domain) are stored as custom properties. These are fully searchable and filterable:
- String properties —
plan,industry,tier - Numeric properties —
mrr,employeeCount,seats(supports range queries like > 10000) - Boolean properties —
isEnterprise,hasSso
Custom User Properties
Similarly, any traits passed to identify() beyond name and email are stored as searchable user properties:
WebRec.identify('user-123', {
name: 'Jane Smith',
email: 'jane@acme.com',
plan: 'pro', // custom property
role: 'admin', // custom property
signupDate: '2025-01-15', // custom property
});These appear on the user detail page and can be used in filters and segments.
Custom Events
Track business events like purchases, sign-ups, or feature usage:
WebRec.track('checkout_completed', {
value: 99.00,
currency: 'USD',
item_count: 3,
});
WebRec.track('feature_used', {
feature: 'dark_mode',
source: 'settings',
});Custom events appear in the session timeline, can be used as funnel steps, and are available in trend breakdowns.
Session Control
Consent-Based Recording
To wait for user consent before recording, call stop() immediately after init(), then start() when consent is granted:
WebRec.init({ apiKey: '...' });
WebRec.stop(); // Paused — no data captured
// When user grants consent:
WebRec.start(); // Recording beginsTeardown
Call destroy() for full cleanup (removes all event listeners, interceptors, and internal state). You can call init() again afterwards.
// In React useEffect cleanup:
return () => WebRec.destroy();Session Timeout
Sessions automatically rotate after 30 minutes of inactivity (configurable via sessionTimeout). A new session ID is generated and the old session is finalized.
Session Replay
Every session is recorded as a pixel-perfect DOM replay using rrweb. The replay player includes:
- Playback controls — play, pause, skip inactive, speed (1x–16x), fullscreen
- Timeline scrubber — with markers for errors (red), rage clicks (orange), and custom events (blue)
- Inspect mode — click any element during playback to see its selector, classes, attributes, and size
- DevTools panel — Console, Network, Events, Errors, and Custom Events tabs
- Right sidebar — session overview, device info, user profile, web vitals, AI summary
- AI summaries — one-click GPT-powered analysis of what happened in the session
- Sharing — generate a shareable link with optional password and expiration
- Comments — add timestamped comments for your team
Space to play/pause, D for DevTools, F for fullscreen.Frustration Detection
Webrec automatically detects three types of user frustration:
Rage Clicks
3 or more clicks within a 30px radius in under 800ms. These indicate an element that isn’t responding as expected.
Dead Clicks
Clicks on interactive elements (buttons, links, inputs) that produce no DOM change, navigation, or network request within 2 seconds.
Error Clicks
Clicks that are followed by a JavaScript error within 1 second. These help you find which user actions trigger bugs.
Frustration Score
Every session gets a composite frustration score (0–100) based on rage clicks, dead clicks, error clicks, and error count. Use this to prioritize which sessions to review.
| Score | Level | Meaning |
|---|---|---|
0 | None | No frustration signals detected |
1–4 | Low | Minor friction — worth monitoring |
5–9 | Medium | Noticeable frustration — review recommended |
10+ | High | Significant frustration — investigate urgently |
Heatmaps
Click Heatmaps
Aggregated click density maps overlaid on your pages. Filter by device type (desktop, tablet, mobile), URL, and time period. Click data is bucketed into a 5px grid for smooth visualization.
Scroll Depth
See how far users scroll on each page. Scroll depth is tracked as a percentage (0–100%) and reported per session when the user navigates away or the tab becomes hidden.
Select pages from the page picker dropdown and switch between exact URL matching or base URL grouping to aggregate variants.
In-App Surveys
Deploy surveys directly in your app. Create them in the dashboard and they’re automatically shown to matching users via the SDK.
Question Types
- NPS — Net Promoter Score (0–10 scale)
- Rating — 1–5 star rating
- Single Choice — radio button selection
- Multiple Choice — checkbox selection
- Open Text — free-form text response
Targeting
Control who sees the survey and when:
- URL match — show on specific pages (supports regex)
- Show after — delay N seconds before displaying
- Show to % — only show to a percentage of visitors
- Once per session — prevent re-showing in the same session
Appearance
Customize position (bottom-right, bottom-left, bottom-center), theme (light/dark), and primary color. Surveys render in a Shadow DOM so your site’s CSS won’t interfere.
Error Tracking
Webrec captures uncaught JavaScript errors and unhandled promise rejections automatically (when captureErrors: true).
- Errors are grouped by type + stack trace fingerprint
- Each group shows first/last occurrence, total count, and affected sessions
- Click any error to jump to the session replay at the exact moment
- Stack traces are displayed with source file, line, and column
- Filter by error type, message, URL, date range, and occurrence count
Web Vitals
Webrec collects Core Web Vitals automatically:
| Metric | What It Measures | Good Threshold |
|---|---|---|
LCP | Largest Contentful Paint — loading speed | ≤ 2.5s |
FCP | First Contentful Paint — time to first render | ≤ 1.8s |
CLS | Cumulative Layout Shift — visual stability | ≤ 0.1 |
INP | Interaction to Next Paint — responsiveness | ≤ 200ms |
TTFB | Time to First Byte — server response time | ≤ 800ms |
View P75 values, rating distribution (good / needs improvement / poor), and daily trends in the Vitals page. Click any metric to see sessions filtered by performance rating.
Funnels
Build conversion funnels to see where users drop off. Each step can be a page URL or a custom action/event.
- Add up to N steps with the page picker (auto-suggests your most visited pages)
- See conversion rate, drop-off count, and median time between each step
- Click any step to view the sessions that reached (or dropped off at) that point
- AI-powered conversion driver analysis shows which actions correlate with completion
Retention
Cohort retention analysis shows how many users return over time. Requires identified users (call WebRec.identify()).
Choose between daily, weekly, or monthly cohorts. The heatmap visualization colour-codes each cell by retention percentage — dark green means high retention.
User Journeys
Sankey flow diagrams visualise the most common paths users take through your site. See which pages users visit before and after any given page, with edge thickness proportional to traffic volume.
Filter by time period and start/end page. A “Top Paths” table below the diagram lists the most frequent multi-step paths with session counts.
Trends
Time-series analysis of key metrics with dimensional breakdowns. Choose a metric (sessions, users, errors, rage clicks, duration, page views), then break down by browser, OS, device, country, or page.
Line charts and stacked area charts with daily, weekly, or monthly granularity. Hover for detailed tooltips. Export data as CSV.
Custom Dashboards
Build your own dashboards with drag-and-drop widgets. Available widget types:
- Metric — single number with trend indicator
- Time series — line/bar chart over time
- Funnel — embedded funnel visualization
- Table — tabular data with sorting
- Retention — cohort retention heatmap
- Journey — Sankey flow diagram
Start with a template or build from scratch. Each dashboard can be shared with your team.
Input Masking & Blocking
Input Masking
All form inputs are masked by default (maskAllInputs: true). Password fields are always masked regardless of configuration. Users see *** in the replay instead of actual values.
Element Blocking
Completely exclude elements from recordings:
<!-- Block by class -->
<div class="wr-block">This entire element is excluded</div>
<!-- Block by data attribute -->
<div data-wr-block>Also excluded</div>
<!-- Block by CSS selector (in config) -->
WebRec.init({
apiKey: '...',
blockSelector: '.sensitive-data, #credit-card-form',
});Blocked elements are replaced with a placeholder in the replay. Ignored elements (wr-ignore) are visible but changes within them are not recorded.
Text Content Masking
For maximum privacy, enable privacy.maskTextContent: true to replace ALL visible text with asterisks. Useful for industries handling highly sensitive data.
Network Redaction
Sensitive query parameters are automatically stripped from captured URLs: token, key, password, secret, auth, access_token, api_key, jwt, session_token.
Request and response bodies are only captured for payloads under 16 KB. Configure excluded domains and patterns in Project Settings.
Consent Controls
Webrec supports consent-based recording out of the box. Three approaches:
1. Stop/Start Pattern
WebRec.init({ apiKey: '...' });
WebRec.stop(); // No recording until consent
onUserConsent(() => {
WebRec.start(); // Begin recording
});2. Delayed Initialization
// Only init after consent
onUserConsent(() => {
WebRec.init({ apiKey: '...' });
});3. Do Not Track
Set respectDoNotTrack: true (default) to automatically skip recording for users who have enabled DNT in their browser.
GDPR Compliance
- Legal basis: Legitimate interest (with proper disclosure) or explicit consent
- Data hosting: GCP europe-west2 (London). Session data stays in the EU
- Data retention: Configurable per plan (7, 90, or 365 days). Data is automatically purged after expiry
- Data subject rights: Access, erasure, and portability requests are supported. Contact support@webrec.app
- Data Processing Agreement: Available on request for enterprise plans
- Sub-processors: GCP (infrastructure), Stripe (billing only)
- No third-party cookies: Webrec uses zero third-party cookies. Session IDs are stored in sessionStorage; anonymous IDs in localStorage
Reverse Proxy
Route SDK traffic through your own domain to avoid ad blockers and keep all requests first-party. This is the recommended production setup.
Nginx
location /wr/ {
proxy_pass https://api.webrec.app/v1/;
proxy_set_header Host api.webrec.app;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}Vercel / Next.js Rewrites
module.exports = {
async rewrites() {
return [
{
source: '/wr/:path*',
destination: 'https://api.webrec.app/v1/:path*',
},
];
},
};Cloudflare Workers
export default {
async fetch(request) {
const url = new URL(request.url);
url.hostname = 'api.webrec.app';
url.pathname = url.pathname.replace('/wr/', '/v1/');
return fetch(url, request);
},
};Then point the SDK at your proxy:
WebRec.init({
apiKey: 'wr_your_project_key',
endpoint: 'https://yourdomain.com/wr',
});Content Security Policy
If your site uses a strict CSP, add these directives:
script-src 'self' https://api.webrec.app;
connect-src 'self' https://api.webrec.app;If using a reverse proxy, replace https://api.webrec.app with your proxy domain. If using the CDN script tag, also add the CDN domain (https://unpkg.com or https://cdn.jsdelivr.net).
Single-Page Apps
Webrec automatically detects SPA route changes by intercepting:
history.pushState()andhistory.replaceState()popstateevents (back/forward navigation)hashchangeevents
Each navigation is recorded as a page view event with from_url and to_url. No additional configuration needed — it works with React Router, Vue Router, Next.js, and any other client-side routing library.
WebRec.destroy() in your component cleanup (e.g. React useEffect return) to prevent duplicate listeners on hot module replacement during development.Sampling & Performance
Session Sampling
Reduce data volume by only recording a percentage of sessions:
WebRec.init({
apiKey: '...',
sampleRate: 50, // Record 50% of sessions
});Event Throttling
Reduce CPU and network overhead by throttling high-frequency events:
WebRec.init({
apiKey: '...',
sampling: {
mousemove: 100, // Throttle to every 100ms (default: 50)
scroll: 250, // Throttle to every 250ms (default: 150)
input: 'last', // Only capture final input value
},
});Performance Impact
The Webrec SDK is designed for minimal impact:
- Bundle size: 147 KB gzipped
- CPU overhead: < 1% on modern devices
- Network: batched + gzipped, typically 5–20 KB per flush
- Memory: events are evicted when queue exceeds
maxQueueSize
Network & Console Capture
Network Requests
When captureNetwork: true, all fetch() and XMLHttpRequest calls are recorded with method, URL, status, duration, and body (text/JSON under 16 KB). Sensitive query parameters are automatically redacted.
Configure in Project Settings:
- Body capture mode: all / errors only / none
- Excluded domains: skip recording for specific third-party APIs
- Excluded patterns: regex patterns to skip
- Allowed methods: only capture specific HTTP methods
Console Logs
When captureConsole: true, all console.log, console.warn, console.error, console.debug, and console.info calls are captured (messages truncated to 5,000 characters). Visible in the session DevTools panel.
Self-Hosting
Webrec can be fully self-hosted (open-source licence). The stack consists of three services:
- Web — Next.js dashboard (port 3000)
- API — Express.js ingest + REST API (port 8080)
- Jobs — Scheduled tasks (session close, AI summaries, retention cleanup)
Requirements: MySQL 8.0, GCS/S3-compatible object storage, Node.js 18+. Set SELF_HOSTED=true to disable billing and usage limits.
docker/ directory. See the repository README for full deployment instructions.Sessions & Filtering
The sessions page shows all recorded sessions with powerful filtering:
Available Filters
- User: name, email, user ID, identified/anonymous
- Session: URL, duration, error count, click count, active status
- Device: browser, OS, device type, screen dimensions
- Location: country, city
- Behaviour: has rage clicks, has dead clicks, frustration score, has errors
- Time: session start date, time of day
Saved Views
Save any filter combination as a named view. Views can be shared with your team or kept private. Switch between views instantly from the dropdown.
Sorting
Sort by most recent or most frustrated (highest frustration score first). Use the settings cog to hide short sessions (< 1 second).
Replay Player
Click any session to open the replay in a slide-over panel. The player includes:
- Timeline: scrub through the session with visual markers for errors, rage clicks, and events
- DevTools: Console (with level filtering), Network (with status/method/URL filtering), Events, Errors, and Custom Events tabs
- Sidebar: session overview, user info, device details, web vitals, AI summary, comments
- Navigation: previous/next session buttons to quickly scan through your session list
- Actions: favourite, share, open in full-page mode, delete
Users & Segments
Users
The Users page lists all identified users with session count, last seen date, and average session duration. Full-text search across name, email, and user ID. When a user is identified, all previous anonymous sessions are merged automatically.
Segments
Create reusable user segments based on conditions like country, browser, OS, device type, session duration, error count, or URL patterns. Segments support AND/OR logic and can be used in session filters and survey targeting.
Collections & Views
Collections
Organize sessions into named, colour-coded collections. Add sessions from the session list (multi-select) or from the replay player. Useful for grouping related sessions during bug investigations or UX reviews.
Favourites
Star any session to add it to your personal favourites list for quick access.
Data Export
Export data as CSV from the sessions list, errors page, users page, and analytics views. Use the download icon in the toolbar.
REST API endpoints for programmatic access:
GET /api/projects/:projectId/sessions?format=csv
GET /api/projects/:projectId/errors?format=csv
GET /api/projects/:projectId/users?format=csvAll API requests require a valid session token (same auth used by the dashboard).
Organization Setup
Organizations are the top-level container for projects, members, and billing. Create one during onboarding, or add more from the org switcher in the header.
Each organization has its own member list, billing plan, API keys, and SSO configuration.
Roles & Permissions
| Role | Permissions |
|---|---|
Owner | Full access. Manage billing, delete org, change any role. |
Admin | Manage projects, invite members, manage settings. Cannot delete org. |
Member | View and create projects, record sessions, view all data. |
Viewer | Read-only access to assigned projects. Cannot modify settings. |
Invite team members by email from Settings → Members. All plans include unlimited seats — no per-seat pricing.
SSO / SAML
Enterprise SSO via SAML 2.0 or OIDC. Configure in Settings → SSO:
- Copy the Entity ID and ACS URL from the Service Provider Metadata section
- Add these to your Identity Provider (Okta, Azure AD, Google Workspace, etc.)
- Paste the IdP Entity ID, IdP SSO URL, and Certificate into Webrec
- Enable SSO. Optionally enforce SSO to require all members to authenticate via your IdP
Plans & Billing
Webrec offers a free tier (100 sessions/month) and paid plans that scale with usage. All plans include unlimited team members. View your current usage and manage your subscription in Settings → Billing.
Overage is billed at the per-session rate for your plan. Set spend limits to cap costs. See the pricing page for full details.
Alerts & Webhooks
Alert Rules
Create rules that fire when thresholds are breached:
- Error Spike — N+ errors within a time window
- New Error — a previously unseen error type appears
- Rage Clicks — N+ rage click sessions in a period
- Slow Vitals — web vital metric exceeds threshold
Notifications can be sent via email, Slack, or webhook.
Webhooks
Send HTTP POST requests to your endpoint when events occur. Available events: new_error, rage_click, session_end, alert_fired. Each webhook includes a secret key for signature verification.
{
"event": "new_error",
"project_id": "abc-123",
"data": {
"error_type": "TypeError",
"message": "Cannot read property 'map' of undefined",
"url": "/dashboard",
"session_id": "sess-456",
"session_url": "https://app.webrec.app/..."
},
"timestamp": "2025-03-28T10:00:00Z"
}Jira & Linear
Create issues directly from a session replay with one click. The issue automatically includes:
- Session replay link
- Error details and stack trace (if applicable)
- Device, browser, and OS info
- Steps to reproduce (from the session timeline)
Jira Setup
In Project Settings → Integrations, add your Jira domain, email, API token, and default project key. Issues are created via the Jira REST API.
Linear Setup
Add your Linear API key and team ID. Issues are created in the selected team with a link back to the session.
Slack
Send alert notifications to a Slack channel. Configure in Project Settings → Integrations. Messages include formatted error details, session links, and quick-action buttons.
Best Practices: Performance
- Use a reverse proxy — eliminates CORS preflight overhead and avoids ad blockers
- Set
sampleRate— if you have high traffic, recording 20–50% of sessions still gives statistically meaningful data - Increase
sampling.mousemove— throttling from 50ms to 100–200ms significantly reduces event volume with negligible replay quality loss - Disable
recordCanvas— canvas recording is CPU-intensive. Only enable if you need to replay canvas-based content - Set
minSessionDuration— discarding sessions under 2–3 seconds filters out bots and accidental visits - Use
ignoreUrls— skip recording on admin pages, internal tools, or healthcheck routes
Best Practices: Privacy-First Recording
- Keep
maskAllInputs: true(default) — you rarely need actual form values for debugging - Block sensitive sections — add
wr-blockto payment forms, personal data views, and admin panels - Use consent-based recording — if required by your privacy policy, use the stop/start pattern
- Configure network exclusions — exclude domains that return sensitive data in responses
- Set appropriate retention — shorter retention windows reduce compliance scope
- Document your legal basis — include session recording in your privacy policy with clear disclosure
Best Practices: Debugging Workflows
- Start with frustrated sessions — sort by frustration score to find the most problematic sessions first
- Use error click correlation — the Error Clicks page shows exactly which user actions trigger bugs
- Filter by error group — from the Errors page, click into a group to see all affected sessions
- Use the DevTools timeline — red markers on the timeline scrubber show exactly when errors occurred
- Create collections for investigations — group related sessions into a collection to share with your team
- Link to Jira/Linear — create issues directly from the replay with all context included automatically
- Use
WebRec.getSessionUrl()— log it to your error reporting tool (Sentry, Bugsnag) to link errors to replays
import * as Sentry from '@sentry/browser';
import { WebRec } from 'webrec-sdk';
Sentry.init({ dsn: '...' });
// After WebRec init:
const sessionUrl = WebRec.getSessionUrl();
if (sessionUrl) {
Sentry.setTag('webrec_session', sessionUrl);
}Troubleshooting
Sessions not appearing
- Check your API key is correct and starts with
wr_ - Verify the SDK is loaded — check for
[Webrec]messages in the browser console - Enable
debug: truein the config for verbose logging - Check for ad blockers — use a reverse proxy to avoid this
- Verify
sampleRateis not set too low - Check that
respectDoNotTrackisn’t blocking you (some dev browsers have DNT on) - Ensure
minSessionDurationisn’t filtering out your test sessions
CORS errors
If you see CORS errors in the console, set up a reverse proxy to route traffic through your domain. This is the recommended approach for production.
CSP violations
Add api.webrec.app (or your proxy domain) to your script-src and connect-src directives. See the CSP section for details.
High CPU usage
Disable recordCanvas, increase sampling.mousemove to 200+, and check if captureNetwork is recording large response bodies. See Sampling & Performance.
Replay looks broken
This can happen if CSS is loaded from a CDN that blocks cross-origin access. Ensure your stylesheets include crossorigin="anonymous" and your CDN sends Access-Control-Allow-Origin headers. Enabling collectFonts: true (default) also helps with font rendering accuracy.
Need help?
Email us at support@webrec.app. We typically respond within a few hours.