Two surfaces mark an element sensitive. They are equivalent, and they are the only two — there is no third, programmatic “mark this” call.
1. The data attribute
<div data-traceitx-sensitive>4242 4242 4242 4242</div>
Scanned from the live DOM at capture time, so it works in any framework’s
template — a Vue <template>, a Svelte component, an Angular view, or hand-
written HTML — with nothing imported.
2. The registry
For elements you hold a reference to rather than markup you control:
import { sensitiveRegistry } from '@traceitx/web';
const el = document.getElementById('credit-card');
sensitiveRegistry.addRef(el);
// when the element is removed, or should stop being masked:
sensitiveRegistry.removeRef(el);
This is the same registry @traceitx/react’s <Sensitive> wrapper calls into —
that component is a JSX shell over addRef, and this package has no JSX.
Call removeRef when the element goes away. The attribute needs no cleanup
because it is re-scanned every capture; the registry holds what you give it.
What it covers
| Screenshot | The region is painted as a solid block. |
| Session replay | The subtree is left out of the recording entirely, so the player shows a blank box of the same size. |
| Tap breadcrumbs | The crumb reads [masked] and no text is read from the subtree. |
| Console & network | Not covered — those are text streams. Use Redaction. |
That last row is the one to remember: this is about pixels. A card number
that also appears in a fetch body needs a redaction rule as well.
The masking happens in the producer, before capture — masked content never enters the screenshot buffer or the replay stream, let alone the upload. It is not a flag a viewer is trusted to honour.
Secure inputs
<input type="password"> is masked automatically — you do not need to mark it.
Anything else that happens to hold a secret does.
There is no markSensitive()
@traceitx/react’s hook exposes a method of that name. It has never been wired
to anything — it does not reach this registry and never has. The handle returned
by init() deliberately does not carry it, so that a privacy call on this SDK
either works or does not exist. Use one of the two surfaces above.
Choosing what to mark
Mark the smallest element that contains the secret. Marking a whole page makes the report useless without making it meaningfully safer, and a blanked screenshot is a common reason a report gets closed as unreproducible.
The default posture is already deny-by-default for text streams — see Redaction — so these surfaces are for the visual layer, where the SDK cannot infer intent from shape alone.