captureCDR()

Capture a snapshot of the page, upload it, and get back a cdrId confirming the evidence is persisted.

Usage

javascript
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);

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.

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.

javascript
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. Contains packageId (the session-level package) and subGroupIdMap. 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.

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.

javascript
// 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.uid

Finding retry-uploaded CDRs

Two approaches for reconciling leads that are missing a CDR ID:

  • API polling: Query GET /v1/domains/:domainId/cdrs with metadataKey and metadataValue to 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 a cdr.completed event 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-disclosure and pass agreement status via the disclosures parameter. The SDK extracts the tagged text and stores it in the CDR as a disclosures array. See Disclosure Tracking for details.

Next