Session replay · Coming soon

See what happened
right before it broke.

Replay the pages, clicks, and requests of a visit, next to the errors it hit. Inputs are masked before anything leaves the browser, and every request links to its trace.

Masked inputs

Before they leave the browser

Captured on error

With the minute before it

Linked to traces

Each request, its exact span

Consent first

Nothing recorded before it

One integration, after consent

Replay is an integration of the browser SDK you already use for errors and analytics. It does nothing until the visitor agrees: the recorder only loads after grantConsent().

  • Records 10% of sessions by default, plus any session that hits an error
  • One recording per tab, continued across reloads on the same site
  • revokeConsent() stops capture and erases what the browser kept
src/monocle.ts
import { errors, initMonocle, network } from '@monocle.sh/browser-sdk'
import { replay } from '@monocle.sh/browser-sdk/replay'

const sessionReplay = replay({
  sessionSampleRate: 0.1,
  captureOnError: true,
})

export const monocle = initMonocle({
  dsn,
  environment: 'production',
  integrations: [network(), errors(), sessionReplay],
})

// From your consent banner
await sessionReplay.grantConsent()

The minute before the error

Sessions that were not sampled are buffered in the browser. When an exception is captured, Monocle keeps up to 60 seconds before it and records the rest of the visit.

  • Open the replay from the exact occurrence of an issue
  • Pages, clicks, requests, and exceptions on the timeline and in the event list
  • Each request links to its trace and span by ID, never guessed from timestamps
an error-triggered replay
buffered in the browser, up to 60 s before the error
  14:31:12  navigation  /checkout
  14:31:49  click       Pay $148.00
  14:31:50  request     POST /api/payments 504  → its trace
  14:32:07  error       PaymentTimeoutError     → its issue

then recorded until the visit ends

Private by default

Masking runs in the browser, before events are buffered or sent. Input values are always replaced, and you choose which text and which parts of the page never get recorded.

  • Every input value replaced with ***, unless you opt a field back in
  • Canvas, video, audio, request bodies, and headers are never captured
  • Query strings and fragments are dropped from page URLs
checkout.html
<!-- Input values are masked by default -->
<input name="card-number" autocomplete="cc-number" />

<!-- This text is masked too -->
<p data-monocle-replay-mask>{{ customer.address }}</p>

<!-- Never recorded, replaced by an empty box -->
<section data-monocle-replay-block>
  <SupportChat />
</section>
Works with

Plugs into your stack

Browser SDK

The replay() integration

Issues

Replay from the occurrence

Traces

Requests linked to their span

Consent banner

grantConsent() and revokeConsent()

Visitor identity

Opt in with captureUser

Same-site reloads

One recording per tab

Early access

See what your apps
are really doing.

Traces, logs, errors and metrics for every app you ship. Bring it all into focus.