sessionable v0.5.0
Sessionable SDK
Session recording and replay SDK for Sessionable, allowing you to capture user sessions and send them to your Sessionable backend.
Installation
npm install sessionable
# or
yarn add sessionable
Quick Start
import { Sessionable } from "sessionable";
// Initialize the SDK
const sessionable = new Sessionable({
apiKey: "your-api-key",
});
// Start recording automatically
sessionable.start();
// Later, stop recording
// sessionable.stop();
React Component
For React applications, we provide a convenient component:
import { SessionRecorder, useSessionable } from "sessionable/react";
function App() {
return (
<div>
<SessionRecorder apiKey="your-api-key" autoStart={true}>
<YourApp />
</SessionRecorder>
</div>
);
}
// In child components, you can access the sessionable instance:
function YourApp() {
// This hook provides stable access to the Sessionable instance with
// optimized rendering - it won't re-render when metrics update
const { isRecording, identify } = useSessionable();
const handleUserLogin = async (userId, orgId) => {
// Identify the user when they log in
if (isRecording) {
await identify(userId, orgId);
}
};
return <div>{/* Your app content */}</div>;
}
Configuration Options
The SDK accepts the following configuration options:
Option | Type | Description | Default |
---|---|---|---|
apiKey | string | Your Sessionable API key | Required |
autoStart | boolean | Start recording automatically | false |
metadata | Object | Custom metadata to include | {} |
maskInputs | boolean | Whether to mask input fields (passwords, text, etc.) | false |
maskTextSelector | string | CSS selector for text elements that should be masked | undefined |
debug | boolean | Enable debug mode (uses localhost:5173 endpoint) | false |
useDeviceId | boolean | Use deterministic device ID generation | true |
userId | string | Identified user ID to link with sessions | undefined |
organizationId | string | Organization ID for the identified user | undefined |
userAttributes | Object | Additional metadata about the identified user | {} |
User Identification
You can identify users to link anonymous sessions with known user accounts:
// Initialize without identification
const sessionable = new Sessionable({
apiKey: "your-api-key",
});
// Start recording
sessionable.start();
// Later, identify the user (e.g., after login)
await sessionable.identify(
"user-123", // User ID (required)
"org-456", // Organization ID (optional)
{
// User attributes (optional)
email: "user@example.com",
plan: "premium",
role: "admin",
}
);
You can also provide identification during initialization:
const sessionable = new Sessionable({
apiKey: "your-api-key",
userId: "user-123",
organizationId: "org-456",
userAttributes: {
email: "user@example.com",
plan: "premium",
},
});
Anonymous User Identification
By default, Sessionable uses device fingerprinting to generate a stable, deterministic ID for anonymous users. This ensures that the same user gets the same ID across sessions, making it easier to track user behavior before they log in.
// Enable device-based ID generation (default)
const sessionable = new Sessionable({
apiKey: "your-api-key",
useDeviceId: true,
});
// Or disable it to use random IDs
const sessionable = new Sessionable({
apiKey: "your-api-key",
useDeviceId: false,
});
The device ID is stored in localStorage as sessionable_anonymous_id
.
Framework Integration
Next.js Integration
For Next.js applications, integrate the SessionRecorder component with client-side only rendering:
// pages/_app.tsx or app/layout.tsx
import dynamic from "next/dynamic";
// Client-side only import of SessionRecorder
const SessionRecorderClient = dynamic(
() =>
import("sessionable/react").then((mod) => ({
default: mod.SessionRecorder,
})),
{ ssr: false }
);
function MyApp({ Component, pageProps }) {
return (
<>
<SessionRecorderClient
apiKey={process.env.NEXT_PUBLIC_SESSIONABLE_API_KEY}
autoStart={true}
metadata={{
environment: process.env.NODE_ENV,
deployment: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA,
}}
maskInputs={true}
>
<Component {...pageProps} />
</SessionRecorderClient>
</>
);
}
export default MyApp;
This approach ensures:
- The recorder only runs on the client side
- Sessions are captured across all pages in your application
- Recording persists during client-side navigation
Remix Integration
For Remix applications, use the client-only module to ensure server-side rendering compatibility:
// app/root.tsx
import { ClientOnly } from "remix-utils/client-only";
import { SessionRecorder } from "sessionable/react";
export default function App() {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
{/* Other meta tags */}
</head>
<body>
<ClientOnly fallback={null}>
{() => (
<SessionRecorder
apiKey={process.env.SESSIONABLE_API_KEY}
autoStart={true}
maskInputs={true}
>
<Outlet />
</SessionRecorder>
)}
</ClientOnly>
{/* Remix scripts */}
<Scripts />
</body>
</html>
);
}
Note: Make sure to include your API key in your environment variables, using the appropriate naming convention for your framework (e.g., NEXT_PUBLIC_
prefix for client-accessible variables in Next.js).
Debug Mode
For local development and testing, you can enable debug mode to use a local API endpoint:
const sessionable = new Sessionable({
apiKey: "your-api-key",
debug: true, // Uses http://localhost:5173 instead of production
});
React Hooks API
When using the React integration, you can access the Sessionable instance and metrics using two optimized hooks, which have been designed to prevent unnecessary re-renders in your application:
useSessionable
Access the Sessionable instance, control methods, and recording state. This hook is optimized to prevent re-renders when metrics change (which can happen frequently). It will only trigger re-renders when the recording state changes:
import { useSessionable } from "sessionable/react";
function RecordingControls() {
const {
sessionable, // The Sessionable instance
isRecording, // Current recording state (updates without causing frequent re-renders)
start, // Start recording
stop, // Stop recording
addMetadata, // Add custom metadata
identify, // Identify user
getUserId, // Get identified user ID
getOrganizationId, // Get organization ID
getUserAttributes, // Get user attributes
} = useSessionable();
// This component will only re-render when isRecording changes,
// not when metrics update every second
return (
<div>
<p>Status: {isRecording ? "Recording" : "Not recording"}</p>
<button onClick={() => start()} disabled={isRecording}>
Start Recording
</button>
<button onClick={() => stop()} disabled={!isRecording}>
Stop Recording
</button>
<button
onClick={() => identify("user-123", "org-456")}
disabled={!isRecording}
>
Identify User
</button>
</div>
);
}
useSessionableMetrics
Access only the session metrics. Components using this hook will re-render when metrics change (approximately once per second when metrics are actively updating):
import { useSessionableMetrics } from "sessionable/react";
function MetricsDisplay() {
// This component will re-render when metrics change (every ~1 second during recording)
const metrics = useSessionableMetrics();
if (!metrics) return <div>No metrics available</div>;
return (
<div>
<p>Session ID: {metrics.sessionId || "Not recording"}</p>
<p>Events: {metrics.eventsRecorded || 0}</p>
<p>Connection: {metrics.connectionStatus || "disconnected"}</p>
<p>Batches: {metrics.batchesSuccessful}/{metrics.batchesSent}</p>
</div>
);
}
Performance Optimized Usage
For optimal performance, follow these patterns:
- Use
useSessionable
for components that need recording controls but don't need to display metrics - Use
useSessionableMetrics
only in components that display metrics data - Memoize components to prevent unnecessary re-renders
import React, { memo } from "react";
import { useSessionable, useSessionableMetrics } from "sessionable/react";
// This component only re-renders when recording state changes
const ControlButtons = memo(() => {
const { start, stop, isRecording } = useSessionable();
return (
<div>
<button onClick={start} disabled={isRecording}>
Start Recording
</button>
<button onClick={stop} disabled={!isRecording}>
Stop Recording
</button>
</div>
);
});
// This component only re-renders when metrics change
const MetricsDisplay = memo(() => {
const metrics = useSessionableMetrics();
if (!metrics) return <div>No metrics available</div>;
return (
<div>
<p>Session ID: {metrics.sessionId || "Not available"}</p>
<p>Events: {metrics.eventsRecorded}</p>
<p>Batches: {metrics.batchesSuccessful}/{metrics.batchesSent}</p>
</div>
);
});
// Main component that includes both control buttons and metrics
function SessionControls() {
return (
<div>
<h3>Session Controls</h3>
<ControlButtons />
<h3>Session Details</h3>
<MetricsDisplay />
</div>
);
}
This architecture ensures that:
- The control buttons only re-render when recording starts/stops
- The metrics display only re-renders when metrics change
- Components not directly consuming these hooks won't re-render at all
Examples
Basic Example
Check out the basic example to see a simple HTML implementation.
SaaS Demo
For a complete React application example, see the SaaS Demo which shows a healthcare platform with the SDK fully integrated.
Advanced Usage
Text Masking with CSS Selectors
You can protect sensitive information on your page by specifying a CSS selector for text that should be masked:
const sessionable = new Sessionable({
apiKey: "your-api-key",
maskTextSelector: ".sensitive-data, [data-mask], .user-pii",
});
With this configuration, any element matching these selectors will have its text content masked in recordings:
<!-- These texts will be masked in recordings -->
<span class="sensitive-data">Account: 1234-5678-9012</span>
<div data-mask>SSN: 123-45-6789</div>
<p class="user-pii">Jane Smith</p>
Adding Custom Metadata
// During initialization
const sessionable = new Sessionable({
apiKey: "your-api-key",
metadata: {
userId: "123",
userType: "premium",
environment: "production",
},
});
// Or later during recording
sessionable.addMetadata({
currentPage: window.location.pathname,
referrer: document.referrer,
timestamp: new Date().toISOString(),
});
Getting Session Metrics
You can retrieve session metrics at any time using the getMetrics
method:
const metrics = sessionable.getMetrics();
console.log("Session ID:", metrics.sessionId);
console.log("Events recorded:", metrics.eventsRecorded);
console.log("Connection status:", metrics.connectionStatus);
TypeScript Support
The package includes TypeScript definitions for all public APIs.
License
All rights reserved. © Sessionable
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
4 months ago
4 months ago