Most OpenCart to Shopify migrations are sold on the catalogue and lost on everything else. Products are the easy part — a CSV, some cleanup, done in a day. Orders, customers and tax are where the weeks go, and they are the three things a merchant notices immediately if you get them wrong.
Here is what each of them actually involves, working from the OpenCart database rather than from an export tool's marketing page.
Orders: what you are really exporting
OpenCart spreads a single order across several tables. oc_order holds the header — customer details, addresses, status, currency and the currency value at the time of sale. oc_order_product holds line items. oc_order_option holds the chosen product options against those lines. And oc_order_total holds the money as a set of rows: sub-total, shipping, coupon, tax, total, each with its own sort order.
That last table is the one that catches people. There is no single "tax" column to read. Tax may be one row, several rows, or folded into line prices depending on how the store was configured. Before you export anything, run a query that totals oc_order_total per order and compares it against the recorded total. If those disagree on historical orders — and on an old store they sometimes do — you need to know that now, not after the import.
Shopify's order import takes a flat structure: line items, subtotal, shipping, tax lines, discounts, total. So the export step is really a reduction step. Decide once how each OpenCart total code maps, apply it consistently, and keep the original order ID on every record as a note or metafield so support can trace anything a customer queries.
What imported orders can and cannot do
Say this to the merchant before the project starts, because it is the single most common surprise: imported orders are historical records. They give you reporting, customer lifetime value, and a support trail. They do not carry the payment relationship. You cannot refund an imported order through the gateway that took the money, because Shopify never took it. Fulfilment status can be set, but the imported order is not a live order moving through your new operational flow.
The practical consequence is a cut-off date. Everything before the cut-off is history, imported for the record. Everything after it is a real Shopify order. Refunds against pre-cutoff orders are handled in the old gateway's dashboard, which means keeping that account open — usually for the length of your refund window plus a margin. Budget for that; it is not free and it is frequently forgotten.
Customers, and the password problem
OpenCart stores customer passwords as salted hashes in oc_customer. Shopify will not accept a foreign password hash — not through the API, not through an app, not through support. There is no workaround and anyone selling you one is describing something else.
So every customer account is rebuilt without its password, and customers are invited to set a new one. Two things make that survivable:
- Time the invitations. Do not fire an account-reset email to your whole list on launch day alongside a launch announcement and a promotional send. Stagger them, lead with the reason, and make the reset link the primary button.
- Expect a measurable dip in logged-in sessions for two to four weeks. Guest checkout carries more of the volume during that window. If your store leans on account-only pricing, plan for the support load.
Two fields deserve care. Address books in oc_address should come across in full, because a saved address is a real conversion asset. And marketing consent must be migrated honestly. OpenCart's newsletter flag is the only defensible source for it; do not opt in customers who never opted in, on the theory that they can unsubscribe. That is a compliance problem and a deliverability problem in one move.
Tax rules: rebuild, do not migrate
This is the section people skip and then regret. OpenCart models tax as tax classes, which contain tax rules, which point at tax rates, which are scoped to geo zones, which are collections of country and zone rows. It is flexible and it is entirely OpenCart's own construct.
Shopify does not have that structure. Tax is calculated from your store's locations and registrations, the destination address, and per-product overrides for anything that is not taxed at the standard rate. Trying to reproduce your geo zone tree inside Shopify is wasted effort.
What to do instead:
- List your registrations, not your rates. Where is the business actually registered to collect? That drives everything in Shopify.
- Find every non-standard product. Zero-rated or reduced-rate goods — children's clothing, books, certain foods, medical items depending on your market — get a product tax override or the appropriate tax category. Everything else inherits the standard treatment.
- Decide tax-inclusive or tax-exclusive display per market and check it against what your OpenCart storefront was showing. A store that displayed inclusive prices and switches to exclusive will look like it raised prices at checkout, and conversion will tell you so.
- Test with real addresses in each region you sell to, including a couple where you are not registered, and confirm the charge is what your accountant expects. Do this before launch, not after the first VAT return.
The order of operations
Products and collections first, because everything else references them. Then customers, so orders can attach to real records rather than creating orphans. Then orders, oldest first, with the original order ID preserved. Tax configuration is built and tested in parallel, on the staging store, against real addresses — it is configuration rather than data, so it does not have to wait its turn.
Then reconcile before you go anywhere near DNS: order count per month against the OpenCart figure, revenue per month within rounding, customer count, and a spot check of ten orders end to end including their line options and totals. If those four checks pass, the data side of the migration is done.
Redirects are a separate job and they go live before the domain moves — the same rule as every other replatform. Our Shopify migration page covers how we scope the whole sequence, and if you want a read on what your particular OpenCart install is going to fight you on, a free audit is the cheapest way to find out.


