Skip to main content

Offline conversions

Offline conversion upload reports qualified leads from your saved data to Google Ads using their paid click identifiers or hashed contact details. Google can then use those outcomes in conversion bidding alongside your website form submissions. Every new Lead Engine ads setup provisions two conversion actions: website form submission (WEBPAGE / SUBMIT_LEAD_FORM) and qualified lead (UPLOAD_CLICKS / QUALIFIED_LEAD). The new campaign includes both in its own conversion goal from launch and keeps MAXIMIZE_CONVERSIONS bidding. Existing campaigns keep their approved goals and bidding when refreshed. You can also ask an agent to report a specific set of historical leads. It reads the saved rows, matches the conversion action and requests approval before uploading.

Automatically report qualified leads

A dataset row action can check each lead when it arrives or changes, then upload only those that meet your qualification rules. Leads hidden by the dataset’s default filters, including spam and not-a-lead exclusions, are excluded before the action runs. Create or find the conversion action with:
Or call POST /v1/paid-media/conversion-actions with:
Add customer_id when operating a client account beneath a connected manager. New actions require approval and are created as secondary, with one conversion per click. Creating the action leaves existing campaign goals alone; a new Lead Engine campaign explicitly selects both owned actions in its custom goal, which can bid on secondary actions. An existing enabled action with the same exact name is returned unchanged. The response reports ready with its account and action IDs, pending_approval with the approval request ID when a new card awaits a decision (call ensure again after approval to obtain the IDs), or in_progress with the prior approved request ID and an execution_phase of started or unknown. An in-progress response creates no card and makes no provider call. Repeat the request to read Google Ads again; only that read can return ready. Declare the upload against those fixed IDs and set the row action’s on_update to act. Saving authorizes that automation to upload to the declared account and conversion action; it refuses dynamic IDs or accounts outside your Google Ads connection. Disabling the row action withdraws that authorization. Use the lead’s stable reference as order_id to identify the conversion. Retain the successful upload’s request ID and conversion identity in a separate destination with when: "answered"; a final script returns a result only for a successful submission. Later skipped updates then preserve that evidence for any correction. Arrival bursts drain in bounded batches. A permanent validation rejection is shown as requiring manual repair and is not repeatedly uploaded. Correct the input and explicitly backfill the affected range to retry. Exclusions stop future uploads. The separate retraction declarations below correct conversions that were already sent.

Reconnect Google Ads once

Google has moved offline conversion upload onto a separate API with a permission of its own, and a connection made before that change does not carry it. If your Google Ads connection predates it, the first upload will stop and ask you to reconnect — it will not try the call and fail halfway. Reconnecting takes one pass through Google’s consent screen from Data → Connectors → Google Ads → Reconnect to grant access, available even while the connection is healthy. Google will ask for the additional permission; if the account uses a manager’s grant, reconnect in that manager organization. Nothing else about the connection changes: your account and campaign selections stay as they are, your synced data keeps flowing, and every other Google Ads capability keeps working before, during, and after. Only the conversion upload waits on it. This is an optional permission on the connection. Listing accounts, campaigns, and existing conversion actions can keep working without it; only offline-upload setup and the upload path require the Data Manager permission. The setup preflight checks the permission actually granted to the connection, so an existing upload conversion action cannot bypass a reconnect.

What “submitted” means

Google acknowledges an upload immediately and processes it later, so the result you get back is honest about which one it is:
Submitted 412 click conversions to Google (processing asynchronously)
That is an acknowledgement that Google accepted the batch, not a report that 412 conversions were recorded. The real processing finishes some time in the next 30 minutes to 24 hours, and Google’s acknowledgement carries no per-row outcome at all — so Erdo reports the number submitted and the request id, and never a number of conversions “recorded”, because that number does not exist yet. To find out what actually happened, ask the agent to check the upload’s status using the request id from the result. It answers with one of: Where records were rejected, Google reports how many for each reason — twelve duplicates, say — but not which rows they were. Erdo reports what Google reports, so nobody acts on a row-level detail that was never sent.

Rejections are all-or-nothing

If anything in an upload fails Google’s validation, the whole batch is rejected and none of it is processed. There is no partial acceptance to sift through: correct what the error names and resubmit the batch. Erdo’s result says so explicitly, so an agent retrying on your behalf resubmits everything rather than a subset that was never the problem.

Click matching and Enhanced Conversions

A conversion is matched by its gclid, gbraid, or wbraid, including iOS click identifiers. Blank identifiers are ignored. If a gclid is present, it is used; otherwise supply at most one braid. A click identifier is not required when a usable email or phone is available. Enhanced Conversions for leads also use the source row’s optional email and phone. Erdo normalizes email and E.164 phone numbers, then sends SHA-256 hex hashes in Data Manager’s userData.userIdentifiers. Blank or invalid identifiers are omitted. Upload all qualifying leads with usable contact details, including those without click identifiers. Rows with neither a click identifier nor usable email/phone are refused. Raw contact details are not included in the upload; transaction IDs remain unchanged. Supply the original contact values to the upload tool; Erdo performs the hashing. The landing kit separately supplies submitted contact fields to Google’s tag, which hashes them before sending. EU/UK/EEA/CH pages keep consent defaults denied until the banner grants ad_user_data. See Google Ads Enhanced Conversions for the page-side behavior and consent requirements.

Retracting conversions for excluded submissions

A reported lead may later be excluded as spam, fake, unreachable, a test or a staff submission. New Lead Engine setups declare separate row actions to retract those conversions after a 24-hour hold. They use the dataset’s existing default exclusion filters and do not run on ordinary arrivals. Brokers stay visible and are never excluded or retracted; both correction declarations check the saved buyer role before sending an adjustment. The declaration selects this mode with:
The hold gives you time to correct an exclusion. If you clear it before the action runs, the pending correction is cancelled. A retraction Google has already applied is irreversible. Clearing the local exclusion afterward does not restore that conversion. Website corrections use the original form transaction ID saved on the lead. A lead does not record which website form action fired it, so the website correction is declared only for a development with exactly one enabled form-submit action (one landing-page route, or routes sharing one action). With several distinct form actions, setup reports that gap instead of declaring it; qualified-lead uploads and their corrections still run. On a refresh, Erdo first disables any website-correction declaration left from an earlier single-action setup, since simply omitting its name would leave that automation active. Qualified-lead corrections use the order ID saved in the upload evidence and require proof that the upload was sent to the same account and action. After a merge, Erdo checks evidence from every member of the lead family and retracts each original transaction separately. Erdo never assumes that qualification alone means a conversion was uploaded. If the identity or prior-upload evidence is missing, it skips that correction and reports the gap. Saving these exclusion declarations authorizes their managed automations to retract each evidenced transaction on the fixed account and action. The grant accepts the row’s original form transaction ID, stable lead reference, or {{after.order_id}} from the declared upload evidence. Erdo verifies that the evidence producer belongs to the same organization and source dataset, uploads to the same account and conversion action, and records the uploaded order ID only after a successful submission. The grant does not authorize value changes or arbitrary conversion IDs. Historical merges without retained source keys require manual reconciliation: Erdo records that outcome on the exclusion event, withholds its retraction, and continues processing later exclusions. Disabling a declaration or removing its retraction steps withdraws that permission. An explicit policy requiring individual approval still takes precedence. Each correction keeps its exclusion ID, filter name, source and exclusion time, with the original conversion identity and provider result. A policy refusal or a Google rejection remains visible. The automation verifies that Google applied the single adjustment; a rejected response stays available in its action receipt and requires reconciliation instead of being sent again. An upload request ID proves submission; Google may still be processing it and can refuse a correction until the conversion exists. A partial correction is reported with its failed rows. Failed or unknown corrections do not replay automatically. Ordinary row recovery cannot replay an exclusion declaration. If Google refused the input before applying an effect, fix it, restore the row and exclude it again to start a new event and hold. Reconcile an unknown outcome with Google first. Backfills reuse completed action receipts. You can also ask an agent to retract a previously reported conversion or restate its value. Both use the existing approval process. Retractions use the Google Ads API and do not require the separate Data Manager permission needed for qualified-lead uploads.
  • Ad accounts — finding the account id an upload reports into
  • Approvals — the gate every ad-account write passes through
  • Dataset row actions — the standing way to report new leads as they arrive, rather than uploading by hand each time
  • Integrations — connecting and reconnecting Google Ads