The challenge: a foundation they couldn’t trust
A luxury wellness resort came to us mid-migration. They were moving lifecycle messaging onto Customer.io while standing up an in-house property management system at the same time, with no downtime window to hide behind.
The messaging wasn’t the risk. The foundation under it was.
Trigger logic and workspace setup were unreliable enough that nobody could say with confidence which guest would get which message, or why. That kind of fragility doesn’t announce itself during setup. It shows up months later as a cancellation notice sent to a guest who never cancelled, or a pre-arrival sequence firing at someone who booked a day pass.
You can’t scale on a foundation you can’t trust.
So the engagement was scoped as implementation QA and launch readiness, not a campaign build. Get the foundation right, prove it, then let the resort scale on top of it.
What we built: event-first, not batch-and-blast
We rebuilt the model so every message traces back to something a guest actually did.
A real guest action gets captured as a clean, structured event. Trigger logic decides what happens next and confirms the guest genuinely qualifies. Only then does a message go out - tied to a verified event and a checked workspace.
That meant modeling guests as people and reservation activity as person events, rather than routing everything through custom objects. Reservation confirmations, major modifications, and cancellations became transactional messages instead of campaign shells, because that’s what they are - one guest, one triggering action, one send.
We also split the paths that had been quietly overlapping. Day-pass and event-ticket bookings stopped inheriting the overnight-stay pre-arrival sequence, which had been the most likely source of guest-visible errors at launch.

Implementation: verified as we went
Ingest runs through Customer.io’s Track API v2, with reservation lifecycle events named explicitly rather than collapsed into one generic booking event. Segments, campaign guardrails, and workflow logic were built directly in the production workspace.
The part that mattered most was how we checked the work. Rather than trusting the build log, we ran read-only passes against the authenticated production workspace and compared what was actually there against what was supposed to be there. That’s how we caught a day-pass reminder still firing on the generic reservation trigger - a bug that would have been invisible until real guests hit it.
Every campaign, transactional message, broadcast, webhook, and data-out action stayed draft or inactive throughout. Not because the build was incomplete, but because activation is a decision the client makes with sender and domain approval in hand, not a side effect of us finishing a task.
The result: an implementation-ready foundation
Trigger logic corrected. Production workspace verified. Launch path controlled.
- Trigger logic: corrected and re-verified in production
- Production workspace: verified against authenticated readback
- Reservation lifecycle: modeled as transactionals, not campaigns
- Send state: draft and inactive by design, pending launch approval
This was a pre-launch engagement, so there are no open rates or revenue numbers here yet - the sends hadn’t gone out. That’s the point of the work. Implementation risk got reduced before scaling rather than discovered afterward, and the resort got a foundation it can turn on deliberately.
What we learned
Verify in the workspace, not in the build log. What you think you configured and what’s actually live in the account drift apart faster than anyone expects, and the only way to know is to read it back from the authenticated workspace.
Draft-by-default is a feature, not a delay. Holding every send inactive until sender approval, content sign-off, and QA all landed meant the launch decision stayed with the client instead of arriving by accident.
Leave open items open. Two activation questions were still unresolved at handoff, and we flagged them as blockers rather than closing them quietly to make the deliverable look finished. A handoff that hides its own loose ends isn’t a handoff.
And separate the journeys that look similar. Day passes, event tickets, and overnight stays are three different guest relationships. Treating them as one because they all arrive as bookings is how resorts end up sending a checkout survey to someone who came for an afternoon.