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 to run loyalty that holds — what to build, what to avoid, 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
Frequently asked
- What earn rate should I set so my loyalty program doesn't eat my margin?
- Set the earn rate as a percentage of margin, not retail. Pick a target loyalty cost first (the rule at Green Life and SCC is 3% of net revenue as a hard cap, accounted for as a marketing expense), then back into the earn rate from gross margin. At 30% gross margin with a 3% target, the redemption discount works out to 10% of the redemption transaction, which translates to 1 point per $1 and redemption at 100 points equals $1 off, not $10 off.
- How do I stop a customer from cashing in a big points balance for almost-free product?
- Cap redemption at 25% of the current pre-discount basket total, so an $80 basket allows a maximum $20 redemption and the customer has to keep buying real product to use points. Lock redemption to the in-store register only, never online where baskets are already discount-stacked, and disable redemption on items that already carry an industry, heroes, medical, or sale discount. Also expire points after 12 months of inactivity, with a 30-day-before-expiry email that triggers re-engagement.
- What does the WSLCB actually care about with a loyalty program?
- Loyalty discounts get the same per-transaction audit-log treatment as any other discount, with the activity row stamped with discount type, points used, and dollar discount applied, queryable on demand per the WAC 314-55 family. Don't let a loyalty discount stack on already-discounted items to a point where the effective discount pushes past the same 50% cap that applies to the industry-discount rule. Loyalty data is customer-level PII, so build the customer export and delete flow before someone asks, since WA HB 1155, OR ORS 646A.602, and CA CCPA all apply.
Related guides
Operational deep-dive
Cannabis banking — keeping the account open, not finding one
7 min read
Operational deep-dive
Cannabis customer-acquisition cost — what to spend, what NOT to spend
7 min read
Real-estate + finance deep-dive
Cannabis dispensary lease — the negotiation that decides 10 years of margin
8 min read
Ready to talk through your migration?
30-minute demo. We end by quoting the cutover from your current setup — fixed scope, no hourly games.