Documentation for automated readers
A curated documentation index is available at: https://grafana.com/llms.txt
A complete documentation index is available at: https://grafana.com/llms-full.txt
These indexes can help with page discovery before fetching individual documents.
This page is also available in Markdown, which may be easier for automated readers and AI tools to parse than HTML. The Markdown version is available at https://grafana.com/docs/grafana-cloud/observe-and-act/monitor-applications/session-replay/instrument.md, or by sending Accept: text/markdown to https://grafana.com/docs/grafana-cloud/observe-and-act/monitor-applications/session-replay/instrument/. For broader documentation discovery, the curated index is available at https://grafana.com/llms.txt and the complete index is available at https://grafana.com/llms-full.txt.
Instrument Session Replay
Note
Session Replay is currently in public preview. Grafana Labs offers limited support, and breaking changes might occur prior to the feature being made generally available.
On this page, you’ll learn how to install and instrument Session Replay in Faro.
Before you begin
To use Session Replay, you need:
- A Grafana Cloud account.
npminstalled on your machine.- An application instrumented with the Faro Web SDK version 2.8.2 or later.
Note
Session Replay doesn’t support Canvas or WebGL.
Caution
Before you instrument Session Replay, review Data privacy in Session Replay. By instrumenting Session Replay in your application, you assume responsibility for disclosing session recording to your end users and obtaining any consent required by applicable law, such as GDPR, ePrivacy, and CCPA. Grafana Labs doesn’t display a consent banner on your behalf.
Install the Faro Instrumentation Replay package
To install Session Replay:
- Open your terminal.
- Navigate to your application folder.
- Run:
npm install @grafana/faro-instrumentation-replayInstrument your application
To enable Session Replay in your application:
Import the
faro-instrumentation-replaypackage:jsimport { ReplayInstrumentation } from '@grafana/faro-instrumentation-replay'; // Make sure to import Faro as well import { getWebInstrumentations, initializeFaro } from '@grafana/faro-web-sdk';Pass the
ReplayInstrumentationobject when initializing Faro:jsinitializeFaro({ // Mandatory, the URL of the Grafana Cloud collector with embedded application key. // Copy from the configuration page of your application in Grafana. url: 'http://faro-collector-us-central-0.grafana.net/collect/{app-key}', // Mandatory, the identification label(s) of your application app: { name: 'my-app', version: '1.0.0', // Optional, but recommended }, instrumentations: [...getWebInstrumentations(), new ReplayInstrumentation()], });
Refer to configuration options for more details on how to customize your session recordings.
Understand data masking and sub-sampling
Before you record sessions in production, it’s important to understand how Session Replay protects sensitive data and how it controls the volume of recordings you collect.
Data masking
Session Replay includes masking and privacy configuration options so that you can control exactly what is and isn’t recorded, and make sure there’s no sensitive or personal data being exposed in session recordings.
All input values and text content are masked by default, client-side, before data leaves the browser. You can make masking more selective by using the maskAllInputs and maskInputOptions properties, or by using CSS selectors combined with the maskTextSelector and blockSelector properties. You can also use the beforeSend hook to filter or transform events before sending them.
After making changes to your input masking properties, make sure to test your configuration locally or in development environments before enabling it in production.
Caution
Personally identifiable information (PII) in page URLs is not masked.
For the full list of privacy properties, refer to Privacy and masking options. For broader guidance on what data is recorded and how to meet privacy requirements, refer to Data privacy in Session Replay.
Sub-sampling
Frontend Observability with Session Replay has two independent layers of sampling:
- Frontend session sampling: Controls which sessions Faro collects telemetry for (logs, errors, traces).
- Session Replay sampling: Controls what fraction of those sessions also get a recording, configured via
samplingRateonReplayInstrumentation.
For example, a Faro samplingRate of 1.0 combined with a replay samplingRate of 0.1 means telemetry is collected for all sessions, but only 10% of those sessions have a recording:
initializeFaro({
url: 'https://your-faro-endpoint.com',
sessionTracking: {
samplingRate: 1.0, // collect telemetry (logs, errors, web-vitals) for all sessions
},
instrumentations: [
...getWebInstrumentations(),
new ReplayInstrumentation({
samplingRate: 0.1, // record replay for only 10% of sessions
}),
],
});
// Effective replay coverage: 1.0 × 0.1 = 10% of globally sampled sessionsTo ensure you have recordings for the sessions you care about most, review any existing Frontend Session sampler logic to control which sessions are kept or dropped upstream. Refer to the Faro Sampling docs.
Configuration options
You can customize how Session Replay records sessions by passing options to ReplayInstrumentation. The following tables list the available recording, privacy and masking, and hook options, along with their types and default values.
Recording options
| Key | Type | Default | Description |
|---|---|---|---|
samplingRate | number | 1 | Fraction of globally sampled sessions that are recorded. Applied on top of sessionTracking.samplingRate. Out-of-range values are clamped. |
recordAfter | 'load' | 'DOMContentLoaded' | 'load' | When to start recording if the document is not ready yet |
recordCrossOriginIframes | boolean | false | Whether to record cross-origin iframes. Each child iframe must also be instrumented for this to work |
collectFonts | boolean | false | Whether to collect fonts used in the website |
inlineImages | boolean | false | Whether to record image content |
inlineStylesheet | boolean | false | Whether to inline stylesheets in the recording events |
inactivityThresholdMs | number | 60000 | Pause recording after this many milliseconds of inactivity. Recording resumes automatically on the next interaction. Set to 0 to disable. |
Privacy and masking options
| Key | Type | Default | Description |
|---|---|---|---|
maskAllInputs | boolean | true | Mask all input content as * |
maskInputOptions | MaskInputOptions | { password: true } | Selectively mask specific input types (used only when maskAllInputs is false) |
maskInputFn | (value: string, element: HTMLElement) => string | undefined | Customize mask input content recording logic |
maskTextSelector | string | '*' | CSS selector for elements whose text content should be masked. The default value matches all elements |
blockSelector | string | undefined | CSS selector for elements that should be blocked from recording. Blocked elements are replaced with a placeholder of the same dimensions |
ignoreSelector | string | undefined | CSS selector for elements whose input events should be ignored |
maskInputOptions
| Key | Type | Description |
|---|---|---|
password | boolean | Password inputs |
text | boolean | Text inputs |
email | boolean | Email inputs |
tel | boolean | Telephone inputs |
number | boolean | Number inputs |
search | boolean | Search inputs |
url | boolean | URL inputs |
date | boolean | Date inputs |
datetime-local | boolean | Datetime-local inputs |
month | boolean | Month inputs |
week | boolean | Week inputs |
time | boolean | Time inputs |
color | boolean | Color inputs |
range | boolean | Range inputs |
textarea | boolean | textarea elements |
select | boolean | Select dropdowns |
Hooks
| Key | Type | Default | Description |
|---|---|---|---|
beforeSend | (event: eventWithTime) => eventWithTime | null | undefined | undefined | Transform or filter events before they are sent. Return null or undefined to skip sending |
Examples
The following examples show common ways to configure ReplayInstrumentation. Use them as a starting point and adjust the masking and privacy options to match your application’s requirements.
Mask passwords only configuration
new ReplayInstrumentation({
// Disable global input masking and use selective masking rules instead
maskAllInputs: false,
// Mask all password inputs
maskInputOptions: { password: true },
// Override default CSS selector to stop masking text content
maskTextSelector: undefined,
});Advanced privacy configuration
new ReplayInstrumentation({
// Disable global input masking and use selective masking rules instead
maskAllInputs: false,
// Mask all text and email inputs, but allow number inputs
maskInputOptions: {
password: true,
text: true,
email: true,
tel: true,
textarea: true,
},
// Mask elements with specific CSS classes
maskTextSelector: '.sensitive-data, .pii',
// Block elements completely from recording
blockSelector: '.payment-form, .credit-card-info',
// Ignore certain elements (won't be recorded at all)
ignoreSelector: '.analytics-widget',
});Best practices
Override maskTextSelector default value to display elements
The maskTextSelector option accepts a CSS selector string and masks any matching elements in your Session Replay recordings. The default value is '*', which means it’ll match and mask all elements on a page, regardless of other options.
To make sure your masking configuration options work correctly when using maskAllInputs and maskInputOptions, override the maskTextSelector default value:
new ReplayInstrumentation({
// Disable global input masking and use selective masking rules instead
maskAllInputs: false,
// Mask all password and email inputs
maskInputOptions: {
password: true,
email: true,
},
// Override default CSS selector to display other inputs
maskTextSelector: null,
});Use maskTextSelector to mask all elements with a CSS class
The maskTextSelector option accepts a CSS selector string and masks any matching elements in your Session Replay recordings.
To selectively mask specific elements, add a class such as masked to any element you want redacted, then pass that class as the selector. This works regardless of which CSS framework you use:
new ReplayInstrumentation({
// Disable global input masking and use selective masking rules instead
maskAllInputs: false,
// Mask all text and email inputs, but allow number inputs
maskInputOptions: {
password: true,
text: true,
email: true,
tel: true,
textarea: true,
},
// Mask elements with specific CSS classes
maskTextSelector: '.masked',
});Was this page helpful?
Related resources from Grafana Labs


