Implement Session Replay (Android)
The iOS Session Replay is in invite-only Alpha access for customers on our Enterprise plan. Reach out to your Account Manager for any questions about Session Replay or the iOS Beta access.
Since our Alpha program offers early access, some functionality, including data masking features, may contain bugs and cause crashes. We recommend thoroughly testing before enabling in production.
Our Session Replay Beta Service Addendum can be found here.
Overview
This developer guide will assist you in configuring your Android app for Session Replay using the Session Replay SDK (Android). Learn more about viewing captured Replays in your project here.
Prerequisite
You are already a Mixpanel customer and have the latest version of the Mixpanel Android SDK installed (minimum supported version is v8.0.2
). If not, please follow this doc to install the SDK.
Installation
You can integrate the Mixpanel Android Session Replay SDK into your Android project by embedding the Android Archive (AAR) file below.
-
Open your existing Android Studio project where you want to integrate the Mixpanel Android Session Replay SDK.
-
Download and unzip mixpanel-android-session-replay.aar.zip to your local drive.
-
Copy the AAR file to the
app/libs
folder in your Android project. -
Configure your project’s Gradle settings:
- For Kotlin DSL (settings.gradle.kts): Add to the repositories section under
dependencyResolutionManagement
:
flatDir { dirs("libs") }
- For Groovy DSL (build.gradle): Add to the repositories section under
buildScripts
:
flatDir { dirs("libs") }
- For Kotlin DSL (settings.gradle.kts): Add to the repositories section under
-
Add the following dependencies to your module’s
build.gradle
orbuild.gradle.kts
:
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:+")
implementation("com.squareup.curtains:curtains:+")
implementation(files("libs/mixpanel-android-session-replay.aar"))
- Sync your project with Gradle files.
Initialize
You should have the main Mixpanel Android SDK installed (minimum version v8.0.2
), if not, please refer to Prerequisite.
Initialize the MPSessionReplay
SDK in your Application
class:
Example Usage
private fun initializeMixpanel() {
val token = "MY_PROJECT_TOKEN"
val trackAutomaticEvents = true
val mixpanel = MixpanelAPI.getInstance(this, token, trackAutomaticEvents)
mixpanel.identify("DISTINCT_ID")
val config = MPSessionReplayConfig(
wifiOnly = false,
recordSessionsPercent = 100.0
)
MPSessionReplay.initialize(this, token, mixpanel.distinctId, config)
}
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 methods provided by the Session Replay Android 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, create a SessionReplayConfig
object and set the recordSessionsPercent
with a value between 0.0
and 100.0
. At 0.0
no sessions will be recorded, at 100.0
all sessions will be recorded.
Start with a low sampling rate, then adjust according to your specific analytics needs.
Example Usage
// records 1% of all sessions
MPSessionReplayConfig(
recordSessionsPercent = 1.0
)
Manual Capture
To programatically start and stop replay capture, use the .startRecording()
and .stopRecording()
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 .startRecording()
to force recording to begin, regardless of the recordSessionsPercent
init option. The recording automatically stops when the app goes to the background. Therefore, if you want to continuously record the replays, you will need to restart the replay once the app becomes active again.
This will have no effect if replay data collection is already in progress.
Example Usage
// manually trigger a replay capture
MPSessionReplay.getInstance()?.startRecording()
Stop Capturing Replay Data
Call .stopRecording()
to stop any active replay data collection. The SDK automatically stops recording when the app goes to the background.
This will have no effect if there is no replay data collection in progress.
Example Usage
// manually end a replay capture
MPSessionReplay.getInstance()?.stopRecording()
Example Scenarios
Scenario | Guidance |
---|---|
We have a sensitive screen we don’t want to capture | When user is about to access the sensitive screen, call .stopRecording() . To resume recording once they leave this screen, you can resume recording with .startRecording() |
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 .startRecording() to force recording on |
We only want to users utilizing certain features | When user is about to access the feature you wish to capture replays for, call .startRecording() to force recording on |
Additional Configuration Options
Upon initialization you can provide a SessionReplayConfig
object to customize your replay capture.
Currently, there are only three config options:
Option | Description | Default |
---|---|---|
wifiOnly | When true , replay events will only be flushed to the server when the device has a WiFi connection. If there is no wifi, flushes are skipped and the events remain in the in-memory queue until wifi is restored (or until the queue reaches its limit and the oldest events are evicted to make room for newer events). When false , replay events will be flushed with any network connection, including cellular. | true |
recordSessionsPercent | This is a value between 0.0 and 100.0 that controls the sampling rate for recording session replays. At 0.0 no sessions will be recorded. At 100.0 all sessions will be recorded. | 0.0 |
autoMaskedViews | This is a Set of enum options for the types of views that should be masked by the SDK automatically. | Image , Text , and Web |
autoMaskedViews Example Usage
// mask images only
MPSessionReplayConfig(
recordSessionsPercent = 100.0,
autoMaskedViews = mutableSetOf(AutoMaskedView.ImageView)
)
// disable auto masking
MPSessionReplayConfig(
recordSessionsPercent = 100.0,
autoMaskedViews = emptySet()
)
// mask image, text and WebViews
MPSessionReplayConfig(recordSessionsPercent = 100.0)
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 getReplayId()
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
MPSessionReplay.getInstance()?.getReplayId()
// {$mp_replay_id: '19221397401184-063a51e0c3d58d-17525637-1d73c0-1919139740f185'}
Server-side Stitching
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.
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.
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 .startRecording()
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.
Logging
No toggle is needed to enable debug logs; logging is always enabled in your developer/debug environment.
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. To protect end-user privacy, input text fields cannot be unmasked.
By default, all text, images, and WebViews are also masked.
You can unmask these element at your own discretion using the autoMaskedViews
config option described above.
Along with other data, the SDK respects all Do Not Track (DNT) settings as well as manual opt-out for any replay data.
Mark Views as Sensitive
All EditText
and TextView
components are masked by default. EditText
cannot be unmasked, while TextView
can be unmasked.
You can also mark any views as sensitive using mpReplaySensitive
or addSensitiveView
. Views marked as “sensitive” will be masked.
Example Usage
// Compose
Image(
painter = painterResource(id = R.drawable.family_photo),
contentDescription = "Family Photo",
modifier = Modifier.mpReplaySensitive(true)
)
// XML
val creditCardView: ImageView = findViewById(R.id.creditCardView)
MPSessionReplay.getInstance()?.addSensitiveView(creditCardView)
Set mpReplaySensitive
to false
to mark any view as safe. Views marked as “safe” will not be masked.
Example Usage
// Compose
Image(
painter = painterResource(id = R.drawable.family_photo),
contentDescription = "Family Photo",
modifier = Modifier.mpReplaySensitive(false)
)
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.
Legal (Beta Terms)
Our Session Replay Beta Service Addendum can be found here.
The alpha and beta of Mixpanel’s mobile session replay SDK will track certain events and send them to Mixpanel so that Mixpanel can understand and improve the alpha and beta mobile session replay feature experience. These events include starting and stopping a session, adding and removing sensitive classes, adding sensitive views and adding safe views. Nothing about your application will be included in this tracking; only your usage of the Mixpanel Session Replay SDK.
FAQ
How does Session Replay work in Android?
Session Replay observes user interactions within your app, capturing UI hierarchy changes and storing them as images, which are then sent to Mixpanel. Mixpanel reconstructs these images, applying recorded events as an end-user completes them.
Within Mixpanel’s platform, you can view a reconstruction of your end-user’s screen as they navigate your app.
However, Session Replay is not a literal video recording of your end-user’s screen; end-user actions are not video-recorded.
Can I prevent Session Replay from recording sensitive content?
The Mixpanel SDK will always mask all inputs. By default, all text, images, and WebViews on a page.
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, SDK configuration options, and manual view masking example 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 app’s bandwidth consumption?
The bandwidth impact of Session Replay depends on the setting of the wifiOnly
parameter.
By default, wifiOnly
is set to true
, which means replay events are only flushed to the server when the device has a wifi connection. If there is no wifi, flushes are skipped, and the events remain in the in-memory queue until WiFi is restored. This ensures no additional cellular data is used, preventing users from incurring additional data charges.
When wifiOnly
is set to false
, replay events are flushed with any available network connection, including cellular. In this case, the amount of cellular data consumed depends on the intensity of user interactions and the typical session length of your app. Users may incur additional data charges if large amounts of data are transmitted over cellular connections.
How does Session Replay for mobile work if my app is offline?
Session Replay for mobile does not work in offline mode.
Does it work in XML/Jetpack Compose apps?
Yes, standard XML-based apps are fully supported while Jetpack Compose apps have limited support for automatic masking of sensitive views. If your app is using Jetpack Compose, it is recommended that you manually mark your views as sensitive.
Does it support Java based app?
Yes, Java and Kotlin are fully interoperable.
Was this page useful?