Session recording
Record and replay user sessions with privacy-aware masking.
Record and replay user sessions with privacy controls (mask inputs, block elements). Recording is opt-in and lazy-loaded — the rrweb-based replay extension only fetches when enabled.
#Enable
Enable session_recording in init with optional privacy options:
vt.init('YOUR_PROJECT_TOKEN', {
api_host: 'https://www.vtilt.com',
session_recording: {
enabled: true,
maskAllInputs: true,
sampleRate: 1.0,
minimumDurationMs: 1000,
},
})typescript
#Options
| Option | Default | Description |
|---|---|---|
enabled | false | Master switch. When false, the recording extension is never loaded. |
maskAllInputs | true | Mask the value of every <input>, <textarea> and <select>. Strongly recommended unless you've audited your forms. |
sampleRate | 1.0 | Fraction of sessions to record (0–1). Use 0.1 to record 10% of sessions. |
minimumDurationMs | 1000 | Skip uploading the recording if the session is shorter than this (cuts noise from bounces). |
blockSelector | — | Extra CSS selectors for rrweb block mode (same-sized placeholder, inner DOM not stored). Merged with built-in selectors below unless skipDefaultInvisibleBlocking is true. |
skipDefaultInvisibleBlocking | false | When true, only your blockSelector / masking.blockSelector values apply; built-in blocking of .sr-only, Webflow w-condition-invisible, hidden inputs, etc. is disabled. |
#Privacy
- DOM mutations are captured and compressed with rrweb's incremental snapshot algorithm — no canvas captures, no media bytes, no clipboard.
- Invisible template copy: By default, rrweb is configured to block serialization of common off-screen nodes (screen-reader-only classes, Webflow CMS condition placeholders,
input[type="hidden"], etc.). They still occupy layout in replay as placeholders, but their inner text is not shipped. CSS-only hiding (e.g.display:noneonly in an external stylesheet) is not detectable at record time; server-side recording analysis still filters those cases. - Inputs, passwords and elements with
data-vt-maskare masked at the source; the masked value never leaves the browser. vt.startSessionRecording()/vt.stopSessionRecording()give you programmatic control if you need to gate recording on a feature flag or consent screen.- Recording snapshots arrive at
/api/son a separate batch key from regular events, so you can route them to a different bucket / region for compliance.