How tour operators can track the real bookings their Google Ads create
Google Ads cannot see every sale your website makes. In tourism the gap is big enough to change your decisions. This guide shows why the gap exists, how to measure it in an afternoon, and how to build a one-page dashboard that puts your ad spend next to your real bookings.
I have been running ads for tour companies for the past five years, and the same thing comes up in almost every account. What the ad account reports and what actually landed in the booking system are two different numbers. Bokun, Rezdy, Ventrata and the others have all been working on this, and it has improved. There is still a big difference.
Here is what that looks like in a real account.
A tour operator in London whose ads I run showed a 0.89x return over three months. Anything under 1.0 means the ads cost more than they brought back. On that number you would pause the campaign and move the budget somewhere else.
The real return was 1.88x. I know that because I went into the booking system and pulled every booking that came through the website in those three months. Then I put that total next to the same ad spend. The conversion tag had only caught about 47% of it. The other bookings came through the same website, got paid for, and never reached Google Ads.
If I had believed Google Ads, I would have switched off ads that were making money. You cannot see this from inside Google Ads, and it costs operators money every month.
Why Google Ads misses sales your website actually made
For Google Ads to count a sale, two things have to work. A conversion tag has to fire when the booking completes, and Google has to be able to connect that booking back to a paid click. In tourism both halves break more often than people expect.
The main reason is where the payment happens. Most operators sell through a booking system like Bokun, Rezdy, Ventrata or FareHarbor. A customer clicks your ad, lands on your website, and then gets handed over to that system to pay. That checkout often sits on a different domain to your website.
Google recognises a paid click by a tag it adds to your link, called the gclid. When the visitor crosses to another domain, or declines cookies on your consent banner, that gclid can get lost on the way. The booking still completes. The money still arrives in your account. Google just never records that an ad caused it.
This is the part the booking systems have been working on. It still breaks often enough that you cannot assume yours is working.
Here is the rest of what I keep finding in real accounts.
- A booking engine that was never wired to the conversion tag at all
- Started checkouts counted as sales, so your conversion number looks far higher than the real one
- Bookings that complete days after the click, once you have stopped checking that week's numbers
Your business also takes bookings by phone, by email, and at the meeting point. A tag on your website cannot count any of those.
Step 1. Get the two numbers out
Two sources feed everything that follows. Google Ads on one side, your booking system on the other.
For Google Ads, do not start with the API. Start with a Google Ads Script. It runs inside your own account, so there are no credentials to set up and nothing to reconnect when access expires. You paste it in once and it writes to a Google Sheet on whatever schedule you set.
Here is one that pulls everything the dashboard needs, including ROAS and cost per conversion.
// Google Ads Script - exports campaign performance to a Google Sheet.
// Google Ads > Tools > Scripts > + New script. Paste this in,
// put your Sheet URL below, click Preview, then Run.
var SHEET_URL = 'PASTE_YOUR_GOOGLE_SHEET_URL_HERE';
var PERIOD = 'LAST_30_DAYS'; // or LAST_MONTH, THIS_MONTH
function main() {
var sheet = SpreadsheetApp.openByUrl(SHEET_URL).getSheets()[0];
sheet.clear();
sheet.appendRow(['Campaign', 'Cost', 'Clicks', 'Conversions',
'Conv. value', 'ROAS', 'Cost / conv.']);
var query =
'SELECT campaign.name, metrics.cost_micros, metrics.clicks, ' +
'metrics.conversions, metrics.conversions_value ' +
'FROM campaign WHERE segments.date DURING ' + PERIOD;
var rows = AdsApp.search(query);
while (rows.hasNext()) {
var r = rows.next();
var cost = r.metrics.costMicros / 1000000;
var conv = r.metrics.conversions;
var value = r.metrics.conversionsValue;
sheet.appendRow([
r.campaign.name,
cost.toFixed(2),
r.metrics.clicks,
conv,
value.toFixed(2),
cost > 0 ? (value / cost).toFixed(2) : 0,
conv > 0 ? (cost / conv).toFixed(2) : 0
]);
}
}
The API is the better long-term answer. It gives you far more fields, and it can push changes back into the account instead of only reading. It also needs a developer token, credentials, and reauthorising when the access expires. Get the script running first.
On the booking side, Bokun, FareHarbor, Ventrata and Rezdy all have an API, and all of them can also export a CSV. Start with the export. You need six fields from it: booking date, tour date, product name, channel, status and revenue.
A monthly export works the first time. Then someone forgets. Or exports the wrong date range. Or pastes a column one cell off. After a few months of that, the page is showing you numbers that are wrong. Once the numbers look right, set the script to run weekly and ask your booking provider about API access.
Step 2. Decide the one question you are answering
The dashboard has one job. You are paying Google to sell certain tours. The dashboard tells you whether those tours are selling more than before.
Sales move up and down with the season anyway, so a rise on its own does not tell you much. Here is what to compare it against.
- The same months last year. If you normally grow 20% in June and this June you grew 60%, something else is going on
- How big the jump is. A normal summer rise and a rise that arrived with the ads do not look the same
- A tour that barely sold before. If you start advertising it and bookings start coming in, that is about as clear as this gets
At one account the advertised tours went up while the rentals, which had no ads on them, stayed flat. That made it easy to read. Most operators advertise everything they sell, so they have no control product. Use the first two comparisons instead.
Pick which of those three comparisons you are using before you open the data.
Step 3. Build the dashboard with four prompts
Four panels, and every one of them serves that single question.
Panel one is two numbers side by side. On the left, the return Google Ads reports. On the right, the same spend measured against direct website revenue from the booking system. Underneath, one line: how much of the real direct revenue the tag caught.
Panel two is the before and after. Direct sales for the advertised products in the period before ads, against the period after. Next to it, the same comparison for the control product. Percentage change sits under each, so you can compare them without doing any maths.
Panel three splits every booking in the period by channel, with each channel's share. It says in plain text that only the direct website line counts against ad spend.
Panel four is a table of direct sales by product, this period against last, with the change. That table shows which tours sold more and which sold less.
Two small things to do every time. Put the currency on every number and the date range at the top of the page. If something on the page is an estimate rather than a real figure, say so right next to it. In three months you will not remember which numbers were real and which ones you guessed.
Here are the four prompts I used. Paste them in order into Claude or ChatGPT. Attach your two exports at prompt three. Prompt three is the one that builds the file.
I run a tour business. I want one dashboard that answers a single question:
did my Google Ads increase my direct website sales?
I have two data sources:
- A Google Ads export: date, campaign, cost, clicks, conversions,
conversion value, ROAS, cost per conversion.
- A booking system export: booking date, tour date, product name, channel,
status, revenue.
Before building anything, tell me what you need from each file, what you would
put on the dashboard to answer that one question, and what you would leave off.
Ask me anything that is ambiguous.
Now set the rules for what counts, and show them to me before you apply them.
- Which booking channels count as a direct website sale.
- Which products my ads actually promote, and which get excluded.
- What happens to cancelled, refunded and test bookings.
- Whether we count by booking date or tour date, and why.
- Which products can act as a control because no ads run on them.
List every rule as a line I can approve or change.
Build the dashboard as one self-contained HTML file. No external libraries.
It must open in a browser by double-clicking it.
Four sections, in this order:
1. Two numbers side by side: the return reported in Google Ads, and the return
measured from direct website booking revenue over the same period and the
same spend. Under them, one line stating what share of real direct sales the
tag captured.
2. Direct sales for the advertised products in the period before ads against the
period after, next to the same comparison for a control product with no ads.
Show the percentage change under each.
3. Every booking in the period split by channel, with each channel's share.
State clearly that only the direct website line counts against ad spend.
4. A table of direct sales by product, this period against last, with the change.
Label every figure with its currency. Put the date range in the header. If any
number is estimated or illustrative, say so on the page itself.
Tell me which products the ads ran on and when they started. Do not infer it
from the data.
Before I trust this, audit it.
- Does the product table sum to the direct website channel total?
- Are cancelled and test bookings excluded everywhere, including the totals?
- Is anything double counted, for example a booking counted in two channels?
- Does the return I calculated match spend and revenue for the same date range?
- Which single number here is most likely to be wrong, and why?
Show me the arithmetic for each check.
The output of prompt three is one HTML file. You double-click it and it opens in a browser. There is no server, no login and no monthly fee attached to it. If you would rather work from a finished template than start cold, message me and I will send you mine.
How to read it
Panel one tells you whether your tracking is broken. It does not tell you whether the ads work. A wide gap between reported and real does not mean your campaigns are good. It means your measurement is broken. Fix the tag first, then judge the campaigns.
Panel two is the budget decision. If the advertised products go up while the control stays flat or falls, the ads are working. If both go up together, it is probably just the season. Neither result is enough on its own to justify doubling the budget.
Panel three stops you counting walk-ins and OTA bookings against your ad spend. Walk-ins and OTA bookings matter to the business, and they belong on the page as context. They do not belong inside the calculation against ad spend.
Panel four tells you which tour to look at next. A tour with live spend and no direct sales is an availability problem, a landing page problem, or a targeting problem. Start with the tour that dropped most, and check its availability and its landing page. Usually one tour is responsible for most of the drop.
Read them in that order: tracking, then sales change, then booking channels, then tours.
What this will not do
Five things it will not do for you.
It only measures direct website sales. Your ads also push people towards your OTA listings and towards picking up the phone. That lift is real, and none of it shows up on this page. I wrote about how to see and measure it in the OTA lift guide.
A rise after launch is not proof that the ads caused it. A mention in a guidebook, a hot week, a competitor selling out of their slots: any of those moves the same numbers. Treat a good result as a strong sign and keep checking it next month.
You have to decide this one yourself. What counts as a direct website booking depends on how your booking system fills that field. Nobody else can decide that for you. Decide the rule, write it down, and apply the same one every month.
It goes stale. Add a product, change your checkout, or move booking systems, and the rules from prompt two no longer match how you sell. Re-read the rules from prompt two every quarter. Correct the ones that no longer hold.
And it does not fix your tracking. Fixing the tag is still the first job on the list. This dashboard shows you how much the tag is missing. Fixing the tag is a separate job.
Common questions
Why does Google Ads show fewer conversions than my booking system?
Because the conversion tag and the click identifier both have to survive the trip through your checkout, and in tourism they often do not. The checkout usually sits on your booking system's domain, and the connection back to the ad click gets lost on the way. The booking completes and the money arrives, but Google never learns an ad caused it.
Should I pause a campaign that shows a return below 1.0?
Not before you check the same period in your booking system. In the London account above, the reported 0.89x was really a 1.88x. Compare both numbers for the same date range first, then decide.
Do I need a developer for any of this?
No. The script runs inside your own Google Ads account, the booking export is a CSV, and the dashboard is one HTML file built by an AI assistant from the prompts above. It took an afternoon.
Run the script on your account this week. Pull the same month out of your booking system. Put the two numbers next to each other and see how far apart they are.
If they are close, your tracking is in good shape and you can trust your ad account. If they are far apart, you have been running your budget on the smaller of the two numbers.
A shorter version of this guide first appeared as an article on LinkedIn.
I am Kourosh. I work as a growth partner for tour and experience operators.
If your reported return and your real return do not match, that is usually where I start.
For tour operators Book a call