Masking Sensitive Data in Microsoft Clarity: Practical Steps and Trade‑offs
Microsoft Clarity captures full DOM snapshots, which can expose PII. Learn how to mask sensitive data with the <code>data-clarity-mask</code> attribute, compare component‑level vs field‑level masking, and audit recordings to keep user privacy intact.
09 Aug 2026, 05:42 UTC

Why Masking Matters in Clarity
Microsoft Clarity captures full DOM snapshots and interaction events so that product teams can replay user sessions and spot UX pain points. Unfortunately, that snapshot can include personally identifiable information (PII) such as names, emails, addresses, or tokens typed into form fields. If Clarity is enabled in production without precautions, those values may be stored in the Clarity data store and could be accessed by anyone with dashboard access.
The good news is that Clarity provides a built‑in mechanism to hide exactly those bits of text while preserving the layout and click coordinates needed for debugging. The technique is simple: add the data-clarity-mask attribute to the element you want to hide.
How the data-clarity-mask Attribute Works
When Clarity sees the attribute, it replaces the element’s inner content with a generic placeholder block in the replay. The placeholder looks like a gray rectangle the same size as the original element, ensuring that the visual flow of the page remains intact. Clicks and hover coordinates are still recorded accurately, so you can still see where a user tapped or hovered.
Clarity masks are applied only during the recording. The actual DOM is untouched on the client, so your application continues to function normally. The placeholder is generated on the server side when the replay is rendered, meaning the original text never travels outside the browser.
Masking Strategy: Component‑Level vs Field‑Level
There are two common approaches:
- Field‑level masking – add
data-clarity-maskto every input or paragraph that may contain PII. This can become brittle: every time you add a new field you must remember to mask it. - Component‑level masking – wrap the entire widget or form that handles sensitive data in a container with
data-clarity-mask. The container hides all child content, reducing maintenance overhead.
For most applications, component‑level masking is preferable. It guarantees that any newly added field inside the container is automatically protected without additional code changes.
Concrete Example: Masking a Contact Form
Below is a minimal React component that demonstrates component‑level masking. The data-clarity-mask attribute is applied to the outer div that encloses the entire form.
import React from "react";
export default function ContactForm() {
return (
<div data-clarity-mask> {/* Mask the whole form */}
<form>
<label>Name:<input type="text" name="name" /></label>
<label>Email:<input type="email" name="email" /></label>
<label>Message:<textarea name="message" /></label>
<button type="submit">Send</button>
</form>
</div>
);
}
When a user submits the form, the replay will display gray rectangles where the name, email, and message were typed, but the click on the Send button will still be visible. No PII leaves the browser.
Alternatives: CSS‑Based Masking
Clarity also respects CSS rules that hide elements. For example, adding .hide-clarity { visibility: hidden; } to a class will hide the element in the replay. However, CSS masking applies globally: if you apply the class to a component that is reused elsewhere, you may unintentionally hide useful debug information. Moreover, CSS alone does not replace the text with a placeholder rectangle; it simply makes the element invisible, which can confuse developers who expect a visible placeholder.
Trade‑offs and Limitations
- Over‑masking risk – If you mask too broadly, you may lose valuable debugging data. For instance, masking a navigation bar that contains dynamic user names might make it impossible to see how many users are logged in.
- Dynamic content – Content rendered after the Clarity script loads (e.g., via AJAX or a third‑party widget) may not be masked unless you add the attribute after it mounts. Test your dynamic flows in a staging environment.
- Existing recordings – Masking only affects new recordings. Data already captured before you added
data-clarity-maskremains in Clarity’s storage. Plan to enable masking before you enable Clarity in production or purge older sessions if necessary. - Version changes – Clarity’s default masking behavior and the attribute name are subject to change. Verify against the latest Microsoft documentation before deployment.
How to Verify Your Masking Works
- Create a test page that includes a known PII string (e.g.,
[contact removed]). - Enable Clarity on that page and record a session.
- Open the Clarity dashboard, replay the session, and confirm that the placeholder rectangle appears instead of the real text.
- Optionally, inspect the network payload in DevTools: the recorded DOM should not contain the original text.
Actionable Checklist
- Wrap any form or widget that handles PII in a
data-clarity-maskcontainer. - Audit dynamic third‑party components and add the attribute after they mount.
- Run a staging test to confirm masking on sample user flows.
- Document the masking strategy in your engineering handbook so future developers know where to apply the attribute.
- Schedule periodic audits of Clarity recordings to catch any accidental leaks.
By following these steps, you can keep Clarity’s powerful user‑experience insights while protecting sensitive user data.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.