Handling sensitive data

In order to protect user privacy, you can configure Smartlook to not record sensitive data.

Currently, there are three methods to handle sensitive data:

Rendering modes

The Smartlook SDK offers three rendering modes to create session recordings. Each rendering mode renders the app screen in a different way. The default rendering mode for the Smartlook SDK is Native (RenderingMode.NATIVE).

📘

When using the Native rendering mode, the SDK can record sensitive data in your application.

The rendering modes available in the Smartlook SDK:

Rendering modeWhat is captured
RenderingMode.NATIVERegularly captures the app screen which the SDK immediately processes to remove sensitive data. The frames are then complied to make the session recording. For more information, see View sensitivity.
RenderingMode.WIREFRAMECaptures the app using only a wireframe representation of the screen data. No user data is recorded. This is the preferred rendering method for user data security.
RenderingMode.NO_RENDERINGNo content is recorded.

Setting the rendering mode

To set the rendering mode:

Smartlook.instance.preferences.renderingMode = RenderingMode.NATIVE
Smartlook.getInstance().getPreferences().setRenderingMode(RenderingMode.NATIVE);

Reading the rendering mode

To see what rendering mode the SDK is using:

val renderingMode = Smartlook.instance.state.renderingMode
RenderingMode renderingMode = Smartlook.getInstance().getState().getRenderingMode();

Wireframe rendering

You can use wireframe rendering to view how your users use your app, but not reveal any of the elements. This is the preferred method for user data safety.

Examples of wireframe rendering:

Example 1Example 2
Native rendering example 1Wireframe rendering example 1Native rendering example 2Wireframe rendering example 2

Sensitivity

👍

Locally hidden elements

Sensitive elements are hidden locally on the device. No sensitive data is transferred to or stored in the dashboard.

You can set sensitivity on elements in your project. Based on how you built your app, choose one of the following:

Sensitivity—Jetpack Compose

Jetpack Compose layout elements can be marked as sensitive using the isSensitivite modifier:

Text(
  text = "I'm sensitive text",
  modifier = Modifier
    .smartlook(
      isSensitive = true
    )
)
Example showing sensitivity on selected texts.

Sensitivity shown on selected texts.

Sensitivity—XML layouts

View sensitivity

You can set sensitivity to any View instance:

sampleView.isSensitive = true|false|null
Smartlook.getInstance().getSensitivity().setViewInstanceSensitivity(sampleView, true|false|null);

Any View can be also tagged directly in the XML layout file:

<View>
    <tag android:id="@id/sl_sensitivity" android:value="true|false"/>
</View>

Class sensitivity

You can also set the sensitivity to all instances of a Class that extends a View rather than setting the sensitivity on a specific View:

SampleViewClass::class.isSensitive = true|false|null
Smartlook.getInstance().getSensitivity().setViewInstanceSensitivity(view, true|false|null);

📘

Default sensitive classes

By default, the EditText and WebView classes are set as sensitive. To override the sensitivity on the class or instance level, set the class or instance sensitivity to false or null.

Sensitivity prioritization

When determining if the View instance is sensitive, the resolution process checks the sensitivity in a strict order.

View instances are not recorded if:

  1. the XML has the sl_sensitivity tag set to true.
  2. the sensitivity is set to true.
  3. the Class sensitivity is set to true.

Class hierarchy and sensitivity

Sensitivity set to a more specific class (deeper in the inheritance tree) has higher priority. We will demonstrate this principle in the example using the inheritance tree:

1684

If TextView is set to be sensitive and RadioButton is explicitly set to not be sensitive:

TextView::class.isSensitive = true
RadioButton::class.isSensitive = false
Smartlook.getInstance().getSensitivity().setViewClassSensitivity(TextView.class, true);
Smartlook.getInstance().getSensitivity().setViewClassSensitivity(RadioButton.class, false);

These statements are factual if we assume no View instance-specific sensitivity is set:

  • All instances of TextView, Button, CompoundButton, RadioButton, Switch, and ToggleButton will be sensitive
  • All instances of RadioButton are not sensitive, even though RadioButton inherits from the sensitive class TextView.
Smartlook.instance.preferences.renderingMode = RenderingMode.NO_RENDERING
Smartlook.getInstance().getPreferences().setRenderingMode(RenderingMode.NO_RENDERING)

📘

Rendering modes

The Smartlook SDK provides rendering modes that hide sensitive information by simplifying the rendered screen for recording. This is still useful to you because all user interactions are still recorded, but no sensitive data is rendered. For more information, see Rendering modes.

🚧

Automatically-detected touch events

Some screens display sensitive data through automatically detected touch events. Read more about this issue in secure custom keyboard example.

When the application no longer displays sensitive data, you can set screen rendering mode to NATIVE:

Smartlook.instance.preferences.renderingMode = RenderingMode.NATIVE
Smartlook.getInstance().getPreferences().setRenderingMode(RenderingMode.NATIVE)

Handling WebView sensitivity

If an app uses WebView and you want record them, you need to enable WebView recording. You can enable WebView recording by removing the sensitivity:

WebView::class.isSensitive = null
Smartlook.getInstance().getSensitivity().setViewClassSensitivity(WebView.class, null);

If WebView is being recorded, all sensitive elements on the displayed website should be marked as sensitive so that they are hidden. You can mark sensitive elements as sensitive using HTML elements with .smartlook-hide css class:

<div class='smartlook-hide'>
   This will be hidden.
</div>

All inputs are hidden by default except button and submit. If some hidden inputs should be recorded, they can be marked with .smartlook-show css class:

<input type="text" class='smartlook-show'>

Recording masks

In cases where areas of the app shouldn't be recorded, but cannot be defined by a view, you can use RecordingMask:

val recordingMask = RecordingMask(
  listOf(
    RecordingMask.Element(
      Rect(left, top, right, bottom),
      RecordingMask.Element.Type.COVERING|RecordingMask.Element.Type.ERASING
    )
  )
)

Smartlook.instance.recordingMask = recordingMask
ArrayList<RecordingMask.Element> elements = new ArrayList<>();

elements.add(
  new RecordingMask.Element(
  	new Rect(left, top, right, bottom),
  	RecordingMask.Element.Type.COVERING|RecordingMask.Element.Type.ERASING
  )
);

RecordingMask recordingMask = new RecordingMask(elements);

Smartlook.getInstance().setRecordingMask(recordingMask);

You can only have one Recording mask set at a time, but the recording mask can contain a list of RecordingMask.Element to cover multiple areas at once.

RecordingMask.Element can be one of two types:

Mask typeHow it works
RecordingMask.Element.Type.COVERINGThe area defined by the element Rect is not recorded
RecordingMask.Element.Type.ERASINGThe area defined by the element Rect is recorded even if a previous RecordingMask.Element inside a list was covering the area.

RecordingMask example

The following example describes a RecordingMask in action.

On the left:

  • The blue box represents a video_item element.
  • The red box represents a video_item_image element.

On the right:

  • The video_item element (blue box) has a .COVERING value. The .COVERING value masks the element in the session recording.
  • The video_item_image element (red box) has an .ERASING value. The image is visible in the session recording because the .ERASING value cancels the .COVERING value.