Hide sensitive data
When using autocapture, Heap collects target text information about the element that was interacted with, as well as text data from UI elements further up in an element's ancestry. However, some of these elements might contain sensitive user information, or PII, that needs to be excluded from data capture.
Hiding Sensitive Data on Android
There are three options for hiding sensitive data on Android: Disabling text capture, per-view text redaction, and ignoring interactions for specific views.
Disabling all text capture
When initializing Heap, you have the option to disable text capture for all events that are automatically captured. To do this, set the disableInteractionTextCapture
in your options object when calling Heap.startRecording
. A similar property is available for disabling capture of all accessibility label text (shown below).
import io.heap.core.Heap
import io.heap.core.Options
Heap.startRecording(
appContext,
"YOUR_ENVIRONMENT_ID",
Options(
disableInteractionTextCapture = true,
disableInteractionAccessibilityLabelCapture = true
)
)
import io.heap.core.Heap;
import io.heap.core.Options;
Heap.startRecording(
appContext,
"YOUR_ENVIRONMENT_ID",
new Options( // Java uses an overloaded constructor.
Options.DEFAULT_URI, // Send data directly to Heap.
15.0, // Default upload interval of 15 seconds.
false, // Whether to capture advertiser ID. Defaults to false.
true // *IMPORTANT* Disable text capture set to true.
)
);
Redacting text for specific views
If you don't want to disable all text capture for your app, you can take a more targeted approach of only redacting text for specific views in your app that you know might contain sensitive data. When text is redacted for a view, it will still have target text, but the actual text will be replaced with ****
. This can be done either in XML or in code, depending on which is most appropriate for your app setup.
If you want to redact text for a view in XML, you can do so by tagging your view with heapRedactText
.
<!-- Button clicks are captured but text is redacted. -->
<Button
android:id="@+id/redact_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This text is redacted"
android:tag="heapRedactText" />
Alternatively, if you want to redact text for a view from your Kotlin or Java code, you can do so using ViewAutocaptureSDK.redactText
.
import io.heap.autocapture.ViewAutocaptureSDK
val button = findViewById<Button>(R.id.redact_button)
ViewAutocaptureSDK.redactText(button) // Text in this view will be redacted.
import io.heap.autocapture.ViewAutocaptureSDK;
Button button = (Button)findViewById(R.id.redact_button);
ViewAutocaptureSDK.redactText(button); // Text in this view will be redacted.
Ignoring all interactions for specific views
If you find that certain interactions are prone to capturing sensitive data, or that a certain interaction might indicate sensitive information about a user during analysis, you have the option of ignoring all interactions on a per-view basis. Again, this can be done in XML or in code.
If you want to ignore all interactions for a view in XML, you can do so by tagging your view with heapIgnoreInteractions
.
<!-- Button clicks are not captured. -->
<Button
android:id="@+id/ignore_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Taps on this button are not captured."
android:tag="heapIgnoreInteractions" />
Alternatively, if you want to flag a view to be ignored from your Kotlin or Java code, you can do so using ViewAutocaptureSDK.ignoreInteractions
.
import io.heap.autocapture.ViewAutocaptureSDK
val button = findViewById<Button>(R.id.ignore_button)
ViewAutocaptureSDK.ignoreInteractions(button) // All interactions with this view will be ignored.
import io.heap.autocapture.ViewAutocaptureSDK;
Button button = (Button)findViewById(R.id.ignore_button);
ViewAutocaptureSDK.ignoreInteractions(button); // All interactions with this view will be ignored.
Hiding Sensitive Data on iOS
There are three options for hiding sensitive data on iOS: Disabling the capture of various fields, per-view property redaction, and ignoring events for specific views.
Disabling all text capture
When initializing Heap, you have several options for disabling capture of event properties containing PII:
disablePageviewTitleCapture
disables capture of pageview titles from navigation and tab items.disableInteractionTextCapture
disables capture of user-visible labels from within a view.disableInteractionAccessibilityLabelCapture
Disables capture of accessibility labels on views. These labels can be either developer-defined or system generated when a user has accessibility features enabled. It is good practice to use this option when usingdisableInteractionTextCapture
to prevent PII from being captured.
To use these options, pass them into the option dictionary when calling Heap.shared.startRecording
.
Heap.shared.startRecording(
"YOUR_ENVIRONMENT_ID",
with: [
.disableInteractionTextCapture: true,
.disableInteractionAccessibilityLabelCapture: true,
]
)
[[Heap sharedInstance]
startRecording: @"YOUR_ENVIRONMENT_ID"
withOptions: @{
HeapOption.disableInteractionTextCapture: @YES,
HeapOption.disableInteractionAccessibilityLabelCapture: @YES,
}
];
Redacting text for specific views
If you don't want to disable all text capture for your app, you can take a more targeted approach of only redacting text for specific views and view controllers in your app that you know might contain sensitive data. When text is redacted for a view, it will still have target text, but the actual text will be replaced with ****
. This can be done either in Interface Builder or in code, depending on which is most appropriate for your app setup.
For view and view controllers, you can set heapRedactText
and heapRedactAccessibilityLabel
.
To set these properties in Interface Builder, first select the element you want to redact, then open the Attributes Inspector sidebar. Towards the top, you will see a category called Responder with four options. Xcode unfortunately truncates these so you will need to hover over the title to confirm the name. You can set Heap Redact Text and Heap Redact Accessibility Label to On to redact these fields.
In code, you simply need to set heapRedactText
and heapRedactAccessibilityLabel
on view, view controllers, or other responders to redact those properties.
import HeapIOSAutocapture
open override func viewDidLoad() {
button.heapReactText = true
button.heapRedactAccessibilityLabel = true
}
@import HeapIOSAutocaptureImplementation;
// Note that this is HeapIOSAutocaptureImplementation and not HeapIOSAutocapture.
- (void)viewDidLoad
{
self.button.heapReactText = YES;
self.button.heapRedactAccessibilityLabel = YES;
}
Redacting pageview titles
There currently isn’t a property for disabling pageview title capture. Instead, you can disable capture by overriding heapPageviewTitle
on a specific view controller subclass and returning nil
for the title.
import HeapIOSAutocapture
extension PrivateViewController {
open override var heapPageviewTitle: String? {
nil
}
}
@import HeapIOSAutocaptureImplementation;
// Note that this is HeapIOSAutocaptureImplementation and not HeapIOSAutocapture.
@implementation PrivateViewController (Heap)
- (nullable NSString *)heapPageviewTitle
{
return nil;
}
@end
Ignoring all interactions for specific views
If you find that certain interactions are prone to capturing sensitive data, or that a certain interaction might indicate sensitive information about a user during analysis, you have the option of ignoring all interactions on a per-view basis. Again, this can be done in Interface Builder or in code.
To set these properties in Interface Builder, first select the element you want to redact, then open the Attributes Inspector sidebar. Towards the top, you will see a category called Responder with four options. Xcode unfortunately truncates these so you will need to hover over the title to confirm the name. You can set Heap Ignore Interactions to On to ignore interactions in this view.
In code, you simply need to set heapIgnoreInteractions
on view, view controllers, or other responders to redact those properties.
import HeapIOSAutocapture
open override func viewDidLoad() {
pinContainerView.heapIgnoreInteractions = true
}
@import HeapIOSAutocaptureImplementation;
// Note that this is HeapIOSAutocaptureImplementation and not HeapIOSAutocapture.
- (void)viewDidLoad
{
self.pinContainerView.heapIgnoreInteractions = YES;
}
Like with the text redaction properties, these properties are recursive. If, for example, you have a view controller containing a custom PIN screen, you could apply heapIgnoreInteractions
to the view or view controller to prevent recording individual button taps.
It is important to note that this property only applies when to interactions that are hosted within the view or view controller. Interactions in pushed or presented view controllers or elements like
UIMenu
will not be ignored.
Hiding Sensitive Data on React Native
There are two options for hiding sensitive data on React Native: Disabling text capture and configurable per-view capture rules.
Disabling all text capture
When initializing Heap, you have the option to disable text capture for all events that are automatically captured. To do this, set the disableInteractionTextCapture
in your options object when calling Heap.startRecording
. A similar property is available for disabling capture of all accessibility label text (shown below).
Heap.startRecording(
"YOUR_ENVIRONMENT_ID",
{
disableInteractionTextCapture: true,
disableInteractionAccessibilityLabelCapture: true,
}
)
import io.heap.core.Heap;
import io.heap.core.Options;
Heap.startRecording(
appContext,
"YOUR_ENVIRONMENT_ID",
new Options( // Java uses an overloaded constructor.
Options.DEFAULT_URI, // Send data directly to Heap.
15.0, // Default upload interval of 15 seconds.
false, // Whether to capture advertiser ID. Defaults to false.
true // *IMPORTANT* Disable text capture set to true.
)
);
Modifying capture for specific views
React Native provides two custom views <HeapIgnore>
and <HeapIgnoreText>
and a withHeapIgnore
higher-order component to restrict some or all event capture in a region.
To see how these are used, consider the following component:
const PinView = (props) => {
return (
<View>
<Button title="1" rounded />
<Button title="2" rounded />
...
</View>
);
};
By default, tapping the 1 button will produce events with the hierarchy PinView Button[title=1][rounded=true]
and target text of "1".
Below are examples of how to use these components to restrict capture in on that view.
<HeapIgnore>
<HeapIgnore>
Wrapping a view with <HeapIgnore>
will suppress all events inside the view. For example:
<HeapIgnore>
<PinView />
</HeapIgnore>
Tapping the buttons in this view will not produce events.
There are 5 props that can be used to expose partial information.
allowInteraction
- This allows events to be captured with the remaining props determining how much is exposed. Without any other options, the bottom of the hierarchy is the view immediately inside<HeapIgnore>
. In the same event from above, the hiearchy would bePinView
.allowInnerHierarchy
- This allows the full hierarchy to be exposed, but without properties or text capture. In the same event, you would have a hierarchy ofPinView Button
.allowProps
- This allows property capture, but will exclude text-containing properties if the below options are omitted. In the same event, you would have a hierarchy ofPinView Button[rounded=true]
.allowText
- This allows text capture. It can be used alongsideallowProps
to expose text-containing properties.allowAccessibilityLabel
- This allowsaccessibilityLabel
capture.
<HeapIgnoreText>
<HeapIgnoreText>
Wrapping a view with <HeapIgnoreText>
will capture events but exclude text and accessibility labels from the event. For example:
<HeapIgnoreText>
<PinView />
</HeapIgnoreText>
Tapping the buttons in this view will produce events but with a hierarchy PinView Button[rounded=true]
and no target text. This is equivalent to <HeapIgnore allowInteractions allowInnerHierarchy allowProps>
.
withHeapIgnore
withHeapIgnore
withHeapIgnore
takes a component and returns a Higher Order Component that wraps it. This component accepts the same arguments but has <HeapIgnore>
already applied.
In the below example, PinView
is implemented with RedactedButton
, a control that wraps Button
. It accepts all the same arguments but has the ignore rules built in.
const RedactedButton = withHeapIgnore(Button, { allowInteraction: true });
const PinView = (props) => {
return (
<View>
<RedactedButton title="1" rounded />
<RedactedButton title="2" rounded />
...
</View>
);
};
Updated about 1 month ago