Skip to content

Session Replay

Visual playback of visitor sessions showing cursor movement, clicks, scroll behavior, and page navigation — all from the R2 event logs captured by tracker.js.

Per-site recording control

Session (rrweb) recording is configurable per site. When the tracker is initialised with a site key (PulseGate.init({ siteKey, ... })), it calls GET /track/config?siteKey=... after session start. Only if the response has recordSession: true does it load rrweb and send recording batches to /track/recording. The same domain rules as form config apply (Origin/Referer must match an allowed domain for that site). You can turn recording on or off in Forms config → expand a site → Record session (replay). Sessions and behavioral events are always stored; only the DOM recording (replay) is conditional. Embeds that do not pass siteKey keep the previous behaviour (recording on for all).

How It Works

The tracker script (/tracker.js) captures behavioral events in real-time:

Event TypeData Captured
mousemovex, y coordinates (throttled 100ms)
clickx, y, element (tag + id + class)
scrollscroll_percent (0-100, throttled 250ms)
page_viewpage URL
navigationSPA route changes
visibility_changetab focus/blur

Events are batched every 5 seconds and stored as append-only R2 objects under sessions/YYYY/MM/DD/{session_id}/events/.

The replay viewer reads these events back and plays them chronologically on a visual canvas.

API Endpoints

All data endpoints require API key authentication (same key as /analytics/*).

GET /replay

Serves the self-contained HTML replay viewer. No auth required — the viewer itself is public; data fetching from within the viewer uses the API key entered by the user.

GET /replay/sessions

Lists sessions with event counts. Supports sorting and filtering.

Query Parameters:

ParamTypeDefaultDescription
limitnumber50Max results (capped at 100)
offsetnumber0Pagination offset
visitor_idstringFilter by visitor ID
sortstringstarted_at_descSort order: started_at_desc, started_at_asc, duration_desc, duration_asc, engagement_score_desc, engagement_score_asc, event_count_desc, event_count_asc
entry_pagestringFilter by entry page URL (substring match)
countrystringFilter by country code (exact)
date_fromstring or numberFilter sessions started on or after this date (YYYY-MM-DD or timestamp ms)
date_tostring or numberFilter sessions started on or before this date (YYYY-MM-DD or timestamp ms)

Response:

json
{
  "sessions": [
    {
      "session_id": "abc-123",
      "visitor_id": "def-456",
      "entry_page": "https://example.com/",
      "country": "IN",
      "started_at": 1708617600000,
      "duration": 300000,
      "engagement_score": 65,
      "event_count": 142
    }
  ],
  "total": 1
}

GET /replay/sessions/:id

Returns full session metadata and all events for playback.

Events are loaded from R2 first (append-only event files). Falls back to D1 events table if R2 has no data.

Response:

json
{
  "session": { "...full SessionRecord..." },
  "events": [
    {
      "event_id": "evt-1",
      "event_type": "click",
      "x": 450,
      "y": 320,
      "element": "BUTTON#cta.hero-btn",
      "page": "https://example.com/",
      "timestamp": 1708617612000
    }
  ],
  "event_count": 142
}

Viewer Features

The HTML viewer at /replay includes:

  • Session sidebar — searchable list with engagement scores, country, event count, duration
  • Visual canvas — shows cursor movement trail, click pulse animations, scroll position indicator, current page URL
  • Timeline — scrubber bar with event type ticks (red = clicks, green = scroll, yellow = page views), elapsed/total time
  • Playback controls — play/pause, 1×/2×/4×/8× speed
  • Keyboard shortcuts — Space (play/pause), arrow keys (skip ±5s), 1-4 (speed)
  • Visitor filter — search by visitor_id to focus on a specific user's sessions