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 initialise 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>Vercel#
If the site is deployed on Vercel, the Webrec integration connects a Vercel project to a Webrec project and writes the API key into it as NEXT_PUBLIC_WEBREC_API_KEY, on Production, Preview and Development. You still install the SDK, but there is no key to copy across by hand and no key sitting in your repository.
import { WebRec } from 'webrec-sdk';
WebRec.init({ apiKey: process.env.NEXT_PUBLIC_WEBREC_API_KEY });Redeploy for the variable to take effect. Disconnecting the project removes the variable the integration created, and nothing else.
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#
Initialise 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) | Initialise recording with configuration |
WebRec.identify(userId, traits?) | Link the session to a known user |
WebRec.group(groupId, traits?) | Associate user with an organisation/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: '[email protected]',
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.
Organisation Tracking#
Associate users with their company or team using group(). This enables organisation-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 organisation context is known. The group association persists across page loads via localStorage.
Organisation 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: '[email protected]',
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 finalised.
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: 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 30px of each other 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 prioritise 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 visualisation.
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#
Customise position (bottom-right, bottom-left, bottom-center), theme (light/dark), and primary colour. 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 visualisation 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 visualisation
- 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 Initialisation#
// 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: our own UK infrastructure, operated by Rouic Ltd. Session data stays in the UK
- 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 [email protected]
- Data Processing Agreement: Available on request for enterprise plans
- Sub-processors: Stripe (billing only); hosting is self-operated
- No third-party cookies: Webrec uses zero third-party cookies. Session IDs and anonymous IDs are stored in localStorage; the session ID is shared across tabs and expires after 30 minutes of inactivity
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: 50 KB gzipped (170 KB raw)
- 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.
Sessions & Filtering#
The sessions page lists every recorded session and lets you filter by:
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#
Organise 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).
Organisation Setup#
Organisations 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 organisation 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 [email protected]. We typically respond within a few hours.