Advanced

Privacy & Scrubbing

What Reliable does to keep PII out of your event payloads — and what you should do on top of those defaults.

Built-in scrubbing#

Several layers of automatic PII protection are wired in by default. None of them are perfect — they're heuristics — but they remove the most common leaks before payloads ever leave the browser.

String scrubbing#

Any string that the SDK serializes (URLs, breadcrumb messages, error messages, browser_state values) is run through a regex scrubber. The scrubber masks:

  • Email addresses[email]
  • Credit-card-shaped numbers (13–19 consecutive digits) → [card]
  • JWT tokens (3 dot-separated base64 segments) → [token]
  • API keys in URLs (?api_key=..., ?token=...) → [redacted]

Cookies & localStorage#

When an error fires, Reliable snapshots document.cookie and localStorage as part of the error's browser_state. Before sending:

  • Keys matching /token|secret|password|auth(?!or)/i are fully redacted (value replaced with [REDACTED]).
  • Other values are truncated to 200 characters and run through the string scrubber above.

Session replay#

rrweb is the most invasive piece of the SDK. By default, Reliable enables aggressive defaults so PII doesn't end up in replays:

  • All <input> values are masked (rendered as ▪▪▪▪).
  • Password fields, credit card inputs, and SSN fields are fully blocked — not even the input shape is recorded.
  • iframe contents are not recorded.

See Session Replay for the full opt-in/opt-out attribute model (data-rr-allow, data-rr-block).

Adding your own scrubbing#

For app-specific PII patterns (internal IDs, custom token formats, anything the defaults miss), use beforeSend:

typescript
init({
  publicKey: 'pk_live_rl_...',
  beforeSend(event) {
    // Strip our internal customer IDs from URLs
    if (typeof event.url === 'string') {
      event.url = event.url.replace(/cust_[a-zA-Z0-9]+/g, 'cust_[id]');
    }
    return event;
  },
});

What every event payload contains#

Even with all scrubbing in place, every event includes:

  • The current path (URL pathname + search, query params scrubbed)
  • User agent string
  • Viewport dimensions
  • The session UUID (random per session, no PII)
  • If identify() was called: the externalId, email, name, and traits you provided

This is the data you control. Reliable doesn't fingerprint, doesn't read storage you didn't authorize, doesn't make third-party requests.

GDPR / consent flows#

For GDPR-compliant apps, gate the entire SDK behind consent. The simplest pattern:

typescript
async function bootstrap() {
  const consent = await waitForConsent();
  if (consent.analytics) {
    init({ publicKey: 'pk_live_rl_...' });
  }
}

Once init() has been called, you cannot un-init it. Reload the page to fully tear down the SDK. (For SPAs that need conditional behavior at runtime, prefer dropping events in beforeSend based on a global consent flag.)

No automatic system is bulletproof

Scrubbing is heuristic. If your domain has unique patterns (e.g. patient IDs in HIPAA, account numbers in finance), audit your event payloads in the dashboard and add custom beforeSend rules before going to production.