Add-on · Session replay

Masked before it is recorded, not after

Redaction that happens on our servers is a promise. Redaction that happens in the browser is an architecture. We do the second one, and the difference is the entire product.

Verified September 2026

The design

Where the redaction happens decides everything

Almost every replay vendor records the real DOM, ships it to their servers, and redacts on the way in or on the way out. That works right up until a rule is misconfigured, a new field ships without a class, or someone with database access goes looking. The sensitive text was transmitted and stored; you are relying on policy to keep it unread.

Our recorder replaces field contents inside the mutation serialiser, before a payload is built. A masked value leaves the browser as a run of bullet characters of the same length. There is no configuration that can turn that off globally, no server-side rule to get wrong, and nothing to leak — because the original characters were never in the request.

  1. In the browser The recorder walks the mutation, finds every field, and substitutes placeholders.
  2. On the wire The payload contains bullets. There is nothing to intercept.
  3. At rest Encrypted, stored apart from analytics, deleted on the schedule you set.
Session 8f2a·41c9 — 4 pages, 2m 18s Masked
shop.example.com/checkout ••••••••••••••••• MASKED •••• •••• •••• •••• ••/•• ••• Complete order
2:18
  • Masked by default. Every input, textarea and [contenteditable] is redacted in the browser. Opt individual fields back in with data-aa-unmask.
  • Never recorded: keystrokes, clipboard, file pickers, or anything inside an element you mark data-aa-block.

The same keystroke, on the wire

One visitor types their email into a checkout. This is the event both recorders put on the network.

Redact-on-arrival recorders Transmitted
{
  "t": "input",
  "node": 148,
  "value": "a.reinholt@example.com"
}

The real characters crossed the network and landed in their store. Whether you ever see them is a matter of their configuration and their access control.

Absolutely Analytics Never sent
{
  "t": "input",
  "node": 148,
  "value": "••••••••••••••••••••••"
}

Substituted inside the mutation serialiser, in the visitor's browser, before a payload exists. Same length, so the replay still looks right. Nothing to leak.

Guarantees

What the recorder cannot capture

Not "does not by default". Cannot — there is no code path that reaches these.

  • KeystrokesWe observe DOM mutations, never key events.
  • Clipboard contentsCopy and paste events are not listened for.
  • File picker contentsOnly that a file input changed, never which file.
  • Password fieldsMasked even if you explicitly try to unmask them.
  • Cross-origin iframesNot accessible, and we do not try.
  • Anything in data-aa-blockThe subtree is replaced with a placeholder box.

Use

Go straight to the sessions that went wrong

Nobody watches recordings at random. Replay is only useful if it hands you the broken ones, so that is what the inbox is sorted by.

Rage clicks

284

up 18.2 percent vs prev 7d vs prev 7d

Dead clicks

1,187

down 6.4 percent vs prev 7d vs prev 7d

JS errors seen

92

down 31.5 percent vs prev 7d vs prev 7d

Rageless, dropped anyway

614

checkout step 3

Every one of those numbers is a filter. Click it and you get the recordings behind it, newest first, already scrubbed to the moment it happened.

Questions

Replay questions, including the awkward one

What exactly is masked?

Every <input>, <textarea>, <select> and [contenteditable] element, plus anything you mark with data-aa-mask. Masking happens in the recorder, in the visitor's browser: the characters are replaced with a placeholder of the same length before the mutation is serialised, so the real text never enters the payload and never reaches us.

Can I unmask a field?

Yes, deliberately, one element at a time with data-aa-unmask. It is opt-in rather than opt-out on purpose — the default has to be the safe one, because the failure mode of getting it backwards is a card number in a recording.

Do you record keystrokes?

Never. We record DOM mutations, not key events. There is no keylogger path in the recorder at all, so there is nothing to misconfigure. Clipboard events and file picker contents are likewise never captured.

Does session replay need a cookie banner?

Realistically, yes — and we will not pretend otherwise. A replay is a recording of one person's visit, so most regulators treat it as personal data even when the fields are masked. Our recorder ships with a consent gate: call aa.replay.allow() after the visitor agrees and recording starts then, not before. Pageview analytics and heatmaps still need no banner.

How long are recordings kept?

30 days by default, and you can set it as low as 24 hours. Recordings are stored separately from your analytics, encrypted at rest, and deleting one deletes it — there is no soft-delete tier and no backup that quietly outlives it.

How is it billed?

One flat fee of $19 a month, with an included allowance of recorded sessions that scales with your volume rung. Sessions you sample out are not recorded and not counted, and recordings sit in their own allowance rather than drawing down the one your plan meters.

Will it slow the page down?

The recorder is around 11 KB gzipped and loads lazily after your page is interactive, never on the critical path. It uses a single MutationObserver, batches to an idle callback and stops recording entirely on a hidden tab.

Ready

Watch the session. Never read the data.

$19 a month on any plan, with an allowance of recorded sessions that scales with your rung. Masked by default, consent-gated, and deletable in one click.