Session Replay records what a user saw and did, so you can watch a bug happen instead of guessing from a stack trace. It is included in @atatus/browser-rum and loads its recorder only when a session is selected for replay, so it costs nothing on sessions you do not record.

This page covers turning replay on, choosing how much to record, and masking sensitive content.

Turn on recording

Set a replay sample rate when you initialize the agent:

atatusRum.init({
  licenseKey: '<license-key>',
  appName: 'Storefront',
  sessionSampleRate: 100,
  sessionReplaySampleRate: 30,
  defaultPrivacyLevel: 'mask-user-input',
});

These are the options that affect replay:

Option Default Purpose
sessionReplaySampleRate 0 Percentage of collected sessions that record replay
defaultPrivacyLevel mask How much of the page is masked
startSessionReplayRecordingManually false Wait for you to start recording
enablePrivacyForActionName false Mask action names, which come from element text
Note:

Replay sampling applies to sessions that sessionSampleRate already kept, so the two multiply. A session rate of 50 with a replay rate of 30 records replay for 15% of all sessions.

Record only the sessions you need

A flat sample rate records a slice of everything, including sessions where nothing went wrong. If you would rather keep the sessions that matter, start recording yourself:

atatusRum.init({
  licenseKey: '<license-key>',
  appName: 'Storefront',
  startSessionReplayRecordingManually: true,
});

Then start recording when something interesting happens, such as an error or a user opening a support form:

atatusRum.startSessionReplayRecording();
atatusRum.stopSessionReplayRecording();

To link to the current session from your own tooling, ask for its replay URL:

const url = atatusRum.getSessionReplayLink();
Tip:

Calling startSessionReplayRecording() inside an error boundary captures replay only for sessions that actually broke. You get the recordings you want at a fraction of the volume.

Privacy

Replay records the DOM, so treat masking as the default on any screen that shows customer data, personal information, or payment details.

Set the level for the whole application with defaultPrivacyLevel:

Level Effect
allow Records everything as it appears
mask Masks all text and inputs. This is the default
mask-user-input Masks form inputs, keeps static page text readable
mask-unless-allowlisted Masks everything except elements you allow

mask-user-input is a good starting point for most applications: the page stays readable in the replay, while anything a user typed is hidden.

Override the level on one element

You can raise or lower the level on any element and everything inside it, with either an attribute or a class:

<div data-atatus-privacy="allow">Safe to record</div>
<div data-atatus-privacy="mask">Masked</div>
<div data-atatus-privacy="hidden">Replaced with a placeholder</div>

<div class="atatus-privacy-allow">Same, written as a class</div>
<div class="atatus-privacy-hidden">Hidden</div>
Note:

The older data-dd-privacy attribute and dd-privacy- class prefix still work, so markup written before the rename keeps masking. Use the atatus- names for anything new.

Mask action names

Action names are built from the text of the element a user clicked, so a button labelled with a customer name leaks that name into the action. Turn on enablePrivacyForActionName to mask them:

atatusRum.init({
  licenseKey: '<license-key>',
  appName: 'Storefront',
  enablePrivacyForActionName: true,
});

Then give the elements that matter a safe name with data-atatus-action-name, which the agent reads by default:

<button data-atatus-action-name="Delete customer">Delete Jane Doe</button>

To read the name from your own attribute instead, set actionNameAttribute. The agent checks it in addition to the default:

atatusRum.init({
  licenseKey: '<license-key>',
  appName: 'Storefront',
  actionNameAttribute: 'data-analytics-label',
});
Note:

The older data-dd-action-name attribute is still read, so existing markup keeps naming actions.

Redact URLs

Credentials often end up in query strings, and those appear on views and resources. Strip them in beforeSend, which runs just before an event is sent:

atatusRum.init({
  licenseKey: '<license-key>',
  appName: 'Storefront',
  beforeSend: (event) => {
    event.view.url = scrub(event.view.url);
    if (event.type === 'resource' && event.resource) {
      event.resource.url = scrub(event.resource.url);
    }
    return true;
  },
});

Next steps