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:- 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
nullclears a field. Every accepted update bumps the pass’sgenerationcounter by one. - The generation counter is the holder-refresh signal. It starts at
0at 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.
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
0so 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.
4. Referrals console: codes, reward steps, leaderboard
The referrals console runs the program → code → conversion → reward chain end to end:- 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/:coderedirect, which records the visit and tags the click-through with the attribution parameter. - Reward steps — a conversion lands as
pendingwhen signup creates the referred contact; nothing pays out until an operator approves it, which flips the conversion topaidand fulfills the reward through the incentives engine.rejectedrows — fraud-guard rejects like same-IP visit-and-signup — never pay out. - 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.
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.
Related reading
- Loyalty program model — points, tiers, and the CDP ledger the loyalty console operates.
- Referral program model — program → code → conversion → reward, attribution, and payout gating.
- Wallet pass lifecycle — the pass state machine, generation counter, and idempotent issuance.
- Incentives: catalog, ledger, and fulfillment — the shared engine that redemptions and referral payouts route through.