Back to the build library
Hospitality & events
Standard

Seasonal Promotion Campaigns

A repeatable campaign machine for occupancy troughs and seasonal peaks, triggered by the calendar rather than by a panicked Tuesday meeting.

Industry
Hospitality & events
Build effort
Standard
Typical time to launch
2–3 weeks
On this page
The problemWhat gets builtHow it runsAutomations in detailWhat changesBefore you start
Want this built for you?

Bring your stack to a call and we will scope it against how your business actually runs.

Book a call
01

The problem

Seasonality is the most predictable thing about a hospitality business and the thing it is worst at planning for. Everyone knows February is quiet, that the second week of January is dead, that the Thursday before a bank holiday fills itself and the Monday after does not. Everyone knows it a year in advance. And yet the response to a soft two weeks is almost always the same: somebody notices the forward book looks thin, a meeting is called, a discount is invented on the spot, and an email goes out to the whole list on Tuesday afternoon with eleven days' notice. That is not a campaign, it is a reflex.

The cost shows up in three ways. First, lead time. A leisure guest planning a weekend away needs three to six weeks; a corporate planner needs longer. An offer that lands eleven days out reaches people who have already made other plans, so it converts badly, which gets read as the offer being wrong rather than late. Second, the discount is deeper than it needed to be, because panic prices. Having left it too late to fill the trough with a reason to visit, you fill it with a price cut instead, and you train your best repeat guests to wait for one.

Third, nothing is learned. The campaign was assembled from scratch, so there is no record of what the subject line was, which segment it went to, or what it produced. Next February somebody calls the same meeting and invents the same discount. Meanwhile the peaks get no treatment at all - the periods where you could be selling earlier and at a better rate to the people who came last year are left to inbound demand, and the guests who would happily have booked a Christmas table in October are sold one in late November at the same price as everyone else.

02

What gets built

Pipeline and stages

Two pipelines, because a campaign has an internal life and an external one.

Campaign Production tracks the campaign itself, one record per campaign, moving left to right on a schedule set by the promotional calendar:

  • Planned - a window exists on the calendar with a goal attached, nothing written yet.
  • Brief Approved - goal, segment, mechanic, dates and booking deadline signed off.
  • Assets In Build - landing page, email copy, SMS copy, social posts, photography.
  • Scheduled - everything loaded and queued, nothing sent.
  • Live - sending.
  • Wrapped - window closed, results recorded against the campaign record.
  • Archived - the whole thing, including the copy that worked, kept for next year.

Seasonal Offer Responders tracks guests against a campaign: Offer Sent, Engaged, Inquiry, Booked, Lapsed. A guest can appear once per campaign, which is what makes attribution possible.

Calendars

  • Promotional Calendar - the spine of the build. A rolling twelve months with every named window on it: the January trough, half-term, Valentine's, the spring shoulder, summer weekday gaps, the August lull in a business-led property, the autumn conference run, the Christmas pre-sell, New Year. Each entry carries the window start and end, the campaign goal, the booking deadline and the lead time before launch. Built once a year in one sitting, then reviewed quarterly.
  • Campaign Production Milestones - derived automatically from each window: brief due, copy due, landing page due, social scheduled, launch day, mid-campaign review, wrap. These generate tasks rather than existing as a document nobody opens.
  • Content Capture - slots for photography and video, booked against the production milestones so you are not shooting a winter menu in March.
  • Sales Call Slots - for the campaigns aimed at corporate and group bookers, who respond to an offer by wanting to talk to somebody.

Custom fields

Contact-level, used for segmentation:

  • guest_segment - local leisure, destination leisure, corporate, group booker, celebration, resident diner.
  • distance_band - walkable, same town, under an hour, day trip, overnight required. The single most useful field for seasonal targeting.
  • last_visit_date, lifetime_visit_count, visit_frequency_band.
  • preferred_daypart and preferred_season - captured from behavior and from the preference center.
  • occasion_history - the occasions this contact has actually booked for, which is how you know who to send the Mother's Day campaign to.
  • average_party_size, party_type.
  • offers_sent_count, offer_last_sent_at, offer_last_engaged_at, offer_fatigue_score - a simple count of offers sent without engagement, used to rest a contact rather than keep shouting.
  • marketing_consent_email, marketing_consent_sms, consent_captured_at, consent_source.

Campaign-level, on the production record:

  • campaign_code - short, dated, unique, and used in every link and every tag. Everything downstream depends on this being disciplined.
  • campaign_goal - fill a trough, pre-sell a peak, launch something new, shift a specific daypart, recover lapsed guests.
  • window_start, window_end, booking_deadline, launch_date.
  • target_segments, offer_mechanic - value-add, package, early access, exclusivity, no-discount reason-to-visit.
  • landing_page_url, tracking_code, inventory_cap - how many covers or rooms the offer is allowed to consume.
  • result_bookings, result_revenue_band, result_notes - filled at wrap, which is what makes next year's version better than this year's.

Tags

  • Segment: seg-local-leisure, seg-destination, seg-corporate, seg-group-booker, seg-celebration, seg-foodie, seg-family, seg-couples.
  • Behavior: repeat-annual, lapsed-6m, lapsed-12m, high-frequency, weekday-only, weekend-only.
  • Campaign state, applied per campaign using the code: offer-sent, offer-clicked, offer-inquired, offer-booked, offer-declined.
  • Control: fatigue-hold, offer-suppressed, vip-early-access, do-not-discount - for guests who book at full rate anyway and should get early access rather than a price cut.
  • Consent: marketing-email-ok, marketing-sms-ok, email-unsubscribed, sms-opted-out.

Forms and landing pages

  • Campaign Landing Page template. One page per campaign, built from a template rather than from scratch: hero image from the content capture, what is included in plain words, the exact dates the offer applies to, the booking deadline stated as a date, the booking widget or inquiry form, three FAQs, and the terms. No countdown gimmicks. The dates and the deadline do the work.
  • Early Access Register. For peak pre-sell campaigns. Guests register interest before the offer opens, which gives you a warm list to launch into and a demand signal before you commit inventory.
  • Offer Inquiry. For campaigns where the guest needs to talk to someone - group bookings, large parties, corporate. Routes to the sales call slots.
  • Preference Center. Which occasions and seasons the guest wants to hear about, and how often. This is the single highest-value form in the build: it lets you send less and convert more, and it is a consent record.
  • Post-Campaign Feedback. Sent to guests who booked from a campaign, asking whether the thing delivered what the offer promised. Protects you from running a second year of something that disappointed people.

BO's role and guardrails

BO handles the inbound wave that every campaign produces - the questions that arrive within minutes of a send and used to pile up unanswered. BO may:

  • Answer questions about a live campaign from the campaign fact sheet attached to the production record: which dates it applies to, what is included, what is not, the booking deadline, whether it applies to a particular daypart.
  • Point guests at the campaign landing page for the published terms and rate rather than restating them in a message.
  • Collect inquiry details for group and corporate responses and offer sales call slots.
  • Capture and update preference center answers from a conversation.
  • Handle an unsubscribe or opt-out request immediately and confirm it.

BO must not:

  • Quote, confirm, negotiate or discount a rate, or state any figure that is not on the published campaign page. If a guest asks for a better deal, that is a human decision.
  • Extend a booking deadline, apply an expired offer, or make an exception to the terms.
  • Invent inclusions. If it is not on the fact sheet, BO says it will check and hands over.
  • Promise availability. Availability is confirmed by the booking engine or by a human, never by BO.
  • Send a campaign message to anyone. BO responds; the workflows send.

Numbers and channels

  • A verified sending domain with SPF, DKIM and DMARC in place, and a sending reputation you have warmed. Seasonal campaigns are the highest-volume email you send; launching them on a cold domain wastes the campaign and damages every send after it.
  • A marketing SMS number, separate from any operational or reservations number. Keeping marketing traffic off the number guests use to reach you matters for deliverability and for the guest's relationship with that number.
  • Landing pages on your own domain under a consistent path, with the campaign code in the URL so attribution needs no detective work.
  • Social accounts connected to the planner, with each campaign's posts scheduled during the production phase rather than written on launch day. The planner holds the launch post, two mid-campaign posts and a deadline reminder, at minimum.
  • The booking engine, with campaign rate codes or packages configured and the landing page linking straight into a pre-filled availability search.
  • A payment link capability for campaigns that take a deposit or sell a prepaid package, such as a festive menu or a package with a fixed inclusion.
03

How it runs, step by step

One campaign, from a line on the promotional calendar to a wrap report - and one guest's path through it.

  1. The promotional calendar carries an entry: late-January weekday trough, window 12 to 29 January, goal fill midweek dinner covers, lead time six weeks. Nobody has thought about it since last spring, and nobody needs to.
  2. Eight weeks before the window opens, the production workflow creates a campaign record in Planned with campaign_code set, and assigns the brief task to the marketing owner with last year's equivalent campaign attached - its copy, its segment, its result, its notes.
  3. The owner writes the brief in a sitting, because last year's is in front of them. The mechanic this year is a value-add rather than a discount: a midweek set menu with a glass included, aimed at locals within an hour. offer_mechanic, target_segments, booking_deadline and inventory_cap are set. The record moves to Brief Approved.
  4. Moving to Brief Approved generates the asset tasks and books the content capture slot. The landing page is cloned from the template, the campaign code goes in the URL, and the dates and deadline are filled from the record rather than retyped.
  5. Four weeks out the segment is built: contacts tagged seg-local-leisure with distance_band of same town or under an hour, marketing-email-ok present, who are not carrying fatigue-hold and have not received another offer in the last twenty-one days. The count comes back, and the owner can see whether the list is big enough to hit the cap before a single word is sent.
  6. Three weeks out the social posts are scheduled: launch day, two mid-window posts, a deadline reminder. The record moves to Scheduled. From here nothing requires anyone's attention until launch.
  7. Six weeks before the window - launch day - the campaign goes live. The record moves to Live. Guests tagged vip-early-access and do-not-discount received their version 48 hours earlier, with the same offer framed as first refusal rather than a price cut.
  8. A guest who last ate with you in October, lives twenty minutes away, and has occasion_history showing two anniversary bookings receives the email. A responder record is created in Offer Sent, the campaign tag is applied, and offers_sent_count increments.
  9. She opens it, clicks through to the landing page, and reads it twice but does not book. The click applies offer-clicked, stamps offer_last_engaged_at, and moves her responder record to Engaged.
  10. Three days later she gets the engaged-but-not-booked follow-up, which is a different message rather than the same one again: it answers the question the landing page analytics suggest people are stuck on, which this year is whether the set menu works for a vegetarian.
  11. She replies to the SMS asking whether the offer covers a Thursday and whether they can sit in the window. BO answers from the fact sheet on the dates, confirms the offer covers Thursdays, and says it cannot promise a specific table but has flagged the preference - then hands the thread to reservations with a task.
  12. Reservations call her back the same afternoon and take the booking. offer-booked is applied, the responder record moves to Booked, and the campaign record's result_bookings increments. She drops out of every remaining message in the sequence immediately.
  13. Mid-window, the campaign review task fires with the numbers to date against inventory_cap. Bookings are tracking behind, so the owner opens the offer to the second segment - destination leisure within a day trip - rather than deepening the offer. The deadline reminder goes out to everyone who clicked but never booked, five days before booking_deadline.
  14. The window closes. The record moves to Wrapped: the workflow writes bookings, covers, the share of the cap filled, and per-segment and per-channel conversion onto the record, then prompts the owner for result_notes in their own words - what worked, what to change. Guests who booked get the Post-Campaign Feedback ask; guests who were sent the offer and never engaged have offer_fatigue_score incremented, and at a threshold pick up fatigue-hold so the next campaign rests them.
  15. The record moves to Archived. Eleven months later, the next late-January entry on the calendar produces a brief task with this whole thing attached, and the cycle starts a year ahead instead of eleven days ahead.
04

Automations in detail

Eight workflows. The first two run the production side and are what makes this a machine rather than a template; the rest run the guest side. Build the production ones first - a beautifully automated send sequence attached to a campaign nobody briefed in time is still a late campaign.

1. Campaign Production Scheduler

Trigger: a daily scheduled check against the Promotional Calendar, looking for windows whose launch date minus the configured lead time falls today.

Actions in order:

  1. Create a campaign record in Planned. Generate campaign_code from the window name and year, write window_start, window_end, booking_deadline, launch_date and campaign_goal from the calendar entry.
  2. Search the archive for last year's campaign with a matching window name. If found, attach it to the new record: brief, segment definition, copy, landing page, result_bookings and result_notes.
  3. Create the brief task for the campaign owner, due in 5 days: "Brief due for late-January trough. Last year's version attached - it filled 62 percent of cap on a value-add mechanic, and the note says launch a week earlier."
  4. Generate the milestone tasks on the production calendar, back-timed from launch_date: brief approved at launch minus 28 days, copy drafted at minus 21, landing page live at minus 14, social scheduled at minus 10, segment built and counted at minus 7, final QA at minus 2.
  5. Notify the owner and the general manager that the campaign has opened.

Escalation: any milestone 2 days overdue notifies the owner; 5 days overdue notifies the GM; 10 days overdue flags the campaign as at risk of launching late, which is the thing this whole workflow exists to prevent.

Exit: record reaches Scheduled, or a human cancels the campaign with a reason.

2. Pre-Launch QA Gate

Trigger: campaign record moved to Scheduled, or 48 hours before launch_date, whichever is first.

Conditions and checks - every one must pass or the launch is blocked and the owner notified:

  1. landing_page_url is populated, returns a page, and the page states window_start, window_end and booking_deadline as literal dates.
  2. The booking link resolves to a live rate code or package, tested end to end with a real test booking that is then canceled.
  3. inventory_cap is set and is a number, not blank.
  4. The segment has been built, the count recorded, and every contact in it carries consent on the channel being used.
  5. Opt-out language is present in the SMS copy and a working unsubscribe plus preference center link in the email.
  6. Social posts are scheduled, and the launch post is not scheduled before the email.
  7. A test send has gone to an internal seed list and been checked on a phone, not a desktop.

Actions: on all checks passing, notify the owner that launch is armed. On any failure, hold the launch, list the failed checks, and create a task due 12 hours before launch. Never launch past a failed check automatically.

Exit: launch armed, or campaign postponed.

3. Segment Build and Suppression

Trigger: the segment-build milestone, 7 days before launch, or manually when a campaign is re-targeted mid-window.

Inclusion logic, applied in order:

  1. Start from target_segments - the segment tags on the campaign record.
  2. Filter by distance_band appropriate to the campaign. A midweek dinner offer goes to walkable, same town and under an hour; a weekend package goes to day trip and overnight required.
  3. Filter by preferred_daypart and occasion_history where the campaign is occasion-led.
  4. Require consent: marketing-email-ok for the email track, marketing-sms-ok for the SMS track. These are separate lists and a contact can be on one and not the other.

Suppression, applied last and absolutely:

  1. Remove anyone with email-unsubscribed from the email track, sms-opted-out from the SMS track, offer-suppressed or do-not-market from both.
  2. Remove anyone carrying fatigue-hold.
  3. Remove anyone whose offer_last_sent_at is within your frequency ceiling, default 21 days.
  4. Remove anyone with an existing booking inside window_start to window_end. Sending a discount to someone who has already booked at full rate is the most expensive mistake in this build.
  5. Remove anyone with an open complaint or issue flag.
  6. Split out vip-early-access and do-not-discount contacts into a separate early list.

Actions: write the final counts to the campaign record, per channel and per segment. If the count is below the number needed to plausibly hit inventory_cap at your historical conversion, notify the owner before launch rather than after.

Exit: segment written and counted.

4. Early Access Wave

Trigger: 48 hours before launch_date, for the vip-early-access and do-not-discount list only.

Actions:

  1. Send the early access email, framed as first refusal rather than as a deal: "Before this goes out to everyone on Thursday - the January midweek menu is open for booking now. You have always come on a Tuesday, so I wanted you to have first pick of the dates."
  2. Create responder records in Offer Sent with the campaign tag, and stamp offer_last_sent_at.
  3. Wait 24 hours. If opened and not booked, send one SMS: "Early access to the January midweek menu is open until Thursday if you want to pick your date: [link]"
  4. On booking: apply offer-booked, move to Booked, increment result_bookings, and remove the contact from the main launch list so they do not then receive the public version of an offer they already took.
  5. Also pull anyone who registered on the Early Access Register for this campaign into this wave, regardless of tags.

Exit: launch day, at which point unbooked early-access contacts join the main sequence at step two rather than step one.

5. Main Campaign Send Sequence

Trigger: launch_date with the QA gate passed. Record moves to Live.

Actions:

  1. Day 0, email. The launch send. Subject line names the thing and the window, not the discount: "Midweek in January, with the set menu back." Body: what it is, which dates, what is included, the booking deadline as a date, one clear link. Create responder records in Offer Sent, apply the campaign tag, stamp offer_last_sent_at and increment offers_sent_count.
  2. Day 0, social. Launch post publishes from the planner two hours after the email, so the email is the first place a guest sees it.
  3. Day 3, branch on engagement. Opened or clicked but not booked: send the objection-handling email - the one that answers whatever the landing page analytics show people hesitating over, such as dietary flexibility, parking, or whether the offer covers a particular night. Not opened: resend the launch email with a different subject line, once only, to the non-openers. Never resend to openers.
  4. Day 7, SMS to the marketing-sms-ok subset who have engaged but not booked: "The January midweek menu is open until the 5th if you fancy a quiet Tuesday: [link]" One SMS per campaign, to engaged contacts only. SMS is the channel you can burn fastest.
  5. Day 10, social. Mid-campaign post, different angle - the chef, the room, the reason to come out in January - rather than a repeat of the offer.
  6. Day 14, mid-campaign review. A task to the owner with bookings to date against inventory_cap, conversion by segment, and the suppressed count. The owner chooses: widen the segment, extend the window, or leave it. The system does not decide this.
  7. Booking deadline minus 5 days, email. Deadline reminder to everyone tagged offer-clicked who never booked. "Bookings for the January menu close on Friday - after that it is back to the regular carte." Factual, no manufactured scarcity.
  8. Booking deadline minus 1 day, SMS to engaged non-bookers only. Last message of the campaign.
  9. Booking deadline. Offer closes. Update the landing page to say the offer has closed rather than leaving a dead link, and record moves to Wrapped.

Stop conditions, applied at every step: a booking removes the contact from the entire remaining sequence immediately. An inbound reply pauses the sequence for that contact and routes to BO or a human. An unsubscribe or opt-out removes them from that channel instantly. If inventory_cap is reached, stop all remaining sends for the campaign and notify the owner - continuing to promote a full offer produces complaints, not covers.

6. Inbound Inquiry Handling

Trigger: any reply to a campaign email or SMS, a web chat mentioning the campaign, or an Offer Inquiry submission.

Branches:

  1. A factual question covered by the fact sheet. BO answers, points at the landing page, and offers the booking link. Apply offer-inquired, move the responder record to Inquiry.
  2. A group or corporate inquiry, or a party above your threshold. BO collects the detail and offers a slot from Sales Call Slots, then notifies the sales owner with a 2-hour task.
  3. A request for a better rate, an exception, or a date outside the window. BO does not answer. Route to a human with the context attached and a 4-hour task.
  4. A complaint, or a reference to a previous bad experience. Suppress all remaining campaign messages for that contact immediately, apply offer-suppressed, and notify the general manager.
  5. Unsubscribe or opt-out language in any form. Honor it on the channel named, apply the tag, confirm in one line, and offer the preference center as an alternative to leaving entirely: "Done - you will not get offers by text again. If you would rather just hear about festive and anniversary dates, you can set that here."

Exit: each inquiry handled once; the responder record keeps its highest-reached stage.

7. Campaign Wrap and Archive

Trigger: campaign record enters Wrapped, which happens at booking_deadline or when inventory_cap is hit.

Actions:

  1. Write the results onto the record: bookings and covers attributed by campaign tag, share of inventory_cap consumed, conversion per segment, conversion per channel, unsubscribe and opt-out count, and lead time distribution between send and booking.
  2. Compare against the attached prior-year record and write the deltas.
  3. Create a task for the owner to write result_notes in plain words - what worked, what to change, what to launch earlier. Due in 5 days. This is the single highest-return five minutes in the build and the one most often skipped, so the task escalates to the GM if it is not done.
  4. Wait 3 days after window_end. Send Post-Campaign Feedback to everyone tagged offer-booked: one question on whether the thing matched what was promised, plus a comment box.
  5. Any feedback indicating the offer oversold what was delivered is flagged to the GM individually, not reported in aggregate.
  6. Move the record to Archived with the copy, segment definition and landing page preserved, so next year's scheduler can attach it.

Exit: record archived.

8. Fatigue Scoring and List Health

Trigger: a weekly scheduled run across all contacts, plus a run at every campaign wrap.

Actions:

  1. For every contact sent an offer in the last period with no open, click, reply or booking, increment offer_fatigue_score.
  2. Any engagement at all resets offer_fatigue_score to zero and stamps offer_last_engaged_at.
  3. At a score of 3, apply fatigue-hold. The contact is excluded from campaign segments for 90 days.
  4. At 90 days, remove fatigue-hold and send one re-permission message rather than silently resuming: "You have not opened anything from us in a while, which is fair enough. Want to keep hearing from us, and if so, about what?" Link to the preference center. No engagement after that message applies fatigue-hold again and the contact is parked indefinitely.
  5. At a score of 6 with no engagement across two re-permission attempts, move the contact to a suppressed state and stop sending entirely. Keep the record and the suppression - do not delete it, or the next import will resurrect them.
  6. Recalculate lapsed-6m and lapsed-12m from last_visit_date, and visit_frequency_band from visit history, so segments stay accurate without anyone maintaining them.
  7. Report weekly: fatigue population, suppressed population, net consenting list size per channel, and the trend on each. A list that is growing in size while falling in engagement is a list being burned.

Exit: runs continuously; this one never completes.

05

What changes

The first change is lead time, which is the change that makes everything else work. Campaigns launch six weeks out rather than eleven days out, because the calendar generates the brief rather than a thin forward book doing it. Guests receive offers while they are still deciding what to do with that two weeks.

The second change is that discounting becomes a choice rather than a default. When you are planning eight weeks ahead you have time to build a reason to visit - a menu, an event, a package, early access - and that is almost always cheaper than cutting the rate. The do-not-discount tag protects the guests who were going to come anyway, which is the group most likely to be trained into waiting for a deal by careless campaigning.

The third change is institutional memory. Every campaign leaves behind its brief, its segment definition, its copy, its landing page and its result in one record. The second year of this build is materially better than the first because the work compounds, and a new marketing hire can run February having read one record rather than interviewing three people about what usually happens.

The fourth is restraint. Fatigue scoring and the preference center mean the list gets sent to less often and more precisely. Sending less is counterintuitive and reliably produces more bookings per thousand sends, plus a list that is still there in three years.

Metrics to watch

  • Bookings attributed per campaign, against inventory_cap - the share of the offer that actually got consumed. An offer that fills fifteen percent of its cap is a targeting problem, not a price problem.
  • Occupancy or covers in the target window versus the same window last year, which is the only number that answers whether the campaign moved the business.
  • Lead time distribution - days between send and booking. This tells you whether your launch timing is right and is the first thing to look at when a campaign underperforms.
  • Conversion by segment and by distance_band, so next year's segment is built on evidence.
  • Channel contribution - email, SMS, social, landing page direct. Watch where inquiries come from separately from where bookings come from; they are rarely the same channel.
  • Discount depth versus value-add performance. Run both mechanics across comparable windows and compare bookings per send, not just total bookings.
  • Unsubscribe and opt-out rate per campaign. This is the cost side of the ledger and should be reported next to the bookings every time.
  • Fatigue population - how many contacts are carrying fatigue-hold and whether that number is growing. A growing number means you are sending to the wrong people.
  • Repeat rate of campaign-sourced bookers - whether guests acquired by an offer ever come back at full rate. If they never do, the campaign bought covers rather than guests, and that is worth knowing before you repeat it.
  • Production adherence - how often the brief, copy and landing page milestones were hit on time. When campaigns underperform, late production is the most common cause and the easiest to fix.
06

Before you start

Decisions to make before building

  • The promotional calendar itself. Sit down with twelve months of occupancy or covers data and mark every trough and every peak, then decide which ones you will actually run a campaign for. Six well-run campaigns a year beat eighteen rushed ones.
  • The lead time per campaign type. Local midweek dining can launch three to four weeks out; destination leisure weekends need six to eight; festive and group pre-sell needs three to four months. Set these per window on the calendar, not as one global rule.
  • Who owns a campaign and who signs off the mechanic. A campaign with two owners launches late.
  • Your sending frequency ceiling per contact - the maximum offers one person receives in a rolling period - and the fatigue threshold at which a contact is rested. Decide these before the first send, because they are impossible to introduce later without an argument.
  • Which guests are on the do-not-discount list and what they get instead. Early access is usually the right answer.
  • The inventory cap per campaign, and who is allowed to raise it mid-window. An uncapped offer in a peak window gives away rate you would have earned anyway.

Integrations and provisioning

  • A verified sending domain with SPF, DKIM and DMARC configured, and a warming plan if the domain is new. Do not launch a large campaign as your first ever send from a new domain.
  • A marketing SMS number, provisioned and verified, kept separate from reservations and operational numbers.
  • Your booking engine, with campaign rate codes or packages set up in advance and tested end to end. The most common failure in this build is a landing page that links to a rate code that does not exist yet.
  • Your property system or POS for the occupancy and covers data that sets the calendar, and for measuring the result against last year.
  • Social accounts connected to the planner.
  • Stripe or your payment provider for prepaid packages and deposits, and QuickBooks or Xero if those need to reconcile.
  • Analytics on the landing pages, with the campaign code carried through in the URL so attribution does not depend on asking guests how they heard about it.

Compliance

  • Marketing consent is the foundation of this build. Every send here is marketing, not transactional, which means you need a defensible consent record per contact per channel - captured at a known time, from a known source, with wording the guest could reasonably have understood. marketing_consent_email, marketing_consent_sms, consent_captured_at and consent_source exist for exactly this reason. A contact without consent on the channel does not get sent to, and the segment builder must enforce that rather than relying on anyone remembering.
  • A2P and 10DLC registration. For US sending, register the brand and campaign before launch, and register it honestly as marketing. Promotional SMS is scrutinized harder than operational traffic, requires clear opt-in language, and may be rejected if the described opt-in does not match what your forms actually say. Keep the registered sample copy in step with what you send.
  • Opt-out. Every marketing SMS carries opt-out instructions. STOP, UNSUBSCRIBE and CANCEL set sms-opted-out and suppress every campaign immediately. Every marketing email carries a working one-click unsubscribe and a link to the preference center, so a guest who only wants to hear about festive campaigns can say so rather than leaving entirely.
  • Quiet hours. Marketing SMS sends between 9am and 8pm in the recipient's local time, and avoid the hours when nothing good happens - an offer text at 7am reads as spam regardless of its content. Email scheduling should respect time zones for the same reason.
  • Truth in the offer. The landing page must state the dates the offer applies to, the dates excluded, the booking deadline, and any condition on the inclusion. Advertising a rate that is only available on two Tuesdays without saying so is the fastest way to turn a campaign into a complaint queue, and in many jurisdictions it is also a consumer-protection problem. If an offer sells out before the deadline, say so on the page rather than leaving it live.
  • Prize draws and competitions - common in seasonal campaigns - carry their own rules on terms, eligibility and data use in most jurisdictions. Treat them as a separate exercise with their own written terms.
  • Data protection. Segmentation here profiles guests by visit history, distance, occasion and party type. Under GDPR, UK GDPR or similar regimes, decide your lawful basis for that profiling, keep the preference center as the guest's real control, set a retention period after which a contact who has never engaged is removed, and have a route for access, objection and deletion requests. Keep a suppression list that survives deletion, so a guest who asked not to be contacted is not re-added by the next import.
  • None of the above is legal advice. Confirm consent wording, promotional terms, competition rules, registration obligations and retention periods with the client's own counsel before launch.

Campaign cadence, segment size and integration work vary by business. To get a promotional calendar and campaign machine scoped for yours, book a call at bookings.appbo.io.

Field notes

Build it with us.

Every build on this page is something we configure, test and hand over with the SOPs your team needs to run it.

Book a call