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:POST /v1/paid-media/conversion-actions with:
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 itsgclid, 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:{{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.
Related
- 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

