Highlighting & Masking
The SDK automatically highlights the element the user interacted with to trigger the capture. You can also redact sensitive fields before evidence leaves the browser.
Auto-highlighting
When the user clicks a submit button (or any element that triggers your captureCDR() call), the SDK automatically identifies that element and highlights it in the visual record. This works out of the box — no HTML attributes or configuration needed.
This is especially important for forms with multiple submit buttons (e.g. “Gold Plan” vs “Silver Plan”, or multiple-choice survey pages). Without highlighting, there would be no way to tell from the screenshot which option the user selected.
// The submit button is automatically highlighted — no extra code needed.
form.addEventListener("submit", async (e) => {
e.preventDefault();
const { cdrId } = await window.ExpressConsent.captureCDR();
console.log("Evidence saved:", cdrId);
e.currentTarget.submit();
});The SDK tracks user interactions (clicks, taps, form submits) in real time. When captureCDR() is called, it identifies the most recent interaction and records which element triggered it. The renderer then draws a visible outline around that element in the screenshot. The detection is fully automatic and does not affect your live page.
Best practices for accurate highlighting
Call captureCDR() as the first thing in the handler
For the most accurate highlighting, call captureCDR() as the first async operation in your event handler. If you do async work (API calls, validation) before calling captureCDR(), the highlight accuracy is reduced because the SDK has to fall back to its interaction log instead of directly detecting the active event.
// ⚠️ Avoid: async work BEFORE captureCDR reduces highlight accuracy.
button.addEventListener("click", async () => {
await someApiCall(); // ← delay; auto-highlight falls back to interaction log
await window.ExpressConsent.captureCDR();
});// ✅ Better: capture FIRST, then do async work.
button.addEventListener("click", async () => {
const { cdrId } = await window.ExpressConsent.captureCDR();
await someApiCall(); // ← async work after capture is fine
});Pass the event for maximum precision (optional)
If you want the strongest possible forensic proof of which element triggered the capture, pass the DOM Event object directly. This uses event.isTrusted, which browsers guarantee cannot be forged by JavaScript.
// For maximum forensic precision, pass the DOM event directly.
form.addEventListener("submit", async (e) => {
e.preventDefault();
const { cdrId } = await window.ExpressConsent.captureCDR({
triggerEvent: e,
});
console.log("Evidence saved:", cdrId);
e.currentTarget.submit();
});Manual override
In rare cases where auto-highlighting selects the wrong element, you can override it by specifying exactly which element to highlight.
1. Add a label to the element
<!-- Add a label to the element you want highlighted -->
<button type="submit" data-expressconsent-highlight-label="consent-submit">
I agree & submit
</button>2. Pass the label to captureCDR
// Pass the label to override auto-highlighting.
await window.ExpressConsent.captureCDR({
highlightTarget: "consent-submit",
});The highlightTarget value must exactly match the data-expressconsent-highlight-label attribute. The SDK matches the first element it finds with that label.
Auto-highlighting works for the vast majority of integrations. Only use highlightTarget if you have confirmed that auto-highlighting is selecting the wrong element on a specific page.
Masking
Masking redacts sensitive data (SSN, CVV, passwords) from the evidence before it leaves the browser. Masked data is gone permanently — you cannot recover it, even as the org owner.
The more you mask, the less useful the visual snapshot is as evidence. Only mask what is strictly necessary (e.g. payment details, government IDs). Never mask consent language, checkboxes, or submit buttons.
Mask a single input
<label>
SSN
<input name="ssn" data-expressconsent-mask />
</label>Mask an entire section
The attribute is inherited by descendants. Place it on a container to redact everything inside.
<section data-expressconsent-mask>
<h3>Payment details</h3>
<input name="cardNumber" />
<input name="cvv" />
<!-- Everything inside is masked -->
</section>