relyv.ai
Skip to main content
How-to

Adding session replay to a React app.

Five-minute install for any React app — Create React App, Vite, Remix, or plain Webpack. The SDK is tree-shaken, fully typed, and runs entirely off the main thread. Here's the code.

TL;DR
Drop the Relyv loader (<script async src="https://cdn.relyv.ai/sdk/v1/relyv.js" data-project-id="..." data-environment-id="...">) into your React app entry — or, once the npm package ships, install @relyv/sdk and call init({ projectId, environmentId }) in main.tsx / index.tsx / root.layout.tsx. Either path auto-captures clicks, network calls, console errors, and DOM mutations from first render; React-specific concerns (StrictMode double-render, error boundaries, route changes) are handled automatically.

The one-line answer

Today: drop the Relyv loader script tag (<script async src="https://cdn.relyv.ai/sdk/v1/relyv.js" data-project-id="..." data-environment-id="...">) into your React entry HTML — records every session from first render with ~14 KB gzipped and sub-1% main-thread overhead. Once the bundled npm package ships, npm install @relyv/sdk + init({ projectId, environmentId }) will give you the same capture in a tree-shaken module form.

Note on install methods (May 2026)

The CDN-hosted loader at cdn.relyv.ai/sdk/v1/relyv.js is the production install path right now. The npm-distributed bundle (@relyv/sdk) is documented in this guide and the install hub because it's on the immediate roadmap — but at the time of writing the package has not yet been published. If you copy-paste an npm install @relyv/sdk command before publish day, it will 404. The script-tag method below works today; the npm import patterns are accurate descriptions of how the bundled package will behave once it lands.

What you need before starting

Three prerequisites:

  • <strong>A Relyv account</strong> (free tier covers 1,000 sessions/mo).
  • <strong>API key + project ID</strong> from dashboard.relyv.ai → Settings → API keys.
  • <strong>Edit access to your React app entry file</strong> (main.tsx, index.tsx, or equivalent).

How Relyv React setup works

The SDK is framework-agnostic but behaves correctly inside React out of the box. It hooks the History API for route-change detection (works with React Router, TanStack Router, Wouter), captures the initial DOM after first paint, and subscribes to MutationObserver for every subsequent change. StrictMode's double-render doesn't cause duplicate sessions — the SDK deduplicates on session ID, not init calls.

Step-by-step

  1. 1

    Install the SDK (today: script tag; once published: npm)

    Today (working install path): add one script tag to index.html (Vite, CRA, etc) — <script async src="https://cdn.relyv.ai/sdk/v1/relyv.js" data-project-id="YOUR_PROJECT_ID" data-environment-id="YOUR_ENVIRONMENT_ID"></script>. The loader is async-loaded, sub-1% CPU, ~14 KB gzipped, served from cdn.relyv.ai behind Cloud CDN.

    Once @relyv/sdk is published to npm (target: shortly after general availability — until then this section describes the package shape rather than a runnable command): npm install @relyv/sdk (or pnpm add / yarn add / bun add). The package is fully typed; types ship alongside the runtime.

  2. 2

    Initialise at app entry

    Script tag (today): the loader self-initialises from the data-project-id + data-environment-id attribute — no further code needed.

    npm import pattern (once the package ships):

    // main.tsx (Vite) or index.tsx (CRA)
    import { init } from '@relyv/sdk';
    
    init({
      projectId: import.meta.env.VITE_RELYV_PROJECT_ID,
      environmentId: import.meta.env.VITE_RELYV_ENVIRONMENT_ID,
    });
    
    // rest of your render code
    ReactDOM.createRoot(...).render(...);

    Init must run on the client (in the browser), not at build time. Vite + CRA satisfy this automatically because main.tsx runs in the browser.

  3. 3

    Mark sensitive fields

    Add the data-relyv-mask attribute to any element rendering PII the SDK can't identify by content alone:

    <input data-relyv-mask name="customer-id" />
    <div data-relyv-mask>{user.fullName}</div>

    Standard PII (emails, phone numbers, credit cards) is masked automatically via regex + Luhn validation — no marker needed.

  4. 4

    Verify in dev before deploying

    Run your app locally, click around for 30 seconds, then open the Relyv Library at dashboard.relyv.ai. The session appears within seconds. Watch the replay end-to-end, open the Network and Console tabs inside the replay viewer, and confirm no PII leaks. Check the "raw payload" tool in Settings if you want to see the exact serialized capture.

  5. 5

    Deploy + monitor

    Push to staging, watch the session corpus grow, look for the first AI-summarised bug ticket in the Triage inbox within a few hours. Production deploy follows the same pattern; no per-environment configuration beyond the API key/project ID for the corresponding workspace.

Frequently asked questions

Does this work with React 19 and the new compiler?

Yes. The SDK doesn't depend on React internals — it operates on the DOM and the History API, both of which the React Compiler doesn't touch. Tested against React 18.3, 19.0, and the Compiler beta.

What about React Server Components / Next.js App Router?

See the Next.js-specific guide (link below). Short version: wrap the init call in a Client Component that mounts once at app root, so it only runs in the browser, not during SSR/RSC streaming.

Does it duplicate sessions in StrictMode?

No. The SDK is idempotent — calling init twice with the same apiKey/projectId creates one session, not two. StrictMode's double-render is fully supported.

How do I capture state from Redux / Zustand / Jotai?

The SDK auto-captures the DOM, network, and console. For state-store snapshots, register a state plugin: import { reduxPlugin } from '@relyv/sdk/plugins'; init({ ..., plugins: [reduxPlugin(store)] }). Plugins exist for Redux, Zustand, Pinia, and Jotai; custom plugins follow a documented interface.

Will it break my CSP?

The SDK loads from a same-origin path if you use npm + bundling (no CSP changes needed). If you use the CDN tag instead (cdn.relyv.ai/sdk/v1/relyv.js), allowlist cdn.relyv.ai in your script-src and ingest-relyv.ai in connect-src.

What about React Native?

React Native has different capture mechanics (no DOM). Native iOS and Android SDKs are in alpha; cross-platform via React Native bridge is on the roadmap. For now, React Native apps are best served by the in-app feedback flow + screenshot capture rather than full DOM replay.

Does it slow down CSR/SSR hydration?

No measurable hydration regression in our benchmarks. The SDK's init schedules its initial DOM snapshot in a requestIdleCallback (or setTimeout 0 fallback), so it never blocks the first interactive frame. Main-thread overhead during ongoing capture is under 1% on production traffic.

Ready to record your first session?

Free 1,000 sessions/mo. No credit card. Cancel anytime, no refunds.