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:
// 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:
await window.periscale.startReplay(); // forces recording on, ignores sample
const id = window.periscale.getReplaySessionId(); // link this id to a support ticketStop recording mid-session:
window.periscale.stopReplay();Privacy defaults
Recording ships with safe defaults so you don't capture sensitive data:
| What | Behavior |
|---|---|
| All text inputs | Masked by default (typed values hidden). |
| Password / phone fields | Always masked. |
| Email fields | Captured (un-masked) — override below if needed. |
| Credit-card inputs | Always blocked (never recorded). |
Elements with [data-p-block] or class p-block | Fully blocked. |
Elements with [data-p-mask] or class p-mask | Text masked. |
Block a sensitive region entirely:
<div data-p-block>
<!-- never appears in any recording -->
…account statement…
</div>Mask just the text of a region (structure stays visible):
<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
window.periscale.init({ apiKey: "sb_live_xxx", replay: false });