How to Update Mobile Privacy Settings via code

Who can use this feature?
- Available with Mobile add-on. 
- Requires an admin role to configure. 

 

The rules specified below apply only to the fully-native portion of applications, and not to any HTML running within WebViews (Android), UIWebView (iOS) or WKWebView (iOS). For privacy management in the HTML portion of hybrid apps, please see the Fullstory exclusion reference.

Overview

The privacy rules for mobile applications are based on the same selectors used for web applications. For users familiar with CSS syntax, these rules will look familiar.

See the Fullstory exclusion reference and the MDN CSS selector reference for additional background.

When the Fullstory for Mobile Apps instrumentation SDK starts up, it immediately fetches the latest privacy rules from the server. No information is captured before these privacy rules have been fetched.

Privacy rules fall under one of three types:

  1. Exclusion: excluded views and all child views are removed from the playback and replaced by a striped box. No information about the contents of the view will leave the device, with the exception of the bounds of the view box. In addition, no tap or swipe events will be visible within the bounds of an excluded element.
  2. Masking: masked views and all children are maintained and available at playback, but all text and image content within a masked view is omitted.
  3. Unmasking: an unmasking rule returns an element to its fully-visible state, including all text and image information contained within.

 

Priority of Privacy Rules

If two rules match the same element, then the more conservative (i.e., mask or exclude) one will win.

If no rules match an element, the element will inherit masking state from its parent.

If an element matches an exclude rule, the element and all of its children are replaced with an exclusion placeholder and no further rule matching takes place.

privacy_states.png

Example of Masking/Unmasking

Masked text elements appear as a rectangle covering the bounds of the text information in the application. The text itself does not leave the client device, only the information describing the approximate width and height of the text. Masked image elements are represented by a dominant color from the image.

masked.png

 

Example of Masking vs Exclusion

Excluded elements appear as a diagonal stripe pattern, in contrast to the bar used to represent a masked text area.

masked_excluded.png

Masking and Exclusion Guarantees

Fullstory guarantees that none of an excluded view’s contents, nor any of the contents of any child views, will leave the device. The hash line pattern represents the original bounds of the excluded elements.

The text and image contents of a masked element are guaranteed not to leave the device. The instrumentation library instead sends the original bounds of masked text, and a dominant color for any images. Any drawing commands alongside the text and images are sent as-is, however.


Limitations of Masking and Exclusions

Masking and exclusions are powerful tools, but there are a small number of circumstances where the information remaining after masking/exclusion may impact privacy aspects of an application.

  • Limitation: Numeric fields where the magnitude of the value may be considered sensitive may have that magnitude revealed by the size of the masked or excluded view box for that view. For example, someone viewing a session may be able to tell $1,000 from $1,000,000 by observing the size of a box.
  • Mitigation: An exclusion rule may be applied at a higher level than the view containing the numeric value. The application may also be redesigned such that the view is always the same size regardless of the numeric value.
  • Limitation: Applications with interfaces that mimic PIN entry systems may reveal the PIN through the location of tap events, even though the interface is masked by default.
  • Mitigation: Interfaces where click events may reveal information based on the location of the click should be fully excluded. Excluding an element will remove interaction information from the data capture stream.
  • Limitation: Applications with custom-drawn views where position may reveal information may still contain sensitive information, even when masked. For example, a slider control where the values at given positions are well-known may reveal the value of that slider field.
  • Mitigation: If non-textual, non-image information inside a view may reveal information, that view should be excluded. This will permanently remove all drawing commands - not just text and images.

 

Virtual Attributes

This section assumes that the reader has basic familiarity with HTML and CSS.

To simplify management of privacy for mobile applications and to be more familiar with individuals who have worked with Fullstory for the web, Fullstory for Mobile Apps instrumentation creates virtual HTML-like elements for native Android or iOS views for the purposes of privacy management, funnel definition, and searches.

In a standard HTML document, an element might appear like so:

<div id="my-id" data-test="some-test-id">


CSS selectors can be used to match that element. Examples of selectors that would match:

div#my-id // # represents the “id" selector
div[data-test="some-test-id"] // [] represents an attribute selector

 

Tag Name

The virtual element’s tag name is mapped from the class name of the view in Android or iOS.

iOS:

For example, a UITextView in an iOS app creates a virtual element with a tag name that looks like so:

<UITextView …

Android:

For an Android TextView, the instrumentation creates a virtual element with a tag name of “TextView". Also note that because Android classes include the Java package of the view in an attribute named “package":     

<TextView package="android.widget" …

The selector rules that would match the above views are:

TextView[package="android.widget"]
UITextView

 

ID

iOS:

The accessibility ID attribute is mapped to the virtual element’s ID attribute. For example, a UITextView with an accessibilityIdentifier of “text" maps to the following virtual element:

<UITextView id="text" …

Android:

On Android, the View’s text ID is mapped to a virtual ID attribute. For example:

<TextView android:id="@+id/text"
android:text="Hello, I am a TextView" />

The virtual element generated for the above view would be:

<TextView package="android.widget" id="text" …

The selector rule that would match both iOS and Android views would be:

#text

 

Attributes

Below is a summary of all mapped virtual attributes:

Virtual Attribute

 Android iOS

Element’s tag

View.getClass()

Objective-C class name of UIView

id

View.getId()

[UIView accessibilityIdentifier]

tag

View.getTag()

[UIView tag]

package

View’s Java package

 

type

TextView.getInputType()

 

href

TextView.getUrls()

 

controller

 

Class of [UIView nextResponder], if this nextResponder is a UIViewController

label

 

[UIView accessibilityLabel]

restoration_id

 

[UIView restorationIdentifier]

storyboard

 

[[UIView storyboard] name]

 

Techniques for Matching Elements


FS.setAttribute

In version 0.99.10 of the Fullstory for Mobile Apps instrumentation SDK, the FS.setAttribute() API is available to create virtual attributes of any kind on native views.

This API is only available to the native parts of the application, and can be used like so:

FS.setAttribute(myView, "my-attribute", "my-attribute-value")
FS.addClass(myView, "my-class")

Assuming that myView is an Android TextView, this would add the attribute “my-attribute" with the value “my-attribute-value" and the class “my-class”, resulting in a virtual element that appears as:

<TextView class="my-class" my-attribute="my-attribute-value" ...

The APIs available map to APIs available for HTML-based pages:

 

Web

Android

iOS

Element.setAttribute

FS.setAttribute

[FS setAttribute]

Element.removeAttribute

FS.removeAttribute

[FS removeAttribute]

Element.classList.add

FS.addClass

[FS addClass]

Element.classList.remove

FS.removeClass

[FS removeClass]

Element.className = ""

FS.removeAllClasses

[FS removeAllClasses]

n/a

FS.setTagName

[FS setTagName]

 

Custom attributes may be used for privacy purposes within the Fullstory ecosystem and in the future will be available for use in search and funnels.

Programmatic Privacy Rules

To control privacy settings via code, native mobile applications can make use of FS.addClass like so:

iOS:

// The password field should be entirely excluded
[FS addClass:myPasswordView className:@"fs-exclude"];
// The hint label field does not contain PII, so it should always be unmasked [FS addClass:myPasswordHintLabelView className:@"fs-unmask"];

Android:

// The password field should be entirely excluded
FS.addClass(myPasswordView, "fs-exclude");
// The hint label field does not contain PII, so it should always be unmasked
FS.addClass(myPasswordHintLabelView, "fs-unmask");

 New in 1.4.0 - You can also specify FS.class in your XML layouts. Here's an example of what that looks like:

<androidx.constraintlayout.widget.ConstraintLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:fullstory="http://schemas.android.com/apk/res-auto"
   android:id="@+id/rootview"
   >

<androidx.appcompat.widget.AppCompatTextView
       android:id="@+id/title_tv"
       fullstory:fs_class="fs-unmask"

First you need to add the Fullstory XML namespace to the root view in the layout. Then you can add the fs_class attribute to the view you want to mask or unmask.

Additionally, you can add your own ‘CSS classes’ to make it easier to search in Fullstory for matching elements.

  • To add more than one class, use comma separated values
    • fullstory:fs_class=“fs-mask,checkout_form_item”

Some notes on using Fullstory XML layout attributes on Android.

  • If you’re seeing a linting issue like “Unexpected prefix ‘fullstory’ on TextView”, make sure to use the AppCompat versions of views, as old Android views didn’t support custom namespaces.
  • Views must have an ID for this attribute to work.

Pre-configured Privacy Classes

The complete set of pre-configured classes that may be applied to control privacy are: 

Type

Always applied *

Consent-modified **

Excluded elements

fs-exclude

fs-exclude-without-consent

Masked elements

fs-mask

fs-mask-without-consent

Unmasked elements

fs-unmask

fs-unmask-with-consent

 

* If this class is applied, the element will be excluded/masked/unmasked unconditionally
** If this class is applied and FS.consent is called with the appropriate value, the element will be excluded/masked/unmasked

The mobile SDKs provide constants for each of these classes, as well as helper methods to apply each of the built-in privacy rules.

See https://developer.fullstory.com/add-class for a complete list.

Advanced Attribute Matching

As with CSS, advanced match rules can be used to match more than one possible attribute value. See the W3Schools CSS selector reference for background.

CSS Attribute Match

Description

Example Matches

view[attribute]

Matches a view with the given attribute present

<view attribute>

view[attribute=value]

Matches a view with the given attribute being exactly “value"

<view attribute="value">

view[attribute*=value]

Matches a view where the attribute contains the substring “value"

<view attribute="abc-value-def">

view[attribute^=value]

Matches a view where the attribute starts with “value"

<view attribute="value-abc">

view[attribute$=value]

Matches a view where the attribute ends with “value"

<view attribute="abc-value">

view[attribute~=value]

Matches a view where the attribute contains the word “value" with whitespace surrounding it

<view attribute="abc value def">

 

React Native

The virtual elements created for React Native applications tend to be difficult to match as most appear to be of the generic form of RCTView/RCTTextView on the iOS platform, or ReactViewGroup/ReactTextView on the Android platform.

React Native provides a testID prop that can be useful as it maps to native properties that are already mapped to virtual attributes. On iOS, the testID prop maps to accessibilityIdentifier, while on Android testID maps to the view’s tag.

Specifying testID="myElement" on a React text element would then generate the following two virtual elements on iOS and Android, respectively:

<RCTView id="myElement">
<ReactTextView tag="myElement">

 

At this time there is no way to match both Android and iOS from a single selector, but the following two rules will correctly match this React view:

#myElement
*[tag="myElement"]


SwiftUI

For customers who are already familiar with using Fullstory on iOS with UIKit or React Native apps, Fullstory’s SwiftUI support is a bit different. To learn more, read our article What's Different in Fullstory for SwiftUI? Or the how-to companion article, Integrating Fullstory into a SwiftUI App.

Supported Selector Reference

The selector rules supported by Fullstory’s for Mobile Apps SDK are:

#idselectors
.classselectors
parent>child
tagname
tagname[attribute]
tagname[attribute=foo]
tagname[attribute*=value]
tagname[attribute^=value]
tagname[attribute$=value]
tagname[attribute~=value]

 

 


Was this article helpful?

Got Questions?

Get in touch with a Fullstory rep, ask the community or check out our developer documentation.