Package Exports
- sigillum-js
- sigillum-js/react
- sigillum-js/ui
- sigillum-js/vue
Readme
sigillum-js
Session recording for the web. Record user behavior, replay it, debug faster.
English | 中文
What it does
Records the entire user session so you can replay every step of user behavior. Data stays on your own servers.
Installation
npm install sigillum-jsyarn / pnpm
yarn add sigillum-js
# or
pnpm add sigillum-jsQuick Start
import { getRecorder } from 'sigillum-js';
const recorder = getRecorder({
onUpload: async (data) => {
await fetch('/api/recordings', {
method: 'POST',
body: JSON.stringify(data),
});
return { success: true };
},
});
recorder.start();
// Later — stop and upload
await recorder.stop();That's it. The recorder captures everything automatically — mouse movement, scrolling, inputs, and route changes. When stop() is called, data is uploaded via your onUpload callback.
Local-only mode (no upload)
For debugging workflows where users export recordings manually:
const recorder = getRecorder({ debug: true });
recorder.start();
// ... user reproduces the bug ...
await recorder.stop();
const data = recorder.exportRecording();
downloadAsJson(data); // your download helperFramework Integrations
| Framework | Import Path | Key Exports |
|---|---|---|
| Vanilla JS | sigillum-js |
getRecorder(), resetRecorder(), isRecorderInitialized() |
| React 16.8+ | sigillum-js/react |
useSessionRecorder(), useAutoRecord() |
| Vue 3+ | sigillum-js/vue |
createSigillumPlugin(), useSessionRecorder(), useAutoRecord() |
React Example
import { useAutoRecord } from 'sigillum-js/react';
function App() {
const { status, sessionId, addTag, identify } = useAutoRecord({
onUpload: async (data) => {
await fetch('/api/recordings', { method: 'POST', body: JSON.stringify(data) });
return { success: true };
},
});
identify('user-123', { plan: 'pro' });
return <div>Status: {status}</div>;
}Vue 3 Example
// main.ts
import { createApp } from 'vue';
import { createSigillumPlugin } from 'sigillum-js/vue';
const app = createApp(App);
app.use(createSigillumPlugin({
onUpload: async (data) => {
await fetch('/api/recordings', { method: 'POST', body: JSON.stringify(data) });
return { success: true };
},
autoStart: true,
}));
app.mount('#app');<script setup>
import { inject, onUnmounted, ref } from 'vue';
import { useAutoRecord } from 'sigillum-js/vue';
const { status, sessionId, addTag } = useAutoRecord(inject, onUnmounted, { ref });
</script>
<template>
<div>Status: {{ status.value }}</div>
</template>Replay UI
Built-in React components for replaying recordings:
import { ReplayPlayer, ReplayPage } from 'sigillum-js/ui';
<ReplayPlayer data={recordingData} />
// Full page with session info
<ReplayPage data={recordingData} showInfo={true} />API Reference
const recorder = getRecorder(options);
// Lifecycle
recorder.start();
await recorder.stop();
recorder.pause();
recorder.resume();
// Data
recorder.exportRecording(); // Export after stop (events + metadata + summary)
recorder.clearRecording(); // Free memory
// Tags & Identity
recorder.addTag(name, data);
recorder.identify(userId, traits?);
// Status
recorder.getStatus(); // 'idle' | 'recording' | 'paused' | 'stopped'
recorder.getSessionId();
recorder.getEventCount();
recorder.getEstimatedSize();
recorder.getSummary(); // { clickCount, inputCount, scrollCount, routeChanges, ... }
// Cleanup
recorder.destroy();
resetRecorder();Configuration
const recorder = getRecorder({
// Upload (optional — without it, runs in local-only mode)
onUpload: async (data) => { return { success: true }; },
// Field mapping (adapt to your backend schema)
fieldMapping: [['sessionId', 'id'], ['events', 'content', JSON.stringify, JSON.parse]],
beforeUpload: (data) => ({ ...data, userId: getCurrentUserId() }),
// Enable condition
enabled: () => user.isVIP || Math.random() < 0.1,
// Crash recovery cache
cache: { enabled: true, saveInterval: 5000, maxItems: 10, maxAge: 604800000 },
// Chunked upload (for long recordings)
chunkedUpload: { enabled: true, interval: 60000 },
onChunkUpload: async (chunk) => { return { success: true }; },
// Callbacks
onEventEmit: (event, count) => {},
onError: (error) => {},
onStatusChange: (status, prev) => {},
// Limits
maxEvents: 50000,
maxDuration: 1800000, // 30 min
maxRetries: 3,
// Privacy (mask inputs, block elements, etc.)
rrwebConfig: {
privacy: {
blockSelector: '.credit-card-form, [data-private]',
maskAllInputs: true,
},
slimDOMOptions: 'all',
},
// Misc
uploadOnUnload: true,
beaconUrl: '/api/beacon',
debug: false,
});Compatibility
| Browser | Version |
|---|---|
| Chrome | 64+ |
| Firefox | 69+ |
| Safari | 12+ |
| Edge | 79+ (Chromium) |
| iOS Safari | 12+ |
| IE | Not supported |
| Framework | Version | Import Path |
|---|---|---|
| React | 16.8+ | sigillum-js/react |
| Vue | 3.0+ | sigillum-js/vue |
| Next.js | 12+ | Via React integration |
| Nuxt | 3+ | Via Vue integration |
Also Check Out
If you need error tracking, log management, and performance monitoring, check out aemeath-js — a lightweight, plugin-based frontend logging & monitoring SDK.
Together, sigillum-js (session replay) + aemeath-js (logging & monitoring) provide a complete frontend observability solution — all data stays on your own servers.
Contributing
Issues and feature requests are welcome! Feel free to open an issue.
License
MIT © TieriaSail
Built with AI assistance.