[CODE]

Real Bookings Replace Click Proxies in the Ads Conversion Pipeline

Google Ads Smart Bidding trained on button taps for months — not confirmed reservations. Closing that gap required building a booking entry tool an elderly operator would use daily, then routing each confirmed booking into three simultaneous systems.

7 min read AI-generated
analytics ga4 automation typescript bnb

Two Hengchun B&B properties run separate Google Ads accounts, each on Smart Bidding. For months, the conversion definition in both accounts was: phone tap, LINE button press, WhatsApp link click, Facebook contact tap. The bidding engine found audiences who reach for contact buttons. Whether those audiences actually book a room was invisible to it.

The gap between those two things is real and measurable. A visitor who spent seven minutes on the property page and tapped a LINE button counts as a conversion; no reservation follows. A guest who visited Tuesday, called directly Friday, and booked the entire property for a September stay leaves zero click trail — no event fired, no session attributed, completely absent from the signal. The engine was optimizing against the taps, not the bookings.

Filling that gap required building a booking data source first. And the harder part was not the data architecture. It was building an entry tool that the operator — a family member in her seventies who manages reservations by phone and messaging — would actually open every day.

The constraint that shaped every decision

B&B operators in Hengchun manage their properties through phone calls and messaging apps. They will not log into a second tool. Any entry experience that requires navigating to an interface, entering credentials, or loading a page on demand will simply not get used. The booking-entry UX had to be as frictionless as tapping an app icon on the home screen — because that’s exactly what it needed to be.

Three directions were evaluated:

Native iOS app: NT$3,000 per year for an Apple Developer account, mandatory app review on every update, and ongoing distribution complexity. The math doesn’t work for two B&B properties.

LINE bot: Operators already live in LINE, which removes onboarding friction. But structured data entry — property, contact channel, booking type, dates — is fundamentally awkward in a chat interface. Purpose-built tap targets beat chat for every field except an optional notes box.

PWA: Next.js deployed to Vercel, added to the iPhone home screen from Safari. No app store submission, no review cycle. Push to GitHub triggers automatic deployment within minutes.

The PWA won on every dimension that mattered for this operator profile. The record screen presents five questions: which property (large tap targets), how the guest made contact (LINE / phone / WhatsApp / Facebook message / other), whole-property rental or single room, check-in and checkout dates. Every answer is a single tap; the only keyboard input is an optional notes field. A standard booking logs in under thirty seconds.

Multi-account access — Wayne plus the family member who manages daytime inquiries — runs on Supabase Auth with Google OAuth. Multiple user accounts link to the same operator row through an operator_members table. A SECURITY DEFINER SQL function handles the uid-to-operator mapping inside RLS policies, so both users query only their operator’s data without sharing a password or any custom user management.

Three things happen when a booking is confirmed

Pressing confirm fires three parallel actions server-side:

Supabase write: Property name, contact channel, booking type, check-in and checkout dates, and optional notes land in the bookings table.

Google Calendar event: A booking event is created in the operator’s shared calendar, showing the property, booking type, contact channel, and night count. All members with write access see it immediately. If the operator is logging in for the first time, the calendar is created and shared with all other members automatically — no manual calendar setup required at any point.

GA4 Measurement Protocol event: A server-side event fires immediately, using a property-specific event name that routes the signal to the correct Google Ads account.

The Google Calendar piece closes the operational loop for the operator. They already check their calendar for what’s coming up; confirmed bookings now appear there automatically, without requiring any additional tool or app.

Why GA4 Measurement Protocol, not the Google Ads Conversion API directly

The direct path was obvious: POST a conversion to the Google Ads Conversion API the moment a booking is confirmed. That API requires a gclid — the click identifier attached to the moment a visitor clicked an ad. Operator-entered bookings are post-fact records; the guest left the website days or weeks ago. No gclid exists to attach, and the API returns a 400 on an empty one.

GA4 Measurement Protocol has no such requirement. Each confirmed booking fires a server-side event to GA4, which syncs to linked Google Ads accounts automatically within 24–48 hours.

Two Google Ads accounts — one per property — link to a single shared GA4 property. Each property in the database carries its own event name. The two Google Ads accounts import different event names and therefore receive independent conversion signals without cross-contaminating each other’s data. One credential set manages the entire setup; two separate bidding engines receive signals they can’t mix.

Conversion value is dynamic: night count multiplied by a per-night rate based on booking type. Whole-property rentals carry a substantially higher per-night rate than single-room bookings — roughly six times — so a two-night whole-property stay and a one-night single room send meaningfully different values. Smart Bidding now learns not just that a booking occurred but what it was worth.

The received/staying split

A single booking count would still have been wrong.

Operators track two timelines simultaneously: how many reservations came in this week, and how many guests are occupying rooms this week. These answer different questions. A reservation received today might be for a September stay. A guest checking in tonight may have booked in April. Collapsing both into one total forces the operator to mentally unpack the number before acting on it — which means the automation would have solved the wrong half of the problem.

received filters by booking-entry timestamp: reservations logged during the report week. This is the leading indicator — what advertising spend and marketing effort actually moved. staying filters by check-in date: guests occupying rooms during the report week. This is operational reality, independent of when those bookings arrived.

The three monthly occupancy windows — prior month settled, current month in progress, next month already confirmed — are separate from the week-over-week queries. Together they let the report show how last month closed, where this month currently sits, and how much of next month is already committed. An operator adjusting an ad budget or planning a promotional rate needs all three. None of the three is recoverable from the others.

How the weekly report reads it

The weekly analytics pipeline reads booking data from Supabase after completing its GA4 and Search Console queries. The integration is opt-in: a booking_tracker block in each site’s configuration file carries an enabled flag, the names of the credential environment variables, and the list of property names to filter by. When the flag is off, the pipeline runs identically and downstream stages receive a null field — sites without booking data don’t break.

When enabled, the fetch stage runs seven parallel Supabase queries: received bookings for the current and prior weeks, staying bookings for the current and prior weeks, and occupancy snapshots for the prior, current, and upcoming calendar months.

What the signal shift changes

CTA events — phone clicks, LINE clicks, WhatsApp clicks, Facebook contact taps — didn’t leave the report. They remain as behavioral signals: how many visitors reached for contact, which pages produced the most intent. But they’re no longer the conversion definition Smart Bidding trains against. That role now belongs to confirmed reservation records with values proportional to actual stay revenue.

For Hengchun B&B operators without an analytics budget or a digital team, a system maintained at this level — real booking signals routed into Smart Bidding, weekly occupancy reporting across three calendar months, confirmed bookings appearing in the operator’s Google Calendar without any extra step — was economically impossible before. Not because better systems didn’t exist, but because building and operating one for two small properties required more than the economics could support. The condition changed. The operators’ need for accurate signal had been there all along.