Skip to main content

Marketing hub model

The dashboard’s Marketing section is a family of consoles — wallet passes, loyalty, referrals, and the shared incentives engine — that together run your customer-facing reward surfaces. The bare /marketing route does not render a page of its own; it redirects to one sub-page. This document models that family as one design: why the index is a redirect today, what each console owns, and what changes when the family grows.

1. The hub redirect: /marketing is a route family, not a page

Visiting /marketing with no sub-path never renders a blank or a 404. The route family is defined so that any nav surface that lands on the bare path — command-K, deep links out of the campaign tooling — resolves cleanly to a real sub-page. Today the family holds one end-user program console that needs a landing, so /marketing redirects straight to /marketing/referrals. The redirect is deliberate product shape, not a placeholder: treat /marketing as the family’s hub whose current tiling is a single tile. Within the family, each console is independent and tenant-scoped: All reads and writes stay inside your workspace — no console ever surfaces another tenant’s programs, passes, or members.

2. Wallet passes console: issue, update, void

The wallet-passes console is the operator face of the pass lifecycle. A pass is a digital card — loyalty card, coupon, or event ticket — rendered for Apple Wallet and Google Wallet from one platform-agnostic content model. Its lifecycle is a strict state machine:
Four properties carry the design:
  • Issuance is idempotent. Send an idempotency key and a retry returns the first issued pass instead of minting a duplicate, so a double-submit can never create two passes for one enrollment.
  • Update patches, never rewrites. Only the fields you send change; explicit null clears a field. Every accepted update bumps the pass’s generation counter by one.
  • The generation counter is the holder-refresh signal. It starts at 0 at issue and increments on each update — compare it across polls to learn “something moved,” and treat each bump as the trigger for telling Apple or Google Wallet to refresh the holder’s copy.
  • Void is terminal. A voided pass renders as expired in the holder’s wallet; further updates return a conflict. A replacement is always a new pass.
The full state machine, the append-only ledger it projects from, and the delivery mechanics (save links, barcode formats, platform connection states) are documented in the wallet pass lifecycle concept.

3. Loyalty console: tiers, member ledger, point balance

The loyalty console operates the points-and-tiers program whose balances project over your CDP event stream. Three views matter to an operator:
  • Tiers — an ordered ladder keyed on lifetime earned points, with a required tier at threshold 0 so every member holds a tier from their first event. Tiers climb one-way: spending the balance never reduces lifetime points, so a member who redeems everything keeps their tier.
  • Member ledger — a per-contact view that recomputes the spendable balance from the event history at read time: unexpired earn lots minus burns, plus the audit trail of every earn, burn, and adjustment behind it.
  • Point balance operations — operator credits and debits are events in the same ledger. A redemption or debit runs under a per-contact lock, so concurrent spends serialize and a balance can never be overspent.
Earn rules (flat per-event grants and per-unit multipliers), the FIFO lot expiry model, and the event-sourced program revisions are the loyalty program model.

4. Referrals console: codes, reward steps, leaderboard

The referrals console runs the program → code → conversion → reward chain end to end:
  1. Unique codes — minting a code for a contact is mint-or-get: the same contact and program always return the same short, unambiguous code, so an “issue my link” action is safe to repeat. Each code’s public face is the unauthenticated /r/:code redirect, which records the visit and tags the click-through with the attribution parameter.
  2. Reward steps — a conversion lands as pending when signup creates the referred contact; nothing pays out until an operator approves it, which flips the conversion to paid and fulfills the reward through the incentives engine. rejected rows — fraud-guard rejects like same-IP visit-and-signup — never pay out.
  3. Leaderboard vs totals — the leaderboard is a capped top-N ranking of codes by conversions; the totals view aggregates every code with no page-size limit. Never sum the leaderboard to drive a stat — it under-counts once a program has more than a page of referrers.
Reward types (billing credit, minted discount code, tracked manual payout), attribution carriers, and the fraud guards are the referral program model.

5. Roadmap: when the redirect becomes a tiled hub

The redirect exists because the family has exactly one end-user program that needs a landing today. The product intent on the /marketing index is explicit: when the family grows more sub-pages that deserve equal standing, the redirect is replaced by a hub that tiles them. At that point /marketing stops forwarding and starts rendering — a hub page that presents the consoles side by side, the same way other hub surfaces present their families. Deep links to /marketing/wallet-passes, /marketing/loyalty, and /marketing/referrals are stable regardless; only the bare index changes behavior. Bookmark sub-routes, not the redirect.