How to migrate loyalty points between Shopify apps

Changing loyalty apps is not a settings migration. It is moving a liability — your customers were promised those points, and they will notice the day the balance is wrong. This is the failure mode that ruins these migrations, and the checks that catch it.

The one-line version: loyalty exports contain several point columns, and only one of them is a spendable balance. Import the wrong one and you silently over-credit every customer in your store.

Why the export is the dangerous part

A points program is, underneath, a ledger. Migrating it means carrying one number per customer — the current balance — from one system to another. That sounds trivial, and the tooling makes it look trivial: export a CSV, upload a CSV.

The problem is that the CSV rarely contains one number. A typical loyalty export ships a current balance alongside some combination of lifetime points, points earned, points spent, points pending, points redeemed and points expired. Several of those columns are larger than the balance — often much larger, because lifetime totals never go down. They all look like plausible integers in a column with "points" in the name.

Pick the wrong one and nothing breaks. The import succeeds. The dashboard looks healthy. The error surfaces weeks later, one customer at a time, as people redeem rewards they were never actually owed — and by then the ledger is real and clawing it back costs you the goodwill the program existed to build.

The columns that are never a balance

Treat any column whose name contains one of these as cumulative, and never import it as a balance:

What you want is the column that means spendable right now: usually named balance, points balance, or in LoyaltyLion's vocabulary, approved points. If your export has no such column, the correct action is to stop and get a different export — not to approximate one by subtracting spent from earned, which will not reconcile once refunds and expiries are in the data.

Identity is the second trap

The balance is only half a row. The other half is which customer, and exports are inconsistent about it.

Match on email. Do not match on a bare customer_id: in a loyalty export that is the vendor's own internal identifier, not your Shopify customer id, and treating one as the other attaches balances to unrelated people. Only a column explicitly named as a Shopify id is safe to use as one.

Then decide what happens to rows that do not match anyone in your store — and they will exist, from deleted customers, typo'd addresses and test accounts. The right behavior is to report them back to you as a list. Silently attaching them to the nearest match is how a migration produces phantom balances nobody can trace.

A pre-flight checklist

How TruePoints handles it

TruePoints was built around this specific failure. It reads any CSV with an email column and a current-balance column, and it recognizes Smile, LoyaltyLion and Yotpo exports by their characteristic columns.

How TruePoints works covers earning, redemption and pricing, and includes an 84-second demo of the whole loop on a live store.

Questions

Why can't I just import the points column from my export?

Loyalty exports usually carry several point columns: a current balance next to lifetime, earned, pending, redeemed, spent or expired totals. Only the current balance is a spendable liability. Import a lifetime total and every customer in your store is instantly owed far more than they actually have, and you will not find out until they try to spend it.

How do I tell a current balance from a lifetime total?

Read the column name, not the number. Anything containing lifetime, total, earned, spent, pending, redeemed, expired or used is a cumulative figure, not a balance. If your export only offers those, go back to the source app and request a current-balance export before you import anything.

What happens to customers who have zero points?

Nothing needs to happen. A zero balance carries no liability, so there is no reason to create a member record for it. In TruePoints those rows are counted and skipped, and the customer enrolls normally on their next order.

What if the same email appears twice in the export?

Decide deliberately rather than letting the importer pick. TruePoints merges duplicate emails by summing their balances and reports how many it merged, so the total credited always reconciles against the file you supplied.

Do reward definitions and tiers migrate too?

No. Balances migrate; rewards, tiers, referral history and past transaction logs do not, in any loyalty migration. Balances are the part your customers can see and will complain about, so that is the part worth protecting. Rewards are quick to recreate.

Should I run the migration before or after installing the new app?

Install first, configure your earning rate and rewards, then import balances last. Importing into an unconfigured program means your first orders after the switch earn at the wrong rate, and unwinding that by hand is worse than the migration itself.