docs: session replay
This commit is contained in:
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"pages": ["sdks", "how-it-works", "..."]
|
||||
"pages": ["sdks", "how-it-works", "session-replay", "..."]
|
||||
}
|
||||
|
||||
152
apps/public/content/docs/(tracking)/session-replay.mdx
Normal file
152
apps/public/content/docs/(tracking)/session-replay.mdx
Normal file
@@ -0,0 +1,152 @@
|
||||
---
|
||||
title: Session Replay
|
||||
description: Record and replay user sessions to understand exactly what users did. Loaded asynchronously so it never bloats your analytics bundle.
|
||||
---
|
||||
|
||||
import { Callout } from 'fumadocs-ui/components/callout';
|
||||
|
||||
Session replay captures a structured recording of what users do in your app or website. You can replay any session to see which elements were clicked, how forms were filled, and where users ran into friction—without guessing.
|
||||
|
||||
<Callout type="info">
|
||||
Session replay is **not enabled by default**. You explicitly opt in per-project. When disabled, the replay script is never downloaded, keeping your analytics bundle lean.
|
||||
</Callout>
|
||||
|
||||
## How it works
|
||||
|
||||
OpenPanel session replay is built on [rrweb](https://www.rrweb.io/), an open-source library for recording and replaying web sessions. It captures DOM mutations, mouse movements, scroll positions, and interactions as structured data—not video.
|
||||
|
||||
The replay module is loaded **asynchronously** as a separate script (`op1-replay.js`). This means:
|
||||
|
||||
- Your main tracking script (`op1.js`) stays lightweight even when replay is disabled
|
||||
- The replay module is only downloaded for sessions that are actually recorded
|
||||
- No impact on page load performance when replay is turned off
|
||||
|
||||
## Limits & retention
|
||||
|
||||
- **Unlimited replays** — no cap on the number of sessions recorded
|
||||
- **30-day retention** — replays are stored and accessible for 30 days
|
||||
|
||||
## Setup
|
||||
|
||||
### Script tag
|
||||
|
||||
Add `sessionReplay` to your `init` call. The replay script loads automatically from the same CDN as the main script.
|
||||
|
||||
```html title="index.html"
|
||||
<script>
|
||||
window.op=window.op||function(){var n=[];return new Proxy(function(){arguments.length&&n.push([].slice.call(arguments))},{get:function(t,r){return"q"===r?n:function(){n.push([r].concat([].slice.call(arguments)))}} ,has:function(t,r){return"q"===r}}) }();
|
||||
window.op('init', {
|
||||
clientId: 'YOUR_CLIENT_ID',
|
||||
trackScreenViews: true,
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<script src="https://openpanel.dev/op1.js" defer async></script>
|
||||
```
|
||||
|
||||
### NPM package
|
||||
|
||||
```ts title="op.ts"
|
||||
import { OpenPanel } from '@openpanel/web';
|
||||
|
||||
const op = new OpenPanel({
|
||||
clientId: 'YOUR_CLIENT_ID',
|
||||
trackScreenViews: true,
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
With the npm package, the replay module is a dynamic import code-split by your bundler. It is never included in your main bundle when session replay is disabled.
|
||||
|
||||
## Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
|---|---|---|---|
|
||||
| `enabled` | `boolean` | `false` | Enable session replay recording |
|
||||
| `maskAllInputs` | `boolean` | `true` | Mask all input field values with `*` |
|
||||
| `maskTextSelector` | `string` | `[data-openpanel-replay-mask]` | CSS selector for text elements to mask |
|
||||
| `blockSelector` | `string` | `[data-openpanel-replay-block]` | CSS selector for elements to replace with a placeholder |
|
||||
| `blockClass` | `string` | — | Class name that blocks elements from being recorded |
|
||||
| `ignoreSelector` | `string` | — | CSS selector for elements excluded from interaction tracking |
|
||||
| `flushIntervalMs` | `number` | `10000` | How often (ms) recorded events are sent to the server |
|
||||
| `maxEventsPerChunk` | `number` | `200` | Maximum number of events per payload chunk |
|
||||
| `maxPayloadBytes` | `number` | `1048576` | Maximum payload size in bytes (1 MB) |
|
||||
| `scriptUrl` | `string` | — | Custom URL for the replay script (script-tag builds only) |
|
||||
|
||||
## Privacy controls
|
||||
|
||||
Session replay captures user interactions. These options protect sensitive content before it ever leaves the browser.
|
||||
|
||||
### Masking inputs
|
||||
|
||||
All input fields are masked by default (`maskAllInputs: true`). Recorded values appear as `***` in the replay. Disable this only if you have a specific reason—form field contents are almost always personal data.
|
||||
|
||||
### Masking specific text
|
||||
|
||||
Add `data-openpanel-replay-mask` to any element to replace its text with `***` in replays:
|
||||
|
||||
```html
|
||||
<p data-openpanel-replay-mask>Sensitive text here</p>
|
||||
```
|
||||
|
||||
Or use a custom selector:
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
maskTextSelector: '.pii, [data-sensitive]',
|
||||
}
|
||||
```
|
||||
|
||||
### Blocking elements
|
||||
|
||||
Elements matched by `blockSelector` or `blockClass` are replaced with a same-size grey placeholder in the replay. The element and all its children are never recorded.
|
||||
|
||||
```html
|
||||
<div data-openpanel-replay-block>
|
||||
This section won't appear in replays
|
||||
</div>
|
||||
```
|
||||
|
||||
Or with a custom selector and class:
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
blockSelector: '.payment-form, .user-avatar',
|
||||
blockClass: 'no-replay',
|
||||
}
|
||||
```
|
||||
|
||||
### Ignoring interactions
|
||||
|
||||
Use `ignoreSelector` to exclude specific elements from interaction tracking. The element remains visible in the replay but clicks and input events on it are not recorded.
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
ignoreSelector: '.debug-panel',
|
||||
}
|
||||
```
|
||||
|
||||
## Self-hosting
|
||||
|
||||
If you self-host OpenPanel, the replay script is served from your instance automatically. You can also override the script URL if you host it separately:
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
scriptUrl: 'https://your-cdn.example.com/op1-replay.js',
|
||||
}
|
||||
```
|
||||
|
||||
## Related
|
||||
|
||||
- [Session tracking](/features/session-tracking) — understand sessions without full replay
|
||||
- [Session replay feature overview](/features/session-replay) — what you get with session replay
|
||||
- [Web SDK](/docs/sdks/web) — full web SDK reference
|
||||
- [Script tag](/docs/sdks/script) — using OpenPanel via a script tag
|
||||
@@ -8,6 +8,7 @@ import { UserIcon,HardDriveIcon } from 'lucide-react'
|
||||
## ✨ Key Features
|
||||
|
||||
- **🔍 Advanced Analytics**: [Funnels](/features/funnels), cohorts, user profiles, and session history
|
||||
- **🎬 Session Replay**: [Record and replay user sessions](/features/session-replay) with privacy controls built in
|
||||
- **📊 Real-time Dashboards**: Live data updates and interactive charts
|
||||
- **🎯 A/B Testing**: Built-in variant testing with detailed breakdowns
|
||||
- **🔔 Smart Notifications**: Event and funnel-based alerts
|
||||
@@ -28,6 +29,7 @@ import { UserIcon,HardDriveIcon } from 'lucide-react'
|
||||
| 🔁 Real-time dashboards | ✅ | ✅ | ❌ | ✅ |
|
||||
| 🔍 Funnels & cohort analysis | ✅ | ✅ | ✅* | ✅*** |
|
||||
| 👤 User profiles & session history | ✅ | ✅ | ❌ | ❌ |
|
||||
| 🎬 Session replay | ✅ | ✅**** | ❌ | ❌ |
|
||||
| 📈 Custom dashboards & charts | ✅ | ✅ | ✅ | ❌ |
|
||||
| 💬 Event & funnel notifications | ✅ | ✅ | ❌ | ❌ |
|
||||
| 🌍 GDPR-compliant tracking | ✅ | ✅ | ❌** | ✅ |
|
||||
@@ -36,10 +38,14 @@ import { UserIcon,HardDriveIcon } from 'lucide-react'
|
||||
| 🚀 Built for developers | ✅ | ✅ | ❌ | ✅ |
|
||||
| 🔧 A/B testing & variant breakdowns | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
✅* GA4 has a free tier but often requires BigQuery (paid) for raw data access.
|
||||
❌** GA4 has faced GDPR bans in several EU countries due to data transfers to US-based servers.
|
||||
✅* GA4 has a free tier but often requires BigQuery (paid) for raw data access.
|
||||
|
||||
❌** GA4 has faced GDPR bans in several EU countries due to data transfers to US-based servers.
|
||||
|
||||
✅*** Plausible has simple goals
|
||||
|
||||
✅**** Mixpanel session replay is limited to 5k sessions/month on free and 20k on paid. OpenPanel has no limit.
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
Before you can start tracking your events you'll need to create an account or spin up your own instance of OpenPanel.
|
||||
|
||||
166
apps/public/content/features/session-replay.json
Normal file
166
apps/public/content/features/session-replay.json
Normal file
@@ -0,0 +1,166 @@
|
||||
{
|
||||
"slug": "session-replay",
|
||||
"short_name": "Session replay",
|
||||
"seo": {
|
||||
"title": "Session Replay - Watch Real User Sessions | OpenPanel",
|
||||
"description": "Replay real user sessions to understand exactly what happened. Privacy-first session replay with masking controls, unlimited recordings, and 30-day retention.",
|
||||
"keywords": [
|
||||
"session replay",
|
||||
"session recording",
|
||||
"user session replay",
|
||||
"hotjar alternative",
|
||||
"privacy-first session replay"
|
||||
]
|
||||
},
|
||||
"hero": {
|
||||
"heading": "See exactly what your users did",
|
||||
"subheading": "Replay any user session to see clicks, scrolls, and interactions. Privacy controls built in. Loaded async so it never slows down your site.",
|
||||
"badges": [
|
||||
"Unlimited replays",
|
||||
"30-day retention",
|
||||
"Privacy controls built in",
|
||||
"Async—zero bundle bloat"
|
||||
]
|
||||
},
|
||||
"definition": {
|
||||
"title": "What is session replay?",
|
||||
"text": "Session replay lets you watch a structured recording of what a real user did during a visit to your site or app. You see every click, scroll, form interaction, and page navigation—played back in order.\n\nMost analytics tools tell you **what happened in aggregate**: 40% of users dropped off at step 2. Session replay shows you **why**: you can watch someone struggle with a confusing form label, miss a button, or hit an error state you didn't know existed.\n\nOpenPanel session replay is built on [rrweb](https://www.rrweb.io/), an open-source recording library. It captures DOM mutations and user interactions as structured data—not video. This matters because:\n\n- **Privacy is easier to manage** — you control exactly what gets recorded with CSS selectors, not hoping a video blur is accurate\n- **Storage is efficient** — structured data compresses far better than video\n- **Playback is instant** — no buffering or waiting for video to load\n\nSession replay in OpenPanel is **opt-in and off by default**. When disabled, the replay script is never loaded and adds zero bytes to your page. When enabled, the recorder is fetched asynchronously as a separate script, so your main analytics bundle stays lean regardless.\n\nPrivacy controls are first-class:\n\n- **All inputs masked by default** — form field values are never recorded\n- **Block any element** with a data attribute or CSS selector\n- **Mask specific text** without blocking the surrounding layout\n- **Ignore interactions** on sensitive elements\n\nReplays are linked to sessions, events, and user profiles. When a user reports a bug, you can pull up their session in seconds and see exactly what happened—no need to ask them to reproduce it."
|
||||
},
|
||||
"capabilities_section": {
|
||||
"title": "What you get with session replay",
|
||||
"intro": "Everything you need to understand real user behavior, with privacy controls built in from the start."
|
||||
},
|
||||
"capabilities": [
|
||||
{
|
||||
"title": "Full session playback",
|
||||
"description": "Replay any recorded session from start to finish. See clicks, scrolls, form interactions, and navigation in the exact order they happened."
|
||||
},
|
||||
{
|
||||
"title": "Linked to events and profiles",
|
||||
"description": "Replays are tied to the user's session, event timeline, and profile. Jump from a funnel drop-off directly to the replay for context."
|
||||
},
|
||||
{
|
||||
"title": "Input masking by default",
|
||||
"description": "All form field values are masked out of the box. You see that a user typed something—not what they typed. Disable per-field if needed."
|
||||
},
|
||||
{
|
||||
"title": "Block and mask controls",
|
||||
"description": "Block entire elements from recording with a data attribute or CSS selector. Mask specific text. Ignore interactions on sensitive areas."
|
||||
},
|
||||
{
|
||||
"title": "Async loading—zero bundle impact",
|
||||
"description": "The replay module loads as a separate async script. When replay is disabled it's never fetched. When enabled it doesn't block your main bundle."
|
||||
},
|
||||
{
|
||||
"title": "Unlimited replays, 30-day retention",
|
||||
"description": "No cap on the number of sessions recorded. Every replay is stored for 30 days and available for playback at any time."
|
||||
}
|
||||
],
|
||||
"screenshots": [
|
||||
{
|
||||
"src": "/features/feature-sessions.webp",
|
||||
"alt": "Session overview showing user sessions with entry pages and duration",
|
||||
"caption": "Browse all sessions. Click any one to open the replay."
|
||||
},
|
||||
{
|
||||
"src": "/features/feature-sessions-details.webp",
|
||||
"alt": "Session detail view showing events in order",
|
||||
"caption": "The session timeline shows every event alongside the replay."
|
||||
}
|
||||
],
|
||||
"how_it_works": {
|
||||
"title": "How session replay works",
|
||||
"intro": "Enable it once and every qualifying session is recorded automatically.",
|
||||
"steps": [
|
||||
{
|
||||
"title": "Enable replay in your init config",
|
||||
"description": "Set `sessionReplay: { enabled: true }` in your OpenPanel init options. That's all the configuration required to start recording."
|
||||
},
|
||||
{
|
||||
"title": "The replay script loads asynchronously",
|
||||
"description": "When a session starts, OpenPanel fetches the replay module (`op1-replay.js`) as a separate async script. It doesn't block page load or inflate your main bundle."
|
||||
},
|
||||
{
|
||||
"title": "Interactions are captured and sent in chunks",
|
||||
"description": "The recorder captures DOM changes and user interactions and sends them to OpenPanel in small chunks every 10 seconds and on page unload."
|
||||
},
|
||||
{
|
||||
"title": "Replay any session from the dashboard",
|
||||
"description": "Open any session in the dashboard and hit play. The replay reconstructs the user's exact experience. Jump to specific events from the timeline."
|
||||
}
|
||||
]
|
||||
},
|
||||
"use_cases": {
|
||||
"title": "Who uses session replay",
|
||||
"intro": "Teams that need to understand real user behavior beyond what metrics alone can show.",
|
||||
"items": [
|
||||
{
|
||||
"title": "Product teams",
|
||||
"description": "When the data says users drop off at a specific step, session replay shows you exactly why. See confusion, missed CTAs, and error states you didn't know existed."
|
||||
},
|
||||
{
|
||||
"title": "Support and success teams",
|
||||
"description": "When a user reports a bug or a confusing experience, pull up their session replay in seconds. You see what they saw—no need to ask them to reproduce it."
|
||||
},
|
||||
{
|
||||
"title": "Privacy-conscious teams",
|
||||
"description": "Input masking is on by default. Block sensitive UI with a data attribute. You get the behavioral insight without recording personal data."
|
||||
}
|
||||
]
|
||||
},
|
||||
"related_features": [
|
||||
{
|
||||
"slug": "session-tracking",
|
||||
"title": "Session tracking",
|
||||
"description": "Structured session data—entry pages, event timelines, duration—without requiring replay."
|
||||
},
|
||||
{
|
||||
"slug": "event-tracking",
|
||||
"title": "Event tracking",
|
||||
"description": "Custom events appear alongside replays in the session timeline."
|
||||
},
|
||||
{
|
||||
"slug": "funnels",
|
||||
"title": "Funnels",
|
||||
"description": "Jump from a funnel drop-off step directly to the session replay to understand why."
|
||||
}
|
||||
],
|
||||
"faqs": {
|
||||
"title": "Frequently asked questions",
|
||||
"intro": "Common questions about session replay with OpenPanel.",
|
||||
"items": [
|
||||
{
|
||||
"question": "Is session replay enabled by default?",
|
||||
"answer": "No. Session replay is opt-in. You enable it by setting `sessionReplay: { enabled: true }` in your init config. When disabled, the replay script is never fetched and adds zero overhead to your page."
|
||||
},
|
||||
{
|
||||
"question": "Does enabling session replay slow down my site?",
|
||||
"answer": "No. The replay module loads as a separate async script (`op1-replay.js`), independent of the main tracking bundle (`op1.js`). It's fetched after the page loads and does not block rendering or the main analytics script."
|
||||
},
|
||||
{
|
||||
"question": "How is this different from Hotjar or FullStory?",
|
||||
"answer": "Hotjar and FullStory record video-like streams. OpenPanel captures structured DOM events using rrweb. The result looks similar in the viewer, but structured data gives you finer-grained privacy controls (CSS-selector masking, element blocking) and is more storage-efficient. OpenPanel is also open-source and can be self-hosted."
|
||||
},
|
||||
{
|
||||
"question": "Are form inputs recorded?",
|
||||
"answer": "No. All input field values are masked by default (`maskAllInputs: true`). You see that a user interacted with a field, but not what they typed. You can disable this on a per-field basis if needed."
|
||||
},
|
||||
{
|
||||
"question": "How long are replays stored?",
|
||||
"answer": "Replays are retained for 30 days. There is no limit on the number of sessions recorded."
|
||||
},
|
||||
{
|
||||
"question": "Can I block specific parts of my UI from being recorded?",
|
||||
"answer": "Yes. Add `data-openpanel-replay-block` to any element to replace it with a placeholder in the replay. Use `data-openpanel-replay-mask` to mask specific text. Both the attribute names and the CSS selectors they target are configurable."
|
||||
},
|
||||
{
|
||||
"question": "Does session replay work with self-hosted OpenPanel?",
|
||||
"answer": "Yes. When self-hosting, the replay script is served from your instance automatically. You can also override the script URL with the `scriptUrl` option if you host it on a CDN."
|
||||
}
|
||||
]
|
||||
},
|
||||
"cta": {
|
||||
"label": "Start recording sessions",
|
||||
"href": "https://dashboard.openpanel.dev/onboarding"
|
||||
}
|
||||
}
|
||||
@@ -2,31 +2,32 @@
|
||||
"slug": "session-tracking",
|
||||
"short_name": "Session tracking",
|
||||
"seo": {
|
||||
"title": "Session Tracking Without Replays - Privacy-First",
|
||||
"description": "Understand user sessions from entry to exit-without recordings or privacy risk. See pages visited, events fired, and session duration with privacy-first analytics.",
|
||||
"title": "Session Tracking - Understand User Journeys | OpenPanel",
|
||||
"description": "Understand user sessions from entry to exit. See pages visited, events fired, and session duration. Optionally add session replay to watch exactly what users did.",
|
||||
"keywords": [
|
||||
"session tracking analytics",
|
||||
"user session tracking",
|
||||
"session analysis without replay"
|
||||
"session analysis",
|
||||
"session replay analytics"
|
||||
]
|
||||
},
|
||||
"hero": {
|
||||
"heading": "What happened in the session",
|
||||
"subheading": "Pages visited, events fired, time spent. No recordings, no privacy risk. You still get the full picture.",
|
||||
"subheading": "Pages visited, events fired, time spent. Full structured session data—and optional session replay when you need to go deeper.",
|
||||
"badges": [
|
||||
"No session recordings",
|
||||
"Privacy-first by design",
|
||||
"Entry-to-exit visibility",
|
||||
"Sessions linked to events"
|
||||
"Sessions linked to events",
|
||||
"Optional session replay"
|
||||
]
|
||||
},
|
||||
"definition": {
|
||||
"title": "What is session tracking?",
|
||||
"text": "A session is the **window of activity** between a user arriving on your site and leaving. It starts with an entry page, includes every page view and event along the way, and ends when the user goes idle or closes the tab.\n\nMost analytics tools either give you **too little** (aggregated page-view counts with no sense of flow) or **too much** (full session recordings that raise privacy concerns and take hours to review). OpenPanel sits in the middle: you get a **structured timeline** of what happened in each session, without recording a single pixel of the user's screen.\n\nFor every session, OpenPanel captures:\n\n- **Entry page and exit page** - where the user started and where they left\n- **Pages visited in order** - the path through your site or app\n- **Events fired** - signups, clicks, feature usage, or any custom event\n- **Session duration** - how long the session lasted\n- **Referrer and UTM parameters** - how the user got there\n- **Device, browser, and location** - context without fingerprinting\n\nThis means you can answer questions like:\n\n- **What pages do users visit before signing up?**\n- **Do users from organic search behave differently than paid traffic?**\n- **How long are sessions for users who convert vs. those who don't?**\n\nUnlike session replay tools (Hotjar, FullStory, LogRocket), there are **no recordings to watch**, **no PII captured on screen**, and **no consent banners** needed for video replay. You get the analytical value of sessions without the privacy overhead.\n\nSessions in OpenPanel connect directly to **events and user profiles**. Every event belongs to a session, and every session belongs to a user. This means funnels, retention, and user timelines all have session context built in."
|
||||
"text": "A session is the **window of activity** between a user arriving on your site and leaving. It starts with an entry page, includes every page view and event along the way, and ends when the user goes idle or closes the tab.\n\nMost analytics tools either give you **too little** (aggregated page-view counts with no sense of flow) or **too much** (full session recordings that can be slow to review). OpenPanel gives you both options:\n\n- **Session tracking** (always on) — a structured timeline of what happened in each session: pages visited, events fired, duration, referrer, and device context\n- **[Session replay](/features/session-replay)** (opt-in) — a playable recording of the session built on [rrweb](https://www.rrweb.io/), so you can see exactly what the user clicked and where they got confused\n\nFor every session, OpenPanel captures:\n\n- **Entry page and exit page** - where the user started and where they left\n- **Pages visited in order** - the path through your site or app\n- **Events fired** - signups, clicks, feature usage, or any custom event\n- **Session duration** - how long the session lasted\n- **Referrer and UTM parameters** - how the user got there\n- **Device, browser, and location** - context without fingerprinting\n\nThis means you can answer questions like:\n\n- **What pages do users visit before signing up?**\n- **Do users from organic search behave differently than paid traffic?**\n- **How long are sessions for users who convert vs. those who don't?**\n\nSession replay is **opt-in and off by default**. When disabled, the replay script is never loaded and adds no overhead. When enabled, it loads asynchronously as a separate script so your main analytics bundle stays lean.\n\nSessions in OpenPanel connect directly to **events and user profiles**. Every event belongs to a session, and every session belongs to a user. This means funnels, retention, and user timelines all have session context built in."
|
||||
},
|
||||
"capabilities_section": {
|
||||
"title": "What you get with session tracking",
|
||||
"intro": "Structured session data that answers real questions-without the privacy cost of recordings."
|
||||
"intro": "Structured session data that answers real questions—with optional replay when you need to see the full picture."
|
||||
},
|
||||
"capabilities": [
|
||||
{
|
||||
@@ -35,7 +36,7 @@
|
||||
},
|
||||
{
|
||||
"title": "Page flow per session",
|
||||
"description": "View the ordered sequence of pages a user visited in a session. Understand navigation patterns without watching a recording."
|
||||
"description": "View the ordered sequence of pages a user visited in a session. Understand navigation patterns at a glance."
|
||||
},
|
||||
{
|
||||
"title": "Events within a session",
|
||||
@@ -50,8 +51,8 @@
|
||||
"description": "Know how users arrived-organic search, paid campaign, direct link-and compare session quality across sources."
|
||||
},
|
||||
{
|
||||
"title": "Device and location context",
|
||||
"description": "Capture browser, OS, and approximate location for each session. No fingerprinting-just standard request headers."
|
||||
"title": "Session replay (opt-in)",
|
||||
"description": "Enable session replay to record and play back real user sessions. Privacy controls built in—inputs masked by default. Loads async so it never bloats your bundle."
|
||||
}
|
||||
],
|
||||
"screenshots": [
|
||||
@@ -63,7 +64,7 @@
|
||||
{
|
||||
"src": "/features/feature-sessions-details.webp",
|
||||
"alt": "Session events timeline showing user actions in order",
|
||||
"caption": "Every event tied to its session. Understand user journeys without replay tools."
|
||||
"caption": "Every event tied to its session. Drill into the timeline or open the replay."
|
||||
}
|
||||
],
|
||||
"how_it_works": {
|
||||
@@ -80,29 +81,34 @@
|
||||
},
|
||||
{
|
||||
"title": "Sessions connect to everything",
|
||||
"description": "Each session links to the user profile, the events fired, and the pages visited. This means funnels, retention, and user timelines all include session context."
|
||||
"description": "Each session links to the user profile, the events fired, and the pages visited. Enable session replay to also record a playable video of the session."
|
||||
}
|
||||
]
|
||||
},
|
||||
"use_cases": {
|
||||
"title": "Who uses session tracking",
|
||||
"intro": "Teams that need to understand user journeys without the overhead of session replays.",
|
||||
"intro": "Teams that need to understand user journeys, from structured data to full session replay.",
|
||||
"items": [
|
||||
{
|
||||
"title": "Product teams",
|
||||
"description": "Understand how users navigate your product. See the page flow and events in a session to identify friction points-without watching hours of recordings."
|
||||
"description": "Understand how users navigate your product. See the page flow and events in a session, then open a replay to see exactly where users got stuck."
|
||||
},
|
||||
{
|
||||
"title": "Support and success teams",
|
||||
"description": "When a user reports an issue, pull up their recent sessions to see what pages they visited and what events they triggered. Context without asking \"can you describe what you did?\""
|
||||
"description": "When a user reports an issue, pull up their recent sessions to see what pages they visited and what events they triggered. Open the replay for the full picture."
|
||||
},
|
||||
{
|
||||
"title": "Privacy-conscious teams",
|
||||
"description": "Get session-level insights without recording user screens. No PII in screenshots, no video consent banners, no GDPR headaches from replay data."
|
||||
"description": "Session tracking works without cookies or recordings. Session replay is opt-in, with inputs masked by default and granular controls to block or mask any sensitive element."
|
||||
}
|
||||
]
|
||||
},
|
||||
"related_features": [
|
||||
{
|
||||
"slug": "session-replay",
|
||||
"title": "Session replay",
|
||||
"description": "Watch real user sessions. See clicks, scrolls, and form interactions played back in the dashboard."
|
||||
},
|
||||
{
|
||||
"slug": "event-tracking",
|
||||
"title": "Event tracking",
|
||||
@@ -119,8 +125,8 @@
|
||||
"intro": "Common questions about session tracking with OpenPanel.",
|
||||
"items": [
|
||||
{
|
||||
"question": "How is this different from session replay tools like Hotjar or FullStory?",
|
||||
"answer": "Session replay tools record a video of the user's screen. OpenPanel doesn't record anything visual-it tracks structured data: which pages were visited, which events were triggered, and how long the session lasted. You get the analytical answers without the privacy cost or the hours spent watching recordings."
|
||||
"question": "Does OpenPanel have session replay?",
|
||||
"answer": "Yes. Session replay is available as an opt-in feature. Enable it by setting `sessionReplay: { enabled: true }` in your init config. When disabled, the replay script is never loaded. See the [session replay docs](/docs/session-replay) for setup and privacy options."
|
||||
},
|
||||
{
|
||||
"question": "Do I need to set up session tracking separately?",
|
||||
@@ -132,7 +138,7 @@
|
||||
},
|
||||
{
|
||||
"question": "Can I see individual user sessions?",
|
||||
"answer": "Yes. You can view a user's session history, including the pages they visited and events they triggered in each session. This is available in the user profile view."
|
||||
"answer": "Yes. You can view a user's session history, including the pages they visited and events they triggered in each session. This is available in the user profile view. If session replay is enabled, you can also play back the session."
|
||||
},
|
||||
{
|
||||
"question": "Does session tracking require cookies?",
|
||||
@@ -144,4 +150,4 @@
|
||||
"label": "Start tracking sessions",
|
||||
"href": "https://dashboard.openpanel.dev/onboarding"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
245
apps/public/content/guides/session-replay.mdx
Normal file
245
apps/public/content/guides/session-replay.mdx
Normal file
@@ -0,0 +1,245 @@
|
||||
---
|
||||
title: "How to add session replay to your website"
|
||||
description: "Add privacy-first session replay to any site in minutes using OpenPanel. See exactly what users do without recording sensitive data."
|
||||
difficulty: beginner
|
||||
timeToComplete: 10
|
||||
date: 2026-02-27
|
||||
updated: 2026-02-27
|
||||
cover: /content/cover-default.jpg
|
||||
team: OpenPanel Team
|
||||
steps:
|
||||
- name: "Install OpenPanel"
|
||||
anchor: "install"
|
||||
- name: "Enable session replay"
|
||||
anchor: "enable"
|
||||
- name: "Configure privacy controls"
|
||||
anchor: "privacy"
|
||||
- name: "View replays in the dashboard"
|
||||
anchor: "view"
|
||||
---
|
||||
|
||||
# How to add session replay to your website
|
||||
|
||||
This guide walks you through enabling [session replay](/features/session-replay) with OpenPanel. By the end, you'll be recording real user sessions you can play back in the dashboard to understand exactly what your users did.
|
||||
|
||||
Session replay captures clicks, scrolls, and interactions as structured data—not video. Privacy controls are built in, and the replay module loads asynchronously so it never slows down your main analytics.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- An OpenPanel account
|
||||
- Your Client ID from the [OpenPanel dashboard](https://dashboard.openpanel.dev/onboarding)
|
||||
- Either the `@openpanel/web` npm package installed, or access to add a script tag to your site
|
||||
|
||||
## Install OpenPanel [#install]
|
||||
|
||||
If you're starting fresh, add the OpenPanel script tag to your page. If you already have OpenPanel installed, skip to the next step.
|
||||
|
||||
```html title="index.html"
|
||||
<script>
|
||||
window.op=window.op||function(){var n=[];return new Proxy(function(){arguments.length&&n.push([].slice.call(arguments))},{get:function(t,r){return"q"===r?n:function(){n.push([r].concat([].slice.call(arguments)))}} ,has:function(t,r){return"q"===r}}) }();
|
||||
window.op('init', {
|
||||
clientId: 'YOUR_CLIENT_ID',
|
||||
trackScreenViews: true,
|
||||
});
|
||||
</script>
|
||||
<script src="https://openpanel.dev/op1.js" defer async></script>
|
||||
```
|
||||
|
||||
Or with npm:
|
||||
|
||||
```bash
|
||||
npm install @openpanel/web
|
||||
```
|
||||
|
||||
See the [Web SDK docs](/docs/sdks/web) or [Script tag docs](/docs/sdks/script) for a full install guide.
|
||||
|
||||
## Enable session replay [#enable]
|
||||
|
||||
Session replay is **off by default**. Enable it by adding `sessionReplay: { enabled: true }` to your init config.
|
||||
|
||||
### Script tag
|
||||
|
||||
```html title="index.html"
|
||||
<script>
|
||||
window.op=window.op||function(){var n=[];return new Proxy(function(){arguments.length&&n.push([].slice.call(arguments))},{get:function(t,r){return"q"===r?n:function(){n.push([r].concat([].slice.call(arguments)))}} ,has:function(t,r){return"q"===r}}) }();
|
||||
window.op('init', {
|
||||
clientId: 'YOUR_CLIENT_ID',
|
||||
trackScreenViews: true,
|
||||
trackOutgoingLinks: true,
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
</script>
|
||||
<script src="https://openpanel.dev/op1.js" defer async></script>
|
||||
```
|
||||
|
||||
The replay script (`op1-replay.js`) is fetched automatically alongside the main script. Because it loads asynchronously, it doesn't affect page load time or the size of your main analytics bundle.
|
||||
|
||||
### NPM package
|
||||
|
||||
```ts title="op.ts"
|
||||
import { OpenPanel } from '@openpanel/web';
|
||||
|
||||
const op = new OpenPanel({
|
||||
clientId: 'YOUR_CLIENT_ID',
|
||||
trackScreenViews: true,
|
||||
trackOutgoingLinks: true,
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
With the npm package, the replay module is a dynamic import resolved by your bundler. It is automatically code-split from your main bundle—if you don't enable replay, the module is never included.
|
||||
|
||||
### Next.js
|
||||
|
||||
For Next.js, enable replay in your `OpenPanelComponent`:
|
||||
|
||||
```tsx title="app/layout.tsx"
|
||||
import { OpenPanelComponent } from '@openpanel/nextjs';
|
||||
|
||||
export default function RootLayout({ children }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body>
|
||||
<OpenPanelComponent
|
||||
clientId="YOUR_CLIENT_ID"
|
||||
trackScreenViews={true}
|
||||
sessionReplay={{
|
||||
enabled: true,
|
||||
}}
|
||||
/>
|
||||
{children}
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## Configure privacy controls [#privacy]
|
||||
|
||||
Session replay captures real user behavior, so it's important to control what gets recorded. OpenPanel gives you several layers of control.
|
||||
|
||||
### Input masking (enabled by default)
|
||||
|
||||
All form input values are masked by default. The recorder sees that a user typed something, but not what they typed. You never need to add special attributes to password or credit card fields—they're masked automatically.
|
||||
|
||||
If you need to disable masking for a specific use case:
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
maskAllInputs: false,
|
||||
}
|
||||
```
|
||||
|
||||
### Block sensitive elements
|
||||
|
||||
Elements with `data-openpanel-replay-block` are replaced with a grey placeholder in the replay. The element and all its children are completely excluded from recording.
|
||||
|
||||
```html
|
||||
<!-- This section will appear as a placeholder in replays -->
|
||||
<div data-openpanel-replay-block>
|
||||
<img src="user-avatar.jpg" alt="Profile photo" />
|
||||
<p>Private user content</p>
|
||||
</div>
|
||||
```
|
||||
|
||||
You can also configure a CSS selector or class to block without adding data attributes to every element:
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
blockSelector: '.payment-form, .user-profile-card',
|
||||
blockClass: 'no-replay',
|
||||
}
|
||||
```
|
||||
|
||||
### Mask specific text
|
||||
|
||||
To mask text within an element without blocking its layout from the replay, use `data-openpanel-replay-mask`:
|
||||
|
||||
```html
|
||||
<p>
|
||||
Account balance:
|
||||
<span data-openpanel-replay-mask>$1,234.56</span>
|
||||
</p>
|
||||
```
|
||||
|
||||
The span's text appears as `***` in the replay while the surrounding layout remains visible.
|
||||
|
||||
Configure a custom selector to avoid adding attributes to every element:
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
maskTextSelector: '.balance, .account-number, [data-pii]',
|
||||
}
|
||||
```
|
||||
|
||||
### Ignore interactions
|
||||
|
||||
Use `ignoreSelector` to prevent interactions with specific elements from being captured. The element is still visible in the replay, but clicks and input events on it are not recorded.
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
ignoreSelector: '.internal-debug-toolbar',
|
||||
}
|
||||
```
|
||||
|
||||
## View replays in the dashboard [#view]
|
||||
|
||||
Navigate to your [OpenPanel dashboard](https://dashboard.openpanel.dev) and open the Sessions view. Any recorded session will show a replay button. Click it to play back the session from the beginning.
|
||||
|
||||
The replay timeline shows all events alongside the recording, so you can jump directly to a click, form submission, or page navigation.
|
||||
|
||||
Replays are also accessible from user profiles. Open any user's profile, find a session in their history, and click through to the replay.
|
||||
|
||||
## Performance considerations
|
||||
|
||||
The replay recorder buffers events locally and sends them to OpenPanel in chunks every 10 seconds (configurable via `flushIntervalMs`). On tab close or page hide, any remaining buffered events are flushed immediately.
|
||||
|
||||
The default chunk size limits are:
|
||||
- **200 events per chunk** (`maxEventsPerChunk`)
|
||||
- **1 MB per payload** (`maxPayloadBytes`)
|
||||
|
||||
These defaults work well for most sites. If you have pages with heavy DOM activity, you can lower `maxEventsPerChunk` to send smaller, more frequent chunks:
|
||||
|
||||
```ts
|
||||
sessionReplay: {
|
||||
enabled: true,
|
||||
flushIntervalMs: 5000,
|
||||
maxEventsPerChunk: 100,
|
||||
}
|
||||
```
|
||||
|
||||
## Next steps
|
||||
|
||||
- Read the [session replay docs](/docs/session-replay) for a full option reference
|
||||
- Learn about [session tracking](/features/session-tracking) to understand what session data is available without replay
|
||||
- See how [funnels](/features/funnels) and session replay work together to diagnose drop-offs
|
||||
|
||||
<Faqs>
|
||||
<FaqItem question="Does session replay affect my page load speed?">
|
||||
No. The replay module (`op1-replay.js`) loads as a separate async script after the page and the main analytics script. It does not block rendering or inflate your main bundle.
|
||||
</FaqItem>
|
||||
|
||||
<FaqItem question="Is session replay enabled for all users?">
|
||||
Yes, when enabled, all sessions are recorded by default. You can use the `sampleRate` option to record only a percentage of sessions if needed.
|
||||
</FaqItem>
|
||||
|
||||
<FaqItem question="Are passwords and credit card numbers recorded?">
|
||||
No. All input field values are masked by default (`maskAllInputs: true`). The recorder captures that a user typed something, but not the actual characters. Disable this only with a specific reason.
|
||||
</FaqItem>
|
||||
|
||||
<FaqItem question="How long are replays kept?">
|
||||
Replays are retained for 30 days. There is no limit on the number of sessions recorded.
|
||||
</FaqItem>
|
||||
|
||||
<FaqItem question="Can I use session replay with self-hosted OpenPanel?">
|
||||
Yes. The replay script is served from your self-hosted instance automatically. You can also use the `scriptUrl` option to load it from a custom CDN.
|
||||
</FaqItem>
|
||||
</Faqs>
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
ChevronRightIcon,
|
||||
DollarSignIcon,
|
||||
GlobeIcon,
|
||||
PlayCircleIcon,
|
||||
} from 'lucide-react';
|
||||
import Link from 'next/link';
|
||||
import { FeatureCard } from '@/components/feature-card';
|
||||
@@ -41,6 +42,16 @@ const features = [
|
||||
children: 'All about tracking',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Session Replay',
|
||||
description:
|
||||
'Watch real user sessions to see exactly what happened. Privacy controls built in, loads async.',
|
||||
icon: PlayCircleIcon,
|
||||
link: {
|
||||
href: '/features/session-replay',
|
||||
children: 'See session replay',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
export function AnalyticsInsights() {
|
||||
@@ -68,7 +79,7 @@ export function AnalyticsInsights() {
|
||||
variant="large"
|
||||
/>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-3">
|
||||
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4">
|
||||
{features.map((feature) => (
|
||||
<FeatureCard
|
||||
description={feature.description}
|
||||
|
||||
@@ -3,4 +3,15 @@
|
||||
- `trackScreenViews` - If true, the library will automatically track screen views (default: false)
|
||||
- `trackOutgoingLinks` - If true, the library will automatically track outgoing links (default: false)
|
||||
- `trackAttributes` - If true, you can trigger events by using html attributes (`<button type="button" data-track="your_event" />`) (default: false)
|
||||
- `sessionReplay` - Session replay configuration object (default: disabled). See [session replay docs](/docs/session-replay) for full options.
|
||||
- `enabled` - Enable session replay recording (default: false)
|
||||
- `maskAllInputs` - Mask all input field values (default: true)
|
||||
- `maskTextSelector` - CSS selector for text elements to mask (default: `[data-openpanel-replay-mask]`)
|
||||
- `blockSelector` - CSS selector for elements to replace with a placeholder (default: `[data-openpanel-replay-block]`)
|
||||
- `blockClass` - Class name that blocks elements from being recorded
|
||||
- `ignoreSelector` - CSS selector for elements excluded from interaction tracking
|
||||
- `flushIntervalMs` - How often (ms) recorded events are sent to the server (default: 10000)
|
||||
- `maxEventsPerChunk` - Maximum events per payload chunk (default: 200)
|
||||
- `maxPayloadBytes` - Maximum payload size in bytes (default: 1048576)
|
||||
- `scriptUrl` - Custom URL for the replay script (script-tag builds only)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user