captureCDR()
Captures the current page and resolves once the evidence has been durably received.
const result = await window.ExpressConsent.captureCDR(options);Every option is optional. Called with no arguments it produces a valid record.
Options
customobjectoptionalYour own fields, stored with the record and returned as
customMetadata.Keys become filterable through the API, primitives directly, array elements under the bare key, and one level of nesting as
key.subkey. Matching is exact but case-insensitive and whitespace-normalized. A single key-and-value pair longer than about 190 characters is not indexed, and a record indexes at most 250 values in total.Validate this before you pass it. The limits are enforced when the record is processed rather than when you call, so an oversized object is not reported back to you.
Keys ≤ 100 characters. Values may be primitives, arrays of primitives, or objects one level deep. The whole object must serialize to 16,000 characters or fewer.autoShareboolean | objectoptionaldefaultfalseGenerate a share URL during the upload instead of making a second API call. Pass
truefor the default expiry, or{ expiresInMs: 604800000 }to set your own. ReadshareExpiresAton the result for the expiry you actually got.Default expiry 30 days. A request longer than 2 years is clamped rather than rejected; a non-positive value falls back to the default.devModebooleanoptionaldefaultfalseCreate a free, uncollected test CDR that still renders for inspection by members of the producing organization, including passthrough organizations. The SDK logs concise diagnostics and an immediate dashboard link that waits for rendering. Remove this option before production.
inlineAssetsbooleanoptionaldefaultfalseEmbed image bytes and
@font-facefonts in the capture rather than referencing their URLs. Intended for local development, where our renderer cannot reachlocalhostasset URLs. It multiplies payload size and can exceed the upload limit, so leave it off in production.
Result
cdrIdstringrequiredThe record identifier. Store it with your lead. Its presence is the guarantee that the evidence is stored.
packageDataobjectrequiredSession grouping details.
packageIdidentifies the managed package for this capture.shareUrlstringoptionalThe absolute URL to hand to a buyer. Present when
autoShareis enabled and the share token was created. Token creation is best-effort and its failure does not fail the capture, so check for the field rather than assuming it, and fall back to the share API if it is absent.A Dev Mode capture may return this field so you can verify your integration passes it through, but API and dashboard claim attempts are permanently denied with
CDR_DEV_MODE.shareTokenstringoptionalThe token from the end of
shareUrl. Same conditions as above.shareExpiresAtnumberoptionalExpiry as a Unix timestamp in milliseconds. Same conditions as above.
Usage
form.addEventListener("submit", async (event) => {
event.preventDefault();
const phone = form.phone.value;
try {
const { cdrId, shareUrl } = await window.ExpressConsent.captureCDR({
autoShare: true,
custom: { phone },
});
await saveLead({ phone, cdrId, shareUrl });
} catch (error) {
console.error("ExpressConsent capture failed", error);
}
form.submit();
});captureCDR() must be the first thing you await in the handler. The capture reads the page at the
moment you call it, so anything you await first is what ends up in the evidence.
If the call resolves, the evidence is stored. That is the guarantee the cdrId carries: you never
receive one for a record that was not saved. The visual record renders shortly afterwards, so a record
fetched in the seconds right after a capture may not be readable yet.
Dev Mode
Use captureCDR({ devMode: true }) while integrating. The CDR remains collected: false, has no API
downloadUrl, creates no billing or access-grant records, and cannot be collected or transferred
through API share tokens. It still renders, sends a cdr.completed webhook marked devMode: true,
and can be reviewed through visibly marked dashboard viewer links and PDFs.
See Test with Dev Mode for the verification workflow.
Supporting documents
Tag a static privacy policy, terms document, arbitration clause, or PDF that should be archived with the CDR:
<a
href="https://example.com/privacy"
data-ec-supporting-document="privacy-policy"
>
Privacy Policy
</a>The attribute value is a lowercase identifier of letters, numbers, hyphens, or underscores, and it
names the document on the record. The link's text, and the absolute URL with any fragment removed,
are recorded during the capture. The destination is retrieved afterwards, so this adds no work to
the captureCDR() request and does not delay the CDR ID.
If the destination paints its legal text with JavaScript, use data-ec-supporting-document-render
instead and we load the page in a browser before archiving it:
<a
href="https://example.com/terms-conditions/"
data-ec-supporting-document-render="terms"
>
Terms & Conditions
</a>The requirements a destination has to meet, and where the archived documents can be read, are on Archive linked documents.
Errors
The call rejects rather than returning a partial result. Every error and its cause is on
SDK errors. Wrap the call in try/catch and let the person's
submission proceed regardless.
Limits
| Upload size | 3 MiB, measured on the compressed upload rather than the page |
custom serialized size | 16,000 characters |
custom key length | 100 characters |
Searchable custom values | 250 per record, each pair under about 190 characters |
| Disclosures read per page | 50 |
| Disclosure name length | 200 characters |
| Disclosure text stored | 5,000 characters |
| Supporting documents per CDR | 10 |
| Supporting-document HTML | HTTPS, static initial response, maximum 2 MiB |
| Supporting-document PDF | HTTPS, maximum 20 MiB |