figma guide

Designing loyalty programs and rewards UI in Figma: points, tiers, and checkout redemption

Design loyalty points, tier badges, earn-and-burn flows, and checkout redemption UI in Figma with component variants, balance states, and Dev Mode specs for ecommerce teams.

Published
Updated
Jun 28, 2026
Read time
7 min
Level
Beginner

Quick answer

Loyalty UI is a small set of reusable components—balance display, tier badge, earn callout, and redemption control—wired to the same points ledger everywhere. Show points balance in the account header, cart drawer, and checkout summary. At checkout, offer a toggle or slider to apply points with live order-total updates. Tier status (Silver, Gold) appears as a compact badge on profile and PDP promos. Never design loyalty as a separate visual language; reuse pricing tokens, badges, and progress indicators from your ecommerce system. Start from the Figma guides hub and templates pillar.


Who this is for

  • Product designers shipping DTC programs where repeat purchase and membership tiers drive revenue.
  • Design system teams standardizing points math, tier visuals, and redemption states across web and app.
  • Engineers implementing ledger APIs, partial redemption rules, promo stacking, and fraud limits.

Loyalty surfaces map

SurfaceComponentPurpose
Global header / account menuPointsBalanceAlways-visible balance pill
PDP promo bandEarnCallout”Earn 120 points with this purchase”
Cart drawerPointsBalance + optional apply linkRemind before checkout
Checkout payment stepPointsRedemptionApply/remove points with live total
Order confirmationPointsEarnedPost-purchase reinforcement
Account loyalty hubLoyaltyDashboardHistory, tier progress, rewards catalog
Order history rowPointsEarnedLinePer-order earn/spend audit

Verdict: checkout redemption is the highest-risk surface—design every state (available, applied, insufficient, expired) before polishing the marketing dashboard.


PointsBalance anatomy

PartSpecNotes
IconStar, coin, or brand mark16–20px; consistent everywhere
Balance numberInteger or formatted”1,240 pts” or “$12.40 value”—pick one model
Label (optional)“Rewards”Hide on compact header variant
Tier badgeTierBadge adjacentGold dot or pill
LoadingSkeleton or spinnerOn account fetch
PointsBalance
├── Variant: density=compact | standard
├── Variant: state=loaded | loading | error | guest
├── Property: balance=1240
├── Property: showTier=true
└── Layers:
    ├── Icon
    ├── BalanceText
    └── TierBadge (optional)

Use Auto Layout with 4px gaps. Guest state should prompt Sign in to earn points with a text link—not a disabled balance that looks broken.


TierBadge and tier progress

Tier patternUI treatmentWhen to use
Named tiersSilver / Gold / Platinum pillsStatus programs with thresholds
Progress to next tierBar + “Spend $80 more for Gold”Annual spend or points-based tiers
Flat membershipSingle “Member” chipNo tiers; perks only
Subscription overlapSeparate badgeWhen loyalty ≠ subscription product
TierProgress
├── Variant: layout=inline | card
├── Property: currentTier=Silver
├── Property: nextTier=Gold
├── Property: progressPercent=65
└── Layers:
    ├── TierBadge
    ├── ProgressTrack → ProgressFill
    └── NextTierMessage

Reuse progress indicator tokens for the track. Tier colors must pass accessibility contrast on both light PDP promos and dark account headers.


EarnCallout on PDP and cart

PlacementCopy patternAvoid
Below price”Earn 50 points ($0.50)“Burying in footer
Cart line itemPer-SKU earn on eligible itemsShowing earn on excluded SKUs
Checkout summaryTotal earn for orderConflicting with applied redemption

Link earn copy to the same points-per-dollar rule documented in Dev Mode. If coupons reduce eligible subtotal, annotate that earn may recalculate.


PointsRedemption at checkout

StateUIUser action
AvailableToggle “Apply 500 points ($5.00)“Toggle on
AppliedGreen check + deducted line in summaryToggle off or edit amount
Partial applySlider or stepper for points amountRare; needs clear max
InsufficientDisabled toggle + explanationNone
Cannot combineInline alert when stacked with couponRemove coupon or points
LoadingDisabled toggle + spinnerWait for ledger
ErrorInline alert + retryRetry fetch
PointsRedemption
├── Variant: state=available | applied | disabled | loading | error
├── Property: maxPoints=500
├── Property: pointsValue=5.00
├── Property: currency=USD
└── Layers:
    ├── ToggleRow (label + switch)
    ├── ValuePreview
    ├── SummaryDeductionLine (applied)
    └── ConflictAlert (optional)

Order summary lines should mirror checkout UI: Subtotal → Discounts → Points applied (−$5.00) → Tax → Total. Tax recalculation after points is a backend rule—note it in handoff.


LoyaltyDashboard (account hub)

ZoneContentComponents
HeroBalance + tierPointsBalance, TierProgress
Quick actionsRedeem, refer, view catalogButton row
Activity feedEarn/spend historyTable or list rows
Rewards catalogRedeemable coupons, free productsCard grid
Referral blockShare link + bonusCopy field + toast on copy
FAQProgram rulesAccordion

Align activity rows with order history patterns so users recognize the same date, status, and amount formatting.


Stacking rules comparison

RuleUX implicationDesign note
Points + site-wide saleUsually allowedShow earn on discounted price
Points redemption + couponOften blockedConflictAlert variant required
Points on gift card purchaseOften excludedHide earn callout on gift card UI
Free shipping tier + pointsIndependentShipping bar unchanged
Partial points + card paymentStandardRemaining balance on card line

Document stacking in a Program rules frame linked from checkout—not buried in legal PDF only.


Responsive and mobile patterns

BreakpointAdaptation
Mobile checkoutFull-width redemption card above payment methods
Mobile headerIcon-only balance with tap → loyalty hub
TabletBalance in account drawer, not crowding header
AppMatch web component names for parity

Use mobile frame presets for checkout and account screens. Sticky checkout summary should still show applied points when user scrolls payment methods.


Handoff checklist

ItemDev Mode annotation
Points ↔ currency ratioe.g. 100 pts = $1.00
Rounding rulesFloor vs round on partial redemption
Ledger fetch timingOn login, cart change, checkout enter
Toggle analyticsloyalty_apply, loyalty_remove, loyalty_error
Tier sourceAnnual spend vs rolling 12 months
ExpirationShow expiry date on balance when applicable
Guest vs memberEarn disabled; CTA to register
a11yToggle has visible label; balance not icon-only without text
API error copyExact strings for insufficient and conflict

Use Dev Mode checklist and share props with coupon components for conflict states.


Common mistakes

MistakeWhy it hurtsFix
Different point icons per pageBreaks trustOne PointsBalance component
Showing earn and apply without mathUsers feel cheatedSingle ledger preview
Tier badge without progress contextStatus feels arbitraryAdd TierProgress or tooltip
Redemption toggle with no summary lineTotal looks wrongMirror deduction in order summary
Loyalty hub uses new card styleVisual fragmentationReuse account cards
No guest stateConfusing empty balanceSign-in CTA variant
Points conflict with coupon silently failsSupport ticketsExplicit ConflictAlert
Dashboard history ≠ order historyDuplicate confusionLink rows to order detail

  1. Define program rules with product—ratio, tiers, stacking, expiration.
  2. Build PointsBalance, TierBadge, and TierProgress with guest and error variants.
  3. Add EarnCallout to PDP and cart frames using pricing placement.
  4. Design PointsRedemption with all checkout states on checkout frames.
  5. Compose LoyaltyDashboard with activity feed and rewards catalog.
  6. Wire conflict states with coupon and free shipping frames.
  7. Annotate ledger API fields and analytics in Dev Mode.
  8. Run accessibility check on toggles and tier color tokens.

FAQ

Points displayed as points or dollar value?

Pick one primary display (usually points) and optional secondary value in parentheses. Switching between pages confuses users and complicates localization.

Show loyalty on every PDP?

Show earn callout on eligible SKUs only. Use a neutral “Not eligible for rewards” line only when competitors do—otherwise omit.

Separate app for loyalty?

If a standalone app exists, still match component names and states on web so design and engineering share one spec document.

Birthday rewards and campaigns?

Treat as time-boxed EarnCallout variants with campaignId prop—do not fork the base component.

B2B accounts with negotiated pricing?

Add loyaltyEligible=false at account level; hide earn and redemption with member-admin explanation in account settings.


Next steps

Share on X

§ Keep reading

Related guides.