captureCDR()
Capture a snapshot of the page, upload it, and get back a cdrId confirming the evidence is persisted.
Usage
const result = await window.ExpressConsent.captureCDR({
custom: {
uid: myLeadRecord.id, // unique ID from your system (see best practices below)
phoneNumber: "+15551234567",
formName: "lead-form",
},
subGroupIds: ["step-1"],
autoShare: true,
});
// Store cdrId with your lead/user record.
console.log(result.cdrId);
// If autoShare is enabled, pass the share URL to your lead buyer.
console.log(result.shareUrl);If page navigation happens before the promise resolves, the CDR may not be saved. Always preventDefault() → await → submit/navigate.
Inputs
custom
Arbitrary metadata stored with the CDR. Every key you include becomes a queryable field — you can filter CDRs by any single key/value pair using the API’s metadataKey/metadataValue params. Include any fields you might want to look up CDRs by later: phone numbers, email addresses, campaign IDs, form names, etc. Must be JSON-serializable. Max 16 KB.
Pass a unique ID from your system (e.g. your lead or form-submission ID) in custom. This is your only way to match the CDR back to the originating record if the initial upload fails and the SDK retries it later. See Offline resilience below.
highlightTarget (optional override)
By default, the SDK automatically highlights the element the user interacted with to trigger the capture. You do not need to set this for most integrations.
If auto-highlighting selects the wrong element on a specific page, pass a string token that matches a data-expressconsent-highlight-label attribute to override. See Highlighting & Masking.
triggerEvent (optional)
Pass the DOM Event object from your handler for the highest forensic precision. The SDK uses event.target to identify the trigger element and event.isTrusted to prove it was a real user action.
If omitted, the SDK auto-detects the trigger automatically, which works in the vast majority of cases. See Highlighting & Masking for details on how auto-detection works.
subGroupIds
Optional array of string identifiers for multi-step / co-registration flows. Creates additional Package CDRs for grouping CDRs. Max 5 unique values. See Sessions & Package CDRs.
autoShare
Auto-generate a share token so you can pass consent evidence to a lead buyer without a separate API call. Pass true for defaults (30-day expiry) or an options object:
autoShare: true— 30-day expiry (default)autoShare: { expiresInMs: 604800000 }— custom expiry (max 2 years)
When enabled, the result includes shareUrl, shareToken, and shareExpiresAt. See Sharing with Lead Buyers.
inlineAssets (dev/local mode)
Set inlineAssets: true per call when testing on localhost or other private environments where your asset URLs are not reachable by cloud workers.
await window.ExpressConsent.captureCDR({
// Dev/localhost mode: inline assets into the snapshot payload.
// Use this when styles/images/fonts are served from your machine.
inlineAssets: true,
});This increases payload size and is intended for development/testing. Keep it off in normal production captures unless you specifically need inline-asset behavior.
timeoutMs
Optional request timeout in milliseconds. Overrides the SDK’s default adaptive timeout budget.
Return value
Always present:
cdrId— the evidence ID. Store this with your lead/user record.packageData— session grouping identifiers. ContainspackageId(the session-level package) andsubGroupIdMap. Only relevant if you’re building package-aware workflows.
Present when autoShare is enabled:
shareUrl— full absolute URL the lead buyer POSTs to with their API key to claim the evidence.shareToken— the raw share token (the last segment of the URL).shareExpiresAt— token expiry as a Unix timestamp in milliseconds.
Error behavior
captureCDR() throws when it cannot guarantee persistence:
- SDK not loaded (missing script tag or
data-ec-cid) - Network failure or timeout
- Upload endpoint unreachable (e.g. from self-hosting the SDK)
CAPTURE_DISABLED— capture has been administratively disabled for this organization. Contact ExpressConsent support if you believe this is an error.
Wrap the call in a try/catch, log the error, and let the form submit proceed. Do not block submission on capture failure.
Offline resilience
The SDK automatically saves the captured CDR data to the browser’s local storage (IndexedDB) before attempting the upload. If the upload fails — due to a slow connection, transient network error, or the user navigating away — the data persists locally and the SDK retries the upload automatically on the user’s next page load on that site.
captureCDR() only returns a cdrId when the evidence is confirmed persisted in ExpressConsent’s storage. If the upload fails, captureCDR() throws — you will not receive a CDR ID. This is intentional: a CDR ID is a guarantee that the evidence exists and is retrievable.
When a retry upload succeeds later, the CDR appears in your dashboard, API, and webhook like any other CDR. However, the original page and code that called captureCDR() is long gone — there is no callback. This is where the custom metadata becomes critical.
Reconciliation via custom metadata
By including a unique identifier from your system in the custom field, you create a link between your lead/user record and the CDR evidence. When the CDR eventually uploads (whether immediately or via retry), you can find it using that identifier.
// Your submit handler
async function handleSubmit(formData) {
const leadId = generateUniqueId(); // your system's unique ID for this submission
try {
const { cdrId } = await window.ExpressConsent.captureCDR({
custom: { uid: leadId, form: "signup" },
});
// Happy path: save cdrId directly with the lead record.
await saveLead({ ...formData, leadId, cdrId });
} catch (err) {
// Upload failed — but the SDK saved the CDR data locally.
// Save the lead WITHOUT a cdrId. The SDK will retry the upload
// automatically on the user's next page load.
await saveLead({ ...formData, leadId, cdrId: null });
}
}
// Later, in your backend — find CDRs that uploaded via retry:
// GET /v1/domains/example.com/cdrs?metadataKey=uid&metadataValue={leadId}
// Or receive the CDR via webhook and match on customMetadata.uidFinding retry-uploaded CDRs
Two approaches for reconciling leads that are missing a CDR ID:
- API polling: Query GET /v1/domains/:domainId/cdrs with
metadataKeyandmetadataValueto find CDRs matching your unique identifier. Run this on a schedule for any lead records missing a CDR ID. - Webhook: The webhook payload includes
customMetadata. When acdr.completedevent arrives, match the unique identifier back to your lead record and save the CDR ID.
Automatic signals
The SDK automatically captures the following signals with every CDR — no code changes needed:
- Signer telemetry — IP address and User-Agent from the upload request.
- Disclosure tracking — tag disclosure text in your HTML with
data-ec-disclosureand pass agreement status via thedisclosuresparameter. The SDK extracts the tagged text and stores it in the CDR as adisclosuresarray. See Disclosure Tracking for details.