---
title: "How to add session replay to your app with Claude Code"
description: "Use Claude Code to record a synthetic report export and check that private text is masked and an excluded panel's contents are absent from the replay."
canonical: "https://amplitude.com/en-us/build/claude-code-session-replay"
---

# How to add session replay to your app with Claude Code

Use Claude Code to record a synthetic report export and check that private text is masked and an excluded panel's contents are absent from the replay.

Source: https://amplitude.com/en-us/build/claude-code-session-replay

---

# How to add session replay to your app with Claude Code

Use Claude Code to record a synthetic report export and check that private text is masked and an excluded panel's contents are absent from the replay. Review the generated changes against a complete browser example and verify the result in Amplitude.

- Claude Code
- Vite
- Unified SDK 1.1.43
- 25 min

Chris Tam · Last updated 3 November 2026

A coding agent can add a recorder quickly, but you still need to choose what it captures. Amplitude [session replay](https://amplitude.com/session-replay) connects a recording to the report events you send from the same browser client.

In this tutorial, you'll give Claude Code an implementation prompt, review its changes, run a report example, and check the result in your development project.

A browser report app that lets you record a synthetic report export and check that private text is masked and an excluded panel's contents are absent from the replay. The agent's code is reviewable against the complete files below.

## Prerequisites

- Claude Code installed and signed in. This tutorial uses its interactive terminal workflow, not an unattended run.
- Node.js 22.12 or later and Corepack with pnpm 10.33.2. The example pins Vite 8.3.4 and `@amplitude/unified` 1.1.43; it doesn't require another Build tutorial.
- A development Amplitude project and its public client API key from Settings > Projects > your project > General. Confirm its US or EU data center. Check that the project has access to the product and capacity for your test.

[Sign up for Amplitude](https://app.amplitude.com/signup) if you need an account, and [compare plans](https://amplitude.com/pricing) for your project's allowances. Use synthetic data throughout this walkthrough.

## 1. Open the project and connect context

I use a small Vite app to make the generated changes easy to inspect. For a new example, create an empty repository. If you're extending an existing app, open its repository and preserve its setup instead.

Terminal

```sh
mkdir amplitude-report-session-replay
cd amplitude-report-session-replay
git init
```

Optionally connect [Amplitude's MCP server](https://amplitude.com/docs/amplitude-ai/amplitude-mcp) so the agent can inspect your project's existing event taxonomy. Run these commands from the project directory before starting the interactive session. Use `https://mcp.eu.amplitude.com/mcp` instead for EU data residency.

Terminal

```sh
claude mcp add --transport http amplitude https://mcp.amplitude.com/mcp
claude mcp list
```

After starting Claude Code in step 2, use `/mcp` to authenticate and confirm the connection. Read the [client's MCP instructions](https://code.claude.com/docs/en/mcp) if your organization manages these settings. Review the requested access. Connecting context doesn't authorize the agent to publish experiences or change targeting.

## 2. Give the agent a precise implementation prompt

Run `claude` in the project directory after configuring MCP, then paste this prompt into the interactive session. It names the event, the SDK boundary, and the checks the agent must preserve.

Implementation prompt

```text
Work in this repository and first inspect its app entry point, existing Amplitude initialization, consent flow, authentication, package manager and CLAUDE.md. Use current Amplitude docs and report the source URLs. Before changing code, describe the files you will touch and any conflicting existing setup.

Read the complete reference app at https://github.com/amplitude/ampli-examples/tree/1c8efa7b11d3d91033198e8ba3ead0579170e5e7/browser/coding-tools/session-replay. Implement that standalone Vite report example, or merge the same behavior into the existing browser app. If you cannot read the reference, ask me to paste its files before implementing it. For the isolated development demo only: Use @amplitude/unified 1.1.43 and initAll once after Start demo. Set top-level serverZone. Enable session events, set replay sampleRate to 1 for the development test, and skip engagement. Mask #sensitive and block #excluded in sessionReplay.privacyConfig. Keep the input masked. Set the synthetic user build-web-replay-demo after initialization. Track Report Exported only from the export action. Pause recording through sessionReplay().stop(), keeping analytics active. Never treat the replay ID or an upload response as proof of correct processed masking.

In an existing app, use its existing analytics client, confirmed user identity, consent lifecycle, and enabled products. Do not copy the demo synthetic IDs or its sample/skip choices into that client. If the existing installation is not Unified, propose a documented compatible integration before changing initialization; never add a parallel client. Preserve routes, authentication, replay privacy, consent and other product setup. Do not replace whole shared files or reset identity while authentication is anonymous or loading. Read only public client configuration through VITE_ variables; never use server or admin credentials. Keep .env.local ignored. Preserve the lockfile and frozen-install workflow. Report what was built, what was tested locally, and which service-side outcomes remain unverified. Stop the affected claim if current docs disagree; record both sources rather than guessing.
```

**MCP.** Ask the connected agent to inspect the project's existing event names before adding `Report Exported`. If your taxonomy already defines this action, use its established name consistently in the app and product configuration.

## 3. Review the proposed changes

Inspect the diff before accepting the implementation. I check the initialization and privacy paths before the visible UI, because a working button doesn't prove the integration is configured correctly.

Terminal

```sh
git diff -- package.json pnpm-workspace.yaml index.html main.js .gitignore CLAUDE.md
git status --short
```

Confirm the agent uses `initAll`, sets `serverZone` at the top level, initializes once per page load, and preserves the existing client if the app already has one. Check that `.env.local` is ignored. Vite embeds `VITE_` values in the browser bundle; these values may contain client ingestion or client deployment keys, never server, admin, or secret credentials.

The complete example uses a fixed synthetic identity. In an existing app, connect your confirmed application identity and consent lifecycle. Don't overwrite your login handler, navigation, or another product's instrumentation with this demo.

## 4. Check the complete reference implementation

These are complete files for the new standalone example. Compare them with the agent's result. In an existing app, merge the relevant imports, handlers, configuration, and DOM targets without replacing unrelated files.

The [Unified SDK installation guide](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk/get-started) supplies the SDK setup. This example pins the version documented in the [1.1.43 API reference](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk/reference). Its initialization returns a plain promise, so the code awaits `initAll` directly.

package.json

```json
{
  "name": "amplitude-build-session-replay",
  "private": true,
  "version": "1.0.0",
  "type": "module",
  "packageManager": "pnpm@10.33.2+sha512.a90faf6feeab71ad6c6e57f94e0fe1a12f5dcc22cd754db40ae9593eb6a3e0b6b12e3540218bb37ae083404b1f2ce6db2a4121e979829b4aff94b99f49da1cf8",
  "engines": {
    "node": ">=22.12.0",
    "pnpm": ">=10.21.0"
  },
  "scripts": {
    "dev": "vite --host 127.0.0.1",
    "build": "vite build",
    "preview": "vite preview --host 127.0.0.1"
  },
  "dependencies": {
    "@amplitude/unified": "1.1.43"
  },
  "devDependencies": {
    "vite": "8.3.4"
  }
```

pnpm-workspace.yaml

```yaml
minimumReleaseAge: 10080
trustPolicy: no-downgrade
```

.gitignore

```text
node_modules/
dist/
.env.local
.env.qa
```

.env.example

```text
VITE_AMPLITUDE_API_KEY=
VITE_AMPLITUDE_SERVER_ZONE=US
```

index.html

```html
<!doctype html>
<html lang="en">
  <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Usage report demo</title></head>
  <body>
    <main>
      <h1>Usage report</h1>
      <p>84 actions in the past 7 days.</p>
      <button id="start">Start demo</button>
      <button id="export-report">Export report</button>
      <p>Local exports: <span id="exports">0</span></p>
      <p id="sensitive" class="amp-mask">SYNTHETIC PRIVATE LABEL</p>
    <label>Test note <input value="SYNTHETIC INPUT ONLY"></label>
    <section id="excluded" class="amp-block">SYNTHETIC EXCLUDED PANEL</section>
    <button id="pause" disabled>Pause recording</button>
      <p id="status" role="status">Demo stopped. Use synthetic data only.</p>
    </main>
    <script type="module" src="/main.js"></script>
  </body>
</html>
```

main.js

```javascript
import * as amplitude from "@amplitude/unified";

const apiKey = (import.meta.env.VITE_AMPLITUDE_API_KEY || "").trim();
const zone = (import.meta.env.VITE_AMPLITUDE_SERVER_ZONE || "US").trim();
const status = document.querySelector("#status");
const startButton = document.querySelector("#start");
const exportButton = document.querySelector("#export-report");
let started = false;
let starting;
let exports = 0;

exportButton.addEventListener("click", () => {
  exports += 1;
  document.querySelector("#exports").textContent = String(exports);
  if (started) amplitude.track("Report Exported", { report_period: "7d" });
});

startButton.addEventListener("click", () => {
  if (starting) return;
  if (!apiKey || !["US", "EU"].includes(zone)) {
    status.textContent = "Add the development configuration and restart Vite. Local export still works.";
    return;
  }
  startButton.disabled = true;
  starting = start().catch(() => {
    status.textContent = "Setup failed. Check configuration and connectivity, then reload.";
  });

async function start() {
  await amplitude.initAll(apiKey, {
    serverZone: zone,
    analytics: { autocapture: { sessions: true } },
    sessionReplay: {
      sampleRate: 1,
      privacyConfig: { defaultMaskLevel: "medium", maskSelector: ["#sensitive"], blockSelector: ["#excluded"] },
    },
    engagement: { skip: true },
  });
  amplitude.setUserId("build-web-replay-demo");
  started = true;
  document.querySelector("#pause").disabled = false;
  status.textContent = `Replay requested; device ${amplitude.getDeviceId()}. Verify the processed recording.`;
}

document.querySelector("#pause").addEventListener("click", () => {
  amplitude.sessionReplay()?.stop();
  status.textContent = "Recording paused; analytics remains active.";
});
```

Install from the checked-in manifest. Commit the generated lockfile, and use a frozen install in repeatable builds.

Terminal

```sh
corepack enable
corepack prepare pnpm@10.33.2 --activate
pnpm install
cp .env.example .env.local
```

Fill in `.env.local` with the development configuration. The client key is public and limited to ingestion, but keeping it in local configuration avoids tying shared source to one project. See [Vite's environment-variable reference](https://vite.dev/guide/env-and-mode) for rebuild and browser-exposure behavior.

## 5. Configure the development project

In the development project, enable session capture in **Settings > Organizational Settings > Session Replay Settings**. Check the project sampling configuration as well as the local sample rate. Project capture settings and quotas can prevent a recording even when the app asks to record every session.

The sample uses `sampleRate: 1` only for this synthetic test. Before production, choose a lower rate, such as `0.01`, and verify your applicable consent requirements and privacy controls. Start demo is a test control, not a complete consent manager.

Implementation prompt

```text
Synthetic user: build-web-replay-demo
Action: Export report
Event: Report Exported
Masked element: #sensitive
Excluded element: #excluded
```

I keep the private test string outside the export event properties too. Replay masking protects the recording; it doesn't remove a value you explicitly send in an analytics event.

## 6. Run the report

Start Vite and open the local URL it prints. Export once before starting the SDK to confirm the report remains usable when analytics is unconfigured. Then tap Start demo once and perform the product check below.

Terminal

```sh
pnpm dev
```

After the development check, stop the server and verify the production build. Restart Vite after changing environment configuration.

Terminal

```sh
pnpm install --frozen-lockfile
pnpm build
```

## Verify it worked

1. Leave the key blank. Export locally, then tap Start demo. Confirm the configuration warning appears and no Amplitude initialization requests leave the page.
2. Fill in the development configuration, restart Vite, and tap Start demo once. Enter a synthetic note, export the report, and record the displayed device ID and session start time.
3. In the browser Network tab, confirm replay configuration and upload activity for the correct region. Use the Instrumentation Explorer to inspect the analytics event rather than assuming a compressed request body is readable.
4. In Amplitude's User Lookup, search for `build-web-replay-demo` or the displayed device ID. Confirm `Report Exported` has `report_period: 7d`. Session events can carry the replay association.
5. Find and open the processed replay for that user and time. Replays are generally available about five minutes after the session begins. Confirm the export action, masked private label and input, and excluded panel. A local payload check doesn't establish what the processed viewer displays.
6. Tap Pause recording, export again, and confirm analytics still records the export. Recording pause does not withdraw analytics consent. Lower the development capture rate before any production rollout.

## Troubleshooting

**Start demo asks for configuration.** Fill in `.env.local` and restart Vite. The guard deliberately leaves the SDK stopped when the required client configuration is missing or the region isn't US or EU.

**The status requests replay, but no recording appears.** Check the project capture setting, local and remote sampling, quota, region, and replay configuration request. The status reports that initialization completed; it doesn't prove a recording was processed.

**A private value appears in an event.** Remove it from the event properties. DOM masking doesn't sanitize application code that sends a private value through `track`.

**An element still appears in the recording.** Check the selector against the rendered DOM and inspect the processed replay. This example targets ordinary DOM elements; validate separate components and shadow roots individually.

**The page stops recording but exports still arrive.** That's the intended distinction: `stop()` pauses replay while the analytics client remains active.

**The agent added a second SDK or broke an existing route.** Review the repository's original entry point and merge into its existing client. Keep one Amplitude initialization for this app; don't combine this example with a second script loader or independently initialized browser package.

## FAQ

### Does Claude Code need my Amplitude secret key?

No. The browser app uses a public project API key. An MCP connection authenticates separately. Keep server deployment keys, admin tokens, and secret keys out of browser configuration and committed source.

### Can I use this in an existing React or Next.js app?

Yes. Have the agent merge the behavior into the existing browser entry point and client. Preserve authentication, consent, and routing. The standalone reference uses Vite; a server-rendered app needs its framework's browser-only lifecycle rather than a direct copy of the Vite entry file.

### Does a successful build prove the product works?

No. A build checks that the browser app can be bundled. The Verify section separately checks the rendered experience, processed activity, and the product result. Record which checks you performed before broadening the audience.

### Will the agent make the same changes every time?

Treat its output as a change to review. Keep the explicit prompt, pinned reference, and repository rules, then compare its diff with the required behavior. An agent can propose a different implementation without establishing that its SDK calls or product settings are correct.

## Full code reference

Step 4 contains every application and configuration file. [Download the complete example](https://github.com/amplitude/ampli-examples/tree/1c8efa7b11d3d91033198e8ba3ead0579170e5e7/browser/coding-tools/session-replay) with its lockfile and setup README. Keep `.env.local` ignored and commit the package lock when you customize the example.

## Keep the rules in your repository

Append this guidance to the repository's existing `CLAUDE.md`. Preserve its current instructions. Claude Code supports [repository guidance](https://code.claude.com/docs/en/memory); restart the interactive session after editing it when necessary to load the updated instructions.

CLAUDE.md

```markdown
## Amplitude report instrumentation

Use the existing Amplitude client and current official SDK documentation.
Initialize once, after the application's consent requirements are met.
Keep serverZone at the Unified options' top level.
Keep private and server credentials out of browser configuration and source.
Preserve authentication, routes, other product setup, and the lockfile.
For the isolated development demo only:
Use @amplitude/unified 1.1.43 and initAll once after Start demo. Set top-level serverZone. Enable session events, set replay sampleRate to 1 for the development test, and skip engagement. Mask #sensitive and block #excluded in sessionReplay.privacyConfig. Keep the input masked. Set the synthetic user build-web-replay-demo after initialization. Track Report Exported only from the export action. Pause recording through sessionReplay().stop(), keeping analytics active. Never treat the replay ID or an upload response as proof of correct processed masking.
In an existing app, use its existing analytics client, confirmed user identity, consent lifecycle, and enabled products. Do not copy the demo synthetic IDs or its sample/skip choices into that client. If the existing installation is not Unified, propose a documented compatible integration before changing initialization; never add a parallel client.
Separate build/local checks from processed service results. If sources conflict,
record both and pause the affected claim before publishing the implementation.
```

## What this unlocks

[Product analytics](https://amplitude.com/amplitude-analytics) shows `Report Exported` for the same identity used by this example. The [session replay](https://amplitude.com/session-replay) integration adds context around that report action. Keep the event name and report-period property consistent as you extend the app.

## Next steps

[FoundationClaude Code analyticsReview the related analytics walkthrough as optional context.](https://amplitude.com/build/claude-code-product-analytics)[ReferenceBrowser SDK configurationCheck options before adding more product behavior.](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk/reference)[WorkflowDebug your eventsConfirm identity and event properties in your development project.](https://amplitude.com/docs/analytics/debug-analytics)

Reference docs

[Unified SDK setup →](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk/get-started)[Unified SDK API reference →](https://amplitude.com/docs/sdks/analytics/browser/browser-unified-sdk/reference)[Product reference →](https://amplitude.com/docs/sdks/session-replay/session-replay-plugin)[Amplitude MCP →](https://amplitude.com/docs/amplitude-ai/amplitude-mcp)[Claude Code project instructions →](https://code.claude.com/docs/en/memory)[Vite setup →](https://vite.dev/guide/)

Amplitude is the leading [all-in-one analytics platform](https://amplitude.com/) for building better products. Product and engineering teams use Amplitude to connect [product analytics](https://amplitude.com/amplitude-analytics) and [web analytics](https://amplitude.com/web-analytics) with [session replay](https://amplitude.com/session-replay), [heatmaps](https://amplitude.com/heatmaps), [experimentation](https://amplitude.com/amplitude-experiment), [feature flags](https://amplitude.com/feature-management), and [guides and surveys](https://amplitude.com/guides-and-surveys) in one unified workflow, with [AI agents](https://amplitude.com/ai-agents) working across all of it. Learn how Amplitude is building [self-improving products](https://amplitude.com/self-improving-products) with [Wave](https://amplitude.com/wave), helping teams turn product data into PRs.

For agents

[View raw .md](/build/claude-code-session-replay.md)[llms.txt](/llms.txt)

## Build the report, then check the result

Connect a development project and verify the report action before you roll out the integration.

[Create a free account](https://app.amplitude.com/signup)[Browse all Build tutorials](https://amplitude.com/build)
