Skip to main content
Every Mage shop runs in one of two loyalty modes, chosen by the merchant:
  • points The loyalty balance is plain points.
  • store_credit The loyalty balance is Mage store credit, denominated in money.
The loyalty engine and every SDK method behave identically in both modes. The SDK returns the same fields either way. What changes is how you interpret and display the numbers, and, for redemption, which method a customer uses.
Store credit here means Mage’s internal store credit, not Shopify native store credit.

How each mode denominates values

Every loyalty number the SDK returns (points, lifetimePoints, redeemedPoints, a reward’s pointsCost, an earning rule’s award) is read in the shop’s loyalty unit: Because the raw numbers look the same in both modes, never assume points. Read the mode and format through the helpers below.

Detecting the mode

Methods that carry loyalty amounts return loyaltyMode and currency alongside their data. These are getCustomerDetails, getCustomerActivity, getShopRewards, getEarningRules, and getShopVipTiers.
The same formatLoyaltyValue call handles both modes, so your rendering code stays mode-agnostic. Pass the mode and currency straight through and let the helper decide.

Formatting helpers

The SDK exposes helpers on window.MageSDK so you never reimplement the unit math. Each one works in both modes.
formatLoyaltyValue(value, mode?, currency?)
string
Formats a loyalty value for display. Points mode returns the number with locale grouping ("1,250"). Store-credit mode returns a localized currency string ("$12.50").
formatSignedLoyaltyValue(value, mode?, currency?)
string
Same as formatLoyaltyValue but prefixes a + or - sign. Useful for activity rows ("+150", "+$3.00", "-300").
loyaltyUnitLabel(mode?, count?)
string
Returns "point" or "points" in points mode (based on count), and an empty string in store-credit mode, where the money value already describes itself.
resolveLoyaltyMode(mode?)
string
Normalizes any input to 'points' or 'store_credit'. Anything that isn’t exactly 'store_credit' resolves to 'points', so an older server or a missing value safely defaults to points.
isStoreCredit(mode?)
boolean
Convenience check. Returns true when the resolved mode is 'store_credit'.
minorToMajor(amountMinor, currency?)
number
Converts a minor-unit amount to major units (300 becomes 3 for USD, 500 stays 500 for JPY). Relevant in store-credit mode when you need the raw number. For display, prefer formatLoyaltyValue.

The storeCredit convenience object

In store-credit mode, getCustomerDetails attaches a ready-to-display storeCredit object to the customer. In points mode it is null, so you can branch on its presence.
balanceMinor
number
The raw balance in minor units. Identical to customer.points in store-credit mode.
balance
string
The balance in major units as a decimal string, e.g. "4.50".
balanceFormatted
string
A localized display string, e.g. "$4.50".
currency
string
The ISO currency code.

Redemption differs by mode

Redemption is the one behavior that is not identical across modes. Points mode supports both redemption methods:
  • redeemReward for fixed rewards (a set cost for a set discount).
  • redeemFlexible for flexible rewards (the customer chooses how much to spend).
Store-credit mode supports only flexible redemption. Calling redeemReward there returns:
So in store-credit shops, redeem through redeemFlexible. A reward is redeemable this way when its redemptionMode is "flexible"; read the amount bounds from the reward’s flexibleConfig (minPoints / maxPoints).
If you want redemption code that works regardless of mode, drive it off the reward’s redemptionMode: call redeemReward for "fixed" rewards and redeemFlexible for "flexible" rewards. Store-credit shops only surface flexible rewards, so this pattern naturally does the right thing in both modes.