Free Shopify store auditSpeed, SEO and conversion leaks — no cost, no obligation.
Claim it
Thriftizer Solutions LLPShopify Select Partner
Book a Growth Audit
Email Marketing Aug 7, 2026 8 min read

Importing Historical Orders to Shopify for Accurate LTV Reporting

Shopify has no admin CSV import for orders. Here's how to import historical orders through the API without firing confirmation emails, courier labels or Klaviyo flows, and get LTV reporting that ties.

Shopify has no order import in the admin. You can upload products, customers, inventory and gift cards from a CSV, and that's the list. To import historical orders into Shopify you need the Admin API, either through an app like Matrixify or EZ Importer, or through a custom app you write yourself. And if you run that import without switching off notifications, transactional apps and courier integrations first, several thousand people will get an order confirmation for something they bought two years ago, and your logistics partner will start printing labels.

We do this on most replatforming projects. It goes wrong on the first pass more often than we'd like, usually in the same three places: transactions, timestamps and refunds.

Order history is analytics data, not archive material

The argument for the import isn't sentimental. Almost every customer metric worth looking at is computed from orders, and Shopify computes them from the orders that exist in your store, not the ones that existed in your old system.

Customer lifetime value, repeat purchase rate, time between first and second order, cohort retention curves, the segment you use to build a VIP audience for Meta: all of it reads from order rows. Launch a Shopify store with a clean order table and every customer you've spent five years acquiring looks like a first-time buyer. Your repeat rate reads near zero for the first quarter. Your cohort chart shows one enormous cohort acquired in launch month. Nobody can make a budget decision from that.

The second reason is duller and matters just as much. Support agents need to see what someone bought before. So do your warehouse and your returns policy.

Kill every outbound message before you write a single order

Shopify's notification settings don't let you globally mute order confirmations, so this is handled at the API level and in your app stack.

On the API call, orderCreate in the GraphQL Admin API takes an options object with sendReceipt and sendFulfillmentReceipt. Both false. Set inventoryBehaviour to BYPASS so a 2022 order doesn't decrement 2025 stock. If you're marking orders fulfilled, do the fulfilment with notifyCustomer set to false. Shopify is moving off REST, so build against GraphQL rather than the old POST /orders.json route.

That covers Shopify's own emails. It does nothing about the apps listening to the orders/create webhook, which is where the real damage happens:

  • Courier and shipping apps. Shiprocket, Delhivery, Pickrr and most aggregators sync new orders automatically. An import can push thousands of shipments into a queue and generate AWBs you'll be billed for. Disconnect these first, not last.
  • Email and SMS platforms. Klaviyo and Omnisend will ingest the webhook. Pause every flow, including the ones you forgot existed. Better still, connect the platform after the import finishes and let it run its own historical sync, which reads real order dates instead of webhook arrival time.
  • Review requests. Judge.me, Loox and similar will happily queue a review invitation for a two-year-old purchase.
  • Loyalty apps. These may retroactively award points for the entire import. Sometimes that's exactly what you want. Decide on purpose rather than discovering it on Monday.
  • GST invoicing apps. A second invoice series against orders already filed is a genuine mess. Exclude imported orders by tag.

Run twenty orders as a test batch. Then check your email platform's activity feed, your courier dashboard and one imported customer's timeline before you go anywhere near the full file.

The four fields that decide whether your LTV is right

processedAt. This is the date Shopify uses for the order, for cohorts and for a customer's first-order date. Omit it and every legacy order is dated today. That single mistake destroys the entire reason you did the import.

Transactions. An order with no transaction sits at financial status pending, and a pending order contributes nothing useful to customer spend. Write a transaction of kind SALE, status SUCCESS, with the amount and currency, and set the gateway to something meaningful: razorpay, cod, manual, whatever the original payment method was. Gateway names become filterable later, and they're the only way to reconstruct payment-method mix from imported history.

Tax lines and taxesIncluded. Don't let Shopify recalculate tax against today's settings. Pass the tax lines from the source system and set taxesIncluded to true if your legacy prices were GST-inclusive, which for most Indian stores they were. Otherwise your imported revenue is 18% off in one direction or the other and your GST reconciliation will never tie.

Customer matching. Match on lowercased email. Where you only have a phone number, and on COD-heavy Indian catalogues you'll have plenty, normalise to E.164 before you start. A store with +919876543210, 09876543210 and 9876543210 in three different exports produces three customers from one buyer, and three customers with one order each look nothing like one customer with three.

COD, RTO and the number that quietly inflates your LTV

Here's the part most import specs miss. If you had a COD business, a chunk of those orders were returned to origin and never paid for. Import them at gross and you're reporting revenue that never landed.

Work it through. Say 12,400 legacy orders at an average of ₹1,750, spread across 9,100 unique customers. Sixty-two percent were COD, so 7,688 orders, and 24% of those came back as RTO, so 1,845 orders. That's 1,845 × ₹1,750 = ₹32.3 lakh of revenue that doesn't exist.

Gross import: ₹2.17 crore across 9,100 customers, average lifetime value ₹2,385. Correct import: ₹1.85 crore across the same 9,100 customers, ₹2,030. You've overstated LTV by roughly 17%, and you'll use that inflated figure to set your target CAC.

The fix isn't complicated, it just has to be in the spec. Import RTO and cancelled orders with cancellation data and no successful sale transaction, or import them as refunded. Tag them. Then your Shopify reports and any BI tool sitting on top of them read net.

Line items: match the variant or accept the gap

Every line item can either point at a real variant ID or be a custom line item with a title and price. Match to a variant where the SKU still exists and product-level reporting works: best sellers by month, units per product, repeat purchase rate for a specific SKU.

For discontinued products the variant is gone, so those become custom line items. Order-level revenue and customer LTV stay accurate, but product analytics won't attribute them anywhere. That's the trade-off, and it's usually the right one. Recreating 400 archived products as hidden Shopify products purely to hold historical line items adds catalogue clutter, slows your admin and rarely earns its keep. We've done it twice, both times for brands where reorder rate by SKU was the core merchandising metric.

Numbering, tags and having a way back

Set the order name explicitly with a prefix, something like L-10432. If imported orders share the numbering pattern of your live sequence, your support team will spend the next year opening the wrong order.

Tag everything. Source system, batch number, import date: legacy, src-magento, batch-04. Tags are how you exclude imported orders from an email flow filter, how you find the batch that came in with the wrong tax setting, and how you delete it. Because you will delete a batch. Plan for a failed run, do batches of 500, and check totals against the source export after each one.

Throughput is governed by API rate limits, and orderCreate is not a cheap mutation. Anything past 20,000 orders wants an overnight window. Anything past 100,000 wants a conversation about whether you need all of it.

The case for not importing at all

Sometimes the honest answer is don't. Five years of Magento or WooCommerce order history, with refunds, partial cancellations, multi-currency and store credit, is real engineering work. If your analytics already live in a BI tool, importing everything into Shopify buys you very little.

The middle path we recommend fairly often: import customers with lifetime spend and order count as metafields, import the last 12 to 18 months of orders in full, and keep the deeper history in a warehouse or a spreadsheet the support team can search. Your cohort and repeat-rate reporting for the period anyone actually looks at is intact, support has the context, and you've cut the scope by three quarters.

What you lose is Shopify-native segmentation on the older data. If your buying cycle is annual, a jewellery or heavy-appliance brand say, that loss is real and you should import the lot. If people reorder every six weeks, eighteen months is more history than any decision needs.

A sequence that holds up

  1. Export from the source system and reconcile totals: order count, gross, refunds, tax, by month. Do this before you touch Shopify. Half the problems in an order import are problems in the export.
  2. Normalise emails and phone numbers, map payment gateways, flag RTO and cancelled orders.
  3. Import customers first, so orders attach rather than creating duplicates.
  4. Disconnect courier apps, pause every email and SMS flow, mute review and loyalty apps.
  5. Run 20 orders. Check the customer timeline, your email platform's activity log, your courier dashboard, and one order's tax lines.
  6. Run in batches of 500. Reconcile monthly revenue against the source after each batch.
  7. Reconnect apps. Set flow filters to exclude the legacy tag as a second line of defence.
  8. Verify in Analytics: first-order dates by month should mirror the old system's shape, and total customer spend should match your export.

Step 8 is the one people skip. It's the only step that proves the import did what it was for.

If you're mid-replatform and the order history is the piece nobody has scoped yet, that's the normal state of affairs. It's usually the last thing on a Shopify migration plan and the first thing the founder asks about after launch. We build these importers as custom apps against the store rather than relying on a generic tool where the data is messy, which it usually is; more on how we approach custom Shopify app work. Send us the order export schema and a month's sample data through a free audit and we'll tell you what's mappable and what isn't before you commit to a timeline.

Previous postNext post

Ready to scale your D2C brand profitably?

Let's build a growth engine that drives more traffic, more conversions and more profit.

Book a Growth Audit
📅 Free Audit💬 WhatsApp