Hide sensitive data
When using autocapture, Product Analytics 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. Similarly, Session Replay captures visual information from your app screens. However, some of these elements might contain sensitive user information, or Personal Data, that needs to be excluded from data capture.
There are three options for hiding sensitive data:
- Disabling text capture globally
- Per-view text masking for Session Replay
- Ignoring text and interactions for specific views in Product Analytics
Disabling all text capture
Section titled Disabling all text captureYou have the option to disable text capture for all events that are automatically captured in Product Analytics. To do this, use the Product Analytics configuration when starting the SDK.
import { CSQ } from '@contentsquare/react-native-bridge';
useEffect(() => { CSQ.configureProductAnalytics({ envId: "YOUR_ENVIRONMENT_ID", enableRNAutocapture: true, disableInteractionTextCapture: true, disableInteractionAccessibilityLabelCapture: true, });
CSQ.start();}, []);Masking text for specific views
Section titled Masking text for specific viewsIf you don’t want to disable all text capture for your app, you can take a more targeted approach of only masking text for specific views in your app that you know might contain sensitive data. When a view is masked for Session Replay, it will be obscured in the replay, and Product Analytics will not capture any data from it unless explicitly allowed.
import React from 'react';import { Text } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask isSessionReplayMasked={true}> <Text>Sensitive Information</Text> </CSQMask> );};Using the CSQMask component, you can wrap any view that might contain sensitive data to ensure that it is masked in Session Replay and ignored in Product Analytics. Its usage will impact all child views contained within the masked view.
import React from 'react';import { Text, Button } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask isSessionReplayMasked={true}> <Text>Sensitive Information</Text> <Button title="Submit" onPress={() => { console.log('Button pressed'); }} /> </CSQMask> );};In this example, both the Text and Button views will have their content masked in Session Replay when displayed, as they are both children of the CSQMask component.
In case of need you can also combine multiple masking configurations by nesting CSQMask components.
import React from 'react';import { Text, Button } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask isSessionReplayMasked={true}> <Text>Sensitive Information</Text> <CSQMask isSessionReplayMasked={false}> <Button title="Submit" onPress={() => { console.log('Button pressed'); }} /> </CSQMask> </CSQMask> );};In this example, only the Text view will have its content masked in Session Replay, while the Button view will retain its original appearance, as it is wrapped in a nested CSQMask with isSessionReplayMasked set to false.
Ignoring text for specific views
Section titled Ignoring text for specific viewsIf you want to allow interactions to be tracked in Product Analytics while hiding sensitive text content, you can use the ignoreTextOnly prop. This is useful when you want to track user engagement with an element without capturing the actual text displayed.
import React from 'react';import { TextInput } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask ignoreTextOnly={true}> <TextInput placeholder="Enter sensitive data" /> </CSQMask> );};Using ignoreTextOnly={true}, you can wrap any view where you want to track interactions but hide the text content and accessibility labels from Product Analytics. The view will still be visible in Session Replay according to the isSessionReplayMasked prop (defaulting to masked).
import React from 'react';import { Text, TextInput, Button } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask ignoreTextOnly={true}> <Text>Enter your password</Text> <TextInput placeholder="Password" secureTextEntry={true} /> <Button title="Login" onPress={() => { console.log('Login pressed'); }} /> </CSQMask> );};In this example, all views will have their text content and accessibility labels ignored by Product Analytics, but interactions (button presses) will still be tracked. The component hierarchy and properties will also be captured.
In case of need you can also combine multiple masking configurations by nesting CSQMask components.
import React from 'react';import { Text, Button } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask ignoreTextOnly={true}> <Text>Sensitive label text</Text> <CSQMask ignoreTextOnly={false}> <Button title="Submit" onPress={() => { console.log('Button pressed'); }} /> </CSQMask> </CSQMask> );};In this example, the outer Text view will have its text content ignored by Product Analytics, while the Button view will capture all data including its title text, as it is wrapped in a nested CSQMask with ignoreTextOnly set to false.
Advanced masking control
Section titled Advanced masking controlFor fine-grained control over what data is captured by Product Analytics, you can use the individual allow* props. This is useful when you need more specific control than ignoreTextOnly provides.
Available control props
Section titled Available control propsallowText: Controls whether text content is captured (default:false)allowAccessibilityLabel: Controls whether accessibility labels are captured (default:false)allowInteraction: Controls whether user interactions are tracked (default:false)allowInnerHierarchy: Controls whether child components are included in the hierarchy (default:false)allowProps: Controls whether component properties are captured (default:false)
Example: Allow interactions but ignore text
Section titled Example: Allow interactions but ignore textimport React from 'react';import { Button } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask isSessionReplayMasked={true} allowInteraction={true} > <Button title="Sensitive Button Label" onPress={() => { console.log('Button pressed'); }} /> </CSQMask> );};In this example, the button interaction will be tracked by Product Analytics, but the button’s text label will not be captured.
Example: Allow text and interactions
Section titled Example: Allow text and interactionsimport React from 'react';import { Text, Button } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask isSessionReplayMasked={false} allowInteraction={true} allowText={true} allowInnerHierarchy={true} > <Text>Product Information</Text> <Button title="Add to Cart" onPress={() => { console.log('Add to cart'); }} /> </CSQMask> );};In this example, the view is unmasked in Session Replay, and Product Analytics will capture interactions, text content, and the inner component hierarchy.
Example: Nested masking with different configurations
Section titled Example: Nested masking with different configurationsimport React from 'react';import { Text, TextInput, Button } from 'react-native';import { CSQMask } from '@contentsquare/react-native-bridge';
const MyComponent = () => { return ( <CSQMask allowInteraction={true} allowInnerHierarchy={true} > <Text>Form Title</Text>
<CSQMask allowInteraction={true} allowText={false} allowProps={true} > <TextInput placeholder="Enter sensitive data" /> </CSQMask>
<Button title="Submit" onPress={() => { console.log('Submit pressed'); }} /> </CSQMask> );};In this example, the outer CSQMask allows interactions and inner hierarchy capture, while the nested CSQMask around the TextInput prevents text capture but allows component properties to be captured.
Default behavior
Section titled Default behaviorBy default, when you use CSQMask:
- Session Replay: Content is masked (
isSessionReplayMasked={true}) - Product Analytics: All data is ignored unless explicitly allowed using
allow*props
If you don’t set any props:
<CSQMask> <Text>This content is masked</Text></CSQMask>Is equivalent to:
<CSQMask isSessionReplayMasked={true} allowText={false} allowAccessibilityLabel={false} allowInteraction={false} allowInnerHierarchy={false} allowProps={false}> <Text>This content is masked</Text></CSQMask>Implementation recommendations
Section titled Implementation recommendationsAvoid dynamically changing masking props
Section titled Avoid dynamically changing masking propsWhile CSQMask supports toggling masking props, we do not recommend changing the props dynamically based on conditions:
// ❌ Not recommended<CSQMask isSessionReplayMasked={someCondition ? true : false}> ...</CSQMask>This approach may lead to unexpected behavior, such as personal data leaks. Instead, structure your layout in a way that ensures predictable masking behavior without frequently modifying the masking props dynamically.
Using ignoreTextOnly vs. allow* props
Section titled Using ignoreTextOnly vs. allow* propsUse ignoreTextOnly={true} when you want to:
- Track interactions while hiding text content
- Use the predefined configuration (interactions allowed, text/labels ignored)
- Simplify your code with a common use case
Use individual allow* props when you need:
- Fine-grained control over specific data types
- Custom combinations not covered by
ignoreTextOnly - To allow text but ignore other data types
Never combine them:
// ❌ This will generate a warning<CSQMask ignoreTextOnly={true} allowText={true}> ...</CSQMask>Nesting behavior
Section titled Nesting behaviorWhen nesting CSQMask components, the inner component’s props override the outer component’s behavior for its children:
<CSQMask isSessionReplayMasked={true}> <Text>This is masked</Text> <CSQMask isSessionReplayMasked={false}> <Text>This is NOT masked</Text> </CSQMask></CSQMask>However, for Product Analytics allow* props, the rules are cumulative - if a parent denies access (allowText={false}), a nested child cannot override it to allow access. Both must allow for data to be captured.
TextInput components
Section titled TextInput componentsNote that TextInput components are masked by default for Session Replay, even when the default masking is set to false globally. If you need to unmask a TextInput, you must explicitly wrap it:
<CSQMask isSessionReplayMasked={false}> <TextInput placeholder="This input is visible in replays" /></CSQMask>