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 mode | What is captured |
---|---|
RenderingMode.native | Regularly 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.wireframe | Captures 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_rendering | No content is recorded. |
Setting the rendering mode
To set the rendering mode:
Smartlook.instance.preferences.setRenderingMode(RenderingMode.native);
Reading the rendering mode
To see what rendering mode the SDK is using:
final RenderingMode renderingMode = await smartlook.state.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 1 | 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.
Native view sensitivity
iOS native sensitivity
iOS native sensitivity is not available at this time.
You can set native sensitivity to EditText, WebView, UITextView, UITextField, WKWebView:
await Smartlook.instance.sensitivity.changeNativeClassSensitivity([
SensitivityTuple(
classType: SmartlookNativeClassSensitivity.WebView,
isSensitive: true,
),
SensitivityTuple(
classType: SmartlookNativeClassSensitivity.WKWebView,
isSensitive: true,
),
]);
Element sensitivity
You can set the sensitivity to just one Widget
so this Container won't be visible on your native recording. Also if the Container will be in the Scrollable Widget
the sensitivity will work.
SmartlookTrackingWidget(
isSensitive: true,
child: Container(
height: 40.0,
width: 40.0,
color: Colors.green,
),
),
Class sensitivity
You can also set the sensitivity to all instances of a Flutter Class
that extends a Widget rather than setting the sensitivity on a specific Widget
:
Smartlook.instance.sensitivity.changeWidgetClassSensitivity(
classType: Text,
isSensitive: true,
);
On Flutter side TextField
and TextFormField
are sensitive by default, to change that you can:
Smartlook.instance.sensitivity.changeWidgetClassSensitivity(
classType: TextField,
isSensitive: false,
);
Smartlook.instance.sensitivity.changeWidgetClassSensitivity(
classType: TextFormField,
isSensitive: false,
);
Default sensitive classes
By default, the
EditText
andWebView
classes are set as sensitive. To override the sensitivity on the class or instance level, set the class or instance sensitivity tofalse
ornull
.
Sensitivity prioritization
When determining if the Widget
instance is sensitive, the resolution process checks the sensitivity in a strict order.
Widget
instances are not recorded if:
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:
If TextView
is set to be sensitive and RadioButton
is explicitly set to not be sensitive:
Smartlook.instance.sensitivity.changeWidgetClassSensitivity(
classType: TextView,
isSensitive: true,
);
Smartlook.instance.sensitivity.changeWidgetClassSensitivity(
classType: RadioButton,
isSensitive: false,
);
These statements are factual if we assume no View
instance-specific sensitivity is set:
- All instances of
TextView
,Button
,CompoundButton
,RadioButton
,Switch
, andToggleButton
will be sensitive - All instances of
RadioButton
are not sensitive, even thoughRadioButton
inherits from the sensitive classTextView
.
await Smartlook.instance.preferences.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
:
await Smartlook.instance.preferences.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:
await Smartlook.instance.sensitivity.changeNativeClassSensitivity([
SensitivityTuple(
classType: SmartlookNativeClassSensitivity.WebView,
isSensitive: true,
),
SensitivityTuple(
classType: SmartlookNativeClassSensitivity.WKWebView,
isSensitive: true,
),
]);
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
:
await Smartlook.instance.setRecordingMask([
RecordingMask(
rect: const Rect.fromLTWH(0, 0, 200, 200),
maskType: RecordingMaskType.covering,
),
]);
You can only have one Recording mask
set at a time, but the recording mask can contain a list of RecordingMask
to cover multiple areas at once.
RecordingMask
can be one of two types:
Mask type | How it works |
---|---|
RecordingMaskType.covering | The area defined by the element Rect is not recorded |
RecordingMaskType.erasing | The area defined by the element Rect is recorded even if a previous RecordingMask inside a list was covering the area. |
RecordingMask
example
RecordingMask
exampleThe 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.erasing
value.