npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@achado/session-replay

v0.0.2

Published

Session replay functionality using rrweb for Achado platform

Downloads

20

Readme

@achado/session-replay

Session recording functionality using rrweb for the Achado platform. Capture complete user sessions with privacy controls and efficient storage.

Installation

npm install @achado/core @achado/session-replay

Quick Start

import { AchadoClient } from '@achado/core';
import { SessionReplay } from '@achado/session-replay';

const client = new AchadoClient({ apiKey: 'your-api-key' });
const sessionReplay = new SessionReplay(client, {
  enabled: true,
  sampleRate: 0.1, // Record 10% of sessions
});

await client.initialize();
await sessionReplay.initialize();

// Sessions are now being recorded automatically!

Features

🎥 Complete Session Recording

  • Full DOM snapshots and incremental changes
  • Mouse movements, clicks, and scrolls
  • Keyboard inputs (with privacy controls)
  • Window resize and focus events
  • Network requests (optional)

🔒 Privacy Controls

  • Text input masking
  • Sensitive element blocking
  • Custom masking rules
  • Selective recording areas
  • Compliance-ready defaults

⚡ Performance Optimized

  • Efficient compression
  • Smart segmentation
  • Background processing
  • Minimal performance impact
  • Automatic cleanup

📊 Error Correlation

  • Automatic error tracking
  • Error replay linking
  • Stack trace capture
  • Context preservation

Configuration

interface SessionReplayConfig {
  enabled?: boolean; // Default: true
  sampleRate?: number; // Default: 1.0 (100%)
  maxDuration?: number; // Default: 1800000 (30 min)
  inactiveThreshold?: number; // Default: 300000 (5 min)
  captureConsole?: boolean; // Default: false
  captureNetwork?: boolean; // Default: false
  maskTextInputs?: boolean; // Default: true
  maskAllText?: boolean; // Default: false
  maskTextSelector?: string; // Custom mask selector
  blockClass?: string; // Default: 'rr-block'
  blockSelector?: string; // Custom block selector
  ignoreClass?: string; // Default: 'rr-ignore'
  checkoutEveryNth?: number; // Default: 200
  checkoutEveryNms?: number; // Default: 300000 (5 min)
  slimDOMOptions?: SlimDOMOptions;
}

Example Configuration

const sessionReplay = new SessionReplay(client, {
  enabled: true,
  sampleRate: 0.2, // Record 20% of sessions
  maxDuration: 900000, // 15 minutes max
  maskTextInputs: true,
  blockClass: 'no-record',
  checkoutEveryNth: 100,
  captureConsole: false,
  slimDOMOptions: {
    script: true,
    comment: true,
    headFavicon: true,
    headWhitespace: true,
  },
});

API Reference

SessionReplay Class

Constructor

new SessionReplay(client: AchadoClient, config?: SessionReplayConfig)

Methods

initialize(): Promise<void>

Start session recording.

startRecording(): Promise<void>

Manually start recording.

stopRecording(): Promise<void>

Manually stop recording.

isRecording(): boolean

Check if currently recording.

getSessionId(): string | undefined

Get the current session ID.

getRecordingDuration(): number

Get recording duration in milliseconds.

getEventCount(): number

Get total recorded events.

getRecordingStats()

Get comprehensive recording statistics.

const stats = sessionReplay.getRecordingStats();
// Returns: { sessionId, isRecording, duration, eventCount }
updateConfig(config: Partial<SessionReplayConfig>): void

Update configuration at runtime.

destroy(): Promise<void>

Stop recording and clean up.

Privacy & Masking

Automatic Masking

By default, sensitive inputs are masked:

  • Password fields
  • Credit card inputs
  • Any field with data-sensitive attribute

HTML Attributes

<!-- Block entire sections from recording -->
<div class="rr-block">This content will not be recorded</div>

<!-- Ignore elements (still recorded but marked) -->
<div class="rr-ignore">This will be in replay but marked as ignored</div>

<!-- Mask text content -->
<div data-mask-text>This text will be masked in recordings</div>

<!-- Mark sensitive inputs -->
<input type="text" data-sensitive placeholder="SSN" />
<input type="password" />
<!-- Automatically masked -->

Custom Masking

const sessionReplay = new SessionReplay(client, {
  maskTextInputs: true,
  maskTextSelector: '.mask-this, [data-private]',
  blockClass: 'no-record',
  blockSelector: '.admin-only, .sensitive-area',
});

Compliance Options

// GDPR-friendly setup
const sessionReplay = new SessionReplay(client, {
  maskAllText: true, // Mask all text content
  maskTextInputs: true, // Mask all inputs
  captureConsole: false, // Don't capture console logs
  captureNetwork: false, // Don't capture network requests
  blockClass: 'gdpr-block', // Custom blocking class
});

Recording Lifecycle

Session Management

  1. Session Start: New session begins on page load
  2. Event Capture: DOM mutations and interactions recorded
  3. Segmentation: Events split into manageable chunks
  4. Transmission: Segments sent to API
  5. Session End: Recording stops on inactivity or max duration

Event Types

  • Full Snapshot: Complete DOM state
  • Incremental Snapshot: DOM changes
  • Mouse Interaction: Clicks, movements, scrolls
  • Input: Keyboard and form interactions
  • ViewportResize: Window size changes
  • Meta: Custom events and errors

Data Structure

Session Metadata

{
  sessionId: 'session_1234567890_abc123',
  userId: 'user-456',
  startTime: 1640995200000,
  endTime: 1640998800000,
  duration: 3600000,
  totalEvents: 1247,
  segments: 12,
  url: 'https://example.com/app',
  userAgent: 'Mozilla/5.0...',
  errors: 2,
  interactions: 45
}

Replay Segment

{
  id: 'segment_uuid',
  sessionId: 'session_1234567890_abc123',
  sequence: 3,
  events: [...], // rrweb events
  startTime: 1640995800000,
  endTime: 1640996100000,
  size: 15420 // bytes
}

Performance Impact

Benchmarks

  • Memory Usage: < 10MB for typical sessions
  • CPU Impact: < 1% additional usage
  • Network: Compressed segments, < 100KB/minute
  • DOM Performance: Negligible impact on interactions

Optimization Features

  • Smart Segmentation: Automatic chunking for efficiency
  • Compression: Event data compressed before transmission
  • Debouncing: Rapid events intelligently merged
  • Cleanup: Automatic memory management

Error Integration

Automatic Error Tracking

Errors are automatically correlated with recordings:

// This error will be linked to the current recording
throw new Error('Payment processing failed');

Manual Error Tracking

try {
  processPayment();
} catch (error) {
  // Error automatically tracked and linked to recording
  console.error('Payment failed:', error);
}

Error Playback

Recordings with errors are automatically flagged and can be filtered for debugging.

Sampling Strategy

Basic Sampling

// Record 10% of all sessions
const sessionReplay = new SessionReplay(client, {
  sampleRate: 0.1,
});

Conditional Sampling

// Custom sampling logic
const shouldRecord = () => {
  // Record all admin users
  if (user.role === 'admin') return true;

  // Record 5% of regular users
  if (Math.random() < 0.05) return true;

  return false;
};

const sessionReplay = new SessionReplay(client, {
  enabled: shouldRecord(),
});

Error-Based Recording

// Start recording when errors occur
window.addEventListener('error', () => {
  if (!sessionReplay.isRecording()) {
    sessionReplay.startRecording();
  }
});

Storage & Bandwidth

Local Storage

  • Session data temporarily stored locally
  • Automatic cleanup after transmission
  • Fallback for network failures

Network Optimization

  • Gzip compression
  • Incremental transmission
  • Retry logic with exponential backoff
  • Offline support

Browser Support

  • Chrome 70+
  • Firefox 65+
  • Safari 12+
  • Edge 79+

Examples

Basic Setup

const sessionReplay = new SessionReplay(client, {
  enabled: true,
  sampleRate: 1.0, // Record all sessions in development
});

Production Setup

const sessionReplay = new SessionReplay(client, {
  enabled: process.env.NODE_ENV === 'production',
  sampleRate: 0.05, // 5% of production sessions
  maxDuration: 1200000, // 20 minutes max
  maskTextInputs: true,
  blockClass: 'no-record',
});

High-Privacy Setup

const sessionReplay = new SessionReplay(client, {
  enabled: true,
  maskAllText: true,
  maskTextInputs: true,
  captureConsole: false,
  captureNetwork: false,
  blockClass: 'sensitive',
  slimDOMOptions: {
    script: true,
    comment: true,
    headFavicon: true,
  },
});

Error-Focused Recording

let hasError = false;

window.addEventListener('error', () => {
  hasError = true;
});

const sessionReplay = new SessionReplay(client, {
  enabled: () => hasError, // Only record sessions with errors
  sampleRate: 1.0,
});