Rewards & redemption
How to use it
Let customers turn points into real discounts:
- Set your redeem rate — how many points equal $1 off. (Loyalty → Setup → Redemption)
- Build a reward catalogue — e.g. "500 pts = free shipping", "1,000 pts = free gift". (Loyalty → Rewards)
- Turn on margin guardrails — a max discount % and a minimum order. (Loyalty → Setup → Guardrails)
- Expose redemption in the storefront widget so customers redeem in one click. (Theme editor)
⏱ ~15 min · 💳 Starter+ · 🎯 Every redemption mints a real Shopify code
Two ways to redeem
| Points → discount | Reward catalogue | |
|---|---|---|
| What the customer spends | Any amount of points | A fixed points cost you set |
| What they get | A code worth points ÷ redeem-rate | The reward you defined (amount / % / free shipping / free gift) |
| Best for | "Spend my balance" flexibility | Curated, memorable rewards ("500 pts = free shipping") |
Points → discount
The customer chooses how many points to burn; the system mints a fixed-amount
Shopify code worth points ÷ redeem_rate. With the default rate, 500 points →
a code worth 5 units of currency.
Reward catalogue
Define rewards where the points cost and the value are decoupled — e.g. 500 points for free shipping, or 1,000 points for a free gift product. Reward types:
| Type | What the code does |
|---|---|
amount | Fixed currency amount off |
percentage | Percentage off (self-capping) |
free_shipping | Free shipping |
free_gift | A 100%-off code for a specific gift product |
Redemption is safe by design
Customers never lose points to a glitch — a redemption only completes if the discount code is actually created, and a network retry can't mint a second code or double-charge points. It's all built in; there's nothing for you to configure. Order of operations is deliberate, because minting is an external call that can fail:
The safety mechanics (for the curious)
- Mint before debit — if Shopify can't mint the code, the customer's points are never touched.
- Roll back on debit failure — if the ledger write fails after minting, the code is voided, so you never issue a live code without a corresponding debit.
- Idempotency key — pass a key and a retried/duplicated request returns the first result (same code, same balance) instead of minting a second discount and double-debiting. A database uniqueness rule is the backstop for the concurrent case.
This is what makes redemption safe to expose on a storefront where network retries and double-taps are the norm.
Margin guardrails (enforced at checkout)
Two optional guardrails protect contribution margin. Both are off by default, so redemption behaves exactly as before until you opt in.
| Guardrail | Effect | Example |
|---|---|---|
| Max redemption % | A fixed-amount code can't exceed this share of the order | A $6 code at 30% requires an order ≥ $20 |
| Minimum purchase | A floor subtotal to use any loyalty code | "Loyalty codes need a $25+ cart" |
The key detail: these are stamped onto the minted code as a Shopify
minimumRequirement. That means Shopify's own checkout enforces them — they
are not a client-side check that can be worked around. A percentage or
free-shipping reward is self-capping, so the max-% cap only applies to
fixed-amount redemptions; the minimum-purchase floor applies to all of them.
Without a floor, a "$10 reward" can be used on an $11 order — a 91% discount on that sale. Turn on max-% (a good starting point is 30%) and a sensible minimum before you push customers to redeem.
Points as a liability
Outstanding points are a real financial obligation. Their monetary value —
points ÷ redeem_rate — is computed from the single source of truth for the
redeem rate, so the liability figure on your
Revenue Hub can't drift from the
"100 points = $1" disclosure customers see. Points expiry (see
Earning points) is what keeps this liability
bounded.
Best practices
✅ Lead with the catalogue, not raw redemption. "500 points = free shipping" is more memorable and easier to cost than an open-ended points-to-cash slider.
✅ Always pass an idempotency key when redemption is triggered from the storefront — it's the difference between one code and three on a flaky connection.
✅ Use free_gift rewards to move specific inventory — a slow-moving SKU as a
reward costs you COGS, not margin on a hero product.
❌ Don't offer high fixed-amount rewards without a max-% cap — that's the single biggest way loyalty erodes margin.