Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
160 changes: 160 additions & 0 deletions docs/platforms/javascript/guides/nextjs/session-replay/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
title: Set Up Session Replay
sidebar_title: Session Replay
sidebar_order: 5
sidebar_section: features
description: "Learn how to enable Session Replay in your Next.js app."
---

<Include name="session-replay-web-report-bug.mdx" />

[Session Replay](/product/explore/session-replay/) helps you get to the root cause of an error or latency issue faster by providing you with a video-like reproduction of what was happening in the user's browser before, during, and after the issue.

By default, Session Replay masks all DOM text content, images, and user input. See <PlatformLink to="/session-replay/privacy">Session Replay Privacy</PlatformLink> for customization options.

## Pre-requisites

<PlatformContent includePath="session-replay/pre-requisites" />

## Install

<PlatformContent includePath="session-replay/install" />

### Canvas Recording

<Alert level="warning">
There is currently no PII scrubbing in canvas recordings!
</Alert>

<SplitLayout>

<SplitSection>
<SplitSectionText>

#### Enable Canvas Recording

Add `replayCanvasIntegration()` to record HTML canvas elements. This is opt-in and tree-shaken if not used.

</SplitSectionText>
<SplitSectionCode>

<PlatformContent includePath="session-replay/setup-canvas" />

</SplitSectionCode>
</SplitSection>

<SplitSection>
<SplitSectionText>

#### 3D and WebGL Canvases

For 3D/WebGL canvases, enable manual snapshotting to avoid performance issues from `preserveDrawingBuffer`.

Call `snapshot()` inside your paint loop, in the same execution loop as draw commands.

</SplitSectionText>
<SplitSectionCode>

```typescript {filename:instrumentation-client.ts}
// Step 1: Enable manual snapshotting
Sentry.replayCanvasIntegration({
enableManualSnapshot: true,
});

// Step 2: Call snapshot in your paint loop
function paint() {
const canvasRef = document.querySelector("#my-canvas");
Sentry.getClient()
?.getIntegrationByName("ReplayCanvas")
?.snapshot(canvasRef);
}
```

</SplitSectionCode>
</SplitSection>

</SplitLayout>

### Content Security Policy (CSP)

<SplitLayout>

<SplitSection>
<SplitSectionText>

#### Configure CSP for Replay

Session Replay uses a WebWorker for compression. Add these CSP entries to allow workers to load.

Safari versions ≤ 15.4 also need `child-src`.

</SplitSectionText>
<SplitSectionCode>

```text
worker-src 'self' blob:
child-src 'self' blob:
```

</SplitSectionCode>
</SplitSection>

</SplitLayout>

If you can't update CSP, see [custom compression worker](/platforms/javascript/session-replay/configuration/#using-a-custom-compression-worker).

## Sampling

Sampling controls how much traffic results in a Session Replay.

<SplitLayout>

<SplitSection>
<SplitSectionText>

#### Configure Sample Rates

- **`replaysSessionSampleRate`** - Percentage of sessions to record fully
- **`replaysOnErrorSampleRate`** - Percentage of sessions to record when an error occurs (buffers 1 minute before the error)

**Tip:** Keep `replaysOnErrorSampleRate` at `1.0` - error sessions provide the most debugging value.

</SplitSectionText>
<SplitSectionCode>

```typescript {filename:instrumentation-client.ts}
Sentry.init({
dsn: "___PUBLIC_DSN___",

// Capture 10% of all sessions
replaysSessionSampleRate: 0.1,

// Capture 100% of sessions with errors
replaysOnErrorSampleRate: 1.0,

integrations: [Sentry.replayIntegration()],
});
```

</SplitSectionCode>
</SplitSection>

</SplitLayout>

### Recommended Production Sample Rates

| Traffic Volume | Session Rate | Error Rate |
| -------------------------- | ------------ | ---------- |
| **High** (100k+/day) | `0.01` (1%) | `1.0` |
| **Medium** (10k-100k/day) | `0.1` (10%) | `1.0` |
| **Low** (under 10k/day) | `0.25` (25%) | `1.0` |

## Verify

Set `replaysSessionSampleRate: 1.0` during testing. Open your app, interact with it, then check [**Replays**](https://sentry.io/orgredirect/organizations/:orgslug/replays/) in Sentry.

**For production:** Lower `replaysSessionSampleRate` but keep `replaysOnErrorSampleRate` at `1.0`.

## Next Steps

<PageGrid />
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
The Replay integration is already included with the Sentry SDK. We recommend installing the SDK through our installation wizard:
Session Replay is included with `@sentry/nextjs`. If you haven't installed Sentry yet, run the wizard:

```bash
npx @sentry/wizard@latest -i nextjs
```

If you already have Sentry installed, skip to [Set Up](#set-up) below.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Session Replay requires `@sentry/nextjs` version `7.27.0` or higher.

<Alert level="info">
Session Replay is **client-side only**. Configure it in
`instrumentation-client.ts`, not in server or edge config files.
</Alert>
90 changes: 69 additions & 21 deletions platform-includes/session-replay/setup/javascript.nextjs.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,20 @@
On your client-side NextJS app, add:
Session Replay is configured in your **client-side** initialization file only.

```javascript {8,12,14-20} {filename:instrumentation-client.ts}
<SplitLayout>

<SplitSection>
<SplitSectionText>

#### Add Replay Integration

Add `replayIntegration()` to your client initialization and configure the sample rates.

**Testing tip:** Set `replaysSessionSampleRate: 1.0` during development to capture all sessions.

</SplitSectionText>
<SplitSectionCode>

```typescript {filename:instrumentation-client.ts}
import * as Sentry from "@sentry/nextjs";

Sentry.init({
Expand All @@ -14,34 +28,68 @@ Sentry.init({
// sessions when an error occurs.
replaysOnErrorSampleRate: 1.0,

integrations: [
Sentry.replayIntegration({
// Additional SDK configuration goes in here, for example:
maskAllText: true,
blockAllMedia: true,
}),
],
integrations: [Sentry.replayIntegration()],
});
```

### Verify
</SplitSectionCode>
</SplitSection>

<SplitSection>
<SplitSectionText>

#### Privacy Options

While you're testing, we recommend that you set `replaysSessionSampleRate` to `1.0`. This ensures that every user session will be sent to Sentry.
By default, Replay masks all text and blocks media. Customize privacy settings based on your needs.

Once testing is complete, **we recommend lowering this value in production**. We still recommend keeping `replaysOnErrorSampleRate` set to `1.0`, so that, whenever possible, every error has an associated replay with additional debugging context.
See <PlatformLink to="/session-replay/privacy/">Session Replay Privacy</PlatformLink> for all options.

### PII & Privacy Considerations
</SplitSectionText>
<SplitSectionCode>

Personally identifiable information (PII), and privacy are important considerations when enabling Session Replay. There are multiple ways in which Sentry helps you avoid collecting PII, including:
```typescript {filename:instrumentation-client.ts}
Sentry.replayIntegration({
// Text masking (default: true)
maskAllText: true,

// Block images/videos (default: true)
blockAllMedia: true,

// Mask specific inputs
maskAllInputs: true,
}),
```

- [Masking](/platforms/javascript/session-replay/privacy/#masking), which replaces the text content with something else. (The default behavior being to replace each character with a \*.)
- Making [Network request, response bodies, and headers](/platforms/javascript/session-replay/privacy/#network-request-and-response-bodies-and-headers) an opt-in feature, because the best way to avoid getting PII into Sentry is by not adding URLs of endpoints that may contain PII.
</SplitSectionCode>
</SplitSection>

While we have certain privacy considerations in place, Sentry's Session Replays allow you to set up the [privacy configurations](/platforms/javascript/session-replay/privacy/#privacy-configuration) that work best for your use case. For example, if you're working on a static website that's free of PII or other types of private data, you can opt out of the default text masking and image blocking settings.
To learn more about session replay privacy, [read our docs.](/platforms/javascript/session-replay/privacy/)
<SplitSection>
<SplitSectionText>

### Lazy-loading Replay
#### Lazy-Loading Replay

Once you've added the integration, Replay will start automatically. If you don't want to start it immediately (lazy-load it), you can use `addIntegration`:
Load Replay only when needed instead of at startup. Useful for reducing initial bundle size.

</SplitSectionText>
<SplitSectionCode>

```typescript {filename:instrumentation-client.ts}
// Don't add replayIntegration to init
Sentry.init({
integrations: [],
});

// Later, when you want to start recording:
import("@sentry/nextjs").then((lazyLoadedSentry) => {
Sentry.addIntegration(lazyLoadedSentry.replayIntegration());
});
```

</SplitSectionCode>
</SplitSection>

</SplitLayout>

### Verify

<PlatformContent includePath="configuration/integrations/lazy-loading-replay" />
Open your app, interact with it, then check [**Replays**](https://sentry.io/orgredirect/organizations/:orgslug/replays/) in Sentry to see your session.