Operations deep-dive
Cannabis customer SMS — what carriers actually filter, what gets you blocked
Cannabis customer SMS is harder than regular retail SMS for three reasons stacked: (1) carrier filters (T-Mobile, Verizon, AT&T) block cannabis-keyword content aggressively under their A2P 10DLC enforcement; (2) WAC 314-55-155 caps the message content even before carriers see it; (3) operators routinely tank their sender reputation by leading with ‘$10 off!’ spam-bait copy. Most operators don’t notice until 40% of their messages stop landing. Here’s the discipline that keeps the channel open + the patterns that don’t trip filters.
Why cannabis SMS is structurally hard
- A2P 10DLC carrier filters. Every business SMS in the US since 2023 must register a 10-digit-long-code (10DLC) campaign with the carriers. Cannabis is on the ‘restricted’ list; carriers approve campaigns at lower rates + sample messages aggressively. Send the wrong content + your registered campaign gets paused, not just the message blocked.
- Cannabis-keyword filtering. ‘THC,’ ‘flower,’ ‘edible,’ ‘ounce,’ ‘eighth’ — all soft-flagged. The combination of cannabis-keyword + discount-language + urgency-language is what carrier ML models score as spam. ANY ONE of those is fine; ALL THREE in one message and the deliverability rate drops to ~30%.
- WAC 314-55-155(2)(c) advertising scope. Customer-facing SMS that promotes cannabis products IS advertising. The age-disclaimer + audience-restriction rules apply. We can’t SMS to a number we haven’t verified is a 21+ customer (loyalty enrollment establishes that; cold prospect lists don’t).
- Sender reputation compounding. Once a number / shortcode hits a complaint threshold, ALL future messages from that sender get filtered harder. Recovery is months, not weeks. The discipline is preventing reputation damage, not recovering from it.
The 4 SMS types — and what works for each
| Type | Carrier filter risk | Recommended pattern |
|---|---|---|
| Transactional (order ready, account update) | Low | Lead with action: ‘Order ready for pickup at the front desk.’ No order-ID in body (PII discipline per memory). No discount tail. |
| Loyalty milestone (anniversary, birthday) | Low-mid | Lead relational: ‘Hey Alex, been a year since your first visit. Stop by when you’re around.’ No price-bait. No urgency. |
| Promotional (new product, weekly deal) | High | Lead with the product, not the discount. ‘New flower from <vendor> just landed; favorites of yours.’ No ‘LIMITED TIME’ / no exclamation marks / no $-bait. |
| Re-engagement (haven’t shopped in 60+ days) | Mid | Soft check-in: ‘Been a few weeks; everything good?’ Don’t lead with points-balance reminder (per memory: that pushes redemption + converts soft liability to hard discount). |
Pattern-level rules worth running
- One short, one URL, one CTA. Carrier ML models score multi-link / multi-CTA SMS as spam. Single link → /menu OR /pickup, NEVER both.
- Name the customer. Per the named-customer-beat operator pattern: ‘Hey Alex’ > ‘Hey there.’ First names only; we never use last names in SMS body. Ungendered.
- No exclamation marks. Carrier filters score them as spam-bait. The voice-rule from /docs/brand-voice.md applies to SMS verbatim.
- No price in the body. ‘Save $10’ / ‘30% off’ / ‘BOGO’ all trip filters. Mention the offer if relevant; don’t structure the message around the price.
- Phone normalization at the lib boundary, not the call site. Per the operator pattern: lib/sms.ts sendSms() calls normalizeToE164() internally. Don’t pre-normalize at call sites; centralized + idempotent.
- Quiet hours. No SMS before 9 AM or after 8 PM in the customer’s tz. Carrier complaint rates spike outside that window.
- Hard-stop on STOP. Customer replies STOP → no more SMS to that number, period. Carrier rule + ethical floor + the unsubscribe page lives at /unsubscribe.
- Cap frequency. No more than 1 SMS per customer per 7-day window. Repeat sends compound carrier-filter risk + customer-irritation risk.
What we don’t do
- No SMS to non-loyalty walk-ins. Single-visit cash customers haven’t opted in beyond the WAC 314-55 retail interaction. Their phone is on file (if at all) for ID-scan purposes only.
- No third-party SMS list rentals. Doesn’t prove 21+ verification; carrier-side complaint rate destroys sender reputation; WSLCB cite-able if they audit.
- No URLs to non-CannAgent / non-shop domains. Off-domain links score as suspicious in carrier ML; brand confusion compounds.
- No emojis in cannabis SMS body. Carrier ML treats heavy-emoji content as spam-marker. Plain text only.
- No order-ID in the customer SMS body. Per the POS customer-display payload schema memory + the pickup-flow guide: order-IDs are operator-side; customer SMS just confirms readiness.
Takeaways
- Cannabis SMS hits 3 stacked headwinds: A2P 10DLC carrier filters / WAC 314-55-155 advertising scope / cannabis-keyword spam-bait detection. ALL THREE in one message → ~30% deliverability
- Lead with relationship + product, not discount. Discount-led SMS hits carrier filters AND trains customers to wait + accelerates margin-leak (per loyalty-design)
- Pattern: one URL / one CTA / first-name only / no exclamation marks / no price-in-body / quiet hours 9-8 / hard-stop on STOP / cap 1 SMS per customer per 7 days
- Loyalty-only audience is the WSLCB floor — opted-in 21+-verified. Cold lists + non-loyalty walk-ins are not in scope
- Sender reputation compounds. Monitor DELIVERY rate (not just send rate); recovery from a hit is months not weeks. Prevention is the discipline
Frequently asked
- Why do my customer texts stop landing, and how would I even notice?
- Carriers score cannabis SMS with ML models, and the combination of a cannabis keyword plus discount language plus urgency language is what gets flagged as spam. Any one of those is fine, but all three in one message drops the deliverability rate to about 30 percent. Most operators discover the cliff retroactively, when a customer says they never got the text or loyalty-engagement metrics drop for no obvious reason, so monitor delivery rate on every campaign, not just send rate.
- Can I text a bought or third-party prospect list to bring in new customers?
- No. Under WAC 314-55-155(2)(c), cannabis advertising to a non-21-plus audience is a violation, and a cold or third-party list can't prove the recipient is 21-plus. Loyalty enrollment is your verified 21-plus list and is the floor for who you can message. Third-party list rentals also carry a carrier-side complaint rate that destroys sender reputation and are cite-able if the WSLCB audits.
- How should I write a promotional text so it doesn't hurt my ability to send?
- Lead with the product, not the discount, for example naming new flower from a vendor rather than the deal. Keep it to one short message with one URL and one CTA, use the customer's first name, and avoid exclamation marks, emojis, and any price in the body. Discount-led SMS trips carrier filters, trains customers to wait for the discount before buying, and accelerates loyalty redemption; let the customer find the discount in-store instead.
Related guides
Operational deep-dive
Cannabis insurance — what coverage actually triggers, what gets denied
7 min read
Operations + analytics deep-dive
Cannabis demand forecasting — the patterns that beat guessing
7 min read
Operations deep-dive
Cannabis pricing — when to discount, when to hold, when to feature
6 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.