How to Add a Loyalty Points Widget to Shopify
Why a Loyalty Points Widget Boosts Repeat Purchases
Acquisition costs keep climbing, so the cheapest sale you'll ever make is to someone who already bought from you. A visible points balance does two things at once: it reminds a logged-in customer that they've accumulated value, and it gives a first-time visitor a reason to create an account. Shopify's theme editor lets you place a small widget on product pages and in the cart without touching a third-party loyalty app, which is useful when you're testing whether a points program moves repeat purchase rates before you commit to a monthly subscription.
This guide builds a working points widget using Liquid, customer metafields, and a bit of JavaScript. It assumes you're comfortable editing theme code in a duplicate theme.
What You Need Before You Start (No App Required)
- A Shopify plan that supports metafields. Customer metafields are available on all current plans; older or restricted accounts may not expose the customer metafield definition editor.
- Theme access. Online Store → Themes → Actions → Duplicate, then work on the copy. Never edit your live theme first.
- A points rule you can state in one sentence. For example: "1 point per $1 spent, 100 points = $5 off." Write this down before you code, because the widget copy and the math both depend on it.
- A way to grant points. Shopify Flow (free on most plans, check current eligibility for yours) can trigger on order creation. Without an automation layer, you'll need to update metafields manually or via the Admin API.
- Basic Liquid familiarity. You need to know how to output variables, write
ifstatements, and loop through objects.
Decide up front whether points are awarded on order creation or on fulfillment. Awarding on creation is simpler but lets customers earn points on orders they later cancel.
Step 1: Create a Loyalty Points Snippet in Your Theme
Create a new snippet so the widget markup lives in one place. In your duplicated theme: Edit code → Snippets → Add a new snippet, name it loyalty-widget.liquid.
Start with the data layer. The snippet should read the customer's points balance and render nothing if the visitor isn't logged in:
{% if customer %}
{% assign points = customer.metafields.loyalty.points.value | default: 0 %}
{% assign tier = customer.metafields.loyalty.tier.value | default: 'Member' %}
<div class="loyalty-widget" data-points="{{ points }}">
<span class="loyalty-widget__label">{{ tier }} status</span>
<span class="loyalty-widget__balance">{{ points }} points</span>
</div>
{% else %}
<div class="loyalty-widget loyalty-widget--guest">
<a href="{{ routes.account_register_url }}">Join to start earning points</a>
</div>
{% endif %}
The | default: 0 filter matters. Metafields return nil for customers who have never earned points, and nil renders as blank rather than zero, which looks broken.
Add minimal styling in your theme's CSS or in a <style> block inside the snippet. Keep class names prefixed (loyalty-widget__) so future theme updates don't collide with them.
Step 2: Add the Widget to Your Product and Cart Pages
Render the snippet where you want it to appear. The two highest-converting locations are the product page (near the add-to-cart button) and the cart (near the subtotal).
Product page: open sections/main-product.liquid and insert the render tag after the buy buttons block:
{% render 'loyalty-widget' %}
Cart page: open sections/main-cart-footer.liquid or sections/cart-drawer.liquid depending on your theme, and place the same render tag above the checkout button.
Where to place it, and why:
| Location | What it does | Best for |
|---|---|---|
| Product page, below buy button | Shows balance at the moment of decision | Stores with high repeat-purchase rates |
| Cart page or drawer | Reminds shoppers of value right before checkout | Stores with larger average order values |
| Account page | Full balance and history | Building a dedicated rewards page |
| Site header | Constant visibility | Mature programs with active members |
Don't put it in all four places at launch. Pick one, measure, then expand.
Step 3: Store and Update Points with Customer Metafields
In Shopify admin, go to Settings → Custom data → Customers → Add definition. Create two definitions:
- Namespace and key:
loyalty.points, type Integer. - Namespace and key:
loyalty.tier, type Single line text.
The namespace and key must match exactly what your Liquid references, or the widget silently renders zero.
To award points automatically, use Shopify Flow:
- Trigger: Order created.
- Condition: exclude orders tagged
refundedorcancelledif you award on creation. - Action: Update customer metafield →
loyalty.points. - Value: use a Liquid expression that multiplies the order total by your points rate, then adds the existing balance.
Flow's metafield action can increment a value, but confirm the exact syntax in Flow's current documentation — the action's input fields have changed across releases. If Flow can't do the arithmetic you need, a small app or the Admin API with a scheduled job will.
If you don't want automation yet, update metafields manually from each customer's detail page in admin. This is fine for a pilot with a few dozen customers and unbearable past a few hundred.
Step 4: Show Points Balance to Logged-In Customers
The snippet already handles the balance display. Two refinements make it feel like a real program:
- Show progress to the next reward. If 100 points equals $5 off, display "23 points until your next $5 reward." Compute it in Liquid:
{% assign remaining = 100 | minus: points %}and render conditionally. - Update without a page reload. After a customer adds to cart via AJAX, the balance doesn't change (points are awarded on order), but if you ever award points client-side, re-render the widget from the JSON returned by your endpoint rather than relying on the cached page.
Keep the widget read-only on the storefront. Never let the browser write to loyalty.points — metafield writes from the storefront require the Admin API and a server-side token, and exposing that token is a serious security problem.
Testing Your Widget and Avoiding Common Pitfalls
Test with three accounts: a guest, a logged-in customer with zero points, and a logged-in customer with a nonzero balance. Use Shopify's Preview on the theme copy, and log in as each test customer.
Common failures:
- Widget renders blank for logged-in users. Almost always a namespace or key mismatch between the metafield definition and your Liquid.
- Points show as zero after an order. Flow ran before the customer record was associated, or the condition filtered the order out. Check the Flow run log.
- Widget appears on the wrong pages. You edited the wrong section file, or a theme update overwrote your render tag. Keep a note of every file you touched.
- Layout breaks on mobile. Long tier names like "Gold Member Plus" wrap badly in narrow cart drawers. Set a max-width and test at 375px.
- Duplicate widgets. Some themes render product sections twice for quick-view modals. Wrap the snippet in a check or accept two instances.
When to Upgrade from a DIY Widget to a Loyalty App
The DIY approach works until it doesn't. Move to a dedicated app when any of these become true:
- You want points on more than purchases — reviews, referrals, birthdays, social shares.
- You need redemption at checkout, not just a balance display.
- You're running tiers with different earn rates, or points that expire.
- Your customer list passes a few thousand and manual metafield updates aren't viable.
- You want reporting: which customers redeem, what the program costs you per month.
Established options include Smile.io, LoyaltyLion, Yotpo Loyalty, and Rivo. They differ mainly in pricing tiers, redemption flexibility, and how well they integrate with your email platform — check current pricing and feature lists directly, since these change often. A reasonable test: run the DIY widget for one quarter, measure repeat purchase rate for members versus non-members, and only pay for an app if the gap justifies the subscription.
Conclusion
A loyalty points widget is a small piece of Liquid backed by two customer metafields and one automation rule. Build it on a duplicated theme, test with real customer accounts, and watch whether members actually come back more often than non-members. If the numbers hold, that's your signal to invest in a full loyalty app.
FAQ
Do I need a paid app to show loyalty points on Shopify? No. Customer metafields, a Liquid snippet, and Shopify Flow cover a basic points balance and display. Apps add redemption, tiers, referrals, and reporting, which is where the subscription earns its cost.
Where should I place the points widget for the best results? Start on the product page below the add-to-cart button, or in the cart drawer above checkout. Pick one location, measure repeat purchase rate for members, then expand to a second location.
Why does my widget show zero points for customers who have earned them?
The most common cause is a namespace or key mismatch between your metafield definition and the Liquid reference. Confirm both read exactly loyalty.points and that the metafield type is Integer.