Session Replay

Record and replay user sessions to understand how users interact with your application. Debug issues faster by watching exactly what users experienced — self-hosted, with full data ownership.


Overview

Temps session replay captures DOM mutations and user interactions using rrweb, then stores the compressed event stream on your own infrastructure. You retain full control over your users' data — nothing is sent to external services.

What's Recorded

  • Full DOM snapshots and incremental mutations
  • Mouse clicks, scrolls, and keyboard events
  • Page navigations and URL changes
  • Viewport and screen dimensions
  • Browser, OS, and language metadata
  • Session duration and activity state

What's Included

  • Complete data ownership — no third parties
  • Privacy controls with CSS-selector masking
  • Configurable sampling rate
  • Path-based exclusion rules
  • Automatic 15-day data cleanup
  • CLI access to sessions and raw events

Setup

Session recording is opt-in and disabled by default. Enable it on the provider and pass a sessionRecordingConfig to control behaviour.

React

React Setup

import { TempsAnalyticsProvider } from '@temps-sdk/react-analytics'

export default function RootLayout({ children }) {
  return (
    <TempsAnalyticsProvider
      projectId="your-project-id"
      enableSessionRecording={true}
    >
      {children}
    </TempsAnalyticsProvider>
  )
}

Controlling recording from a component

Use useSessionRecording() inside any component that is already wrapped by TempsAnalyticsProvider (or SessionRecordingProvider):

useSessionRecording hook

import { useSessionRecording } from '@temps-sdk/react-analytics'

export function CookieBanner() {
  const { isRecordingEnabled, enableRecording, disableRecording } =
    useSessionRecording()

  return (
    <div>
      <p>Session recording is {isRecordingEnabled ? 'on' : 'off'}.</p>
      <button onClick={enableRecording}>Allow recording</button>
      <button onClick={disableRecording}>Opt out</button>
    </div>
  )
}

The hook exposes:

FieldTypeDescription
isRecordingEnabledbooleanWhether recording is currently active
enableRecording() => voidStart recording this session
disableRecording() => voidStop recording this session
toggleRecording() => voidToggle recording on/off
sessionIdstring | nullCurrent rrweb session ID

If you need recording control without a provider (for example in a standalone component tree), use useSessionRecordingControl(defaultEnabled?) instead — it requires no wrapper.

Svelte

Svelte store

import { sessionRecordingStore } from '@temps-sdk/svelte-analytics'

// Create a store — pass `true` to enable immediately
const recording = sessionRecordingStore(false)

// In response to a user action:
recording.enable()
recording.disable()
recording.toggle()

Vanilla JS

Vanilla JS

<script src="https://cdn.jsdelivr.net/npm/@temps-sdk/browser-analytics/dist/index.js"></script>
<script>
  TempsAnalytics.init({
    projectId: 'your-project-id',
    sessionReplay: {
      enabled: true,
      sessionSampleRate: 0.5,
      maskAllInputs: true,
      excludedPaths: ['/checkout/*'],
    },
  })
</script>

Privacy Controls

Session replay is built on rrweb, which provides fine-grained control over what is — and is not — recorded.

Always redacted

Password inputs (type="password") are always masked by rrweb regardless of configuration. No additional setup is needed.

Mask text in specific elements

Add data-rr-mask to any element whose text content should appear as **** in the replay:

<p data-rr-mask>Sensitive information shown to the user</p>

Or configure a CSS selector to mask all matching elements:

sessionRecordingConfig: {
  maskTextSelector: '[data-mask], .pii-field',
}

Block entire elements from recording

Add data-rr-block (or the configured blockClass) to remove an element entirely — it is replaced by a placeholder rectangle in the replay:

<div class="rr-block">
  <!-- This element will not appear in the replay at all -->
  <img src="/user-photo.jpg" />
</div>
sessionRecordingConfig: {
  blockClass: 'rr-block',  // default — matches elements with this CSS class
}

Ignore interaction events on an element

Use data-rr-ignore (or ignoreClass) so that clicks and keyboard events on that element are not recorded, while the element's DOM content still appears:

<input class="rr-ignore" placeholder="Untracked field" />

Mask all inputs

Enable maskAllInputs (the default) to replace every input value with * characters across the entire recording. Disable it only if you have verified that no sensitive values flow through your inputs.

sessionRecordingConfig: {
  maskAllInputs: true,  // default — recommended for all production apps
}

Path-based exclusion

Use excludedPaths with * wildcards to skip recording on specific routes:

sessionRecordingConfig: {
  excludedPaths: [
    '/admin/*',
    '/account/payment',
    '/profile/edit',
  ],
}

GDPR / sampling

Set sessionSampleRate: 0 to record no sessions by default, then call enableRecording() only after users give explicit consent:

// Record zero sessions globally
sessionRecordingConfig={{ sessionSampleRate: 0 }}

// Enable only after consent
const { enableRecording } = useSessionRecording()
<button onClick={enableRecording}>Accept analytics</button>

Recording Lifecycle

How events are stored

Events are sent to the Temps backend in batches. Each batch is base64 + zlib compressed in transit, then decoded and stored in the session_replay_events table as raw JSON in rrweb format.

The following rrweb event types are captured:

TypeConstantDescription
0DomContentLoadedInitial DOMContentLoaded event
1LoadWindow load event
2FullSnapshotComplete DOM snapshot
3IncrementalSnapshotDOM mutations, mouse moves, clicks, scrolls
4MetaViewport metadata
5CustomSDK-defined custom events
6PluginPlugin-generated events

Session metadata

Each session is stored in session_replay_sessions with:

  • Browser name and version
  • Device type, operating system, and OS version
  • Screen and viewport dimensions (width × height)
  • Language and timezone
  • Entry URL, total duration, and active/idle state
  • Project and environment IDs

Batching and flush behaviour

Events are buffered client-side. You can tune both limits:

sessionRecordingConfig: {
  batchSize: 100,       // send after accumulating this many events (default: 100)
  flushInterval: 5000,  // or after this many ms, whichever comes first (default: 5000)
}

Lower flushInterval means fewer lost events if a user closes the tab, at the cost of more frequent network requests.


CLI

The Temps CLI provides full access to session replay data for scripting, debugging, and export.

List sessions for a project

bunx @temps-sdk/cli session-replay list \
  --project-id <project-id> \
  [--environment-id <env-id>] \
  [--page <n>] \
  [--per-page <n>] \
  [--json]

List sessions for a specific visitor

bunx @temps-sdk/cli session-replay visitor <visitor-id> \
  [--page <n>] \
  [--per-page <n>] \
  [--json]

Show session metadata

bunx @temps-sdk/cli session-replay show <visitor-id> <session-id> [--json]

Export raw events

# Print event stream to stdout
bunx @temps-sdk/cli session-replay events <visitor-id> <session-id>

# Write to a file for offline replay or debugging
bunx @temps-sdk/cli session-replay events <visitor-id> <session-id> \
  --output session-events.json \
  [--page <n>] \
  [--limit <n>]

Delete a session

bunx @temps-sdk/cli session-replay delete <visitor-id> <session-id>

# Skip the confirmation prompt (useful in scripts)
bunx @temps-sdk/cli session-replay delete <visitor-id> <session-id> -y

Viewing Replays

Recorded sessions appear in your project dashboard under Analytics → Session Replay. The replay player renders the rrweb event stream and provides:

  • Play, pause, and variable-speed playback
  • A timeline scrubber with event markers (clicks, navigation, input)
  • Session metadata panel (browser, OS, device, screen size, duration)
  • Per-session visitor history (all sessions by the same visitor ID)

Sessions are listed in reverse chronological order. Use the environment selector to filter between production, staging, and preview environments.


Data Retention

Session replay data is automatically purged after 15 days by default. This applies to both session metadata (session_replay_sessions) and the associated event stream (session_replay_events).

The retention window is configurable on self-hosted deployments via the Temps server configuration. Reducing the retention period is recommended for GDPR Article 5(1)(e) storage-limitation compliance.


Configuration Reference

Full SessionRecordingConfig interface:

OptionTypeDefaultDescription
sessionSampleRatenumber1.0Fraction of sessions to record. 0.0 = none, 1.0 = all.
maskAllInputsbooleantrueReplace all input values with * characters.
maskTextSelectorstring"[data-mask]"CSS selector — matching elements have their text replaced with asterisks.
maskTextClassstring"rr-mask"CSS class — elements with this class have text masked.
blockClassstring"rr-block"CSS class — elements with this class are replaced by a placeholder.
ignoreClassstring"rr-ignore"CSS class — interaction events on these elements are not recorded.
excludedPathsstring[][]URL paths to skip. Supports * wildcards (e.g. "/admin/*").
recordCanvasbooleanfalseCapture <canvas> element contents. Increases payload size significantly.
collectFontsbooleanfalseInline font files into the recording for accurate replay on other machines.
batchSizenumber100Number of events to accumulate before flushing to the server.
flushIntervalnumber5000Milliseconds between periodic flushes, regardless of batch size.

Provider props (React)

PropTypeDefaultDescription
enableSessionRecordingbooleanfalseMust be true to activate recording.
sessionRecordingConfigSessionRecordingConfig{}Recording options — see table above.

Additional Resources

Was this page helpful?