We've decided to make less money: We've slashed our pricing for session replay. They're now more than 50% cheaper for most customers.

Mobile Recording

Last updated:

|Edit this page

🚧 NOTE: Mobile recording is currently only available on Android and iOS and is considered beta. We are keen to gather as much feedback as possible so if you try this out please let us know. You can send feedback via the in-app support panel or one of our other support options.

Overview

Mobile Session Recording allows you to record user sessions on mobile devices. This includes screen recordings, network requests, logs, and touches. This data can then be used to understand how users are interacting with your app and to identify bugs and issues.

How it works

We have taken our time to make sure we provide a useful and detailed recording experience whilst keeping the performance and security of your app as a top priority. By default, the configuration is restrictive with automatic masking.

Wireframe mode (Default)

Mobile recording is primarily done using native APIs to grab the view hierarchy state when the screen is drawn. This is done carefully so as not to affect performance in any way a user may notice.

The view hierarchy is transformed to a JSON data structure and later rendered as an HTML wireframe. Since it is a wireframe, the UI won't have the original look and feel but it should be close enough to understand the user's behavior.

Screenshot mode

If the screenshot (Android) or screenshotMode (iOS) option is enabled, the SDK will take a screenshot of the screen instead of making a representation of the user's screen (A.k.a. Wireframe mode). The screenshot may contain sensitive information, use it with caution. The automatic masking for the screenshot mode already works on Android and we'll be working on the iOS next.

Network recording

If the captureNetworkTelemetry option is enabled, the SDK will record Network requests. Only metric-like data is currently gathered to give a picture of speed, size, and response code. No data is captured from the request or response body.

Installation

Android

Add the dependency, check out the installation docs.

Initialize the SDK, check out the configuration docs.

Add the OkHttp Interceptor for enabling the captureNetworkTelemetry option.

Android
import com.posthog.PostHogOkHttpInterceptor
import okhttp3.OkHttpClient
private val client = OkHttpClient.Builder()
.addInterceptor(PostHogOkHttpInterceptor(captureNetworkTelemetry = true))
.build()

Recording specific configuration

SDK configurations during the SDK initialization.

Android
val config = PostHogAndroidConfig(apiKey = POSTHOG_API_KEY).apply {
// enable session recording, requires enabling on the project configuration as well.
sessionReplay = true
// all texts are masked or redacted (default is enabled)
sessionReplayConfig.maskAllTextInputs = false
// all images are placeholders or redacted (default is enabled)
sessionReplayConfig.maskAllImages = false
// capture logs automatically (default is enabled)
sessionReplayConfig.captureLogcat = true
// screenshot is disabled by default
// The screenshot may contain sensitive information, use with caution
sessionReplayConfig.screenshot = false
// debouncerDelayMs is 500ms by default
sessionReplayConfig.debouncerDelayMs = 500
}

Masking and Redaction

View configuration, if setting the View#tag to ph-no-capture, the view will be a placeholder or redacted, this setting applies to any type of View.

XML
<ImageView
android:id="@+id/imvProfilePhoto"
android:layout_width="200dp"
android:layout_height="200dp"
android:tag="ph-no-capture"
/>

Limitations

  • Requires the PostHog Android SDK version >= 3.4.0 - use the latest version.
  • Requires Android API >= 26, otherwise it's a NoOp.
  • Jetpack Compose is only supported if the screenshot option is enabled.
  • Custom views is partly supported, and only fully supported if the screenshot option is enabled.
  • WebView is not supported, a placeholder will be shown.
  • Keyboard is not supported, a placeholder will be shown.
  • React Native and Flutter for Android aren't supported.

iOS

Add the dependency, check out the installation docs.

Initialize the SDK, check out the configuration docs.

Recording specific configuration

SDK configurations during the SDK initialization.

Swift
let config = PostHogConfig(apiKey: apiKey)
// sessionReplay is disabled by default
config.sessionReplay = true
// sessionReplayConfig is optional, they are enabled by default
config.sessionReplayConfig.maskAllTextInputs = true
config.sessionReplayConfig.maskAllImages = true
config.sessionReplayConfig.captureNetworkTelemetry = true
// screenshotMode is disabled by default
// The screenshot may contain sensitive information, use with caution
config.sessionReplayConfig.screenshotMode = true

Masking and Redaction

UIView configuration, if setting the accessibilityIdentifier or accessibilityLabel to ph-no-capture, the view will be a placeholder or redacted, this setting applies to any type of UIView.

Swift
let imvProfilePhoto = UIImageView(frame: CGRect(x: 50, y: 50, width: 100, height: 100))
imvProfilePhoto.accessibilityIdentifier = "ph-no-capture"

Limitations

  • Requires the PostHog iOS SDK version >= 3.6.0 - use the latest version.
  • SwiftUI is only supported if the screenshotMode option is enabled.
  • It's a representation of the user's screen, not a video recording nor a screenshot.
    • Custom views are not fully supported.
    • If the option screenshotMode is enabled, the SDK will take a screenshot of the screen instead of making a representation of the user's screen.
  • WebView is not supported, a placeholder will be shown.
  • React Native and Flutter for iOS aren't supported.

Questions?

Was this page useful?

Next article

Privacy Controls

PostHog offers a range of controls to limit what data is captured by session recordings. Our privacy controls run in the browser or mobile app. So, masked data is never sent over the network to PostHog. Input elements As any input element is highly likely to contain sensitive text such as email or password, we mask these by default . You can explicitly set this to false to disable the masking. You can then specify inputs types you would like to be masked. Mask or un-mask specific inputs You can…

Read next article