Implement Session Replay (Web)

Overview

This developer guide will assist you in configuring your web platform for Session Replay using the Mixpanel JavaScript SDK. Learn more about viewing captured Replays in your project here.

By default, Session Replay is disabled and will not be loaded into your application until explicitly enabled. In most cases, implementation is extremely simple, requiring only a single line of code to be changed.

Prerequisite

You are a Mixpanel customer and have the latest version of the Mixpanel Javascript SDK installed (minimum supported version is v2.50.0). If not, please follow this doc to install the SDK.

Capturing Replays

⚠️

Test in a sandbox project and start with a smaller sample rate. This allows you to monitor performance, usage, and ensure your privacy rules align with your company policies.

You can capturing replay data using a sampling method (recommended), or customize when and where replays are captured manually using Session Replay methods provided by the SDK.

Sampling

We recommend using the sampling method unless you need to customize when you capture replay data.

To enable Session Replay and set your sampling rate, set the recording_sessions_percent when initializing the SDK. This is the only change needed in your existing JavaScript SDK implementation to enable Session Replay.

Start with a low sampling rate, then adjust according to your specific analytics needs.

Example Usage

mixpanel.init(
    "<YOUR_PROJECT_TOKEN>", 
    {
        record_sessions_percent: 1  //records 1% of all sessions
    }
);

Manual Capture

To programatically start and stop replay capture, use the start_session_recording() and stop_session_recording() methods. This is optional, and can be used primarily to programmatically start and stop recording, or exclude something specific from recording.

Start Capturing Replay Data

Call start_session_recording() to force recording to begin, regardless of the record_sessions_percent init option.

This will have no effect if replay data collection is already in progress.

Example Usage

// manually trigger a replay capture
mixpanel.start_session_recording();

Stop Capturing Replay Data

Call stop_session_recording() to stop any active replay data collection.

This will have no effect if there is no replay data collection in progress.

Example Usage

// manually end a replay capture
mixpanel.stop_session_recording();

Example Scenarios

ScenarioGuidance
We have a sensitive screen we don’t want to captureWhen user is about to access the sensitive screen, call mixpanel.stop_session_recording(). To resume recording once they leave this screen, you can resume recording with mixpanel.start_session_recording()
We only want to record certain types of users (e.g. Free plan users only)Using your application code, determine if current user meets the criteria of users you wish to capture. If they do, then call mixpanel.start_session_recording() to force recording on
We only want to users utilizing certain featuresWhen user is about to access the feature you wish to capture replays for, call mixpanel.start_session_recording() to force recording on

Additional Configuration Options

You can customize the behavior of replay captures by using the init options outlined below.

Example Usage

mixpanel.init(
    "<YOUR_PROJECT_TOKEN>", 
    {
        record_sessions_percent: 1,  	//records 1% of all sessions
		record_idle_timeout_ms: 1800000 //End a replay capture after 30mins of inactivity
    }
);

Init Options

OptionDescriptionDefault
record_block_classCSS class name or regular expression for elements which will be replaced with an empty element of the same dimensions, blocking all contents.new RegExp('^(mp-block|fs-exclude|amp-block|rr-block|ph-no-capture)$')
(common industry block classes)
record_block_selectorCSS selector for elements which will be replaced with an empty element of the same dimensions, blocking all contents."img, video"
record_collect_fontsWhen true, Mixpanel will collect and store the fonts on your site to use in playback.false
record_idle_timeout_msDuration of inactivity in milliseconds before ending a contiguous replay. A new replay collection will start when active again.1800000
(30 minutes)
record_mask_text_classCSS class name or regular expression for elements that will have their text contents masked.new RegExp('^(mp-mask|fs-mask|amp-mask|rr-mask|ph-mask)$')
(common industry mask classes)
record_mask_text_selectorCSS selector for elements that will have their text contents masked."*"
record_max_msMaximum length of a single replay in milliseconds. Up to 24 hours is supported. Once a replay has reached the maximum length, a new one will begin.86400000
(24 hours)
record_min_msMinimum length of a single replay in milliseconds. Up to 8 seconds is supported. If a replay does not meet the minimum length, it will be discarded.0
(0 seconds)
record_sessions_percentPercentage of SDK initializations that will qualify for replay data capture. A value of “1” = 1%.0
record_canvasWhen true, Mixpanel will record snapshots of <canvas> elements on your site at up to 15 frames per secondfalse

Replay ID

When a replay capture begins, a Replay ID is generated by the SDK and is attached as an event property ($mp_replay_id) to events tracked by the SDK during the capture session. Events containing the same $mp_replay_id will appear in the same Replay.

If you are sending any events not coming from the SDK, add the $mp_replay_id event property to attribute the event to a specific Replay.

You can use the get_session_recording_properties() method to return the Replay ID for the current replay capture. The method will return an empty object if there is no active replay capture in progress.

Example Usage

// return the $mp_replay_id for the currently active capture
mixpanel.get_session_recording_properties();
// {$mp_replay_id: '19221397401184-063a51e0c3d58d-17525637-1d73c0-1919139740f185'}

Server-side Stitching

⚠️

We still recommend including the $mp_replay_id property on your events regardless of Server-side Stitching for guaranteed accuracy.

Server-Side Stitching allows you to easily watch Replays for events that were not fired from the SDK.

It works by inferring the Replay that an event belong using the Distinct ID and time property attached to the event. This is especially useful if you have events coming in from multiple sources (E.g. your server or warehouse import) and it does not make sense to pass around the value of mixpanel.get_session_recording_properties().

For example, let’s say a user with Distinct ID “ABC” has a Replay recorded from 1-2pm. Two hours later, an event was sent from your warehouse with a timestamp of 1:35pm with Distinct ID “ABC”. Server-side Stitching will infer that the event should belong in the same Replay.

To ensure Server-Side Stitching works, call identify() from the client-side using our SDK with the user’s $user_id. This guarantees that events generated from both the client-side and server-side share the same Distinct ID. Learn more about identifying users.

Replay URL

Replay URLs are accessible only by authenticated users with the necessary permissions for the Mixpanel project.

You can programatically generate URL links to view the current Replay in the Mixpanel UI using the get_session_replay_url() method. The method will return null if there is no Replay in progress.

This is useful for debugging or for adding metadata to other platforms. (E.g. adding replay URL to support tickets for troubleshooting)

Example Usage

// return the Mixpanel URL to view the current replay in the UI
mixpanel.get_session_replay_url();
// https://mixpanel.com/projects/replay-redirect?replay_id=19307d78e24394fe15-0cd98d8fd9ad1d-1f525636-4b9600-19307d78e28194fe15&distinct_id=123&token=my-project-token

Debugging

$mp_session_record is exempt from your plan data allowance.

When a Replay capture begins, a “Session Recording Checkpoint” event will appear in your project, tracked as $mp_session_record. You may use this event to verify whether you have implemented Session Replay correctly.

If you are using the recommended sampling method to capture your Replays but having trouble finding the Replays in your project, try calling start_session_recording() manually and see if the $mp_session_record event appears. If it does appear but you are still struggling to locate your Replays, you may want to increase your sampling rate.

You can also check the Home page for your project to check for any recent Replays listed in the “Latest Replays” card.

If you are still struggling to implement, submit a request to our Support team for more assistance.

Session Replay with a CDP

You can use Session Replay with customer data platforms (CDPs), such as Segment and mParticle.

In order to use Session Replay, your app must have the Mixpanel Javascript SDK installed with Session Replay enabled.

Once you have included the Mixpanel SDK in your app add the following code snippets in order to connect your CDP’s data stream with Mixpanel’s Session Replay.

Segment: Analytics.js

By adding middleware to Segment’s SDK we can ensure that all event calls include the session replay properties. We can also ensure that any identify calls are also passed to Mixpanel.

// Middleware to add Mixpanel's session recording properties to Segment events
analytics.addSourceMiddleware(({ payload, next, integrations }) => {
	if (payload.obj.type === 'track' || payload.obj.type === 'page') {
		if (window.mixpanel) {
			const segmentDeviceId = payload.obj.anonymousId;
			// -------------------------------------------
			// Comment out one of the below mixpanel.register methods depending on your ID Management Version
			// Original ID Merge
			mixpanel.register({ $device_id: segmentDeviceId, distinct_id : segmentDeviceId });
			// Simplified ID Merge
			mixpanel.register({ $device_id: segmentDeviceId, distinct_id : "$device:"+segmentDeviceId }); 
			// -------------------------------------------	
			const sessionReplayProperties = mixpanel.get_session_recording_properties();
			payload.obj.properties = {
				...payload.obj.properties,
				...sessionReplayProperties
			};
		}
	}
	if (payload.obj.type === 'identify') {
		if (window.mixpanel) {
			const userId = payload.obj.userId;
			mixpanel.identify(userId);
		}
	}
	next(payload);
});

mParticle: Web SDK

mParticle’s Web SDK has a .getDeviceId() method which can be used to retrieve the device_id. In the following example, we use this method to bind mParticle’s device_id to Mixpanel’s device_id, as well as patching logPageView() and logEvent() to include session replay properties on all mParticle events.

This configuration assumes you are forwarding web requests server side in the connection settings.

mixpanel.init('MIXPANEL-PROJECT-TOKEN', {
	record_sessions_percent: 10,
	loaded: function (mixpanel) {
		window.mParticle.ready(function() {
			const mParticle_device_id = mParticle.getDeviceId();
			if (mParticle_device_id) {
				mixpanel.register({ $device_id: mParticle_device_id, distinct_id : "$device:"+mParticle_device_id });
			}
 
			// Patch logEvent and logPageView to include sessionReplayProperties
			const originalLogEvent = mParticle.logEvent;
			mParticle.logEvent = function (eventName, eventType, eventAttributes, flags, opts) {
				const sessionReplayProperties = mixpanel.get_session_recording_properties();
				eventAttributes = {
					...eventAttributes,
					...sessionReplayProperties,
				};
				originalLogEvent(eventName, eventType, eventAttributes, flags, opts);
			};
			const originalLogPageView = mParticle.logPageView;
			mParticle.logPageView = function (eventName, eventAttributes, flags, opts) {
				const sessionReplayProperties = mixpanel.get_session_recording_properties();
				eventAttributes = {
					...eventAttributes,
					...sessionReplayProperties,
				};
				originalLogPageView(eventName, eventAttributes, flags, opts);
			};
		});
	}
});

Rudderstack: Cloud Mode

Rudderstack’s Javascript SDK has a .getAnonymousId() method which can be used to retrieve the device_id. In the following example, we use this method to bind Rudderstack’s anonymousId to Mixpanel’s device_id, as well as patching track and page event methods to include session replay properties on every Rudderstack event.

mixpanel.init('MIXPANEL-PROJECT-TOKEN', {
  record_sessions_percent: 10,
  loaded: function (mixpanel) {
    window.rudderanalytics.ready(function() {
      const rudderAnonymousId = rudderanalytics.getAnonymousId();
      if (rudderAnonymousId) {
	mixpanel.register({ $device_id: rudderAnonymousId, distinct_id : "$device:"+rudderAnonymousId });
      }
 
      // Patch track method to include sessionReplayProperties
      const originalTrack = rudderanalytics.track;
      rudderanalytics.track = function (eventName, eventProperties, options, callback) {
        const sessionReplayProperties = mixpanel.get_session_recording_properties();
        eventProperties = {
          ...eventProperties,
          ...sessionReplayProperties,
        };
        originalTrack(eventName, eventProperties, options, callback);
      };
 
      // Patch page method to include sessionReplayProperties
      const originalPage = rudderanalytics.page;
      rudderanalytics.page = function (category, name, properties, options, callback) {
        const sessionReplayProperties = mixpanel.get_session_recording_properties();
        properties = {
          ...properties,
          ...sessionReplayProperties,
        };
        originalPage(category, name, properties, options, callback);
      };
    });
  }
});

Google Tag Manager

You can use session replay with Google Tag Manager (GTM). First, make sure you have the Mixpanel GTM Template installed in your workspace.

Once that is added, you can add a new Mixpanel tag to your workspace which turns on Session Replay by following these instructions:

  • Add a new tag, and choose the Mixpanel tag type.
  • For Project Token fill in your Mixpanel project’s token
  • For Tag Type choose init from the dropdown
  • For Initialization choose Set Options Manually
  • In the Option key / Option value dropdown, ensure you choose record_sessions_percent and the value should be a number between 1 and 100.
  • This is also where you can configure other Session Replay options like record_block_class etc…
  • For the Triggering section, you’ll want to choose something early in the GTM lifecycle; typically this is Initialization - All Pages or Consent Initialization - All Pages to ensure that Session Replay starts recording as soon as the GTM container is initialized.
  • Save + Deploy this template to your website and you should be up and going with session replay

Here’s a screenshot of a working session replay tag for a visual comparison:

Privacy

Mixpanel offers a privacy-first approach to Session Replay, including features such as data masking. Mixpanel’s Session Replay privacy controls were designed to assist customers in protecting end user privacy. Read more here.

User Data

The Mixpanel SDK will always mask all inputs. By default, all text on a page will also be masked unless a different record_mask_text_selector is specified (see Additional Configuration above).

Along with other data, the SDK respects all Do Not Track (DNT) settings as well as manual opt-out for any replay data.

Retention

User replays are stored for 30 days after the time of ingestion. There is no way to view a replay older than 30 days old.

FAQ

Can I prevent Session Replay from recording sensitive content?

By default, all on-screen text elements are masked in replays. Additionally, you can customize how you leverage our SDK to fully control (1) where to record and (2) whom to record. Consider the manual capture example scenarios and init options provided above to customize the replay capture of your implementation.

How can I estimate how many Replays I will generate?

If you already use Mixpanel, the Session Start events are a way to estimate the rough amount of replays you might expect. This is especially true if you use timeout-based query sessions. However, because our sessions are defined at query time, we cannot guarantee these metrics will be directly correlated.

When you enable Session Replay, use the above proxy metric to determine a starting sampling percentage, which will determine how many replays will be sent. You can always adjust this as you go to calibrate to the right level.

How does Session Replay affect my website’s performance?

Mixpanel leverages the open-source library, rrweb, to power Session Replay. Both rrweb and Mixpanel are designed with the highest standards of performance in mind.

Below is a high-level overview of how the SDK will work on your website:

  • Initial Snapshot: When recording starts, rrweb takes a snapshot of the entire webpage’s structure (the DOM), assigning unique IDs to each element for change tracking.
  • Change Detection: Asynchronously monitors any changes that occur to the DOM using MutationObserver, minimizing work so that we do not need to keep taking full snapshots.
  • User Interactions: Listens for actions like clicks and mouse movements and throttles any high frequency events.
  • Collection & Delivery: Mixpanel collects the recording data and sends it to our servers in batches every 10 seconds.
  • Optimized Compression: Before sending, Mixpanel will compress the payload using the asynchronous CompressionStream API. This will optimize bandwidth while not blocking the UI thread.

We have tested the SDK extensively and it generally has minimal impact on how your website performs. The initial snapshot takes a bit of work, and naturally, more complex and interactive pages generate more data for rrweb and Mixpanel to handle. So, it is always a good practice to do some performance testing after you have implemented Session Replay, just to be sure everything is running smoothly.

Was this page useful?