Migrate to verifiable consent
What changed
Previously you told the SDK what the user agreed to by passing disclosures: { key: boolean } to captureCDR(). Those booleans were client-asserted, so ExpressConsent stored them verbatim without verifying them.
Now you tag the disclosure, the consent checkbox, and the submit button in your HTML. ExpressConsent detects the submission and derives the facts server-side from the captured DOM, producing a per-disclosure consentMechanism. Nothing about consent is taken on the client’s word, so the evidence is stronger.
The legacy path is still fully supported. disclosures and triggerEvent are accepted (the latter is ignored), and legacy webhook/API fields keep flowing. Migrate when you’re ready. The steps below are additive and safe to ship incrementally.
Step 1: Swap your HTML tags
Replace the legacy text/checkbox attributes with the disclosure model. The old data-ec-consent-text becomes data-ec-disclosure, the checkbox gets data-ec-consent-checkbox, and the submit button gets data-ec-submit.
Before
<!-- Legacy: text + checkbox paired by a matching label value. -->
<p data-ec-consent-text="tcpa">
By submitting, you agree to be contacted at the number provided.
</p>
<input type="checkbox" data-ec-consent-checkbox="tcpa" />
<!-- The submit button was untagged. -->
<button type="submit">Submit</button>After
<!-- New: the disclosure language. -->
<p data-ec-disclosure="tcpa">
By submitting, you agree to be contacted at the number provided.
</p>
<!-- The consent checkbox, bound to the disclosure by id. -->
<input type="checkbox" data-ec-consent-checkbox data-ec-consent-for="tcpa" />
<!-- Tag the submit buttons. The one the user presses gets outlined in the evidence. -->
<button type="submit" data-ec-submit>Submit</button>The full tag set:
data-ec-disclosure="<id>": the disclosure language. Its text is captured so the record is searchable. (Replacesdata-ec-consent-text.)data-ec-consent-checkbox: the consent checkbox.data-ec-consent-for="<id>": which disclosure a checkbox governs. (If there are multiple.)data-ec-submit: the button the user submits with. ExpressConsent outlines this control in the rendered evidence. This tag is new.
When the page has exactly one disclosure and one checkbox, the <id> on data-ec-disclosure and the whole data-ec-consent-for binding are optional:
<p data-ec-disclosure>By submitting, you agree to be contacted.</p>
<input type="checkbox" data-ec-consent-checkbox />
<button type="submit" data-ec-submit>Submit</button>Step 2: Remove legacy captureCDR() parameters
Once the page is tagged, drop disclosures and triggerEvent from your captureCDR() call. They are no longer needed:
Before
await window.ExpressConsent.captureCDR({
// Legacy: client-asserted agreement booleans.
disclosures: {
tcpa: tcpaCheckbox.checked,
},
// Legacy: hint about which event triggered the capture.
triggerEvent: event,
custom: { phoneNumber: phone },
});After
await window.ExpressConsent.captureCDR({
// No disclosures, no triggerEvent. ExpressConsent derives the facts
// from the tagged DOM + the detected submission.
custom: { phoneNumber: phone },
});Step 3: Update the payload you read
If you consume webhooks or the API, switch from the legacy fields to detectedDisclosureDetails. Both can appear on the same CDR during a rollout, so prefer the derived object when present.
Field mapping
consentLanguage[].language→detectedDisclosureDetails.disclosures[].textdisclosures[].key→detectedDisclosureDetails.disclosures[].keydisclosures[].agreed(client-asserted boolean) →detectedDisclosureDetails.disclosures[].consentMechanism(server-derived:checkbox/button_submission/none_detected)
Before
// Legacy fields you may have read:
const agreed = event.disclosures?.[0]?.agreed; // client-asserted boolean
const language = event.consentLanguage?.[0]?.language; // auto-detected textAfter
// New: server-derived facts.
const agreed = detectedDisclosureDetails.disclosures?.[0]?.consentMechanism;
const language = detectedDisclosureDetails.disclosures?.[0]?.text;The same detectedDisclosureDetails object appears on the webhook payload, the CDR API responses, and share pages. Treat a missing consentMechanism on a historical CDR by falling back to the legacy fields.