Campaigns
A campaign is a named marketing initiative with a goal, a date range and a set of activities (coupons, email blasts, on-site banners). Owners run their own; platform admins can run cross-property promos. Every campaign tracks impressions, clicks, bookings and revenue against a UTM tag.
A coupon is an atomic discount. A campaign is the wrapper that gives the discount a reason for existing — a goal, a date, an audience, a way to reach them, and a way to measure if it worked. A coupon can exist without a campaign; a campaign usually has at least one coupon.
Goal presets
Pick a goal at creation time. Each preset seeds defaults (suggested coupon type, audience, reporting view).
Fill low-occupancy dates
System suggests dates with < 40 % forecast occupancy. Seeds a stay-window-scoped coupon.
Drive direct bookings
Reduce OTA dependence. Coupon excluded from OTAs by design; banner above search results.
Launch a new property
Auto-creates a feature banner + email to past guests + opening-week coupon.
Convert past guests
Audience = "stayed in last 12 months". Returning-guest coupon. Email-led.
Seasonal push
Diwali / Christmas / monsoon getaway. Date-bounded with a thematic banner template.
Custom
Blank canvas — define your own audience, activities and reporting.
What a campaign contains
| Component | How many | Purpose |
|---|---|---|
| Basics | 1 | Name, goal, owner, start/end dates, optional ad budget for ROAS |
| Audience | 1 | Who this is for (everyone · logged-in · past-guests · custom segment) |
| Coupons | 0..N | Discount codes — pulled from Coupons module |
| Email blast | 0..1 (V1.1) | Templated email scheduled to a segment |
| On-site banner | 0..1 (V1.1) | Hero strip on public site or city/property pages |
| UTM tags | auto | utm_source / medium / campaign auto-applied to outbound links |
| Landing page | 0..1 (V2) | Custom slug like /offer/summer-in-manali |
Lifecycle states
Campaigns list UI
Campaign builder — 4-step wizard
Basics
Name · goal preset · start & end dates · optional ad budget. Goal seeds defaults for the rest of the wizard.
Audience
Everyone · logged-in users · past guests (last 12 m) · custom segment (filter by property, channel, lifetime value). Estimated reach shown live.
Activities
Toggle which components to include: Coupon (create new or attach existing), Email blast (pick template + send date), Banner (image, headline, CTA, target pages).
Review & schedule
Summary of all the above + a preview email + preview banner. Save as draft or schedule.
Campaign builder — step 3 (Activities)
abc.com/offer/summer-in-manaliCampaign detail — live performance
Attribution model
Every interaction picks up the campaign in one of three ways. Most specific wins.
| Priority | Signal | How it's set |
|---|---|---|
| 1 (strongest) | Coupon redemption | Booking applies a coupon linked to the campaign → attributed. |
| 2 | UTM in landing URL | Visitor lands with ?utm_campaign=summer-manali → stored on the session and on any booking they make within 7 days. |
| 3 | Banner / email click | Click recorded with campaign ID; if the same visitor books in 7 days → attributed. |
Data model
campaigns
- iduuid
- owner_id→ users · nullable
- nametext
- slugtext uniq
- goalenum
- audiencejsonb (filters)
- starts_attimestamptz
- ends_attimestamptz
- budget_inrmoney · nullable
- utm_sourcetext
- utm_mediumtext
- utm_campaigntext
- statusenum
- created_attimestamp
campaign_assets
- iduuid
- campaign_id→ campaigns
- typecoupon · email · banner · landing
- asset_refuuid (poly fk)
- configjsonb
- statusenum
campaign_metrics_daily
- iduuid
- campaign_id→ campaigns
- datedate
- impressionsint
- clicksint
- bookingsint
- revenuemoney
- discount_givenmoney
API contract
{
"name": "Summer in Manali 2026",
"goal": "fill_low_occupancy",
"starts_at": "2026-06-01T00:00:00+05:30",
"ends_at": "2026-08-31T23:59:59+05:30",
"budget_inr": 30000,
"audience": { "type": "past_guests", "within_months": 12 },
"assets": [
{ "type": "coupon",
"config": { "code": "SUMMER25", "discount_type": "percent", "value": 25, "max_cap": 2000 } },
{ "type": "email",
"config": { "template": "summer_2026_hero", "send_at": "2026-06-01T09:00:00+05:30" } }
]
}
// Response — 201
{
"campaign": { "id": "cmp_01HX…", "slug": "summer-in-manali-2026", "status": "scheduled" },
"created_assets": [ "cpn_…", "eml_…" ]
}
Integration points
| Module | Touch point |
|---|---|
| Coupons | Campaign creates / links coupons. Coupon redemptions roll up to campaign metrics. |
| Emails | Email blasts use the same notify-svc pipeline. Each send records campaign_id for open/click attribution. |
| Public site | Banner zone above search results renders the active campaign's banner if rules match the visitor. |
| Analytics | "Campaigns" tab shows mix, revenue, ROAS, top performers. |
| Audit | Every campaign edit (pause / resume / change dates) audit-logged with actor and diff. |
MVP vs later
MVP (Phase 1)
Campaign wrapper with coupons + UTM tracking + daily metrics rollup + basic detail view.
Phase 1V1.1
Email blast composer + on-site banner editor + audience segments + send-test.
Phase 2V2
Custom landing pages + A/B variants on email and banner + paid-ad cost ingestion for true ROAS.
Phase 3