For months, the automated weekly report told three B&B operators in Hengchun how their conversion funnel was performing. It was measuring the wrong thing the entire time.
Not wrong by accident. Wrong because it was the only signal available. GA4 could see when a visitor tapped the phone number, hit the WeChat button, or clicked “book now” — on-site CTA events that happen after someone lands on the site. What it could not see was whether any of those taps turned into a guest actually sleeping in a room. So the engine used on-site button clicks as a conversion proxy and ranked everything — ad spend, landing pages, sitelinks — against a number that correlated with bookings only loosely, and sometimes not at all.
That is the gap this cluster of work closed. This piece is about the analytics engine and the decisions behind it; the client-site work it drives — the Astro sites for the operators’ own properties — sits alongside it as the surface being optimized.
Why a small B&B never had this before
The larger system here is a complete digital operation stack for businesses that could never afford one. OTAs dominate B&B bookings for three compounding reasons: advertising budgets that buy search and social traffic, brand trust built over years, and full-time professional marketing teams. Against that, a standalone B&B website with no SEO strategy, no analytics anyone can act on, and ad spend nobody is watching is simply invisible — while the OTA takes a commission on every booking that is higher than most people realize, on every booking, forever.
The answer was never “build a brochure site.” A site alone loses. The answer is the operation around it: a site that ranks, ads backed by data, and a weekly report an owner can act on without hiring a specialist. Each of those used to require its own headcount — an engineer, an analyst, an ad manager, someone writing reports. Together, far out of reach for a small operator. This work exists at all because AI made a previously unaffordable service economically viable. It didn’t replace a team; it made the service exist for a client category that was priced out of having one.
The weekly report is the spine of that stack. And a report optimizing against the wrong number is worse than no report — it spends real money chasing a proxy.
Reading the booking data was the actual problem
The fix sounds simple: feed real bookings into the report instead of click proxies. The engine now pulls from a booking tracker and ranks ad and funnel performance against received reservations rather than CTA taps.
The non-obvious decision was splitting the booking data into two views — bookings received versus guests staying. These answer different questions. “Received” is the demand signal: how many reservations came in this week, which is what you judge marketing against. “Staying” is the occupancy signal: who is actually in the building on which nights, which is what you judge availability and pricing against. Collapsing them into one number, which the first pass did, produces a report that is internally contradictory — a strong booking week that looks like a weak occupancy week, or the reverse, with no way to tell which lever to pull. Keeping the primary view (received) and the secondary view (staying) separate is what makes the occupancy analysis trustworthy.
That occupancy analysis is its own layer: per-property occupancy, weekday versus weekend split, remaining open dates, and a forward look at next month. The reporting rules force it to surface gaps even when the honest answer is bleak — a property at zero this month still gets written up, and any forward data that exists must appear. A report that quietly omits the empty weeks is the report that lets a slow month sneak up on an owner.
A four-layer funnel health check, with named owners
Real bookings made a real funnel analysis possible. The report now runs a four-layer conversion funnel health check — traffic, engagement, on-site CTA, and booking — instead of stopping at the click. The section name is enforced programmatically so it can’t drift between runs, and the engine must state why it chose this week’s rotating deep-dive topic rather than presenting the selection as arbitrary.
The part I spent the most time on isn’t the analysis — it’s who acts on it. An action list is useless to a B&B owner if every item reads like it needs an engineer. So the list now routes by executor with a transparency rule on top: say plainly what needs doing regardless of who does it, and only flag “needs a technician” when the owner genuinely cannot do it themselves. For one property, that meant encoding an architectural fact — the site is not on a CMS, so the owner cannot edit the code, which means code changes there genuinely do require a technician. The earlier version guessed at a generic list of technician tasks. Replacing the guess with the actual structure of that specific site is the difference between an action list an owner trusts and one they learn to ignore.
Fail-open, loudly
The decision I’d defend hardest: when the report’s own verification step can’t reconcile its numbers, it now fails open — it still produces a report, but flags it with a warning and sends it only to the maintainer, not the client. The alternative, failing closed and sending nothing, means a silent gap in a weekly cadence the owner has come to rely on. Failing open loudly means I see the broken run, the client never sees a wrong number, and the rhythm holds.
The specific bug that drove this was a verification path reconstructing session counts by back-calculating from an engaged-sessions ratio, which produced orphaned numbers that didn’t tie out. Catching that class of inconsistency and refusing to ship it to a client — while still shipping it to me — is the posture I want every automated client-facing system to have.
Once the funnel was honest, the ad work followed: an ads health check on one property, negative keywords, a paused Performance Max campaign that was spending against the wrong intent, and four broken sitelinks repaired. None of that was reachable while the report measured clicks. You can’t optimize a funnel you can’t see the bottom of.
Using clicks as a proxy wasn’t an avoidable mistake — it was the only way to give the report something to measure when operators recorded bookings on paper and the system couldn’t see real orders at all. The proxy filled a real gap. Replacing it wasn’t fixing a flaw; it was removing a constraint that no longer existed once there was a booking tool operators would actually open every day. The tool exists now. But whether it delivers depends on the other half: operators need onboarding, and they need to maintain the discipline of logging every booking after confirmation. The clicks served their purpose. What replaced them is a bet on whether that discipline holds.