Operational deep-dive
Cannabis loyalty program — earn rates that don’t bankrupt the margin
Most cannabis loyalty programs leak margin because the earn rate was set by feel (‘1 point per $’) and the redemption math was never modeled. The customer earns points at retail prices, redeems against retail prices, and the operator absorbs the discount on already-thin margin. Here’s how we run loyalty at Green Life + Seattle Cannabis Co — what we shipped, what we’d undo, and the audit cadence that keeps the program from quietly turning into a 12% margin haircut.
The default-bad earn rate
Most operators ship loyalty with ‘1 point per dollar’ + ‘$10 off when you hit 100 points.’ That math is 10% off every customer’s purchase, applied retroactively. On 30% gross margin, that’s a one-third margin haircut on every loyalty member who redeems. The operator doesn’t see it until quarter-close.
The earn rate that doesn’t leak
Set the earn rate as a percentage of MARGIN, not retail. Two-step calculation:
- **Pick a target loyalty cost.** Doug’s rule at Green Life + SCC: 3% of net revenue, hard cap. That number gets accounted for as a marketing expense, not a cost-of-goods item — it’s an investment in retention.
- **Back into the earn rate from the gross margin.** If gross margin is 30% and target loyalty cost is 3% of net revenue, then redemption-discount-as-%-of-redemption-purchase = 3% / 30% = 10% of the redemption transaction. Translate to earn: 1 point per $1 + redemption at 100 points = $1 off (not $10 off). That’s a 1% discount on each redemption transaction — but at the redemption rate of ~10%, the blended cost equals 0.1% per dollar earned, well inside the 3% cap.
- **Kill the round-number redemption tiers.** ‘100 points = $10 off’ is round, easy to remember, and bankrupts you. ‘100 points = $5 off’ or ‘200 points = $15 off’ both run the math under control. We use 200 points = $5 off at Green Life — the inconvenient ratio is a feature; it slows redemption velocity without telling the customer the system is hostile.
Redemption tiers that protect the basket
The classic loyalty trap: a customer accumulates 1,000 points, walks in to redeem, and the budtender applies $50 off a $52 basket. Customer leaves with $2 of cannabis at a 96% effective discount. Three tier rules that stop this:
- **Cap redemption at a % of the current basket.** No redemption can exceed 25% of the pre-discount basket total. $80 basket → max $20 redemption. Forces the customer to keep buying real product to use their points; prevents the ‘$2-of-cannabis-for-points’ raid.
- **Lock redemption to in-store, never online.** Online basket is already discount-stacked (delivery, first-visit, online-only deals). Letting points pile on top is a margin compounding event. We allow redemption ONLY at the in-store register where the budtender can see the full basket math.
- **Disable redemption on already-discounted items.** If the customer already has industry / heroes / medical / sale discount applied, no points on top. The budtender stops the redemption and the customer chooses one or the other. Stacking is the silent margin killer.
- **Expire points after 12 months of inactivity.** A customer who hasn’t shopped in a year isn’t coming back; their 800 points sitting on the books is a contingent liability. Annual expiry on the customer’s account anniversary, with a 30-day-before-expiry email that triggers re-engagement. Doubles as a clean balance-sheet practice.
What the audit cadence catches
- **Monthly: loyalty cost as % of net revenue.** Calculated as (sum of redemptions in dollars) / (sum of net revenue in dollars). Target 2.5-3.0%; alert at 3.5%.
- **Monthly: redemption velocity per active member.** Number of redemptions / number of active members in the month. Sudden spikes signal a stacking exploit or a budtender ringing wrong.
- **Quarterly: top-redeemer concentration.** What % of redemptions came from the top 5% of members? If >25%, the program is rewarding heavy-discount-seekers more than retention. Re-tune.
- **Quarterly: re-engagement rate from the 30-days-before-expiry email.** What % of expiring-points members shop within the email-trigger-to-expiry window? >15% = the program is doing real retention work; <5% = the email is wasted send and the points were already abandoned.
- **Annual: full earn-rate re-tune.** Pull the prior 4 quarters of data; recalculate the blended discount-as-%-of-redemption; adjust earn rate or tier structure to keep loyalty cost inside the 3% cap.
What WSLCB / OLCC / DCC actually care about
- **Loyalty discounts get the same per-transaction audit-log treatment as any other discount.** Activity row stamped with discount type, points used, $-discount applied. Per WAC 314-55 family the audit log is queryable on demand.
- **No loyalty discount on already-discounted items where the stack would push effective discount above 50%.** Same 50% cap as the industry-discount rule; once the stacked discount approaches that line, the WSLCB starts asking whether the ‘loyalty’ is actually a dressed-up kickback.
- **Loyalty data is customer-level PII.** Treat it like any other contact data. Don’t sell, don’t share with brand partners without explicit consent, don’t leak via vendor-portal scoping.
- **Customer can request their loyalty data + opt out.** State privacy laws (WA HB 1155 / OR ORS 646A.602 / CA CCPA all apply). Build the export + delete flow before someone asks; CannAgent ships both as one-click admin actions.
Takeaways
- Default 1pt/$1 + 100pts/$10-off is a 10% margin haircut on every redemption — set earn rate as % of margin, not retail
- 3% of net revenue is the operator-side cap; back into the earn rate from the gross-margin number; expect blended cost around 2.5%
- Cap redemption at 25% of basket / lock to in-store / no stacking on already-discounted items / 12-month expiry — these four rules prevent every common margin-leak failure
- Audit monthly (cost-as-%, velocity-per-member) + quarterly (top-redeemer concentration, re-engagement-rate) + annually (full earn-rate re-tune)
- WSLCB cares: loyalty discount in the audit log, no stacking past 50% cap, customer can request export + delete — build all three before someone asks
Ready to talk through your migration?
30-minute demo. We end by quoting the cutover from your current setup — fixed scope, no hourly games.