# segi · Session recording & heatmap · LLM integration guide This file describes how to wire segi's session recording + click heatmap into an end-user's project. It is browser-only — the NestJS SDK does not run the recorder. If the user has a Next.js front-end, use this guide. If they have a separate Vite/CRA/etc SPA, see the "Browser SDK" section. ## TL;DR 1. Install `@extn/segi-nextjs` (or `@extn/segi-js` for non-Next stacks). 2. Mount `` (Next) or call `Segi.init({ replay: withReplay({...}) })`. 3. Have the org owner enable recording at Project → Settings → Recording in the segi dashboard. **It is OFF by default per project.** 4. Open Project → Recordings to see sessions, DOM replays, and the heatmap. ## Architecture in one sentence The SDK posts session metadata + click batches to `POST /api/trace/*` and DOM-replay chunks to `POST /api/trace/replay`. The admin UI reads them back through JWT-guarded admin endpoints. ## Plan-gated quota | Plan | Recordings / org / month (KST) | | --- | --- | | Free | 30 | | Team | 100 | | Enterprise | unlimited | Counted at the first replay chunk per session (subsequent chunks are free). On 429 quota_exceeded, the SDK stops the recorder for the rest of the session; heatmap and signals continue. The org owner can recover within the current period by upgrading the plan or paying a one-off top-up — both are available from the billing pages in the dashboard. ## Required server state - Project must have `recordingEnabled = true` (org-owner toggle in dashboard). - Optional per-project deny-list of path prefixes (e.g. `/auth`, `/checkout`) edited in the same settings page. - SDK calls `POST /api/trace/session/start` first; response includes `{ recordingEnabled: boolean }`. When false, the SDK skips all collection. ## Next.js — recommended ```tsx // app/layout.tsx import { SegiReplayProvider } from "@extn/segi-nextjs/replay"; export default function RootLayout({ children }) { return ( {children} ); } ``` `endpoint` defaults to the hosted segi service; pass `endpoint=...` only when self-hosting. `sample`, `blockRoutes`, and `mask` are all optional. The provider wires `Segi.init` idempotently and uses `usePathname()` to push SPA route changes to the recorder. The replay module is dynamic-imported, so non-replay pages pay zero bundle cost. MCP: `claude mcp add segi-nextjs -- npx -y @extn/segi-mcp-nextjs`. Call the `get_session_recording_setup` tool to receive ready-to-write file patches and an operator reminder note. ## Browser SDK (Vite / CRA / plain bundler) ```ts import Segi from "@extn/segi-js"; import { withReplay } from "@extn/segi-js/replay"; Segi.init({ projectKey: "segi_pk_live_...", endpoint: "https://segiapi.extn.ai", replay: withReplay({ enabled: true, sample: 100, blockRoutes: ["/auth", "/checkout"], mask: { inputs: "all", class: "segi-mask" }, }), }); // Anywhere after init: Segi.replay.pause(); Segi.replay.resume(); Segi.replay.setUser({ id: "u_123", email: "alice@example.com" }); Segi.replay.event("checkout_started", { amount: 9900 }); Segi.replay.notifyRouteChange(); // for SPAs without next/router ``` CDN bundle (`segi.min.js`) does NOT include the replay submodule. ## NestJS — note Session recording is a browser feature. The NestJS SDK is server-only. Configure the browser client on whatever framework serves your HTML. The `@extn/segi-mcp-nestjs` MCP exposes `get_session_recording_info` which returns this guidance plus stack-specific next-steps. ## Masking Two layers: 1. **Class-based** (`mask.class`, default `segi-mask`): any DOM element with this class, plus all descendants, is excluded from heatmap clicks AND DOM replay. The class climbs the ancestor chain when a click fires. 2. **Input mask mode** (`mask.inputs`): - `"all"` (default) — masks every input: password, email, tel, number, text, textarea. - `"sensitive"` — masks only password / email / tel / number. - `"none"` — masks only password. **Not recommended** for forms with PII. ## blockRoutes guidance `blockRoutes` is optional. Password/email/tel/number inputs are auto-masked regardless of route, so explicitly skipping `/login`, `/signup`, etc. adds little security value and discards click-heatmap data on pages where users genuinely do click. Recommended: omit the prop. If a specific UI region needs to be excluded, mark it with `className="segi-mask"` — both heatmap and DOM replay then skip its subtree. ## Admin UI surfaces | Path | Purpose | | --- | --- | | `/projects/[id]/recordings` | List + filters + plan-usage banner | | `/projects/[id]/recordings/[sessionUid]` | Stat grid + timeline + DOM replay | | `/projects/[id]/recordings/heatmap` | URL × device click heatmap layered over a DOM-replay backdrop of a matching session | | `/projects/[id]/settings/recording` | Owner-only toggle + deny-list | The heatmap viewer renders an interactive DOM backdrop (the matching session's replay frozen at frame 0, decoratively dimmed) underneath the heat cells. The matching session is picked automatically from the active URL/device filter. Click coords are viewport-relative (each click's `x / viewportW`, `y / viewportH`) so dots align with the elements visible on the backdrop. ## Verifying 1. Mount the provider, deploy. 2. Have the operator enable recording in the dashboard. 3. Visit a page in your browser, click around, scroll. 4. Within ~5 seconds the click should show under Project → Recordings → click heatmap. 5. After ~30s on the page, a DOM replay chunk lands. Visit the session detail to play it back. ## Privacy mechanisms - Password/email/tel/number inputs are masked by the recorder by default. - Class `segi-mask` excludes whole regions, recursive on descendants. - Per-project deny-list of path prefixes skips collection server- AND client-side. - IP hashed daily-salted before persistence; raw IPs never stored. - Recording off by default per project; owner enables explicitly.