All posts
Performance Ads

Google Ads Conversion Adjustments for No-Show Appointments

A Google Ads conversion adjustment for a no-show or canceled appointment retracts it, fixes your report, and often reaches the bidder too late to matter.

September 6, 2026·16 min read·by Olexander Cheberko
Table of contentstap to expand

Seven days. That is the whole window in which a Google Ads conversion adjustment can still change what Smart Bidding believes, and in an appointment funnel the no-show is usually confirmed after it has closed. The adjustment still works past that line, but it has stopped being a bidding correction and become a bookkeeping one, and nobody selling retraction automation says which of the two you are buying.

Here is the runbook for taking a conversion back: the two operations, the clock they run on, and the nightly job I would write instead of a status webhook. Reviewed September 6, 2026 against Google's adjustment documentation and the Ads API reference; every threshold below is a number Google controls.

Quick answer

Point on the clockWhat is true then
T+0The conversion is uploaded and starts teaching Smart Bidding
T+4 to 6 hoursA new conversion action becomes adjustable. Sooner returns TOO_RECENT_CONVERSION_ACTION
T+24 hoursEarliest Google recommends adjusting a conversion
T+7 daysAutobidding stops reading adjustments. Past here you correct reports only
T+54 daysReporting stops accepting adjustments. The number is permanent
A retraction landsThat conversion accepts no further adjustment, silently

Two operations run on that clock. RESTATE changes a conversion's value and leaves the count alone. RETRACT removes it and zeroes the value, which is what a no-show earns. Filing either is cheap, and the expensive decision sits one step earlier, in the design of offline conversion tracking for a practice: which stage of the appointment fires a conversion at all.

What is the difference between retracting a conversion and restating its value?

A restatement corrects a number. A retraction corrects a fact.

Restate when the conversion happened and its value turned out wrong: a deposit partly refunded, a plan downgraded at the chair, a billed amount that posts under the estimate. The count does not move. Which number belongs there is not this article's question, because what value to send already answers it.

Retract when the event you reported did not happen, and a booked appointment that becomes a no-show is exactly that. One constraint covers both: adjustments are accepted only on conversion actions of type SALESFORCE, UPLOAD_CLICKS or WEBPAGE, and anything else returns INVALID_CONVERSION_ACTION_TYPE on every retry.

How do I file the adjustment, and what has to match the original conversion?

The adjustment is a separate call from the upload, and it finds the original row one of two ways. If the conversion carried an order id, that order id is required, and for a web page action it is required outright. Otherwise the identity is the gclid plus the original conversion time, which is fragile: reproduce that timestamp wrong and the adjustment matches nothing, quietly. That is why I put an order id on every conversion I upload. How the upload works in 2026 covers the ingest path.

{
  "conversionAdjustments": [
    {
      "conversionAction": "customers/1234567890/conversionActions/9876543210",
      "adjustmentType": "RETRACTION",
      "orderId": "8f41c0b6d92e7a35",
      "adjustmentDateTime": "2026-09-06 21:40:00-04:00"
    }
  ],
  "partialFailure": true
}

No value field on a retraction, by definition, and a restatement is the same envelope with a value on it. That payload is also the whole vocabulary of an adjustment, which is why the cancellation reason never travels: an appointment type, a procedure code, a status of "canceled, symptomatic" are clinical context with no field to hold them. Only an anonymous click id, a value and a timestamp ever leave the system, no patient record is persisted, and the order id is a salted hash of the booking id rather than the EHR's appointment number, so nothing in the payload is a handle back into a clinical record.

That salt has a consequence most build guides skip. The order id lives on Google's side as a durable join key for the full 54 days, so rotating inside that window costs you the order ids of conversions you may still need to correct. Rotate outside 54 days. Engineering posture, not legal advice.

Why does an adjustment that fixes your report do nothing for your bidding?

Because reporting and bidding read the same adjustment on two different clocks.

An adjustment filed more than 7 days after the conversion was recorded is ignored by autobidding, while reporting keeps accepting adjustments to 54 days. Both numbers are published, they are not the same number, and the gap between them is where every "we file your retractions automatically" pitch lives. You will also meet a 55 day figure scoped to Hotel Ads, and build guides that say 60. Design to the smallest published number, never to a blog's, including this one.

A retraction reaches the bidder only if your median booking-to-visit gap plus your reconciliation lag is 7 days or less. Consults that book 11 days out, reconciled nightly, land at day 12: inside reporting, five days past bidding. The report gets fixed. The bidder spent twelve days learning from a booking that never became a patient, and it keeps that lesson.

Walk 100 bookings through both timelines and see what the bidder learns

One invented practice, one month, three campaigns, 100 booked appointments from paid search.

CampaignBookingsMedian gapAttendedShow rateSpendCost per bookingCost per attended visit
brand-exact243 days2188%$2,100$87.50$100.00
implant-consult-exact4611 days3065%$6,800$147.83$226.67
cosmetic-broad3019 days1447%$3,500$116.67$250.00
All three10011 days6565%$12,400$124.00$190.77

Illustrative: synthetic figures, proportions typical.

The inversion in the last two columns is the hub's argument, so I will not re-run it: cosmetic-broad wins on cost per booking at $116.67 and loses on cost per attended visit at $250.00, which is the case for uploading the attended visit instead of the booking. What the hub does not price is what a retraction repairs after the budget has already moved.

So price it. Move $2,060 into cosmetic-broad on the booked-stage number and you buy 17.7 bookings at a 47 percent show rate, so 8.3 attended visits at $248 each. The same $2,060 into brand-exact buys 23.5 bookings at an 88 percent show rate, so 20.6 attended visits at $100 each. Same money, 12 fewer patients in the chair, and the retraction that would have exposed it arrives after the reallocation is already spending.

Design A: upload at booked, retract laterDesign B: upload on attended
Conversions the bidder sees in month 110065
Cost per conversion it optimizes toward$124.00$190.77
Cheapest campaign in its viewcosmetic-broad, $116.67brand-exact, $100.00
Retractions filed350
Retractions inside the 7 day window3 of 35 (8.6%)not applicable
Spend behind a signal no correction reaches$10,300 of $12,400 (83%)$0
What the bidder believes at day 54the day-1 population, minus 3 rowsthe attended population

Illustrative: the same synthetic cohort, run through both designs.

Both designs end the month with an accurate report, and only one spent the month bidding on an accurate population. Now split those 35 retractions by campaign, where the argument turns from lag to direction.

CampaignBookings that never became visitsAge of the conversion when the retraction landsRetractions the bidder reads
brand-exact34 days3
implant-consult-exact1612 days0
cosmetic-broad1620 days0
All three353

Illustrative: the same synthetic cohort, split by campaign.

Read the last column again. Every retraction that reaches Smart Bidding is filed against brand-exact, the campaign with an 88 percent show rate and the lowest cost per attended visit, while the 32 that would have corrected the campaigns actually producing no-shows land after the bidder has stopped listening. The correction does not merely arrive late, it runs backwards: it subtracts from your healthiest campaign and leaves the unhealthy ones as attractive as they looked on day one. Short-gap campaigns are the ones whose retractions arrive in time and also the ones least likely to need retracting, which is why the conversion stage is the first thing I settle on a patient conversion tracking build.

A retraction pipeline also adds one query, one idempotency table, one irreversible operation and one silent failure mode, all four there to undo something, which is why I fire on arrived rather than booked whenever the source system can tell me arrival.

Are a no-show, a cancellation, and a refunded deposit the same event?

One adjustment, three diagnostics, and one of the three is not a retraction. A no-show and a cancellation both retract a booked-stage conversion that never became a visit. A refunded deposit is different, because the visit may have happened: a full refund retracts, a partial refund restates.

A cancellation six days out is a scheduling signal while a no-show is a demand-quality signal, so collapsing them into one row throws away the only diagnostic the retraction gives you for free.

The trap underneath is that EHR and practice management status vocabularies are not two-valued. Canceled by patient, canceled by office, rescheduled, bumped, no-show and left without being seen are separate codes, a webhook on "status changed" fires on all of them, and a mapping that treats every non-attended code as a retraction will retract appointments the office moved for its own convenience.

What breaks when a patient reschedules instead of canceling?

A front desk marks an appointment canceled at 10:40 in the morning. A status webhook fires, the retraction goes out inline, and at 3 in the afternoon the patient moves to next Tuesday, where she attends. That conversion is now retracted and accepts no further adjustment. No error, no row in a failure log. Nothing tells you.

Recovery exists and it is lossy. Google documents an un-retract path: re-upload the outcome as a new event with a new unique order id, since the same one reads as a duplicate, and a shifted timestamp that is no longer the date anything happened. It also silently requires a conversion action set to count every conversion, which rules it out for the one-conversion-per-click setting most lead-gen practices run, and the row's age has usually passed the 7 day line anyway. Getting a retracted conversion back is conditional, expensive and often unavailable to you.

Status flips to cancelled or no-show
in the schedule
Has it been terminal for a full calendar day?
no, still today
Hold
nothing leaves tonight, re-check tomorrow
yes
Is there a newer live appointment on the same booking key?
yes, a reschedule
Keep it
the outcome rides on the new date
no
Did this conversion fire at the booked stage?
no, on attended
Nothing to take back
the cheaper design
yes
Queue a retraction
keyed on order id
Most of the work is deciding whether there is anything to take back at all. Two of the four paths end without an upload, which is the cheaper design arguing for itself.

Once a retraction is queued, how much good it does depends entirely on how old the conversion is when it lands.

Age of the conversionReportingBiddingPractical meaning
Under 7 dayscorrectedcorrectedThe only window where a retraction fully pays for itself
7 to 54 dayscorrectednot readYour report gets honest, the bidder already learned the wrong thing
Over 54 daysignoredignoredThe number stays wrong. Design so this window is unreachable

After a retraction lands it is a one-way door: no further adjustment is accepted on that conversion, so a retraction sent in error cannot be undone by sending another one.

Build the nightly pass, and run the retractions last

I have run these uploads both ways, out of a warehouse and out of a flat scheduled job, and the ordering came out identical: new conversions first, restatements second, retractions last, once a day, after the schedule closes. That order is a property of the operations rather than tidiness, because a retraction is the only one that cannot be replayed and so has to be the job's last decision. A busy front desk can move one appointment through three or four statuses between morning and close, and a webhook fires on every one of them, which is why the job reads the day's final status instead.

  1. Snapshot the day's final statuses after the schedule closes. Once, not on every status change.
  2. Emit attended-stage conversions for visits that completed today.
  3. Emit restatements for conversions whose value changed.
  4. Only now, emit retractions, each gated on the two conditions in the query below.
  5. Stamp retracted_at on every row you sent, so a failed re-run cannot spend a second adjustment on the same conversion.
  6. Write the in-window percentage to a monitoring table.
-- Nightly selection: terminal for a full day, and not quietly rescheduled.
SELECT a.order_id,
       a.conversion_action,
       a.conversion_time
FROM   attribution a
JOIN   appointments p ON p.booking_key = a.booking_key
WHERE  p.status IN ('no_show', 'canceled')
  AND  p.status_changed_at < DATE_TRUNC('day', CURRENT_TIMESTAMP)
  AND  NOT EXISTS (
         SELECT 1
         FROM   appointments r
         WHERE  r.booking_key = p.booking_key
           AND  r.created_at  > p.status_changed_at
           AND  r.status NOT IN ('no_show', 'canceled')
       )
  AND  a.uploaded_at  IS NOT NULL
  AND  a.retracted_at IS NULL;

Both guards live in the WHERE clause rather than in application code on purpose: the select that picks rows to retract and the update that stamps them run in one transaction, so no status flips between the read and the write. I key the adjustment on a salted hash of the booking id, the value the original upload carried, because a row id the job generates for itself does not survive a backfill.

A pipeline that can only add conversions is half a pipeline, so when I build patient conversion tracking this pass sits in the same estimate as the upload. It is not in every build, and the difference is the decision this article is about: the offline loop in that case study fires on arrived and restates when billing posts, which is why it files no retractions at all. The nightly pass is the version you need when a booked-stage action already exists and someone is bidding on it today.

How do I measure adjustment lag as a number of its own?

Retraction count is the number a vendor reports, and it measures activity rather than effect. What matters is how many landed where the bidder could still read them.

SELECT DATE_TRUNC('week', conversion_time) AS wk,
       COUNT(*) AS retractions,
       COUNTIF(DATE_DIFF(retracted_at, conversion_time, DAY) <= 7) AS in_bidding_window,
       ROUND(100 * COUNTIF(DATE_DIFF(retracted_at, conversion_time, DAY) <= 7)
             / COUNT(*), 1) AS pct_readable
FROM   attribution
WHERE  retracted_at IS NOT NULL
GROUP BY wk
ORDER BY wk;

Chart pct_readable, not retractions. If that line sits in single digits for a quarter, you have built a bookkeeping machine and you should say so to whoever pays for it. It may still be worth running, because a report that reconciles to the practice ledger has real value, but that is not what the automation was sold as. Group it by campaign too: a pipeline whose readable retractions all belong to one healthy campaign is taxing your account, not correcting it.

Which cancellations deserve an adjustment, and which are churn you should leave alone?

Compute four gates on your own data before you write a line of the job. The cohort above is the worked example, not the answer.

GateCompute it fromWhat the outcome means
1. Median booking-to-visit gap90 days of schedule history6 days or less, the retraction plus one reconciliation day lands inside the bidding window. 7 days or more, it is a reporting operation, so stop designing around it
2. In-window shareNo-shows whose gap plus one reconciliation day is 7 days or lessBelow 30 percent, build it only to reconcile the report to the practice ledger. The cohort scores 3 of 35, or 8.6 percent
3. No-show plus cancellation rateNon-attended over booked appointmentsUnder 10 percent, the booked-stage action is a decent proxy. 10 to 25 percent, fire on attended and keep the booked action observation-only. Above 25 percent, it must never carry bidding
4. Can a terminal status go live again?Ask the source system, not the vendorIf yes, webhook-triggered retraction is off the table at any volume, because one reschedule becomes an unrecoverable row. This gate overrides the rest

There is a case where the industry default is right. If the gap between booking and service is measured in hours rather than days, the retraction lands on day 0 or day 1, both the report and the bidder get corrected, and the pipeline is the right design: a walk-in urgent care slot, a same-day add-on, a deposit refunded that afternoon. Ecommerce returns are the other clean case, with the caveat that a 30 day return window has the same disease as an 11 day booking gap. The dividing line is not the industry. It is the distance between the conversion and the truth.

Everything here is arithmetic you can redo with your own numbers, and I would rather you redo it than trust mine, because the single number deciding whether a retraction pipeline is worth building is your median gap from booking to visit. Ninety days of schedule history gives it to you in an afternoon.

So compute it, then send me that number and the share of your bookings that never become visits, and I will tell you which of the two operations you would be buying. On a gap like the 11 days in the cohort above the answer is bookkeeping, and the build worth paying for is the one that never has to file a retraction.

Tags

google ads conversion adjustmentno-show appointmentsoffline conversionsretractionsmart bidding

Frequently asked questions

Can you undo a conversion you already uploaded to Google Ads?

You can retract it, which removes it from your conversion columns and sets its value to zero. Undoing that retraction is a different problem: the documented path is to re-upload the outcome as a new event with a new unique order id and a shifted timestamp, and it only works if the conversion action is counting every conversion. Treat a retraction as a one-way door and you will design the job correctly.

How late can I adjust a conversion and still have it change anything?

After 7 days from when the conversion was first recorded, autobidding ignores the adjustment, so you are correcting reports and nothing else. Reporting stays adjustable up to 54 days, and Google also recommends waiting at least 24 hours after the original conversion before you upload an adjustment. If you see 60 days quoted in a build guide, design to the smaller published number.

Does retracting a conversion hurt the campaign that originally earned it?

It removes that conversion from the totals for the day it was originally recorded, so the campaign's historical cost per conversion gets worse and its real cost per attended visit gets honest. There is no separate penalty beyond that. Inside 7 days the retraction also stops that row from teaching Smart Bidding; after 7 days it is bookkeeping.

What do I do when a no-show reschedules and then actually shows up?

Do not retract on the cancellation in the first place. Hold every terminal status for a full calendar day and check for a newer live appointment on the same booking key before anything leaves your system, and if it was a reschedule, keep the conversion and let the outcome ride on the new date. If you already retracted it, that conversion accepts no further adjustment and your only route back is a fresh event with a new order id and a timestamp that is no longer the truth.

Do I need an order ID to retract an offline conversion, or is the gclid enough?

You need the order id whenever the original conversion carried one, and for a web page conversion action it is required outright. Otherwise the gclid plus the original conversion time identifies the row. I put an order id on every conversion I upload for exactly this reason: it is the only stable handle you get for reaching that row again later.

Should a cancellation and a no-show be treated the same way in reporting?

They are the same adjustment and two different diagnostics. Both retract a booked-stage conversion that never became a visit, but a cancellation six days out is a scheduling signal while a no-show is a demand-quality signal, and a campaign whose bookings cancel early is not the same problem as one whose bookings evaporate on the morning. Keep the reason inside your own system and never send it to Google.

Need something like this built?

Free 15-min discovery call. I'll listen, ask honest questions, and tell you if I can help.

More in Performance Ads