MindSwarm
Case study

When the ad platform can't see the sale

Sergej June 15, 2026 ~9 min read

A small rental business was spending about €15 a day on Google Ads. Two campaigns, roughly 4,200 ad impressions and 99 clicks on a normal day. The platform's conversion column read zero. Not low — zero. And yet bookings kept arriving: the summer calendar was steadily filling. By the platform's own numbers the advertising was pure waste. By the bank account it clearly was not. Both could not be true, and the gap between them is the entire story.

This is a case study from MindSwarm's own proving ground — visaginasapartments.com, a three-apartment, owner-operated rental in Lithuania that I run as a live testbed before any method is offered to a client. It is small on purpose. The point is that the failure it exposed is not small at all: it is the exact failure that sinks enterprise AI projects, reproduced at a scale where you can see every moving part.

Why the sale was invisible

The booking does not happen on the website. A guest clicks an ad, lands on the site, reads, and then leaves to complete the reservation on Booking.com — a separate platform the ad system has no visibility into. From Google's point of view the customer journey ends at the outbound click. Everything that matters after that — the reservation, the price, the cancellation, the repeat stay — happens in a system it cannot see.

So the algorithm optimizes on what it can measure: clicks. It cheerfully buys the cheapest clicks it can find, learns nothing about which of them became guests, and reports a conversion count of zero because no sale was ever fed back to it. The business was not buying guests. It was buying clicks that looked like activity, while the actual revenue signal lived in a Booking.com confirmation email that the ad platform would never read.

The core problem: the system was being optimized against the wrong number, not because the number was wrong, but because the right number was somewhere the optimizer could not reach.

The last mile, in miniature

This is the enterprise "last mile" problem at the scale of three apartments. The model — Google's bidding AI — is excellent. The failure is everywhere around it: data fragmented across four systems that were never designed to talk to each other (the website, the ad platform, the booking platform's email, and a spreadsheet), and a real-world constraint no benchmark captures — the sale closes on someone else's platform.

No better model fixes this. You can swap in the smartest bidding algorithm in the world and it will still optimize on clicks, because clicks are still the only thing it can see. The fix is not a model. The fix is plumbing: a loop that carries the real outcome back to the place where the decision is made.

The loop we had to build

The goal was a closed attribution loop — the ad platform retrained on real reservations instead of raw clicks. The shape is simple to draw and unforgiving to build:

guest clicks ad ──► site (captures gclid) │ ▼ click on "Book" → outbound to Booking.com click logger (React → Apps Script → ClickLog sheet) │ ▼ reservation confirmed on Booking.com booking email → matcher (gclid ↔ reservation, 48 h window) │ ▼ offline conversion upload Google Ads ──► algorithm now learns on revenue, not clicks

When a guest arrives from an ad, the click carries a tracking identifier (the gclid). The site captures it and logs the outbound click to a sheet. When a real reservation later lands in the Booking.com email, a matcher ties that reservation back to the click within a 48-hour window, and the confirmed booking is uploaded back to Google Ads as an offline conversion. Now — and only now — the bidding AI is learning from money instead of from motion.

What actually broke (the honest part)

Drawing the loop took an afternoon. Making it true took far longer, because every component failed in a way that looked like success. This is the part that does not appear in a strategy deck, and it is the part that is the actual job.

1,937 silent failures

The piece that writes bookings into the CRM is a Google Apps Script. Its OAuth permissions had never actually been granted — the consent screen for a time-driven trigger silently never appeared. For eighteen days the script ran on schedule, reported success, and did nothing: roughly 1,937 executions that all "passed" while writing zero rows. Nothing alerted, because from the outside everything was green. A failure that announces itself is cheap; a failure that reports success is the expensive kind, and it is the kind automation produces by default.

A trigger that could never fire

The original conversion was configured to fire on a page load whose URL could never load — the trigger pointed at an address that did not exist in the user's journey. In the dashboard it looked perfectly configured: named, enabled, green. It had simply never fired, and would never fire, and the only way to know was to trace the actual path a real user takes rather than trust the configuration screen.

The thing you must not "clean up"

Audits create a temptation to tidy. One conversion goal looked misconfigured and orphaned — the obvious move was to delete it. It was quietly producing 56 conversions a month of genuine engagement signal. Deleting it would have been the clean-looking decision and the wrong one. Equally, the website showed €50 and Booking showed €138, which read like a pricing bug; it was not — it was base price plus 9% VAT plus the platform's 15% commission. Knowing what not to touch is half of the work, and it is the half a model cannot do for you, because it requires standing inside the business and understanding why each strange thing is there.

After the fix: web conversions came back to life — ten real conversions in the first seven days — and, more importantly, the bidding algorithm finally had a revenue signal to learn from instead of a click count to chase.

Why this is the job

Notice that none of the hard parts were the model. They were the glue between systems, the failures that disguise themselves as success, and the judgment about which strange-looking thing is load-bearing. That is the forward-deployed last mile, and it is exactly where AI projects die — 88% of pilots never reach production, almost always in the integration, never in the model. The work is not "add AI." The work is to make the real outcome visible to the system that makes the decisions, in production, against the actual mess.

A three-apartment rental and a large enterprise have the same shape of problem: the model is a commodity, the data is fragmented, the sale closes somewhere the optimizer cannot see, and the failures are quiet. The difference is only how many zeros are attached. Solving it small first is the point of a proving ground — the loop runs on my own business, with my own money on the line, before it is ever proposed to anyone else.

MindSwarm is Sergej's independent Forward Deployed AI Engineering practice. The method is the one in this story: embed close enough to the real work to find the silent failures, own the integration end to end, measure truth instead of motion, and hand back a loop the team can run without you. If your dashboards are green and your results are not, that gap is the work — and it is the work I do.

Green dashboards, flat results?

The gap, the method, and the 90-day model — in one brief.

Read the brief →