Skip to main content

Session Recordings

Session recordings let you replay exactly what a user did on your site — mouse movements, clicks, scrolling, and form interactions — without capturing any sensitive input data.

How Recordings Work

Recording uses rrweb, an open-source library that serialises the DOM and records mutations, pointer events, and scroll events into a structured event stream.

The recording data never leaves the browser in one large payload. Instead, it is split into segments (chunks of ~60 seconds each) sent incrementally to the Platform. This keeps individual requests small and allows partial recovery if the user leaves mid-session.


Session Segments

A recording session is composed of numbered segments: 0, 1, 2, 3, ...

The Platform checks for gaps in the sequence. If segment 2 arrives before segment 1, or a segment is missing entirely, the recording is flagged:

{
"sessionId": "abc-123",
"hasGaps": true,
"missingSegments": [1]
}

This hasGaps flag is displayed in the Dashboard with a warning, so you know the playback may be incomplete.


Sample Rate

To reduce storage costs you can configure a Recording Sample Rate in the Plugin Settings. A value of 25 means only 25% of sessions are recorded.

The decision is made once per page load using Math.random() and stored in sessionStorage so a single user journey is either fully recorded or not at all.


Rage Clicks & Dead Clicks

Detected by their own collector, not by the recorder, and stored as their own rows rather than as a JSON blob on the session. That split is deliberate: a JSON array hanging off one session can tell you a person got frustrated, but it cannot answer where on the checkout people rage-click, which is the only version of the question worth asking.

It also means frustration data keeps working with session replay switched off — the interactions bundle carries no rrweb and costs a few KB.

Interaction typeDefinition
Rage click3 or more clicks within 800 ms, inside 30 px, on the same element
Dead clickA click after which nothing changes for 700 ms — no DOM mutation, no scroll, no navigation, no network request — and the element was rendering a pointer cursor

The cursor condition is what makes dead clicks a signal instead of noise. Without it every click on a paragraph counts as dead. With it, the statement is precise: the page showed this was clickable, someone took the offer, and nothing happened.

Positions are normalised in the browser before they are sent:

  • rx — a 0–1 fraction of the content root's width, not the viewport's. A click on the edge of a centred 1200px container sits at 0.26 of a 2560px screen and 0.03 of a 1280px one; storing viewport fractions smears every heatmap into the empty margins.
  • yBand — the offset down the content root in 20px bands. Vertical position is not a fraction of anything, because page height changes with content.
  • devicemobile / tablet / desktop / wide. These buckets never mix. The same CSS renders different layouts, so averaging across them draws a page nobody was served.

Clicks are also grouped by a page key — a hash of the normalised path, with numeric and id-like segments and product slugs collapsed. Without it a 10 000-SKU catalogue produces 10 000 heatmaps of three clicks each. The trade is stated plainly: a collapsed page is an average of its instances, which is right for layout questions and wrong for questions about one specific product.

rage and dead are annotations over the click stream, not extra clicks: every click is recorded once as click, and a burst or a silent click adds a second row describing it. Summing all three types double-counts — each is its own overlay.


Privacy Considerations

rrweb does not capture:

  • Passwords or credit card numbers (<input type="password"> and payment fields are masked)
  • Content inside <iframe> cross-origin elements
  • Any element with the data-wpel-mask attribute set

You can add data-wpel-mask to any element you want excluded from recordings:

<div data-wpel-mask>This content will not be recorded</div>

Storage

By default, recording segments are stored on the Platform server filesystem.

For high-volume sites, configure S3-compatible object storage — see Configuration → Storage.


Session Stitching

Multiple recording sessions by the same visitor (across different page loads) are linked under a single visitor profile. You can view the full chronological session history for a visitor in Dashboard → Visitors → [Visitor] → Sessions.

This allows you to trace a user's entire journey across multiple visits.