A loyalty program for the self-serve individual buyer — the maintenance technician, the single-location facility buyer, and the owner-operator. National Accounts are deliberately out of scope, and §09 explains why that boundary is drawn by the platform rather than by preference.
This is the sequel to Recently Purchased, which named guest-bridge login conversion as the retention metric that matters and then stopped short of saying how to move it. This brief is how you move it.
Live preview: v2/account-rewards.html · v2/cart.html · Date: July 2026
01TL;DR
BigCommerce ships no loyalty program — but it ships most of one. Tiers, freight perks, store credit, coupons and progress messaging are all native and free. The only pieces genuinely missing are the points ledger and the earn engine.
And USA Clean doesn't need a ledger yet. At ~1.61% of sessions including a login, this is not a retention problem — it is an identity problem, and a loyalty program is a solution to a retention problem. Every mechanic in this brief is worthless against an anonymous session. Buying a points app today would mean paying ~$199/month to run a balance for people who never sign in to see it.
The recommendation is "USA Clean Pro" — a free, login-gated status program whose currency is freight, not points, built entirely on native Customer Groups + the Promotions API, at zero recurring cost. Signing in lowers your free-freight threshold; spending more lowers it further. The points question is deferred until logged-in order share justifies paying for a ledger.
Loyalty is not one build-tier decision — it is two, and the first one is free. Native Customer Groups is a genuine zero-app tier engine (§04). A points ledger is not (§05). Don't let "should we do loyalty?" be evaluated as a single monolithic build-vs-buy call, because the answer differs for each half: tiers = OOTB. Points = app or custom.
On a $60 consumables basket carrying $12–15 of freight, waiving the freight is a 20–25% effective discount. The richest points program in the competitive scan — NAPA, ~5% nominal — returns about $3 on that same order, and only after clearing a 90-day reward-expiry hurdle a twice-a-year technician will never clear. Category norms are lower still (O'Reilly ~3.3%, Ace ~2%).
Freight is worth roughly 5–10× points to this buyer, it needs no explanation, and it is free to build. If the instinct is "we need a points program," the answer is not to price the apps — it is to show the client this arithmetic.
| Phase | Surface | What it solves | Effort |
|---|---|---|---|
| Quick wins Ship now | Auto-create-account at guest checkout · login-gated free-freight threshold · native progress nudge · instrumentation | The identity gap. Manufactures the logged-in population a loyalty program would later serve. | Lowest — admin settings and two promotion objects. A radio button and a form, not a build. |
| Phase 1 The program | Silver / Gold / Platinum on native Customer Groups · the nightly tier job · "claim your past orders" backfill · passwordless login | Gives a returning buyer a reason to sign in, and something waiting for them when they do. | Low–Medium — one scheduled job + promotion config. No app, no recurring fee. |
| Phase 2 Data-gated | Store credit as the reward instrument + our own earn ledger | A real reward currency, once there are logged-in buyers to spend it. | Medium — BC gives a balance but never a ledger; the ledger is ours to build. |
| Phase 3 Future | "My Machines" registry · paid Freight Pass · referral · points, if ever | Switching cost and acquisition, once the account has a population. | High — and each is independently gated; none is owed. |
Decision of record: pending — no client decision yet; will be logged as PD-006 in decisions.md.
02Current state
There is no loyalty program, no rewards surface, no tier, and no store-credit mechanic anywhere on shop.usaclean.com or in this prototype. A repo-wide grep for loyalty|rewards|points|rebate|VIP returns nothing but the eyebrow on Band 04 of the prototype landing page, which already reads "Post-purchase · Loyalty & personalization." The slot has been named for this feature since the index was restructured. It has been empty ever since.
What's actually broken is upstream of loyalty. The IA roadmap found 39% of sessions are returning visitors, but only ~1.61% include a login. Thousands of repeat buyers re-derive "what do I order for my Tennant T5" from scratch, every visit. That number is the whole reason this brief exists — and it is also the reason the obvious answer (buy a points app) is wrong.
What a self-serve buyer loses today by staying anonymous
- Their own history. Guest orders are orphaned — they exist in BigCommerce attached to an email address, but to no customer record. A returning technician cannot see what he bought for the T300 last time, because as far as the storefront is concerned he has never been here.
- Any reason to come back to us. There is no status, no accrued value, no saved machine — nothing worth more on the second visit than the first. The relationship resets every session.
- Themselves, in the account area. account.html leads with "Type: National," three sites, five users, fleet, approvals. As Recently Purchased put it: a single-location buyer with one machine and one past order sees none of themselves in it. An empty dashboard built for a 40-location chain is worse than no dashboard.
The data is already there. It is not surfaced, not claimed, and not rewarded.
03References
Zoro — the login-gated freight threshold (the most copyable mechanic in the scan)
Free ground shipping at $50 when signed in, $75 as a guest. No membership fee, no points, no ledger. The customer is paid — in the currency they care about most — to authenticate.
That is the entire acquisition engine of this brief, and on BigCommerce it is two automatic promotions, buildable in the admin UI with zero code. Everything else here is downstream of it.
Grainger RED PASS PLUS — the destination
$129/yr, free next-day delivery with no minimum, up to 15% off — and aimed explicitly at non-contract customers, which is precisely USA Clean's self-serve segment. The largest MRO distributor in North America has concluded that, for this buyer, freight is the product. Note that even Grainger offers a 60-day free trial: the paid tier is sold after the buyer has felt the benefit, never before.
Sherwin-Williams PRO+ — a major trade program with no points engine at all
One of the largest trade loyalty programs in America runs on tiered daily discounts. No points, no ledger, no expiry, no liability. It is the clearest evidence that a serious trade program does not require a currency.
NAPA / O'Reilly / AutoZone — why points fail this buyer, specifically
Automotive parts is the most mature individual-technician loyalty category, and its math is instructive:
| Program | Nominal rate | The disqualifying detail |
|---|---|---|
| NAPA Rewards | ~5% | Points expire after 1 year; issued rewards expire in 90 days |
| O'Reilly O'Rewards | ~3.3% | Rewards expire in 90 days |
| Ace Rewards | ~2% | — |
| SiteOne Partners | 1pt/$1 | $5,000 annual spend floor before points are redeemable at all |
A maintenance technician buys on failure — unpredictable cadence, perhaps 2–4 times a year. Under every program above, his points die before they ever reach a threshold. The mechanic is structurally incompatible with the buyer.
AutoZone is the exception worth stealing: it rewards trip frequency, not spend — a credit per qualifying visit regardless of size. That shape fits a failure-triggered buyer, and it maps onto BigCommerce's native customer.minimum_order_count with no ledger at all (§04).
Parts Town — the best technician UX in parts distribution
- My Equipment360 — save your machine, get the exact parts that fit it, its manuals and diagrams, and your own order history against that machine. This is the reason a technician creates an account, and it is the highest-value feature in this brief (§08, Phase 3).
- Order tracking is deliberately NOT gated. Anyone can track with an order number and a ZIP. The best operator in the category considered using tracking as an account lever and chose not to. Copy the decision, not just the feature.
SiteOne Partners — the channel-shift lever
2× points for ordering online. A direct, cheap attack on exactly the behavior USA Clean needs to change. Even if points never ship, the principle — pay more for the self-serve channel than the phone channel — belongs in the program.
Tractor Supply Neighbor's Club — reachable thresholds
Tier thresholds in the $500 / $2,000 annual range, not Home Depot Pro Xtra's $25,000 (Elite) / $250,000 (VIP). For a single-location buyer with one scrubber, a $25k ladder is not aspirational — it is an insult. Set the ladder where this buyer can actually climb it.
Harbor Freight Inside Track / WebstaurantStore Plus — how you sell a paid membership
Both are paid memberships that work, and both carry a device that de-risks the purchase for a P&L owner: Harbor Freight's 90-day full refund, and WebstaurantStore's "Guaranteed Savings" clause (they credit you the difference if annual savings don't beat the fee). If a Freight Pass is ever sold (§08), it ships with one of these or it doesn't ship.
The floor-care whitespace — opportunity, or warning?
There is no end-customer loyalty program at Imperial Dade, Bunzl, Veritiv, SweepScrub, or any of the Tennant / Nilfisk / Kärcher direct parts channels. The optimistic reading is first-mover advantage. The pessimistic reading is that JanSan consumables margins will not support a 2–5% giveback, and everyone in the category has already run this math. Get the gross-margin number (§09) before anyone puts "industry-first loyalty program" on a slide.
04What BC Stencil gives us
More than expected. This is the section that changes the shape of the recommendation.
- Customer Groups are a real, zero-app TIER ENGINE.
POST /v2/customer_groupscreates a group carrying adiscount_rules[]array; each rule has atype(all|category|product|price_list) and amethod(percent|fixed|price). Silver is one rule —{type:'all', method:'percent', amount:3}. Gold is 5. Platinum is 8. Membership is the single scalarcustomer_group_id, writable viaPUT /v3/customers. The entire "engine" is a nightly job that reads trailing-12-month spend from the Orders API and writes one integer. Two REST endpoints. No app, no custom storefront code, no recurring fee. (Note the v2/v3 asymmetry: group membership is writable on v3, but the groups themselves are v2-only.) - Free shipping, gated on customer group, as an automatic promotion.
action: {shipping: {free_shipping: true, zone_ids: '*'}}+customer: {group_ids: [GOLD]}+rules[].condition.cart.minimum_spend, withredemption_type: 'AUTOMATIC'so it applies with no code. This is Zoro's mechanic, natively, for free — and it is buildable in the admin UI with zero code. Schema gotcha:customeris a top-level key on the promotion object, not a clause nested insidecondition— the nesting most write-ups get wrong returns a 422. Also:group_idsandexcluded_group_idsare mutually exclusive on one promotion, andgroup_id 0means guests + customers in no group, which is exactly the handle the guest-tier promotion needs. customer.minimum_order_count— a native, ZERO-LEDGER loyalty trigger. "Your 5th order ships free" works with no counting infrastructure whatsoever; BigCommerce evaluates the customer's order count itself. This is the AutoZone trip-frequency shape, free, today.- Promotion
notifications— the free progress bar. Four types (PROMOTION/UPSELL/ELIGIBLE/APPLIED) across four locations (HOME_PAGE/PRODUCT_PAGE/CART_PAGE/CHECKOUT_PAGE), HTML-capable, with BigCommerce handling the UPSELL → ELIGIBLE → APPLIED progression itself. And because the notification hangs off a group-gated promotion, the messaging is automatically tier-aware: a Gold member sees "you're $18 from free freight" against $50; a guest sees it against $125. This is normally a custom cart-drawer build. It shipped into the Standard Editor on 2025-08-19 — anything the team remembers from before that is stale. - Store credit — the right rail for an individual. Per-customer (the "no company-scoped balance" problem that kills this for National Accounts simply does not apply here), API-writable (
store_credit_amountsonPUT /v3/customers), storefront-readable via GraphQL (customer.storeCredit), and it auto-applies at checkout with no code for the buyer to dig out of an old email. - Gift certificates —
POST /v2/gift_certificates, with a realexpiry_date, partial redemption, a carrying balance, and no email sent on API creation, so we own the delivery. - Auto-create-account-after-guest-checkout is a native radio button. Settings › Checkout › Customer Accounts → "Customers are not required to have an account to check out, but automatically create one after ordering." It converts every guest purchase into a customer record with an order history and a set-password email. This is the precondition for literally every other mechanic in this brief.
- Passwordless magic-link login is native — a one-time email link to
/login.php?action=check_passwordless_login&token={token}. - Multi-coupon shipped 2026-01-05 — up to 5 codes in the native cart and checkout.
- Order webhooks for an earn ledger:
store/order/statusUpdatedandstore/order/refund/createdare the settle/claw-back pair.store/order/createdis the wrong accrual trigger — the order isn't paid yet.
Native gives us the tiers, the freight benefit, the progress messaging, the reward rail, the account-creation flow, and the login mechanic — the whole program as recommended, for $0/month. What it does not give us is a ledger: a record of what was earned, when, and why. That is the one thing we would ever pay for, and we should not pay for it until there are logged-in buyers to put in it.
05Stencil limitations
Per rule #2, exactly what native BC cannot do here:
- No loyalty, points, or referral feature of any kind. No object, no admin screen, no API. BigCommerce's own rewards glossary routes merchants to the App Marketplace, and its 2026 product-roadmap post is silent on loyalty while explicitly framing retention as a promotions problem. Waiting for BC to ship loyalty is not a strategy.
- No ledger. Store-credit grants leave no trace at all — only redemptions are reconstructible from order data, and there is no "total outstanding credit" report anywhere in the platform. If we grant credit, we must keep our own book, or we cannot answer "how much do we owe?"
- No store-credit expiry. Gift certificates have one; store credit does not.
- Store-credit application is all-or-nothing. BC applies all available credit up to the order value; the buyer cannot elect to spend $40 of a $120 balance and save the rest. (Leftover value is not forfeited — but the choice isn't theirs.) Mitigate by not defaulting the toggle on: "You have $42.50 — apply now, or save it for a larger order?" We control when the endpoint fires.
minimum_order_countis lifetime and monotonic. Counts only go up, so a tier built on it can never demote, and the giveaway compounds forever. It is also API-only — promotions using it aren't creatable in the control panel, so merchandising staff can't self-serve them.- No native guest-order claim, and no native guest-order lookup. Both are sold as marketplace apps, which is the strongest available evidence the platform lacks them.
- Customer Groups require the Growth plan or above — the tier engine does not exist on Core. (BigCommerce renamed its plans on 2026-06-01: Standard→Core, Plus→Growth, Pro→Scale, Enterprise→Performance. Do not say "Plus" in the deck.) USA Clean is almost certainly above Core given they are buying B2B Edition — but this must be a checked box, not an assumption, because the entire engine collapses without it.
- Customer Segments are Performance-plan-only and in closed beta. Not an escape hatch for orthogonal segmentation below the top plan.
- No review webhook — so "points for writing a review" has no native trigger.
The program as recommended ships entirely on native BigCommerce. The limitations bite only when we reach for a currency — and that is exactly the part we are deferring.
06App marketplace shortlist
The client's rule is that an app loses if its recurring fee passes a one-time custom build within 12–18 months. Here there is a prior test the apps have to pass first: they have to beat free. Native Customer Groups + Promotions + store credit deliver the recommended program at $0/month. Every app below is therefore being asked to justify a fee against a working, zero-cost alternative — not against a build.
| App | What it does | Pricing (2026-07 — confirm on listing) | Pricing shape | Verdict |
|---|---|---|---|---|
| Lootly | BC-native points, VIP tiers, referrals, points for non-purchase actions | Growth ~$79/mo · Ultimate ~$249/mo · Enterprise ~$599/mo. Unlimited orders and customers on every plan. | Friendly — flat, unlimited orders | Secondary. The only BC-native option whose pricing shape fits a many-small-orders parts catalog, and the right call if points are ever wanted. But it duplicates a tier engine we already have for free, and buying it now means paying for a ledger before there are logged-in users to put in it. Revisit at Phase 3. |
| Smile.io | Points, VIP, referrals | Free (200 orders/mo) · $15 (500) · $79 (1k) · $199 (2.5k) · $999/yr (7.5k) + overage. Pricing page is Shopify-positioned; BC pricing is a sales conversation. | Hostile — order-gated | Exclude. Order-count metering taxes exactly the many-small-orders reordering behavior the program exists to create. You would pay more, per month, the better the program worked. |
| Yotpo Loyalty | Points, referrals | ~$199/mo (500 orders) + ~$0.20/order overage — secondary sources, unverified | Hostile — order-gated + per-order overage | Exclude. Same defect as Smile, with an explicit per-order tax on top. |
| LoyaltyLion | Points, tiers | ~$199/mo published; higher tiers "custom." BigCommerce is not mentioned on the pricing page. | Hostile | Exclude. B2C per-shopper architecture; no evidence of meaningful BC investment. |
| PayWhirl | Subscriptions/memberships — and crucially, it assigns a native BC customer group on signup and removes it on cancellation | ~$49/mo (Business Pro) + ~2% of subscription revenue | Flat + % | Hold → the paid-membership path. This is how "Freight Pass" gets built: PayWhirl + a native customer group + one free-freight promotion. Nothing custom. Gate on repeat-frequency evidence (§08), and configure dunning to auto-cancel on failed payment — otherwise the group stays active and we give freight away to lapsed members. |
| ReferralCandy | Referral | ~$79/mo + 3.5% success fee on referred customers' first orders | Pay-for-performance | Hold. The only shape here that doesn't charge for orders we'd have got anyway. But you cannot refer from nobody — this is the last mile. Confirm the BigCommerce integration is real before committing; its pricing page carries a Shopify CTA. |
| Mira Commerce — Guest Order Status | Un-gated order lookup by order # + billing ZIP, as a Page Builder widget | Unpublished — confirm on listing | — | Worth it now (small). Buy, don't build. And do not put a login in front of it (§09). |
The honest reframe on build-vs-buy
The apps do not lose on price. A $199/mo app is ~$3,582 over 18 months — plausibly under what a custom points ledger would cost to build (~280–420h ≈ $35k–$55k, plus $8k–$15k/yr to run). By rule #3's arithmetic alone, the app wins.
They lose on shape and on sequence.
- Shape: the order-gated meters (Smile, Yotpo, LoyaltyLion) charge more as reorder frequency rises — they tax the exact behavior the program is built to create. Only Lootly's flat/unlimited pricing survives this catalog.
- Sequence: every one of them sells a ledger, and a ledger is the last mile. At ~1.61% login, buying one means paying a subscription to run balances for people who never sign in to see them. Manufacture the logged-in population first — with native tools that cost nothing — and only then ask whether a currency is worth renting.
Native for the whole program. No app in Phase 1 or 2. One small app purchase (guest order lookup) because it is cheaper than a week of work. Lootly and PayWhirl are Phase-3 options, each gated on evidence we don't yet have.
This is the mirror image of Subscribe & Save's conclusion — there, native genuinely could not produce the recurring charge, so an app was the honest answer. Here, native genuinely can produce the whole program, so it is.
07Caster impact
Everything new stays inline in the consuming page — rule #7, first-consumer scope. Nothing in shared Caster CSS changed, so the cache-bust stays at ?v=0.16.3 and /bump-cache-bust was not run.
| Pattern | Classes | Consumers today |
|---|---|---|
| Tier ladder + progress | .tier-ladder, .tier-step, .tier-progress | v2/account-rewards.html |
| Freight benefit table | .freight-table, .freight-row--you | v2/account-rewards.html |
| Credit balance + earn history | .credit-hero, .earn-row | v2/account-rewards.html |
| Freight progress nudge | .freight-nudge, .freight-nudge__bar, .freight-nudge--guest | v2/cart.html |
.freight-nudge is the one to watch. The moment it appears on a second surface — the PDP, or a mini-cart — it has earned promotion to components.css with a showcase page and a design-system/decisions.md entry. It is also the pattern most likely to spread, because it is the program's whole voice: you are $18 from something you want.
The account chrome (.acct-tabs, .acct-tabs__item, .pill-count, .card) is reused unchanged from the existing account surfaces.
08Phased recommendation
Quick wins — ship now (OOTB, hours to days, ~zero cost)
None of these is a loyalty program. All of them are the precondition for one, and several are worth doing even if the program is never built.
- Turn on auto-create-account-at-guest-checkout. It is a radio button. It is free. It converts every guest purchase into a customer record with an order history, and it is the precondition for tiers, store credit, and every targeted promotion. Ship it first.
- The login-gated free-freight threshold — two automatic promotions ($50 signed in, $125 guest). Scope
zone_idsto the contiguous US, and scope the promotion to parts/consumables categories so it can never fire on a freight-classed machine. - Native progress messaging — attach
notificationsto those promotions. Commit to CART + CHECKOUT (dependable); validate HOME/PDP in the live theme before promising them. - Enable multi-coupon, and set
can_be_used_with_other_promotions: trueon tier promotions — otherwise a Gold member who clicks a promo code in an email has their tier discount silently cancelled, the precise opposite of the behavior we're trying to buy. - Instrument the real numbers (§09) — before building anything.
- Write the three non-goals down as explicit decisions (§09).
Trigger to graduate to Phase 1: the account-creation switch is live and guest→registered conversion is measurable, and the answer to the logged-in-order-share question (§09) says there is a real gap to close.
Phase 1 — the program (Low–Medium; native, no app, no recurring fee)
"USA Clean Pro." Silver / Gold / Platinum on native Customer Groups, earned on trailing-12-month spend, with thresholds in the $500 / $2,000 range — Tractor Supply's order of magnitude, not Home Depot's.
| Guest | Silver | Gold | Platinum | |
|---|---|---|---|---|
| Free freight above | $125 | $75 | $50 | $0 |
| Store-wide discount | — | 3% | 5% | 8% |
| Priority processing | — | — | ✓ | ✓ |
| Saved machines | — | ✓ | ✓ | ✓ |
| Priority support line | — | — | — | ✓ |
Plus the two things that make an account worth having on day one:
- "Claim your past orders" — match orphaned guest orders by email and write
customer_idonto them. This is the direct answer to what the anonymous returning technician actually loses: not a discount — his own history. Without it, a new account is an empty room and the buyer must wait until their next purchase for it to mean anything. - Passwordless magic-link login — for a technician with greasy hands on a phone at 11pm, "tap the link in your email" beats any password flow ever designed. Ship it with the backfill: together they are the technician unlock — "tap here to see everything you've ever ordered for your T300." Ship it without the backfill and the magic link opens an empty room.
Ship the un-gated guest order lookup (order # + ZIP) at the same time, as the program's deliberate counterweight. Parts Town proves the best operator in the category chose not to use tracking as a lever.
Trigger to graduate to Phase 2: logged-in order share is high enough that a credit balance would actually be seen and spent. Until then, credits accrue to accounts nobody signs into and become an un-auditable liability.
Phase 2 — a reward currency (data-gated)
Store credit as the reward instrument, with our own earn ledger. Store credit is the redemption rail (per-customer, auto-applies, no code); the ledger is a small table written from store/order/statusUpdated + store/order/refund/created, because BC gives us a balance and never a ledger. The account-area "how you earned this" view is built from our records, not BC's.
Settle two policy questions before building: the all-or-nothing redemption behavior (§05), and whether a welcome credit is survivable against consumables margin (§09).
Phase 3 — future (each independently gated; none is owed)
- "My Machines" — the equipment registry (the Parts Town pattern). The highest-value technician feature in this brief and the reason a technician creates an account at all. Hard dependency: does a reliable machine-model → compatible-parts mapping exist? If not, this is a catalog-data project before it is a UX project, and the estimate changes by an order of magnitude. This is the same mapping PD-004 is already data-gated on — the two should be resolved together.
- Paid "Freight Pass" (Grainger RED PASS PLUS is the destination). Two gates, measured not assumed: self-serve repeat frequency ≥ ~6 orders/year (below ~4–6 a paid tier will not renew), and the free freight program has already proven freight is the lever. Sell it with a Harbor-Freight-style refund or a WebstaurantStore-style guaranteed-savings clause.
- Technician-to-technician referral — after a population of logged-in, repeat, satisfied technicians exists. You cannot refer from nobody.
- A points currency — only if the client wants one. If forced, argue hard for the AutoZone shape: reward trip frequency, not spend, which fits a failure-triggered buyer and maps onto native
minimum_order_countwith no ledger at all. Treat "do we want points?" as a separate, later, independently-justified decision — not a sub-item of "do we want loyalty." - QR code on the machine → straight to its parts. Depends on "My Machines" existing first, and it is an operations commitment (who applies the stickers, at what touchpoint?) before it is a feature.
Decision of record: pending — no client decision yet; will be logged as PD-006 in decisions.md.
09Implementation notes
The two traps (both will actually happen)
BigCommerce applies customer-group discounts before product-level bulk pricing, and a fixed-amount bulk rule overrides the group discount entirely at that quantity break. USA Clean runs quantity breaks on consumables (see volume discounts). If any are configured as fixed-price rather than percent-off, the Silver/Gold/Platinum discount is silently discarded on exactly the SKUs these buyers buy most — the tier member sees no tier benefit precisely where they'd most expect one. Audit product-level bulk pricing before shipping.
Product-level discounts shrink the subtotal before the order-level free-freight threshold evaluates. So a Platinum buyer's own 8% discount can knock them back under the free-freight line — and freight is the benefit they actually care about. BigCommerce's execution order will not honor your priority intent here; priority and stop order promotions within a class, not across classes. Model the freight threshold against a realistic post-discount basket, not a list-price one, and test it.
Discount precedence
BC's real execution order: customer-group discounts hit product price → product-level bulk pricing (which a fixed-amount rule can override) → product-level promotions → order-level promotions (subtotal only — explicitly excluding shipping, which is why free freight must be a shipping-scoped action, not an order-level percentage) → coupons, up to 5.
Unlike National Accounts, there is room in the price here — these buyers pay list, not a negotiated contract price. But the worst-case stack is now legally reachable since multi-coupon shipped: Platinum 8% + a welcome credit + a seasonal coupon + free freight, on one order. Model it, put a floor under it (minimum spend, category exclusions), and price it before raising the coupon count above 1.
Data sources
- Tier computation: trailing-12-month spend from the Orders API →
PUT /v3/customerscustomer_group_id. A nightly scheduled job. - Derive the tier from our own spend record, never from state that lives only in
customer_group_id— see the graduation trap below. - Earn ledger (Phase 2):
store/order/statusUpdatedto accrue on a settled status,store/order/refund/createdto claw back. Notstore/order/created— the order isn't paid yet.
The B2B boundary — why this brief is scoped the way it is
A BigCommerce customer carries exactly one customer_group_id. For a B2B Edition company user, that slot is consumed by the contract price-list group. For a self-serve individual, it is empty — which is the entire reason the native tier engine is available for this segment and structurally unavailable to National Accounts. A customer can be in a loyalty tier or a contract price-list group. Never both.
It compounds: National Account orders arrive via Net-30 / PO / rep-keyed / EDI / punchout and bypass the storefront checkout entirely, so store credit, gift certificates and cart promotions do not function for them at all. The same instruments work perfectly for the self-serve buyer precisely because they reach checkout. National Accounts want an off-invoice rebate; that is a different brief.
Four requirements follow:
- Exclude B2B Edition customers from every loyalty promotion, explicitly, via
customer.excluded_group_ids. (Budget an extra promotion object per tier boundary —group_idsandexcluded_group_idsare mutually exclusive on one promotion.) - Guard the nightly tier job: it must never write a loyalty group id onto a customer linked to a B2B Edition company. One bad
PUTsilently destroys a negotiated contract price. - Design for graduation, not collision. A single-location buyer who grows into a small chain is the success case — and on the day they become a company user, the group slot is taken and their loyalty tier silently vanishes. So (a) derive the tier from an external, re-projectable spend record, and (b) make graduation an upgrade: the negotiated contract price must beat Platinum, visibly. If a customer's contract price is worse than the tier they just left, we have built a trap and they will find it.
- Keep the two programs invisible to each other in the UI. Tier badges and credit balances must not render for B2B-linked customers; contract-pricing language must not render on self-serve surfaces. This is why account.html and account-home.html are untouched by this work — that separation is the boundary, made visible in the prototype.
One shared surface is fine, and only one: identity. Passwordless login, guest-order claiming, order tracking and the machine registry are useful to a National Account technician too, and none of them touch pricing. Build the identity layer once, for everyone. Build the reward layer twice, separately, and never let them meet.
Non-goals (write these down as decisions)
- Do NOT force account creation before purchase. Baymard Institute (n=4,384): 24% of shoppers abandoned a cart solely because they were forced to create an account — the #2 abandonment reason after surprise costs. Amplified, not softened, for a technician on a phone next to a dead machine at 11pm. Offer the account after the purchase, as a benefit — never before it, as a toll.
- Do NOT hide prices from guests. The peer set shows list price to everyone and reveals a better price on login (MSC: "Log in to save on over 1 million products"). "Sign in to see YOUR price" works. "Sign in to see A price" does not. And there is a USA-Clean-specific reason: hiding prices from guests hides them from AI answer engines too, which directly contradicts the GEO/AEO audit already delivered on this account.
- Do NOT put order tracking behind a login. Parts Town — the most sophisticated technician UX in parts distribution — deliberately lets anyone track with an order number and a ZIP. A tech whose machine is down needs the tracking number, not a signup form.
The questions the client must answer
- Of customers with at least one prior purchase, what share of their subsequent orders are placed logged-in? This one query decides whether the program is urgent or optional — it isolates the real retention failure from ordinary anonymous browse traffic. If it comes back high, the 1.61% figure is an artifact and a real rewards program becomes a legitimate next move rather than a premature one. Run it first.
- What is freight as a share of a typical self-serve order — and do we already ship free above some threshold? If free freight is already given away, the strongest lever in this research is already spent and the recommendation changes materially.
- What is the gross margin on consumables? Decides whether a 2–5% giveback is survivable — and whether the floor-care whitespace (§03) is an opportunity or a warning.
- What BigCommerce plan are we on? Customer Groups require Growth or above — the entire tier engine collapses on Core.
- Are any consumables bulk-pricing rules configured as fixed-amount rather than percent-off? If yes, they will silently void the tier discount on the highest-velocity SKUs (Trap 1).
- Is
customer_idwritable on an existing guest order? Decides whether the "claim your past orders" backfill is a one-week build or an app purchase.
Auth + role gating
Everything here is signed-in-only by construction — which is the point, not a limitation. The tier engine is invisible to a logged-out shopper, and that is precisely what makes it a login incentive. But it means the logged-out surface is the load-bearing half: "Sign in — members ship free at $50" on the cart is what converts. That copy is theme work, and it is where the program lives or dies.
Accessibility
The freight nudge is a live region, not just a visual bar — when the remaining-to-threshold figure changes on a qty update, it must announce. The <progress> semantics carry aria-valuenow / aria-valuetext ("$18 remaining to free shipping"), and the bar is never the only carrier of the information — the text states it. Tier badges are text, not color alone. The tier ladder is a list with a programmatic current-step indicator, not a purely visual highlight.
Performance
The tier resolves server-side on login (it's a customer-group price), so there is no client-side flash. The nudge is rendered by BC's native promotion notifications, so it costs no additional request.
Analytics
Split every metric by segment — self-serve only. National Account volume will swamp the numbers and make the freight and margin math wrong in both directions.
- Guest → registered conversion (the quick-win metric — does the radio button work?).
- Logged-in order share, and the sharper cut: of customers with ≥1 prior purchase, the share of subsequent orders placed logged-in. This is the metric the whole program is judged on.
- Freight-nudge conversion — carts that crossed the threshold after seeing the UPSELL banner.
- Tier distribution and tier-up rate — is the ladder reachable?
- Credit redemption rate (Phase 2) — and outstanding liability, from our ledger, because BC will not tell us.
10Catalyst / replatform candidacy
This feature is not a replatform argument, and it would be dishonest to make it one.
Can it ship well in Stencil? Yes — entirely. The tier engine is two REST endpoints and a nightly job. The freight benefit and the progress nudge are native promotion objects that BigCommerce renders itself. The account surface is one Stencil template. There is no part of the recommended program that Stencil expresses awkwardly.
Would Catalyst make it materially easier? No. The constraints that shape this brief — no ledger, one customer_group_id, all-or-nothing store credit — are platform-data constraints, not rendering constraints. A React storefront does not give BigCommerce a points ledger. Replatforming would change nothing about the parts that are hard.
What is lost by holding for the replatform? Everything, for no gain. This is the rare brief where the honest answer is that the replatform is irrelevant. Ship it on Stencil.
The one Phase-3 item with a genuine headless flavor is "My Machines" — a stateful, fleet-aware registry that wants a server-side data layer, and which converges with the Phase-3 personalization case in Recently Purchased, Search and Model landing. As those briefs already note: personalization is the through-line that eventually justifies the headless move, but none of them justify it alone — and this one justifies it least, because its Phase 1 needs nothing.