Skip to content

Session replay

Watch real visitor sessions as DOM replays — see exactly what someone did before opening chat, abandoning checkout, or hitting an error.

PostHog required

Replay is gated on your business having PostHog configured. The tag checks /analytics/config at boot and only starts recording when the business has a publishable PostHog project key. If PostHog isn't configured, replay is a silent no-op — nothing records, nothing breaks.

How it records

Periscale does not run its own recording server. Recording is handled by posthog-js (self-hosted on cdn.periscale.app/vendor/posthog.min.js) in recording-only mode: PostHog captures the session and uploads it natively, while Periscale's own bundle continues to own all analytics events. The visitor's distinct_id is bootstrapped into PostHog so recordings line up with the events you already see.

Sampling

By default, 25% of visitors are recorded (sampleRate: 0.25). The decision is deterministic and sticky per visitor — once someone is in (or out) of the sample, they stay that way across visits.

Tune the rate, or record everyone:

js
// Record ~10% of visitors
window.periscale.init({ apiKey: "sb_live_xxx", replay: { sampleRate: 0.1 } });

// Record every visitor
window.periscale.init({ apiKey: "sb_live_xxx", replay: { sampleRate: 1 } });

Force a recording

Ignore sampling and start recording the current session immediately — useful when a visitor opens chat or reports a bug:

js
await window.periscale.startReplay();   // forces recording on, ignores sample
const id = window.periscale.getReplaySessionId(); // link this id to a support ticket

Stop recording mid-session:

js
window.periscale.stopReplay();

Privacy defaults

Recording ships with safe defaults so you don't capture sensitive data:

WhatBehavior
All text inputsMasked by default (typed values hidden).
Password / phone fieldsAlways masked.
Email fieldsCaptured (un-masked) — override below if needed.
Credit-card inputsAlways blocked (never recorded).
Elements with [data-p-block] or class p-blockFully blocked.
Elements with [data-p-mask] or class p-maskText masked.

Block a sensitive region entirely:

html
<div data-p-block>
  <!-- never appears in any recording -->
  …account statement…
</div>

Mask just the text of a region (structure stays visible):

html
<span data-p-mask>{{ classified_value }}</span>

TIP

Combine with Privacy & consent: optOut() disables replay along with all other capture for that visitor.

Disable replay entirely

js
window.periscale.init({ apiKey: "sb_live_xxx", replay: false });

© Periscale