Occlusion - Hide Sensitive Data
Occlusion is a data privacy technique used to mask or hide sensitive information from being recorded or exposed during analytics tracking. In the context of the UXCam SDK, occlusion ensures that user inputs—such as passwords, credit card numbers, emails, and other personal data—are automatically or manually hidden from session recordings and logs. This helps protect user privacy and maintain compliance with data protection regulations like GDPR and CCPA.
Note
Occluded input field texts are replaced with asterisks (***). Occluded input field numbers are replaced with zeros (000)
Elements that are occluded by default
Inputs will be occluded by default if they meet any of the following criteria:
| Input Types | Input Names Containing | Autocomplete Properties Containing |
|---|---|---|
| 'password' 'email' 'tel' 'hidden' 'number' | 'password' 'cc-' 'email' 'phone' | 'cc-' 'address' 'phone' 'email' 'password' |
Password and hidden fields, and fields whose name or autocomplete contains password or cc-, are always masked. The other fields in the table can be shown with an unmask on the field itself; see Sensitive input fields.
Enabling Occlusion
Enables occlusion of sensitive data in URLs and query parameters.
Occluding Query Parameters
Query parameters to be occluded should be listed under queryParams.
occlusion: {
queryParams: ['product', 'userId']
}
// Example
// Input: http://www.uxcam.com/query?product=shoes&userId=321
// Output:http://www.uxcam.com/query?product=_occluded_&userId=_occludedOccluding URLs
A custom function can be used to occlude parts of the URL before the query parameters.
occlusion: {
url: function(url) {
// Custom logic to modify the URL
return url.replace(/\/invite\/\w+/, '/invite/:inviteId');
}
}
// Example
// Input: http://www.uxcam.com/invite/12345
// Output: http://www.uxcam.com/invite/:inviteIdMasking page content
Choose what to hide with the data-uxc attribute in your HTML:
| Attribute | Effect |
|---|---|
data-uxc="obfuscated" | Hides the element and everything inside it. |
data-uxc="unmask" | Shows the element and everything inside it again, inside an obfuscated area. |
The occlusion option does the same with CSS selectors, without changing your HTML: occlusion.mask works like adding data-uxc="obfuscated" to every matching element, and occlusion.unmask like adding data-uxc="unmask".
A masked element looks like this in the replay:
- Text: every letter and digit becomes
*. Spaces and punctuation stay, so the layout is kept. - Input values:
******, or000000for number fields. - Attributes:
placeholder,title,aria-label,aria-description,altandlabel, and dropdown option values, are masked too. - Images and videos: an empty box of the same size. Their URLs aren't recorded.
- Everything else: layout, styles, clicks and scrolling are still recorded, so replays and heatmaps keep working.
Masking happens in the browser, so masked content never reaches UXCam.
Mask specific elements
Add the attribute to the element:
<div data-uxc="obfuscated">Account balance: $1,234.56</div>Or list CSS selectors, without changing your HTML:
occlusion: {
mask: ['.account-balance', '#checkout-summary']
}Mask the whole page, then show selected parts
Mask everything with the html selector, then list the parts that should stay visible:
occlusion: {
mask: ['html'],
unmask: ['header', 'nav', '.product-list']
}The same with attributes:
<html data-uxc="obfuscated">
<body>
<header data-uxc="unmask">...</header>
</body>
</html>Use html rather than body, so the page title is masked too.
Which rule wins
UXCam checks the element, then each of its parents in turn. The first one it finds that is obfuscated (by the attribute or a mask selector) or unmasked (by the attribute or an unmask selector) decides:
- An unmasked element inside an obfuscated area is shown.
- An obfuscated element inside an unmasked area is hidden again.
- If an element is both obfuscated and unmasked, for example because it matches selectors in both lists, it's masked.
- Content with nothing obfuscated or unmasked above it is recorded as usual, apart from the fields in the table above.
<section data-uxc="obfuscated">
<p>Jane Doe</p> <!-- masked -->
<div data-uxc="unmask">
<p>Order status: shipped</p> <!-- shown -->
<p data-uxc="obfuscated">Card ending 4242</p> <!-- masked -->
</div>
</section>Sensitive input fields
- Always masked: password fields, hidden fields, and fields whose name or autocomplete contains
passwordorcc-. Nounmaskcan show them. - Masked unless you target the field: email, phone and number fields, and fields whose name or autocomplete suggests an email, phone number or address. They stay masked inside an unmasked area. To show one, unmask the field itself:
occlusion: {
mask: ['html'],
unmask: ['input[type="number"]'] // show quantity fields
}
Broad unmask selectorsA selector such as
input,por*matches many elements directly, including fields, and elements inside areas markeddata-uxc="obfuscated". Email, phone and number fields matched this way are shown. Prefer specific selectors, such as#promo-codeor.product-list.
Iframes and shadow DOM
- Masking works inside shadow DOM: obfuscating a component's host masks everything it renders, and an
unmaskinside the component still shows that part. - Masking reaches into same-site iframes.
mask: ['html']masks them too, because each iframe page has its own<html>. - A cross-site iframe is recorded by the SDK in the iframe page, so it follows that page's own attributes and
occlusionoptions. See Iframe Recording: Privacy.
Things to know
- Put the attributes in your HTML, or add them before the UXCam script loads. Adding or changing
data-uxclater doesn't change what was already recorded. - Invalid CSS selectors are ignored, and the SDK logs a warning in the browser console (unless
silentis on).
Updated 17 days ago
