@chaseleto/sessions-sdk
v1.0.15
Published
Privacy-conscious session recording SDK for self-hosted session tracking
Maintainers
Readme
Session SDK
A privacy-conscious, self-hosted session recording SDK for capturing user sessions with essential metadata, network requests, console logs, and session replays.
Features
- 🎥 Session Recording: Full session replay using rrweb
- 📝 Console Logging: Capture console.log, warn, error, info, debug
- 🌐 Network Monitoring: Track fetch and XHR requests
- 🔒 Privacy First: All input fields masked by default, respects Do Not Track
- 📊 Sampling: Configurable sampling rates
- 🚀 Lightweight: Minimal bundle size with tree-shaking
- 🔄 Reliable Upload: Retry queue with exponential backoff
- 📱 Cross-Platform: Works in all modern browsers
Installation
NPM
npm install client-sdkCDN
<script src="https://unpkg.com/client-sdk@latest/dist/index.umd.min.js"></script>Development
Prerequisites
- Node.js 16+
- npm or yarn
Setup
# Install dependencies
npm install
# Run tests
npm test
# Run tests with coverage
npm run test:coverage
# Run tests in watch mode
npm run test:watch
# Type checking
npm run type-check
# Build (includes tests and type checking)
npm run build
# Full CI process (tests + type check + build)
npm run ciBuild Process
The build process automatically runs:
- Tests - Ensures all functionality works correctly
- Type checking - Validates TypeScript types
- Build - Creates distribution files
This ensures that any published version has passed all quality checks.
Quick Start
Basic Usage
import { init } from 'client-sdk';
// Initialize with your API key
init('your-api-key-here', {
projectId: 'your-project-id',
userId: 'user-123',
attributes: {
plan: 'premium',
environment: 'production'
}
});Next.js Usage (Recommended - Like HyperDX)
// pages/_app.tsx or app/layout.tsx
import { initSessionRecording } from '@chaseleto/sessions-sdk';
// Initialize session recording (runs once on app load)
initSessionRecording(process.env.NEXT_PUBLIC_SESSION_API_KEY!, {
projectId: 'my-nextjs-app',
userId: 'user-123',
attributes: {
environment: process.env.NODE_ENV,
framework: 'nextjs',
},
});
export default function App({ Component, pageProps }) {
return <Component {...pageProps} />;
}Next.js with React Hooks (Alternative)
// pages/_app.tsx or app/layout.tsx
import { useSessionRecording } from '@chaseleto/sessions-sdk';
export default function App({ Component, pageProps }) {
const { sessionId, isActive } = useSessionRecording(
process.env.NEXT_PUBLIC_SESSION_API_KEY!,
{
projectId: 'my-nextjs-app',
userId: 'user-123',
attributes: {
environment: process.env.NODE_ENV,
framework: 'nextjs',
},
}
);
return <Component {...pageProps} />;
}CDN Usage
<script>
// Initialize with your API key
SessionSDK.init('your-api-key-here', {
projectId: 'your-project-id'
});
</script>Configuration Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| endpoint | string | 'https://api.sessions.chxse.dev/api/v1/sessions' | API endpoint for sending session data |
| projectId | string | '' | Project ID for the session |
| userId | string | '' | User ID to associate with sessions |
| attributes | object | {} | Custom attributes to attach to all sessions |
| captureConsole | boolean | true | Whether to capture console logs |
| captureNetwork | boolean | true | Whether to capture network requests |
| samplingRate | number | 1.0 | Sampling rate (0-1) for session recording |
| maxSessionDuration | number | 1800000 | Maximum session duration in milliseconds (30 min) |
| uploadInterval | number | 10000 | Upload interval in milliseconds (10 sec) |
| respectDNT | boolean | true | Whether to respect Do Not Track headers |
| headers | object | {} | Custom headers to include in requests |
| maskAllInputs | boolean | true | Whether to mask all input fields in session replay |
| recordCanvas | boolean | false | Whether to record canvas elements (see Performance) |
| collectFonts | boolean | false | Whether to collect web fonts for replay (see Performance) |
| inlineStylesheet | boolean | true | Whether to inline stylesheets for replay fidelity |
Performance Options
The recordCanvas, collectFonts, and inlineStylesheet options control rrweb recording features that affect client-side performance and payload size:
| Option | Performance Impact | When to Enable |
|--------|-------------------|----------------|
| recordCanvas | High - Continuously serializes canvas pixel data on every frame. Adds significant CPU and memory overhead. | Only when your app uses <canvas> elements (games, charts, drawing tools) and you need them in replays. |
| collectFonts | Medium - Fetches and embeds font files into the recording payload, increasing upload size. | When custom fonts are critical for replay fidelity and your pages use non-system fonts. |
| inlineStylesheet | Low - Inlines CSS into the snapshot instead of referencing external URLs. Slightly increases payload but improves replay reliability. | Enabled by default. Disable only if payload size is a concern and your stylesheets are served from stable URLs. |
// Example: Enable canvas recording for a drawing app
init('your-api-key', {
recordCanvas: true,
collectFonts: true,
});API Reference
Core Functions
init(apiKey, options?)
Initialize the session SDK.
const sdk = init('your-api-key', {
endpoint: 'https://your-backend.com/sessions',
projectId: 'project-123'
});Next.js Integration
The SDK includes Next.js-specific utilities for easy integration:
useSessionRecording(apiKey, options?)
React hook for Next.js applications:
import { useSessionRecording } from '@chaseleto/sessions-sdk';
function MyComponent() {
const { sessionId, isActive, setUserId, setAttributes } = useSessionRecording(
'your-api-key',
{
projectId: 'my-app',
userId: 'user-123',
enabled: process.env.NODE_ENV === 'production',
}
);
return <div>Session ID: {sessionId}</div>;
}SessionRecorder Component
Invisible component for easy integration:
import { SessionRecorder } from '@chaseleto/sessions-sdk';
export default function App({ Component, pageProps }) {
return (
<>
<SessionRecorder
apiKey={process.env.NEXT_PUBLIC_SESSION_API_KEY!}
projectId="my-app"
userId="user-123"
/>
<Component {...pageProps} />
</>
);
}withSessionRecording(Component, apiKey, options?)
HOC for wrapping components:
import { withSessionRecording } from '@chaseleto/sessions-sdk';
const MyComponent = () => <div>My App</div>;
export default withSessionRecording(MyComponent, 'your-api-key', {
projectId: 'my-app',
});destroy()
Stop recording and destroy the SDK instance.
destroy();setAttributes(attributes)
Add custom attributes to the current session.
setAttributes({
plan: 'premium',
userType: 'admin',
page: 'checkout'
});setUserId(userId)
Set the user ID for the current session.
setUserId('user-123');getSessionId()
Get the current session ID.
const sessionId = getSessionId();
console.log('Current session:', sessionId);isActive()
Check if recording is currently active.
if (isActive()) {
console.log('Session recording is active');
}Advanced Usage
Using the SessionSDK Class
For more control, you can use the SessionSDK class directly:
import { SessionSDK } from 'client-sdk';
const sdk = new SessionSDK('your-api-key', {
endpoint: 'https://your-backend.com/sessions',
projectId: 'project-123'
});
// Start recording
sdk.init();
// Add attributes
sdk.setAttributes({ plan: 'premium' });
// Stop recording
sdk.stop();
// Destroy instance
sdk.destroy();Data Structure
The SDK sends session data in the following format:
interface SessionData {
sessionId: string;
projectId: string;
userId?: string;
attributes: Record<string, any>;
metadata: {
userAgent: string;
url: string;
referrer: string;
viewport: { width: number; height: number };
timestamp: number;
timezone: string;
language: string;
};
events: Array<{
type: 'rrweb';
data: any;
timestamp: number;
}>;
consoleLogs: Array<{
level: 'log' | 'warn' | 'error' | 'info' | 'debug';
message: string;
args: any[];
timestamp: number;
stack?: string;
}>;
networkRequests: Array<{
method: string;
url: string;
status?: number;
statusText?: string;
requestHeaders?: Record<string, string>;
responseHeaders?: Record<string, string>;
requestBody?: any;
responseBody?: any;
duration: number;
timestamp: number;
error?: string;
}>;
timestamp: number;
duration: number;
}Privacy & Compliance
What Data Is Captured
The SDK uses rrweb to record DOM mutations, mouse movements, clicks, scrolling, and page content for session replay. This means the visible content of your pages is captured, including text rendered on screen.
By default, all input field values are masked (maskAllInputs: true). This prevents the SDK from recording text typed into form fields such as email addresses, phone numbers, credit card numbers, and other user input. Password fields are always masked regardless of configuration.
If you set maskAllInputs: false, the SDK will capture the actual values of all non-password input fields. This includes any personally identifiable information (PII) users type into forms. Only use this setting if your forms do not collect sensitive data, or if you have appropriate data processing agreements in place.
Privacy Configuration
init('your-api-key', {
// Mask all input fields (default: true)
maskAllInputs: true,
// Respect Do Not Track browser setting (default: true)
respectDNT: true,
// Disable console log capture
captureConsole: false,
// Disable network request capture
captureNetwork: false,
});Do Not Track
The SDK respects the Do Not Track (DNT) header by default. When DNT is enabled, no session data is recorded.
Data Minimization
- All input field values are masked by default to prevent PII capture
- Password fields are always masked regardless of configuration
- Console logs and network requests are truncated to prevent data bloat
- Session data is automatically cleaned up after upload
- Sensitive HTTP headers (Authorization, Cookie, API keys) are redacted from network captures
Data Size Limits & Memory Management
The SDK implements comprehensive size limits to prevent memory issues and ensure reliable uploads:
Individual Item Limits
| Item Type | Size Limit | Description | |-----------|------------|-------------| | Console Logs | 5KB per log | Large console objects are truncated | | Network Requests | 10KB per request | Large request/response data is limited | | Request Bodies | 1KB | Request payloads are truncated | | Console Arguments | 1KB per argument | Large objects in console calls are limited |
Total Collection Limits
| Data Type | Maximum Items | Server Validation | |-----------|---------------|-------------------| | Events (rrweb) | 10,000 | 10,000 | | Console Logs | 1,000 | 1,000 | | Network Requests | 1,000 | 1,000 |
Memory Management Features
- Preventive Filtering: Items that would exceed size limits are skipped entirely
- Frequent Cleanup: Data is cleaned up every 5 seconds to prevent accumulation
- Progressive Truncation: If upload data is too large, items are progressively reduced
- Automatic Cleanup: Old data is automatically removed after successful uploads
- Size Validation: Data is validated before upload to prevent server rejections
Upload Limits
- Client-side limit: 25MB per upload
- Server-side limit: 50MB per upload
- Automatic retry: Failed uploads are retried with exponential backoff
- Graceful degradation: If data is still too large after truncation, upload is skipped
Best Practices
- Avoid large objects in console logs: The SDK will truncate them, but it's better to log smaller, focused data
- Monitor network requests: Large API responses will be limited to metadata only
- Use sampling for high-traffic sites: Reduce the sampling rate to limit data collection
- Set appropriate session durations: Long sessions accumulate more data
GDPR Compliance
- All form input values are masked by default to minimize PII collection
- DOM content visible on screen (text, labels, etc.) is still captured for replay
- Users can opt-out via Do Not Track browser headers
- Session data can be deleted by session ID
- Review your pages to ensure no sensitive data appears in non-input page content
Browser Support
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
Development
Building
npm install
npm run buildDevelopment Mode
npm run devTesting
npm testLicense
MIT License - see LICENSE file for details.
