Session Recording Privacy

Session Replay lets you watch how a user experienced your site. To protect users, Middleware provides client‑side masking and exclusion so sensitive data never leaves the browser. Use the controls below to tune privacy for your product and region.

What gets recorded (and what doesn’t)

  • Recorded: DOM structure & attributes, user interactions (clicks, inputs), viewport/scroll, and visual changes needed to reconstruct the session.
  • Not recorded by default: Sensitive input values (e.g., password fields) are masked. You can further mask text or exclude DOM regions entirely.
  • Session boundaries: A session ends after 15 minutes of inactivity or 4 hours of continuous activity (whichever comes first). Recording is tied to the RUM session.

Treat masking/exclusion as defence in depth: combine selective blocking on sensitive regions with targeted text masking for the rest.

Quick Start (recommended defaults)

Add a minimal privacy configuration at initialisation so you start from a safe baseline, then tighten over time.

1<script>
2  if (window.Middleware) {
3    Middleware.track({
4      // ...your existing config...
5      recording: "1",
6      recordingOptions: {
7        maskAllInputs: true,                  // mask all input values as ***
8        maskTextSelector: ".pii, [data-pii]", // mask text inside these elements
9        blockSelector: ".auth-widget, .payment-form" // don't record these regions
10      }
11    });
12  }
13</script>

Configuration Reference (browser)

OptionTypeDefaultPurpose
maskAllInputsbooleanfalseMasks the values of input, textarea, and select fields in the recording. Structure remains for usability.
maskTextSelectorstring (CSS selector)Masks innerText of matching elements (e.g., .pii, [data-pii], [data-secret]). Use for names, emails, IDs that appear as text.
blockSelectorstring (CSS selector)Excludes matching DOM regions from recording (no pixels, no text, no attributes). Use on auth/payment widgets, tokens, secure modals.
ignoreSelectorstring (CSS selector)Prevents interaction events from being recorded on matching nodes (structure may remain). Useful for low‑value/high‑volume elements.
blockClassstring (CSS class)Convenience: any element with this class is treated like blockSelector. Use when you can’t easily inject selectors.

Selectors can be combined (comma‑separated). Favour specific rules (e.g., .checkout [data-pii]) over global wildcards to preserve useful context.

Selector Patterns

ScenarioExample
Mask all user‑provided text in a profile form.profile-form [data-pii], .profile-form .pii
Exclude 3rd‑party auth & billing widgets.auth-widget, .payment-form, #card-hosted-iframe
Ignore noisy UI (ad placeholders, carousels).ad, .carousel, .video-autoplay
Mask by attribute flags from your app[data-secret], [data-sensitive], [data-pii]
xclude cookie banners & A/B overlays.consent-modal, .ab-test-overlay

If your site requires user consent for analytics or recording, gate initialisation, or set recording: "0" until consent is granted.

1<script>
2  function hasAnalyticsConsent() {
3    return document.cookie.includes("consent_analytics=true");
4  }
5  if (hasAnalyticsConsent() && window.Middleware) {
6    Middleware.track({
7      // ...config...
8      recording: "1",
9      recordingOptions: { maskAllInputs: true, maskTextSelector: ".pii, [data-pii]" }
10    });
11  }
12</script>

In stricter regimes, separate analytics vs replay consent. Keep RUM on, but start with recording: "0" until replay consent is granted.

Testing Your Privacy Rules (dev checklist)

  1. Mark a few obvious PII spots (name, email, phone) with [data-pii].
  2. Reload and perform a short session that touches each spot.
  3. Review the replay: verify that text values are masked and blocked areas are absent.
  4. Iterate: narrow/expand selectors as needed, avoid over‑blocking critical UI.
  5. Automate: add a smoke test step in staging to exercise sensitive flows before releases.

Example Playbooks

Login & account pages

  • blockSelector: ".auth-widget, .magic-link, .otp-modal"
  • maskTextSelector: ".profile .pii, .profile [data-pii]"
  • maskAllInputs: true

Checkout & Payments

  • blockSelector: ".payment-form, #card-hosted-iframe, .bank-redirect"
  • maskTextSelector: ".billing [data-pii], .shipping [data-pii]"
  • Keep order IDs visible if they’re non‑PII and useful for support.

Support & admin tools

Performance & UX notes

  • Cost: Masking is lightweight; blocking prevents capture entirely and can modestly reduce payload size.
  • Specificity > breadth: A few targeted selectors often beat a single global * rule that hides useful context.
  • Accessibility: Masking does not affect your live DOM; it only changes what’s captured.

Troubleshooting

  • I still see sensitive text:
    • Check that the text node is actually inside a matching maskTextSelector element.
    • In dynamic UIs, ensure the attribute/class is applied before user input.
  • A widget still appears in replay:
    • Use blockSelector (or blockClass) on the widget container instead of only masking inputs.
  • Too much is hidden:
    • Narrow selectors (e.g., scope to .checkout [data-pii] rather than [data-pii] globally).
  • Consent logic seems ignored:
    • Verify you’re calling Middleware.track() only after your consent check passes, and that recording is set accordingly.

Need assistance or want to learn more about Middleware? Contact our support team at [email protected] or join our Slack channel.