GDPR-Safe Session Replay: A Field Guide to PII Masking and Lawful Basis
LogRocket and FullStory have faced wiretap lawsuits over replay PII leaks. Here's how to implement session replay that won't get you sued — default masking, lawful basis selection, and the specific Article 6 options that actually work.
GDPR-Safe Session Replay: A Field Guide to PII Masking and Lawful Basis
I was reviewing a client's session replay setup last February when I spotted something that made my stomach drop. A user had typed their full credit card number into a promo code field by mistake — fat-fingered the wrong input box — and the replay had captured all sixteen digits plus the CVV. Sitting there, unmasked, in a third-party vendor's database. For a company processing €40M in annual transactions.
That's not a hypothetical compliance scenario. That's an actual data breach waiting for an auditor to discover. I felt physically ill.
Session replay is one of the most powerful tools for understanding user behavior. It's also one of the easiest ways to accidentally build a GDPR violation into your stack. When combined with error tracking and funnel analysis, replay becomes even more powerful — but also riskier if not configured properly. Old Navy, Patagonia, and dozens of other companies have faced class action lawsuits under wiretap laws for exactly this kind of recording. The settlements run into the millions — Old Navy reportedly paid $1.4M in 2024.
This guide covers how to implement session replay that won't get you sued — or fined. We'll go through the technical masking requirements, the GDPR Article 6 lawful basis options that actually hold up, and the specific configuration you need for different replay tools.
What session replay actually captures (and why that matters for GDPR)
Most session replay tools record far more than people realize.
The standard recording includes: every DOM change, every mouse movement, every click, every scroll position, every form input, every piece of text rendered on the page. Some tools go further — recording network requests, console logs, and session storage contents.
Under GDPR, this creates an immediate problem. Personal data isn't just names and email addresses. Article 4(1) defines it as "any information relating to an identified or identifiable natural person." A combination of browser fingerprint, IP address, and behavioral patterns can identify someone — even without their name.
Here's what a typical unmasked replay captures that qualifies as personal data:
- Form inputs: Names, emails, addresses, phone numbers, payment details
- Chat messages: Support conversations, feedback, complaints
- URL parameters: User IDs, session tokens, reset links
- Displayed content: Account dashboards showing PII, order histories, profile pages
- Behavioral patterns: Mouse movements and interaction patterns can be surprisingly unique
The Swedish saying goes: "Den som gräver en grop åt andra faller själv däri" — dig a hole for others and you'll fall in yourself. Most companies deploying session replay don't intend to collect this data. They just fail to prevent it.
The masking hierarchy: what to block and when
Not all masking is equal. Here's the hierarchy from most aggressive (safest) to least aggressive (riskiest). Skip to Level 1 if you want my actual recommendation — the other levels exist because I need to explain why people get this wrong.
Level 1: Default-mask-everything
The only configuration I recommend for GDPR compliance. Every text node, every input field, every image gets masked unless you explicitly allow it. You start with a blank recording and selectively reveal what you need.
JustAnalytics takes this approach. Here's what the default configuration looks like:
// JustAnalytics default: everything masked
JA.init({
siteId: 'your-site-id',
replay: {
maskAllText: true,
maskAllInputs: true,
maskAllImages: true,
// Only unmask specific elements you've audited
unmaskSelector: '[data-ja-visible]'
}
});
With this configuration, your replay shows the DOM structure, layout changes, and interaction patterns — but all text appears as ████████. You can see that a user clicked the checkout button, filled out four form fields, and scrolled to the bottom of the page. You can't see what they typed or what the page content said.
To reveal specific elements (like navigation labels or button text), you explicitly tag them:
<!-- This text will be visible in replay -->
<button data-ja-visible>Add to Cart</button>
<!-- This text will be masked -->
<span class="user-email">user@example.com</span>
Level 2: Selective masking with input defaults
More common with tools like LogRocket and FullStory — they mask form inputs by default but record all rendered text. This catches the obvious PII (what users type) but misses the subtle PII (what the page displays).
The problem: if your checkout confirmation page says "Thank you, Sarah — your order will ship to 123 Main St, Stockholm," that's all in the replay. Unmasked.
// LogRocket default configuration (illustrative)
LogRocket.init('your-app-id', {
dom: {
inputSanitizer: true, // Masks inputs
textSanitizer: false // Does NOT mask page text
}
});
You can tighten this, but it requires knowing every page that might display PII and manually adding mask classes. Miss one and you've got a compliance gap.
Level 3: No default masking
Some older tools and self-hosted options ship with masking disabled. Everything records. Don't do this. I've seen companies running no-mask configurations for years without realizing it — usually because someone copied a quick-start snippet in 2019 and never revisited it.
GDPR Article 6: picking the right lawful basis
Every data processing activity needs a lawful basis under GDPR. For session replay, you have three realistic options. (The other three — vital interests, public task, and legal obligation — don't apply to commercial session recording.)
Option A: Consent (Article 6(1)(a))
The safest legal ground, but the highest friction. If you obtain explicit consent before recording, you've got clear authorization. The catch: consent must be freely given, specific, informed, and unambiguous.
In practice, this means:
- A cookie banner isn't enough — session replay needs separate, specific consent
- The user must affirmatively opt in (no pre-checked boxes)
- You must explain what you're recording and why
- Users must be able to withdraw consent as easily as they gave it
Consent works well for tools like Hotjar where you want heat maps and recordings from users who actively agree. But it kills your sample size — expect 15-30% opt-in rates on a good day. If you're evaluating privacy-first alternatives, our comparison of JustAnalytics vs Plausible vs Fathom covers the consent requirements for each. Honestly, I've seen as low as 8% on sites with aggressive cookie banners. Brutal for any kind of statistical validity.
Option B: Legitimate interest (Article 6(1)(f))
The most common basis for privacy-focused replay, but it requires a documented Legitimate Interest Assessment (LIA).
The three-part test:
- Purpose test: Do you have a legitimate business interest? (Yes — understanding UX issues, debugging errors, improving conversion.)
- Necessity test: Is session replay necessary to achieve that interest? (Usually yes — there's no equally effective alternative for seeing exactly how users interact.)
- Balancing test: Do the individual's rights override your interest? (This is where masking becomes critical.)
If you're recording masked replays — no PII captured, just behavioral patterns — the balancing test tips in your favor. The data subject's privacy impact is minimal because you can't identify them or see their personal information.
Here's the key insight: legitimate interest only works if you actually minimize the data. Recording everything and then claiming legitimate interest is a losing argument in front of any DPA.
A properly documented LIA for masked session replay looks like this:
Legitimate Interest Assessment: Session Replay
Purpose: Identify UX issues causing checkout abandonment
Necessity: Session replay shows interaction patterns; analytics alone cannot reveal form confusion or layout problems
Processing: DOM structure, mouse movements, clicks — all text/inputs masked by default
Retention: 30 days, automatically deleted
Balancing: Data subjects cannot be identified from recordings; no PII captured; minimal privacy impact
Conclusion: Legitimate interest applies
Date: 2026-05-14
Reviewer: [DPO signature]
Option C: Contract performance (Article 6(1)(b))
A stretch for most cases, but sometimes applicable if session replay is genuinely necessary to deliver the service the user signed up for. Example: a customer support tool that uses replay to help agents understand reported issues.
This basis is narrower than people think — way narrower. "We might use replays to improve the product someday" doesn't qualify. The processing must be actually necessary for the specific contract with that specific user. I've seen legal teams try to stretch this. It doesn't hold up.
The LogRocket / FullStory configuration gap
I want to be direct about this because I've audited dozens of session replay setups and the same problem appears constantly.
LogRocket and FullStory are genuinely useful — I've used both. They also ship with defaults that don't meet GDPR requirements out of the box. You have to configure them correctly, and most teams don't. (I've probably broken this news to fifteen different CTOs at this point. Nobody enjoys that conversation.)
Here's a side-by-side of default behavior:
| Aspect | LogRocket (default) | FullStory (default) | JustAnalytics (default) |
|---|---|---|---|
| Form inputs | Masked | Masked | Masked |
| Page text | Visible | Visible | Masked |
| Images | Visible | Visible | Masked |
| URLs | Full capture | Full capture | Path only (no params) |
| Network requests | Captured | Captured | Headers only |
| Console logs | Captured | Opt-in | Disabled |
The first two columns are why companies get sued. A user's email appears in a header, their name appears on a dashboard, their address appears on a confirmation page — all captured, all stored on a third-party server, all potential GDPR violations.
To make LogRocket GDPR-compliant, you'd need something like:
LogRocket.init('your-app-id', {
dom: {
textSanitizer: true,
inputSanitizer: true,
// Mask all images
privateAttributeBlocklist: ['src', 'srcset', 'data-src'],
},
network: {
isEnabled: false, // Or very careful request sanitization
},
console: {
isEnabled: false,
},
});
But even then, you're opting out of features rather than opting in. The architecture is backwards from a privacy-by-design perspective. And honestly? That frustrates me. These are well-funded companies with excellent engineering teams — they could flip the defaults tomorrow.
Implementing default-mask-everything in practice
Let me walk through what a GDPR-compliant replay setup actually looks like with JustAnalytics. The principle: mask everything, reveal only what you've explicitly audited.
Step 1: Base installation with maximum masking
<script
defer
data-site="your-site-id"
data-replay="true"
data-replay-mask="all"
src="https://cdn.justanalytics.app/script.js">
</script>
At this point, replays show a wireframe of your site. Users interact, clicks happen, scrolling occurs — but all content is blocked out. You can debug layout issues and understand flow, but you can't see anything personal.
Step 2: Selectively reveal non-sensitive content
Audit your templates and tag elements that are safe to show:
<!-- Navigation labels — no PII -->
<nav data-ja-visible>
<a href="/products">Products</a>
<a href="/pricing">Pricing</a>
<a href="/about">About</a>
</nav>
<!-- Button text — no PII -->
<button data-ja-visible class="cta">Start Free Trial</button>
<!-- Product names on listing page — no PII -->
<h2 data-ja-visible class="product-title">Enterprise Plan</h2>
Don't tag:
- Anything in a user dashboard
- Order confirmations
- Profile pages
- Support chat
- Any dynamic content that could contain user input
Step 3: Verify with a test recording
Before going live, record a test session where you deliberately enter PII in various places. Review the replay. If you can see any personal information, you've missed a masking rule.
I do this quarterly even on established setups. Tedious? Yes. But pages change, new features launch, developers add content that wasn't there before. I missed a "Hello, " greeting once — took three weeks to notice. Never again.
Step 4: Document your DPA compliance
Your Data Processing Agreement with your replay vendor matters. Under GDPR Article 28, processors must follow your instructions and implement appropriate security measures.
For JustAnalytics, the DPA is at justanalytics.app/legal/dpa — it explicitly covers:
- Data stays in EU (Frankfurt, eu-central-1)
- No sub-processor access to replay content
- 30-day default retention with configurable shorter periods
- Automatic deletion on contract termination
Compare this to US-based vendors where you need to worry about SCCs, transfer impact assessments, and (if the Schrems III ruling goes a certain way) potential complete invalidity of your transfer mechanism.
The wiretap lawsuit pattern and how to avoid it
The lawsuits against companies using session replay follow a predictable pattern:
- User visits website, browses, maybe makes a purchase
- Plaintiff's attorneys discover the site uses FullStory/LogRocket/similar
- Complaint filed under California Invasion of Privacy Act (CIPA) or state equivalent
- Allegation: recording keystrokes and browsing without consent = illegal wiretapping
- Company faces class action, settles for $X million to avoid discovery
The legal argument is that session replay tools intercept communications in transit — like a wiretap on a phone line — without the user's knowledge or consent. Whether this theory ultimately wins in court is still being litigated, but the cost of defending these cases has already changed how companies approach replay.
Key mitigations:
Disclosure: Update your privacy policy to explicitly describe session replay. Not buried in paragraph 47, but in a clearly labeled section. "We use session replay technology to record how visitors interact with our website. These recordings capture mouse movements, clicks, and scrolling — but not any text you type or personal information displayed on the page."
Consent where required: If you're recording anything beyond masked behavioral data, get explicit consent. A pre-recording modal, not just a cookie banner.
Minimize: The best defense is not having the data in the first place. If your recordings literally can't contain PII because everything is masked, the wiretapping theory is much harder to sustain.
Vendor choice: US-based replay vendors are more frequently targeted because plaintiff's attorneys can subpoena the recordings during discovery. EU-hosted tools with genuine data minimization are less attractive targets.
Common mistakes (and how to fix them)
Running legacy configurations. Someone installed LogRocket in 2021 with default settings and nobody's touched it since. Fix: audit your replay configuration annually. Set a calendar reminder.
Masking inputs but not dynamic content. Your form fields are masked, but your "Welcome back, Marcus" header isn't. Fix: use default-mask-everything or do a complete DOM audit.
Trusting "anonymization." Some tools claim to anonymize data while still capturing it. Under GDPR, pseudonymized data is still personal data — you need actual minimization. Fix: don't capture what you shouldn't have.
No LIA documentation. You're claiming legitimate interest but you've never written down the assessment. If a DPA asks, you've got nothing. Fix: document now, before anyone asks. See our Django middleware tutorial for an example of privacy-first implementation.
Storing too long. Replay data sitting in perpetuity is liability sitting in perpetuity. Fix: set retention to 30 days max. Be honest — you're not going to watch 90-day-old recordings anyway. Nobody has time for that.
Ignoring third-party scripts. Your replay tool is configured correctly, but a third-party chat widget or support tool is rendering user names in the DOM. Fix: audit all scripts that modify your page content.
FAQ
Do I need consent to run session replay under GDPR?
It depends on what you're recording. If your replay captures form inputs, chat messages, or any text a user types — yes, you almost certainly need explicit consent under GDPR Article 6(1)(a). But if you mask all text inputs by default and only record DOM structure, mouse movements, and clicks, you can potentially argue legitimate interest under Article 6(1)(f). The key is what data actually hits your servers, not what the tool is theoretically capable of recording.
What's the difference between client-side and server-side PII masking?
Client-side masking replaces sensitive data before it leaves the browser — the PII never touches your replay servers. Server-side masking strips data after it's already been transmitted and stored. For GDPR compliance, client-side is far safer because you can truthfully say the personal data was never collected. Server-side masking still means you processed the PII, even if you deleted it later, which triggers GDPR data processing obligations.
Can I use session replay on checkout pages without violating PCI DSS?
Only with aggressive masking. PCI DSS requires that cardholder data never be stored in replay recordings — not even temporarily. JustAnalytics masks all input fields by default, including payment forms, which keeps you compliant. But if you're using a replay tool that requires you to manually configure masking, assume it's recording card numbers until you've explicitly tested otherwise. We've seen companies fail PCI audits because their replay tool captured CVVs in the DOM.
Why are companies like Old Navy and Patagonia getting sued over session replay?
The lawsuits under the California Invasion of Privacy Act (CIPA) and similar state wiretap laws argue that recording keystrokes, mouse movements, and form inputs without consent constitutes illegal wiretapping. The plaintiffs claim they didn't know their browsing sessions were being recorded and shared with third-party vendors like FullStory. Whether these cases succeed long-term is still playing out, but the legal costs alone have pushed many companies to switch to privacy-first replay tools or disable recording entirely.
What to measure this week
If you're running session replay today, here's your immediate action list:
- Pull your current replay configuration and compare it to the masking table above
- Record a test session and look for any visible PII in the playback
- Check if you have a documented Legitimate Interest Assessment — if not, write one
- Review your privacy policy for explicit session replay disclosure
- Confirm your vendor's data residency and DPA terms
For teams considering migration to a privacy-first replay tool, our GA4 migration guide covers the parallel-tracking approach that works for any observability switch — including replay. The process is similar: run both tools for 30-45 days, validate you're getting the insights you need, then cut over.
If your stack is Next.js 15 with the App Router, the framework-specific implementation walkthrough covers where the masking script should sit relative to server components — a small detail that's easy to get wrong on first install and harder to fix once recordings are flowing.
Session replay doesn't have to be a liability. With default masking, proper lawful basis documentation, and a vendor that takes privacy seriously, you can get the UX insights you need without building a GDPR violation into your stack.
Mask first. Reveal deliberately. Document everything. It's not glamorous work, but neither is explaining a data breach to your board.
Try JustAnalytics
All-in-one observability in one under-5KB script: cookieless analytics + error tracking + APM + session replay + uptime + structured logs. Replaces GA4 + Sentry + Datadog + Pingdom + LogRocket. Free tier (100K events/mo), Pro $49/month ($39 annual).
Author at JustAnalytics.