Send offline conversions from your CRM back to Google Ads
On this page
This page shows how to tell Google Ads which clicks turned into paying customers. You save the ad click ID with every lead, record a status and a value in the CRM when the job is won, and upload those wins to Google Ads against the original click. It is the method I use to close the loop for businesses that sell over the phone or in person, days or weeks after someone clicks an ad.
Why send conversions back
Google Ads optimizes for whatever you tell it counts. If the only conversion in the account is a form submission, automated bidding learns to find more people who submit forms, with no way to tell a real customer from a tire kicker, a spammer, or someone far outside the service area. Tell it which clicks became jobs, and what each job was worth, and it has a better target to aim at.
The same data answers the owner's real question: which campaigns and keywords bring in money, not just leads. This is level 4 in how attribution works, and it does not require a data warehouse. A CRM with a few extra fields and a scheduled upload is enough to start.
Before you begin
- Auto-tagging turned on in the Google Ads account, so ad clicks arrive with a
gclidin the address. - An account role in Google Ads that can create conversion actions and upload conversions.
- A CRM, or at minimum a disciplined spreadsheet, where every lead is a record with room for extra fields.
- Lead forms you can add hidden fields to, and the basic tracking from the GA4 and Tag Manager quickstart.
- An agreement about who marks jobs won, how soon after the sale, and what value goes in. Without that, there is nothing to send.
Capture the click ID with every lead
- Add hidden fields to every lead form
Add hidden inputs named
gclid,gbraid, andwbraid, plusutm_source,utm_medium,utm_campaign, andlanding_page. Some iPhone traffic arrives withgbraidorwbraidinstead of agclid. Google's API accepts either one in place of agclid, so save them, but check your upload tool's template before relying on them in a file. - Save the values when the visitor lands
The click ID is only in the address on the first page. A Tag Manager tag should copy it into a first-party cookie on arrival, replace it when a newer ad click comes in, and fill the hidden fields from that cookie on whatever page the form sits on. Server-side tagging keeps that cookie alive past Safari's seven-day limit on script-written cookies.
- Carry the fields into the CRM record
Make sure the form handler writes the hidden values into fields on the lead record, not only into the notification email. Test it: land on the site with
?gclid=TEST123in the address, click to a second page, submit the form, and findTEST123on the new lead. Then delete that test lead so it never gets uploaded. - Decide how phone leads get a click ID
A caller leaves no hidden field behind. Phone wins can only be uploaded by click ID if something records it, such as a call tracking system that ties each call to the visitor's session. Google Ads also has its own call conversion tracking, which is a separate setup. Without either, record the lead source by hand and accept that those wins stay out of the upload.
Forms that drop hidden fields, or that email the office without ever creating a record, are a website problem first. Contact forms that work covers what a lead form needs underneath.
Record status and value in the CRM
Every lead record needs these fields. Most CRMs can hold them as custom fields, and a pipeline stage can stand in for the status.
| Field | What it holds | Why it matters |
|---|---|---|
| Click IDs | gclid, gbraid, and wbraid from the hidden fields | This is what the upload matches against. |
| Status | New, contacted, quoted, won, or lost | Only won records get uploaded as sales. |
| Won date and time | When the job was sold, in the business's time zone | This becomes the conversion time. |
| Won value | The amount of the sale, as a plain number | Tells Google which clicks were worth more. Use revenue, or gross profit if margins vary widely between services. |
| Uploaded | The date the win was sent to Google Ads | Prevents double uploads and shows what is still waiting. |
Setting up stages that people actually keep current is covered in building a CRM pipeline.
Create the conversion action
- Create an import conversion action
In Google Ads, create a new conversion action, choose to import conversions, and pick the option for conversions from clicks. The menu wording changes from time to time, so look for importing from a CRM, a file, or another data source. Give the action a plain name such as
Won job. The name in every upload must match it exactly, including capitalization. - Set the value, count, and window
Choose to use a different value for each conversion, so the won amount comes through. Set the count to One, so a single ad click cannot be credited with several conversions. Set the click-through conversion window to cover the sales cycle, up to the maximum of 90 days.
- Start it as a secondary action
A secondary conversion action reports results without steering bidding. Keep it there until several uploads have gone through cleanly, then decide whether bidding should optimize toward it. That choice is covered in conversion goals.
- Wait before the first upload
Google asks you to wait four to six hours after creating a conversion action before uploading conversions to it.
Upload the wins
The file import uses a template with one row per won job. The first line sets the time zone, and the second holds the column headers.
Parameters:TimeZone=America/Chicago
Google Click ID,Conversion Name,Conversion Time,Conversion Value,Conversion Currency
EXAMPLE_CLICK_ID_FROM_THE_LEAD,Won job,2026-09-10 14:30:00,1200,USD
gclid from the lead record, exactly as captured.America/Chicago in the parameters line handles daylight saving time better than a fixed offset.USD.The template also has optional columns for an order ID and for consent signals. Download the current template from the account before you build an export around it.
The timing rules
- The conversion time has to fall inside the conversion action's window, counted from the click. Google keeps click IDs for 90 days, so a sale that closes later than that cannot be matched to its click. For long sales cycles, upload an earlier milestone that happens inside the window, such as a booked estimate, as its own conversion action.
- Clicks less than six hours old are rejected. Leave those rows for the next upload.
- The conversion time cannot be earlier than the click. A wrong time zone can make a same-day sale look like it happened before the click.
- Include an extra day of overlap in each upload, as Google recommends. A row already uploaded with the same click ID, conversion name, and conversion time is rejected as a duplicate, so the overlap is safe.
The routine
- Start with a manual upload on a fixed day
Once a week, export the won records that have a click ID and no uploaded date, plus the day of overlap. Build the file, upload it on the Uploads page in the conversions section of Google Ads, and read the results before you close the tab.
- Mark what went through
Put the upload date on every accepted record. Fix rejected rows at the source, in the CRM, so the same mistake does not come back next week.
- Schedule it once the data is clean
Google Ads can pull the file on a schedule from Google Sheets, HTTPS, or SFTP, so a CRM export that refreshes a sheet can feed the upload without anyone building a file by hand.
- Automate from the CRM when volume justifies it
Most CRMs can send a webhook when a deal moves to won. A small service receives it, looks up the stored click ID, and sends the conversion through the Google Ads API, which needs API access that Google has to approve. I automate only after the manual routine has run cleanly for a while, because a broken automation fails quietly, and a person reading the upload results each week does not.
The enhanced conversions for leads route
Enhanced conversions for leads matches on contact details instead of depending on the click ID alone. When a visitor submits a lead form, the Google tag sends a hashed copy of the email address or phone number they entered. When the job is won, you upload the same hashed value with the conversion, and Google matches the two on its side.
- Why it helps: it can still match a sale when the click ID never made it into the CRM, because the match runs on the contact details from the form.
- What it needs: enhanced conversions for leads turned on in the account's conversion settings, Google's customer data terms accepted, and the Google tag set up to capture the email or phone field on the lead form. Imports run through Google Ads Data Manager or the API.
- Formatting: contact details are normalized before hashing (email addresses lowercased with spaces trimmed, phone numbers in international E.164 format) and hashed with SHA-256. Follow Google's current rules exactly, and check whether your import tool hashes the data for you or expects it hashed already.
- Click IDs still matter: Google recommends including the
gclidwith each import whenever you have it, and requires it if no tag collects the hashed form data.
Verify it works
- Read the upload results
The Uploads page shows how many rows each upload accepted and why any were rejected.
- Check the diagnostics
Google Ads has an offline data diagnostics page for imports, and an enhanced conversions diagnostics report for the enhanced route. Check them after the first few uploads and whenever the numbers look off.
- Allow for processing time
Imported conversions usually process in under 12 hours, and conversions keyed to
gbraidorwbraidcan take up to 72. Do not judge an upload the same afternoon. - Reconcile against the CRM
For a closed month, compare the won records that had click IDs with the conversions recorded on the action. Use the conversion columns reported by conversion time, since the standard columns credit each conversion to the date of the click. A large gap means records are missing click IDs, or uploads are being rejected.
Common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Won records have no click ID | Auto-tagging is off, a redirect strips the query string, the cookie was never saved, or the form plugin drops hidden fields | Repeat the ?gclid=TEST123 test from landing page to CRM record and find the step where the value disappears. |
| Rows rejected as earlier than the click, or conversions on the wrong day | Times exported in UTC but uploaded as local time, or no time zone at all | Set the time zone line with a time zone ID, or include the offset in every conversion time. |
| Rows rejected as expired | The upload came too late, or the conversion window is shorter than the sales cycle | Upload on a fixed schedule, lengthen the window, or upload an earlier milestone for long cycles. |
| Rows rejected for an unknown conversion name | A spelling or capitalization mismatch, or the file went to a different account from the one that holds the action | Copy the name straight from the conversion action, and upload to the account that holds it. |
Google keeps its own list of import errors and fixes in Fix discrepancies and errors in offline conversion imports.
What's next
- Checklist: verify a tracking setup before you trust it: A phase-by-phase checklist for proving tracking works: tags on every page, single events, real test leads, source data in the CRM, consent, and ad platforms.
- Set up Consent Mode v2 and handle data deletion requests: pick a consent model that fits your audience, send Consent Mode v2 signals through Tag Manager, gate your own tags, and handle deletion requests.
- How marketing attribution works for a local business: the plain-language model behind tracking: how a call or form gets tied back to the ad, search, or post that started it, and where most setups lose the thread.
Rather have me do this for you?
I set up tracking that ties every call and form to the marketing that earned it, inside accounts you own, and report it in plain language.