Session Replay Without Cookies: How Xine Records User Journeys Privately
Session replay is one of the most powerful tools for understanding user experience. Watching how real users navigate your site reveals rage clicks, confusing layouts, and broken flows that analytics dashboards alone cannot capture. But traditional session replay tools come with significant privacy concerns.
In this post, we explain how Xine Analytics implements session replay without cookies, without collecting PII, and without third-party data processors.
The Privacy Problem with Traditional Session Replay
Most session replay tools (Hotjar, FullStory, LogRocket) operate as third-party SaaS platforms:
- Third-party scripts send DOM mutations and user interactions to external servers
- Sensitive data like form inputs, passwords, and personal information can be accidentally captured
- Cookies and fingerprinting are used to associate replays with user profiles
- Data leaves your infrastructure and is stored on servers you do not control
This creates significant GDPR liability. Under GDPR Article 28, using a third-party session replay service means you need a Data Processing Agreement (DPA), and you must ensure the processor complies with all data protection requirements.
How Xine Handles Session Replay Differently
1. Self-Hosted by Default
All session replay data is stored in your own PostgreSQL database in the replay_events table. The replay footage never leaves your server. There is no third-party processor to worry about.
2. Cookie-Free Session Association
Xine associates replays with sessions using sessionStorage—not cookies. When a visitor opens a new tab or closes the browser, the session ID is discarded. This means:
- No cross-session replay tracking
- No persistent user identification
- No cookie consent requirements
3. Automatic PII Redaction
Xine's tracking script applies automatic masking to sensitive elements:
- Input fields: All
<input>,<textarea>, and<select>values are replaced with placeholder characters in the replay - Password fields: Always fully masked, stored as
•••••• - Custom masking: Developers can add
data-xine-maskattributes to any element to exclude it from replay entirely
<!-- This element's content will be masked in replays -->
<div data-xine-mask>
<p>User's personal information here</p>
</div>
4. DOM Mutation Recording (Not Screenshots)
Unlike screenshot-based replay tools, Xine records DOM mutations—the actual changes to the page structure. This approach is:
- Significantly smaller: A typical 3-minute session generates ~50KB of mutation data compared to 5-10MB of screenshots
- More accurate: Replays show the exact DOM state, including CSS transitions and animations
- More private: Only structural changes are recorded, not the rendered pixels
Technical Implementation
Xine's replay system uses a MutationObserver-based architecture:
// Simplified version of Xine's replay recording
const observer = new MutationObserver((mutations) => {
const events = mutations.map(mutation => ({
type: mutation.type,
target: serializeNode(mutation.target),
timestamp: Date.now() - sessionStart,
// PII is stripped during serialization
}));
batchAndSend(events);
});
observer.observe(document.body, {
childList: true,
attributes: true,
characterData: true,
subtree: true,
});
Additional interaction events are recorded alongside DOM mutations:
- Mouse movements: Sampled at 20fps for smooth replay
- Clicks: Position, target element, and whether it was a rage click (3+ clicks in 500ms)
- Scroll position: Tracked at key intervals
- Window resize: Viewport dimension changes
Opt-In Feature Flag
Session replay in Xine is disabled by default. Site owners must explicitly enable it in the dashboard settings. When disabled, the tracking script does not initialize the MutationObserver or send any replay data.
This opt-in approach means:
- No surprise data collection
- Minimal overhead when not needed
- Clear developer intent
Storage Considerations
Session replay data can accumulate quickly on high-traffic sites. Xine provides configuration for:
- Retention period: Automatically purge replays older than N days
- Sampling rate: Record only a percentage of sessions (e.g., 10% for high-traffic sites)
- Maximum duration: Cap replay length to avoid recording excessively long sessions
Conclusion
Session replay does not have to come at the cost of user privacy. By self-hosting the data, using sessionStorage instead of cookies, automatically masking PII, and recording DOM mutations instead of screenshots, Xine proves that powerful UX insights and strict privacy compliance can coexist.
See it in action. Explore Xine Analytics →
Published by Melvin Prince at Unisource