How do you upload offline conversions to Google Ads from a clinic CRM?
Capture the Google click identifier on the landing page into a hidden form field, store it against the patient record in the CRM, write the treatment value onto that same record when the patient pays, then upload the click ID, conversion action name, timestamp and value back to Google Ads. Three constraints are specific to healthcare. Google Ads is not HIPAA compliant, so the payload may carry no patient name, plaintext email, condition or appointment type, and the conversion action name itself must be generic because it travels attached to an identifiable click. Google discards click identifiers after 90 days, and enhanced conversions for leads after 63, while patient journeys run 8 to 180 days, so the upload should target a milestone inside the window rather than final payment. Since 15 June 2026 these uploads run through the Data Manager API and are blocked in the Google Ads API.
Only about 1% of healthcare marketing teams can tie more than half their spend to patient outcomes. Offline conversion import is the mechanism that fixes that, and it is unglamorous plumbing rather than strategy: you take the treatment revenue sitting in your CRM and send it back to Google Ads, so the bidding algorithm optimises toward money instead of toward form fills.
This is step four of closing the attribution loop, and it is where most implementations stop being generic.
The general guides for this are written for ecommerce and B2B. Healthcare has three constraints none of them mention, and two of those will silently discard your data.
What the upload actually is
When someone clicks a Google ad, Google appends a GCLID, a Google Click Identifier, to the landing page URL. That string is the only thing connecting a later booking back to the advertising click.
Four steps, in order:
- Capture the GCLID on the landing page and write it into a hidden field on the enquiry form. If your form handler drops unknown fields, the chain breaks here, and it breaks silently.
- Store it against the patient record in the CRM, and keep it attached through the consultation, the follow-up and any reschedule. Not every system survives this; what to ask a CRM vendor covers how to test it before you buy.
- Write the treatment value onto the same record when the patient pays.
- Upload the click ID, conversion action, timestamp and value back to Google Ads.
Step three is the one almost everyone skips, and it is the only step that turns a lead into evidence. It is also why an ad platform reports more leads than a practice has patients.
The payload, and why it is a compliance surface
Google Ads is not HIPAA compliant and should be treated as a non-HIPAA third party. Protected health information must never reach it.
The upload may contain the click identifier, the conversion action name, the conversion date and time with timezone, and the conversion value and currency. It must not contain a patient name, a plaintext email address, a health condition, an appointment type, or any of the eighteen HIPAA identifiers in readable form.
Here is the part that gets missed. The conversion action name travels with the upload and is attached to one specific identifiable click. Name that action “Hair Transplant Consultation Booked” and you have told Google that the person behind that click is seeking hair restoration. The value field leaks the same way: a figure that maps to exactly one procedure is a diagnosis in disguise.
Name conversion actions generically. “Treatment Booked” and “Consultation Attended” are enough for the algorithm to optimise against. It does not need to know which treatment, and you are not permitted to tell it.
If you need per-service optimisation, separate campaigns by service line and let the campaign structure carry that information instead of the conversion payload.
The two deadlines
This is where healthcare breaks in a way ecommerce does not.
Google keeps a click identifier for 90 days. An offline conversion uploaded more than 90 days after the click will not be imported. It does not fail loudly. It simply never appears in your conversion statistics.
Enhanced conversions for leads, which uses hashed contact details instead of a click identifier, has a shorter window of 63 days. Teams often reach for it as the fallback when the click ID is lost, without noticing they have moved to a tighter deadline rather than a looser one.
Now set that against the healthcare buying cycle. Patient journeys run 8 to 180 days, against 1 to 7 for ecommerce. A meaningful share of your treatments will be paid for after the window has closed, which means the conversion Google needs in order to learn from it can never be delivered.
The fix is to upload an earlier event rather than the final one. Choose a milestone that reliably happens inside 90 days and correlates with revenue. For most practices that is consultation attended, sometimes deposit paid. Upload that as the optimisation signal, valued at the average treatment revenue that milestone historically produces. You still report actual revenue internally. Google gets a proxy it can act on in time.
That is a genuine tradeoff and worth stating plainly: you are handing the algorithm a slightly blunter signal in exchange for it arriving at all.
The deadline most guides have not caught up with
Since 15 June 2026, offline conversion imports and enhanced conversions for leads have migrated to the Data Manager API, and these uploads are blocked in the Google Ads API.
Almost every setup guide published before mid-2026 tells you to build against the Google Ads API. If your developer follows one, the integration will fail. If you already had an automated upload running through the old endpoint, check whether it is still delivering, because a job that quietly stopped posting looks identical to a month with no conversions.
Manual and scheduled uploads through the Google Ads interface still work. This affects anything automated.
Two healthcare-specific decisions nobody makes for you
Phone calls. Between 40 and 60% of healthcare conversions happen by phone rather than through a web form. A click ID captured only on a form therefore misses the majority of bookings. Call tracking has to carry the identifier into the call record, or the upload only ever covers the smaller half of your enquiries.
No-shows. Somewhere between 15 and 30% of scheduled appointments do not happen. Upload on booking and you are training the algorithm on appointments that never occurred, after which it gets efficient at finding people who book and do not attend. Upload on attendance instead, or upload on booking and send a negative adjustment when the appointment is missed. Either works. Doing neither means paying to acquire no-shows more effectively every month.
Before any of this works: auto-tagging
Google only appends a click identifier if auto-tagging is enabled on the Google Ads account. It sits under Account settings, and it is off in a surprising number of accounts that have been running for years, usually because someone disabled it long ago to keep URLs clean for a legacy analytics setup.
With auto-tagging off there is no identifier to capture, no matter how well the rest of the chain is built. Check this first. It takes ten seconds and it invalidates everything downstream.
What the file looks like
The conversion action has to exist before you can upload against it. In Google Ads, create a conversion action under Goals, choosing Import and then the option for tracking conversions from clicks rather than from a website tag. Until that exists, every row you upload is rejected.
The upload itself is five columns:
| Column | Example |
|---|---|
| Google Click ID | Cj0KCQjw... |
| Conversion Name | Consultation Attended |
| Conversion Time | 2026-08-25 14:30:00+04:00 |
| Conversion Value | 4500 |
| Conversion Currency | AED |
The timestamp is where most first attempts fail. It needs a timezone offset, and the conversion time must be after the click time. A record exported without timezone information, or exported in a spreadsheet that has quietly reformatted the column as a date, will be rejected.
Why rows get rejected
Uploads report errors rather than silently succeeding, but nobody reads the report unless something looks wrong. The recurring causes, roughly in order:
- The click is older than 90 days. Covered above, and the most common cause once a system has been running for a while.
- Conversion time precedes click time. Usually a timezone problem rather than a real ordering problem.
- The conversion action is not configured for imports. A tag-based action will not accept uploaded rows.
- The click identifier was never captured. Auto-tagging off, or a form handler that dropped the hidden field.
- Formatting. Truncated identifiers are almost always a spreadsheet issue, since long strings get mangled on export.
Set a monthly reminder to read the error report. A rejection rate that climbs from 2% to 30% is a broken form field somewhere, and it will not announce itself anywhere else.
How to tell it is actually working
Three checks, in order of how quickly they answer:
- Rows accepted. Upload, then confirm the count that landed matches the count you sent. Do this on the first upload and after any change to the form or CRM.
- Conversions appearing against campaigns. Within a day or two the imported conversions should attach to specific campaigns and keywords. If they land but attach to nothing, the identifier is arriving without a matching click.
- Cost per booked treatment moving. The one that matters, and the slowest. Compare it against cost per lead over the same period. The two should start to diverge.
If the first two pass and the third does not move after six weeks, the plumbing is correct and the problem is elsewhere, which is a useful thing to have established.
What changes afterwards
Expect cost per lead to rise and cost per booked treatment to fall. That is the trade, and it surprises people who have reported on cost per lead for years. The algorithm stops chasing cheap form fills and starts finding people who resemble those who paid, and those people cost more to reach.
Allow four to six weeks of consistent uploads before judging it. Smart Bidding needs volume before the new signal outweighs the old one, and a fortnight of data tells you nothing except that the numbers moved.
The work itself is a form handler change, a CRM field, an export and a scheduled upload. A few days of engineering, not a campaign. Which is precisely why it does not get done: nobody is hired to build it, and it stays invisible until someone asks which spend produced which patient.
Show us where the revenue stops.
Thirty minutes, your real numbers, an honest read on which layer is costing you most.