The conclusion: prove the move is justified before planning the move
Moving from WooCommerce to Shopify is not an export-and-import task. It is a coordinated change to commerce rules, data relationships, URLs, payments, fulfillment, applications, and team ownership. A new homepage returning 200 proves only that a storefront is reachable. A migration is complete only when customers, products, orders, inventory, money, search entry points, integrations, and operating procedures are demonstrably correct, with a named response when they are not.
Shopify’s official migration overview describes manual copy, CSV, migration apps, partners, and APIs as different routes. Its WooCommerce guide recommends importing products before customers and historical orders so that relationships can be connected. Treat that as a useful baseline, not as a promise that plugin fields, subscriptions, or payment transactions will map automatically.
| Outcome | Evidence required | Misleading substitute | Action if it fails |
|---|---|---|---|
| Complete data | Source snapshot equals created, updated, skipped, quarantined, and failed rows | An “import complete” banner | Build a difference set and pause downstream jobs |
| Correct relationships | SKU, customer, order line, location, and discount references trace end to end | Comparing product totals only | Repair mappings and replay the affected batch |
| Operable commerce | Payment, refund, tax, shipping, fulfillment, and notification replay | One successful test checkout | Isolate the failing path and delay cutover |
| Preserved discovery | URL inventory, one-hop redirects, target pages, and sitemap checks | Checking the homepage only | Repair routes, canonicals, and links |
| Recoverable operation | Freeze window, rollback owner, compensation steps, and read-only backup | A single CSV export | Preserve the old store and rehearse recovery |
This guide keeps the project-level decision and operating boundary. For API, bulk-job, and performance trade-offs, continue with the Shopify data migration engineering guide. Identity, consent, accounts, and privacy mechanics are covered in the Shopify customer data migration guide, while platform cost assumptions belong in the Shopify versus WooCommerce total-cost breakdown. For implementation coordination, see WESWOO’s migration and build services and Shopify store setup guides.
Stay on WooCommerce, repair it, or move
Write the platform choice as an evidence-based decision rather than a brand preference. If the existing WooCommerce store reliably serves the critical journeys and the problem is a replaceable extension, repairing and retaining it may be safer. If maintenance, hosting, releases, or market expansion remain measurable bottlenecks, compare the target operating model with migration risk. A migration signal never overrides an unresolved payment, tax, privacy, or integration blocker.
| Decision signal | Stay on or repair WooCommerce | Reason to move to Shopify | Evidence needed |
|---|---|---|---|
| Business outcome | The current funnel, markets, and fulfillment meet targets; fix a local defect | Release, market, team, or reliability bottlenecks remain measurable | Baseline metrics, incidents, target |
| Data and extensions | Critical fields depend on a few maintainable extensions and tested backups | Extension coupling, upgrades, or hosting operations create recurring risk | Extension register, data dictionary, restore rehearsal |
| Commerce and fulfillment | Payment, tax, stock, and subscription journeys repeat reliably | Target markets require new payment, location, or operating controls | End-to-end replay, provider eligibility, stock reconciliation |
| SEO and content | Existing URLs have stable value and the migration benefit is unclear | Structure, performance, or content governance requires a rebuild | URL ledger, logs, organic entries, redesign plan |
| Readiness | There is no freeze window, owner, or delta method | Rehearsal is complete, thresholds exist, and rollback is testable | Go/no-go record, timeline, rollback report |
This guide absorbs the five pre-migration questions
Before choosing a tool, answer five questions: Which measurable problem should the move solve? Which data and relationships must survive? Can the required functionality and integrations be rebuilt on Shopify? How will old URLs and search signals be preserved? Can the team cut over within a controlled freeze and return safely if needed? These questions capture the preflight intent of post 9671 and turn it into inventories, mappings, tests, and acceptance gates.
The five preflight questions: make a written go/no-go decision
Do not start because WooCommerce has many plugins or because Shopify appears easier to operate. Compare three real options—keep and repair WooCommerce, migrate in stages, or cut over once—using three-year platform, hosting, extension, development, maintenance, payment, SEO, and opportunity costs. Any unanswered critical question is a blocker, not a line item labelled “to be handled later.”
| Preflight question | Evidence to collect | Pass condition | Pause signal |
|---|---|---|---|
| What problem should the move solve? | Incidents, maintenance hours, release time, checkout funnel, market plan | Owner and post-launch metric exist | The goal is only “change platforms” |
| What must be retained? | Object list, retention rules, support and finance queries, privacy requests | Every field has a destination | “Move everything” without a field map |
| Can the functionality be rebuilt? | Plugin behavior, workflows, APIs, quotes, failure paths | Critical journeys pass on a prototype | Subscriptions, B2B, or ERP exist only in screenshots |
| How will SEO continue? | Sitemap, logs, analytics, Search Console, backlinks, old and new URLs | Every valuable URL has one destination | Many URLs point to the homepage |
| Can the cutover be controlled? | Duration, delta method, freeze window, rollback rehearsal | Stop thresholds are signed off | Nobody owns the pause decision |
Write stop conditions before writing the launch date
Pause if payment-entity or market eligibility lacks written confirmation, tax ownership is unclear, the ERP or WMS has not passed create/update/cancel/refund tests, the next subscription charge has no owner, high-value URLs have no mapping, or the team lacks a content, inventory, or rollback window. A pause is a risk-control decision, not a rejection of the project.
Select a migration route and freeze the scope
Shopify’s WooCommerce guide names manual copy, CSV, the first-party Store Migration app, third-party migration apps, and migration experts as separate routes. A small standard catalogue may work well with CSV. A store containing extension fields, historical orders, media relationships, continuous deltas, or strict audit requirements generally needs an app, API, or a conversion layer. Combining methods is fine, but each object type needs one defined write path; tools must not overwrite each other.
Use a scope matrix to prevent an accidental redesign
Classify each object as migrate, rebuild, archive, or retire, with a reason. Keep visual redesign, content rewriting, data cleansing, market expansion, and platform migration as distinct work packages. This prevents both blind copying of broken source structures and last-minute untested promotions or countries.
| Scope object | Migration method | Owner | Acceptance evidence | Target treatment |
|---|---|---|---|---|
| Catalogue facts: SKU, title, price, weight, variants, media | Product CSV, app, or API; hard samples first | Merchandising | SKU, variant, and media sample report | Shopify products, variants, media |
| Customer relationships: email, addresses, tags, consent, external ID | Customer CSV plus identity/privacy workflow | Customer and privacy leads | Deduplication, consent, and activation samples | Customer records and controlled archive |
| Transaction history: number, lines, money, tax, refunds | Migration app/API, or read-only archive | Finance | Currency, amount-equation, and refund reconciliation | Historical orders or read-only warehouse |
| Commercial rules: discounts, gift cards, subscriptions, loyalty | Native rebuild plus specialist app or retained system | Operations | Rule lifecycle and balance/charge replay | Rebuild, specialist migration, or retain |
| Content and entry points: pages, posts, media, old URLs | Content import, media review, and redirect ledger | Content and SEO leads | Content samples, crawl, and status report | Pages, articles, files, redirects |
Target operating model and gap analysis: assign ownership before import
The target is not a new set of admin menus. It is a written answer to who owns each fact, who may write it, and who handles an exception. For products, prices, inventory, orders, customers, content, payments, tax, and fulfillment, name the system of record, fallback system, tolerated delay, approver, and service objective. If customer support or finance needs manual compensation, lookups, or exports, put those actions in the SOP and training instead of assuming an app will make the decision.
Use a capability gap table to choose rebuild, replacement, or retention
Compare current WooCommerce behavior with the Shopify design by trigger, fields, permissions, notifications, failure path, reports, and retention. Classify each gap as configurable, app or middleware, custom development, manual, or not migrating. A similar-looking screen is not evidence of equivalent behavior.
| Capability | Current WooCommerce fact | Shopify target design | Gap and decision | Owner/evidence |
|---|---|---|---|---|
| Products and prices | Which extension or role changes titles, prices, and sale prices? | Products, price lists, and market rules have one writer | Configurable, app, custom, or manual | Merchandising sign-off |
| Stock and fulfillment | Warehouse, reserved, in-transit, and split-order rules | Location inventory, fulfillment service, and WMS events | Complete locations or retain WMS | Supply-chain replay |
| Orders and refunds | Capture, refund, cancel, and support permissions | Order, processor, finance, and notification chain | Rebuild states and compensation | Finance test order |
| Customers and consent | Accounts, marketing consent, privacy requests, duplicates | Customer accounts, consent record, controlled manual path | Separate identity/privacy design | Privacy sample |
| Content and SEO | Page builder, translations, shortcodes, rewrite rules | Pages, articles, files, templates, canonical, redirects | Clean, rewrite, or archive | Content crawl report |
Inventory WooCommerce: identify source data and live extensions
WooCommerce facts live across the WordPress database, wp-content, media, themes, extension tables, order metadata, scheduled actions, and external systems. A standard product export does not necessarily include subscriptions, gift cards, composite products, memberships, reviews, custom fields, or a warehouse’s stock ledger. Freeze a plugin and version inventory with each extension’s purpose, tables, events, cron jobs, external account, licence, and shutdown impact.
The WooCommerce REST API v3 documentation covers products, variations, customers, orders, and coupons. Woo’s product import/export guide explains the built-in CSV, field mapping, and custom metadata export. Cross-check admin exports, REST API reads, a read-only database snapshot, and interviews; no single export should be treated as the complete source of truth. Test import/export on staging or a restore copy first.
Treat customer, order, and coupon CSV export as an extension boundary. WooCommerce’s official export-extension documentation describes what is available after that extension is installed; it is not a universal core guarantee, and fields also depend on custom plugins. Batch large exports and close the count and amount equation for every batch.
Build an object, count, and relationship ledger
For every object, record source ID, business key, state, created and modified times, relationships, privacy class, count, extraction method, owner, and sample method. For orders, add guest status, refunds, cancellations, partial fulfillment, tax lines, shipping lines, coupon lines, and payment transactions. For products, classify simple, variable, bundled, composite, downloadable, pre-order, and subscription types. Version the ledger and bind it to export hashes.
| Domain | Inventory questions | Minimum output | High-risk example |
|---|---|---|---|
| Products | Where are attributes, variations, SKUs, media, categories, and custom fields? | Product and relationship counts | Options exceed the target model |
| Customers | How are registered, guest, duplicate-email, multi-address, and consent cases represented? | Identity and consent list | One email represents two entities |
| Orders | Are transactions, refunds, taxes, shipping, fulfillment, and status complete? | Amount equation and status distribution | Partial refund in a second currency |
| Content | Do pages, posts, shortcodes, images, and downloads depend on extensions? | URL, body, media, and template list | Page-builder shortcode breaks |
| Runtime | Who writes through webhooks, cron, cache, search, email, and ERP? | Integration topology and shutdown plan | Double write or double charge |
Backups, privacy, and recoverability come before the first import
WooCommerce’s backup documentation says a complete backup includes the database and the wp-content folder; WordPress XML does not contain WooCommerce orders, products, or settings. Before migration, create encrypted copies of the SQL database, wp-content and media, theme and extension versions, configuration inventory, CSV/API exports, URL ledger, DNS records, payment and shipping settings, and the migration runbook. Store one copy away from the production host.
The backup is useful only after a restore test. Restore SQL and files into an isolated environment, open products, customers, orders, media, checkout, and subscription administration, and record restore time, missing files, permissions, and database versions. Real customer, address, order, and token data should be limited to necessary personnel. Logs should use internal IDs, hashes, and error paths, never full personal data or payment credentials.
Treat the target store as an evidence-bearing system too
Shopify is hosted, but the migration still needs target theme versions, product/customer/order exports, redirect CSVs, market and translation settings, app configuration, API version, import results, and review reports. Do not assume an admin undo action is a full rollback. Generate a run_id, configuration hash, and timestamp for every execution so the team can explain which rule version wrote a record.
Field mapping: turn the source model into an auditable contract
A field map should include source path and type, target object and field, requiredness, enum mapping, null behavior, length, units, timezone, sensitivity, system of record, transformation version, and verification query. Use decimal values and currencies for money, not floating point; preserve source timezone and UTC for timestamps; sanitize shortcodes, scripts, and obsolete media from HTML. Define uniqueness separately for SKU, external order number, and email.
Use immutable IDs and semantic hashes for replay
Create an identity map from source_system + object_type + source_id to a Shopify GID, handle, or external key. SKUs can change, emails can change, and displayed order names can have prefixes, so they are useful for conflict detection but not sufficient as global primary keys. Store a normalized payload hash. On replay, compare the identity map and semantic hash before choosing create, update, skip, or quarantine. After a timeout, query for a successful write before creating anything again.
| Source fact | Shopify candidate | Transformation | Acceptance focus |
|---|---|---|---|
| Woo product ID and SKU | Product/Variant identity map and SKU | Preserve source ID; quarantine duplicate SKU | Parent-child and SKU closure |
| Attributes and variations | Options, variants, and metafields | Normalize names, values, and units | Each combination is unique and sellable |
post_content and shortcodes | Product description, Page, or metaobject | Sanitize HTML and replace shortcodes with components | No broken shortcode or media URL |
| User ID, email, addresses | Customer, addresses, and tags | Normalize email; adjudicate duplicates | Login, address, consent, privacy request |
| Order number and lines | Order, lines, and metafields | Preserve source number; do not recalculate history | Currency, tax, discount, refund equation |
Migrate products, variants, media, and inventory as layers
Products are not one CSV row. First map product types, attributes, options, variants, media, collections/categories, prices, inventory, and sales channels. Use the hardest examples first. Shopify’s product CSV documentation notes that CSV data affects commercial fields such as price, weight, and inventory; WooCommerce exports normally require editing to match Shopify’s template. The Shopify WooCommerce guide says its first-party Store Migration app is early access and documents a limitation for products with more than three options. If those products exist, plan an app/API, a metafield/metaobject model, or a deliberate rebuild, and reconfirm the current limitation before execution.
Shopify product CSVs have dependent fields: changing variant data requires the corresponding option columns. Missing dependencies can create a default variant or delete existing variants, so run a dry-run in an isolated store and diff the result before every production load. Multi-location stock belongs in the inventory CSV, not in one product-level Inventory quantity; prefer the all-states format for a fuller view and protection against accidental overwrites, then reconcile every SKU × location row. Define product metafields first, and use another reviewed method for variant metafields because product CSV does not support them.
Load structure before media, publication, and stock
Use a dependency order: product types and options, products and variants, media and alt text, collections/categories, prices and markets, locations and inventory, then sales-channel publication. A media upload succeeding does not prove that the asset is usable; check processing state, order, dimensions, alt text, duplicates, and page references. Shopify’s multi-location inventory guide says locations track inventory independently. Matching the total while assigning the wrong warehouse still causes promises and fulfillment failures.
Customers, orders, and accounts: preserve relationships before interfaces
Shopify’s customer CSV guide states that passwords from another store cannot be migrated by CSV; imported customers must be invited to create new passwords, and customer CSV does not import orders, Total Spent, or Total Orders. The file must be UTF-8 and is currently limited to 15 MB per file; only defined, supported customer metafields can be imported by CSV. Recheck these limits and supported fields against the target store immediately before execution. Apply the current import rules to duplicate email or phone values. Decide whether the target will use new customer accounts, legacy accounts, an identity provider, or a controlled reactivation process. Test verification email, reset, address, and order-history behavior.
Historical orders can use a migration app or API. Shopify warns that staff members who receive new-order notifications may receive an email for each imported historical order. Before importing, pause notifications, Flow, ERP, fulfillment, loyalty, and marketing actions that should not run. Restore them only from a checklist. Preserve source order number, original processing time, currency, tax, discount, payment state, fulfillment, and refund meaning; do not create a fresh live transaction by accident.
Reconcile an amount equation and customer identity
For every sampled historical order, check: line subtotal minus discounts plus shipping plus tax equals the order total, then reconcile refunds and captured amount. Preserve both shop and presentment currency where relevant. Sample guests, duplicate emails, multiple addresses, unsubscribed customers, privacy deletions, historical orders, and high-value customers. An admin record existing does not prove that consent, activation, and support access are correct.
Discounts, gift cards, and subscriptions represent future obligations
WooCommerce’s coupon management guide supports percentage, fixed-cart, and fixed-product coupons with product, category, email, minimum-spend, combination, and usage limits. Shopify’s discount documentation distinguishes code, automatic, amount/percentage, buy-X-get-Y, and free-shipping methods. Rebuild the rule, not just the code and amount: include timezone, validity, scope, stacking, usage counts, and customer context. Archive expired campaigns rather than reopening them.
The WooCommerce Gift Cards extension distinguishes prepaid gift cards from store credit and promotional coupons. Shopify’s giftCardCreate requires the relevant permission and can create a card with initial value, code, expiry, and customer association. Reconcile balance, currency, status, expiry, redeemed amount, and legal terms, then test purchase, redemption, partial use, and refund with a controlled card.
Subscriptions require a separate plan. WooCommerce Subscriptions says an agreement links a product, customer, payment gateway, and one or more orders, and that payment-token portability depends on the gateway. Shopify’s subscription contract model is app-owned around selling plans, contracts, billing attempts, and later orders. Shopify’s migration guide describes supported payment-method migration without directly moving card numbers and recommends pausing old billing to avoid double charges.
Reviews, store credit, and legal archive also need their own boundary. Retain review author, product, rating, body, creation time, moderation state, and consent basis, and confirm whether the target review app accepts historical imports. Reconcile store credit like a gift card, including balance and usage events. Completed orders’ original tax, payment, and refund facts may remain in a controlled read-only archive; finance and privacy owners approve access, retention, and deletion handling. Do not fabricate transactions to make admin counts match or treat a promotion code as spendable credit.
Split old and new subscribers into explicit paths
Preserve product/variant, interval, quantity, next charge, status, discount, delivery, consent, payment provider, and retry policy for every subscription. Existing contracts may be billed by the old gateway for a short period while new sign-ups use a Shopify subscription app; alternatively, customers can update their payment method before cutover. Test initial charge, renewal, failure retry, pause, skip, product change, cancellation, refund, tax, and notifications. Finance must approve billing pauses and compensation.
Pages, blogs, policies, and files: content needs an owner too
A successful product load does not prove that the site is complete. Register WordPress pages, blog posts, authors, dates, categories, media, downloads, policies, forms, shortcodes, navigation, and templates. Mark extension-generated content, components that need rewriting, legal approvers, and files that must remain available after the old store is retired. Business or legal owners must approve privacy, refund, shipping, and market-specific policy versions; a migration script should not rewrite them silently.
Restore content meaning before visual layout
Convert shortcodes, embeds, forms, relative image paths, download permissions, and internal links in the HTML into maintainable Shopify pages, articles, files, metaobjects, or theme blocks. Copying only a page-builder screenshot can leave an uneditable image. A stronger acceptance test is that an owner can update the content in the target admin, visitors can reach it in each required language and market, and form submissions arrive at the right handler.
| Content asset | Source checks | Target treatment | Pass evidence |
|---|---|---|---|
| Pages/blogs | Author, date, category, body, shortcode, draft state | Page, article, blog, or rebuilt component | Body, metadata, media, author samples |
| Policies/legal | Market, language, version, review date, links | Policy pages and market display rules | Business/legal sign-off and checkout links |
| Media/downloads | Path, alt, dimensions, access, reference count | Shopify files or controlled external storage | Resource state, access, no 404 |
| Forms/navigation | Fields, recipient, consent copy, menu hierarchy | Form app/middleware and navigation | Test submission, email, internal-link crawl |
SEO URL inventory: collect every entry point before designing paths
Old WooCommerce URLs come from product and category permalinks, WordPress pages, posts, media, language plugins, historical rewrite rules, sitemaps, analytics, Search Console, backlinks, and server logs. A navigation crawl misses ranking pages, ad landing pages, old campaigns, and language-prefixed paths. For each URL, record status, recent traffic, revenue, backlinks, language, intent, retention decision, and final target.
Prefer one-to-one 301 redirects over a homepage dump
Shopify’s URL redirect documentation supports admin and CSV imports but has reserved prefixes that cannot be redirected, broken-URL behavior, and plan-dependent limits. List reserved-prefix cases as explicit exceptions in the ledger. Import and test the mapping before domain cutover. A product should target the matching product, a category the relevant collection, and an article the equivalent article. Only an approved page with no useful alternative should follow a deprecation strategy. Check encoding, case, trailing slash, query parameters, loops, and chains; the intended result is one redirect followed by a 200 target.
| Old URL class | Target strategy | Context to preserve | Acceptance |
|---|---|---|---|
| Product or variant | Matching Shopify product/variant or canonical product | SKU, language, market, canonical | 200, correct title, purchase path |
| Category or tag | Matching collection, search, or content page | Original intent and internal links | No irrelevant homepage target |
| Content or blog | Matching page, article, or blog | Author, media, date, structured data | Body, images, and schema work |
| Duplicate or parameter | One canonical page; filter parameters where needed | Canonical, robots, campaign parameters | No crawl loop or soft 404 |
| Retired with no substitute | Approved deprecation response | Reason and business evidence | Status, sitemap, and links agree |
Multilingual stores and Markets: test language, region, and currency together
WooCommerce multilingual plugins often combine translations, language directories, tax, pricing, and product IDs. Do not copy Chinese or English body text without mapping each country’s domain or subfolder, default language, currency, price, tax display, payment, shipping, returns, and catalogue. Shopify’s Markets documentation says a market can control currency, language, price, product availability, domain, and tax. Its domain and language guide describes subfolders, subdomains, and top-level domains.
Shopify generates hreflang, canonical, and international sitemap behavior from market and language configuration; automatic geographic redirection serves customers while crawlers are excluded so each localized URL can be crawled. Still review translation coverage, URL slugs, email, checkout, app copy, right-to-left layout, market fallback, and selectors. Do not force every visitor to one language by IP, and do not assume a product has the same price or stock in every market.
Test localization as country-by-language journeys
For each core market, sample a homepage, collection, high-revenue product, article, cart, checkout, order email, and return page. Use a local address and currency to verify price formatting, tax, payment, shipping, delivery promise, and legal copy. Then use an incognito window, different browser language, and manual selectors to verify that visitors can reach the intended market. Translation that covers product titles but misses policies and app errors is incomplete.
Payments, tax, and shipping: rebuild eligibility and rules, not screenshots
Shopify Payments is available only to eligible countries and business types. The official country list requires checking entity, bank, and verification documents; otherwise a third-party provider is needed. Shopify’s third-party payment guide says third-party transaction fees and processor charges must be checked for the target market. WooCommerce payment methods are commonly gateway plugins connected to processors, so eligibility, fees, refunds, disputes, and tokens remain provider-specific.
Tax configuration cannot replace professional tax advice. Shopify’s tax guide says the merchant remains responsible for registration, collection, filing, and remittance unless an applicable automated filing service is configured. WooCommerce’s tax setup guide likewise separates software settings from legal advice and requires decisions about tax-inclusive pricing, tax address, and shipping tax class. Preserve original tax lines for historical orders; calculate new orders under the approved target rules.
Shopify shipping zones and rates depend on markets, locations, shipping profiles, weight, dimensions, and carriers. WooCommerce shipping zones, classes, live-rate extensions, and warehouse rules must be rebuilt. Test free, flat, weight-based, price-based, remote-area, digital-product, split-order, and return shipping by market. Missing package dimensions can undercharge shipping at checkout. For cross-border flows, put duties, import taxes, customs responsibility, carrier tracking, fraud review, and order notifications in the same test matrix; payment success, order creation, or an email delivery is not fulfillment or finance reconciliation.
Rehearse payment, tax, and fulfillment as one matrix
Replay successful and failed authorization, 3DS, wallets, local methods, duplicate callbacks, partial and full refunds, disputes, tax-exempt buyers, tax-inclusive prices, discount-after-tax behavior, multiple-location stock, split fulfillment, cancellation, returns, and tracking. Payment success is not the same as an ERP order. Creation, capture, stock deduction, tax record, fulfillment, and notification must reconcile as events.
Apps and integrations: replace capabilities, not plugin names
Build a WooCommerce capability matrix for discovery/search, reviews, memberships, discounts, subscriptions, tax, payment, shipping, inventory, ERP, WMS, OMS, CRM, email, support, analytics, advertising, and privacy. For each capability mark Shopify native configuration, app, Flow/Functions, middleware, custom API, manual process, or retirement. Record permission scope, data export, performance, price, support boundary, owner, and exit procedure. A same-name app is not proof of equivalent behavior.
Shopify’s webhook guide says webhooks help with near-real-time sync but do not guarantee delivery order or completeness; it recommends periodic reconciliation, HMAC verification, and duplicate handling. WooCommerce’s webhook guide covers order, product, coupon, and customer events, logs, and automatic disabling after consecutive delivery failures. Both platforms require a reconciliation path beyond webhooks.
Draw lifecycle and dead-letter paths for every integration
For create, update, cancel, refund, delete, retry, and backfill, specify source, target, business key, direction, tolerated delay, idempotency key, dead-letter queue, alert, and human action. During cutover, one system must be the authoritative writer for products, prices, stock, orders, or customers. The other may be read-only, event-driven, or batch-fed. Before retiring an old plugin, export its data, revoke credentials, and document historical lookup.
Import architecture: let CSV, apps, and APIs do different jobs
CSV works for large basic product, customer, or inventory loads that people can review. An app may handle historical orders, reviews, media, or extension objects, but review its permissions, data residency, retries, billing, uninstall behavior, and support boundary. An API is appropriate when you need identity maps, idempotency, deltas, complex transforms, and machine reconciliation. Shopify’s Bulk Operations guide covers JSONL, staged uploads, bulk mutations, status, and result files; neither HTTP 200 nor a completed bulk job proves every row succeeded.
WooCommerce REST API v3 uses pagination and exposes total headers or Link headers. Its order endpoints support filters such as modified_after, which can help build a delta process. For a large catalogue, many orders, or a substantial media library, measure memory, latency, failure rate, and result-download behavior per batch before choosing concurrency. Never copy a fixed sleep interval as the throughput strategy.
Give every batch an input, output, and retry boundary
Persist object range, source snapshot time, payload hash, request ID, target ID, success/failure/skip counts, error code, and last verification. Separate retryable network, throttling, and temporary 5xx errors from permanent field, permission, and duplicate-key errors. Put permanent rows in quarantine and replay only those rows after fixing the rule. Encrypt input and result files, retain hashes, and delete them on the approved schedule.
Incremental sync: use high-water marks, overlap, and reconciliation
The source store continues to receive orders, customers, refunds, stock, prices, and content changes after the first full extract. A modified_at cursor alone can miss records sharing a timestamp, clock-skewed writes, deletes, merges, or independently managed inventory. Store a high-water mark plus a stable ID, query with a safe overlap window, and deduplicate using the identity map and payload hash. Advance the cursor only after submission, result persistence, and reconciliation succeed.
Treat deletes, cancellations, and refunds as deltas
Define an event or difference query for deletion, unpublishing, customer merge, unsubscribe, order cancellation, refund, gift-card redemption, inventory adjustment, and URL removal. Shopify does not guarantee complete webhook delivery, and WooCommerce webhooks can be disabled after repeated failures, so schedule reconciliation between source valid sets, target sets, event logs, and business ledgers. Resolve conflicts according to the system of record and business time; the last-arriving request must not overwrite newer information blindly.
| Change | Capture method | Idempotency key | Quality gate |
|---|---|---|---|
| New order or customer | API high-water mark plus webhook | Source type + source ID + version | One target identity |
| Price or content update | Overlapping modified_after query | Source ID + timestamp + hash | Only approved fields overwrite |
| Inventory change | WMS event or controlled snapshot | SKU + location + version | Location-level quantity matches |
| Cancel, refund, or delete | Event, audit table, or tombstone | Source event ID | Target state and finance agree |
| Missed event | Scheduled reconciliation | Run ID + object range | Difference is zero or signed off |
Rehearsal: hard samples first, then two timed full runs
In a development or isolated store, start with difficult samples: three-layer variants, duplicate SKUs, special characters, missing images, long rich text, multi-address customers, guest orders, partial refunds, multiple currencies, gift cards, subscriptions, retired content, and multiple languages. Record field gaps, manual steps, notification side effects, API time, and cleanup. After rules are corrected, run a full rehearsal to measure throughput, delta catch-up, and rollback time; finish with a rehearsal that includes the intended freeze window.
Turn rehearsal results into signed gates
Every rehearsal should output source and target counts, field samples, relationship closure, amount differences, URL status, payment and fulfillment replay, sync lag, manual hours, failed rows, and cleanup instructions. P0/P1 differences must be zero. Lower-risk differences need an owner, deadline, mitigation, and business sign-off. If the run exceeds the acceptable freeze, improve batching, reduce scope, or choose staged cutover instead of taking the risk overnight.
Cutover runbook: write owners and stop conditions minute by minute
The runbook should cover change freeze, source backup, final full/delta extract, inventory and order watermarks, old-store notifications, app webhooks, payments, tax, shipping, DNS/domain, SSL, cache, robots, sitemap, monitoring, customer communications, and the first-order path. Shopify’s migration guidance recommends creating redirects before transferring the domain. Confirm that the old platform will not continue claiming the domain in a way that creates SSL or DNS conflicts.
Execute the cutover with an evidence-bearing timeline
Proceed only after the evidence at the previous checkpoint is signed. The relative times below are examples; the actual freeze length must come from rehearsal rather than a universal hour promise.
| Time | Owner | Dependency | Evidence to retain | Rollback trigger |
|---|---|---|---|---|
| T−30 to T−14 days | Project lead | Scope, method, and owners approved | Go/no-go, object ledger, rehearsal report | Critical object has no destination |
| T−7 days | Data/SEO leads | Target structure and URLs stable | Final field map, redirect ledger, restore record | Valuable URL or field remains unmapped |
| T−1 day | Operations/finance | Payment, tax, shipping, notification replay passes | Integration matrix, stock watermark, pause list | Payment or fulfillment still has a P1 gap |
| T−0 freeze | Migration lead | Staff online; snapshot hashes match | Freeze time, final delta, write-lock record | Delta cannot catch up or snapshot differs |
| T+0 to 2 hours | Store/payment leads | Domain, SSL, redirects, checkout ready | First order, payment, stock, ERP, email replay | Checkout or capture keeps failing |
| T+1 day | Business/SEO/finance | Monitoring and support queues owned | Reconciliation, 404/301 logs, sign-off | Order, amount, or stock gap exceeds threshold |
Freeze relationship-changing writes, not every conversation
Announce exactly which product, price, SKU, stock, discount, content, plugin, and setting changes are frozen, and who may approve an exception. If the old store cannot fully stop writing, use a high-water mark and delta queue to shorten the window. After cutover, validate a test or small real order through checkout, payment, ERP, inventory, fulfillment, and notification before releasing advertising and email traffic.
Acceptance: collect business-journey evidence, not just counts
Acceptance has five layers: count, field, relationship, value, and behavior. Count means source valid records close; fields include title, price, weight, address, status, time, and custom data; relationships connect customer, order, line, variant, and location; value covers currency, tax, discount, shipping, payment, refunds, gift-card balance, and stock; behavior covers browsing, search, cart, checkout, failed payment, fulfillment, return, login, email, and support lookup.
Risk-weight the sample instead of sampling randomly only
Prioritize highest-revenue products, hardest variants, oldest and newest orders, largest totals, multiple currencies, subscriptions, refunds, guest customers, duplicate identities, multiple addresses, special characters, primary languages, and every market. Capture request IDs, order numbers, timestamps, and environment along with screenshots; a screenshot is not the only evidence. Every difference needs severity, root cause, remedy, retest, and approver.
| Acceptance layer | Representative checks | Pass definition | Evidence |
|---|---|---|---|
| Counts | Products, variants, customers, orders, media, URLs | Differences are explained and within threshold | Reconciliation report |
| Fields | Price, weight, address, state, language, SEO | Required fields match source or contract | Field samples |
| Relationships | Order lines to variants, customers to orders, SKU to location | No critical orphan records | Relationship query |
| Value | Totals, tax, discounts, refunds, gift cards, inventory | Equations and balances pass | Finance and stock sign-off |
| Behavior | Checkout, payment, fulfillment, return, account, search | Critical journeys repeat successfully | Replay record |
Use one reconciliation matrix for counts, money, and locations
Use the same keys and definitions for every full load, delta, and post-cutover check. Zero is the default tolerance. Any non-zero difference needs a cause, compensation, owner, and due date; rounding or a global total must not conceal differences by location, currency, or state.
| Reconciliation object | Source count/value | Target count/value | Tolerance | Owner |
|---|---|---|---|---|
| Products and variants | Valid SKU count / sale-price view | Shopify SKU count / target-price view | Count 0; price per approved rule | Merchandising |
| Customer identities | Customer count / mailable-consent count | Customer count / mapped-consent count | Identity 0; activation pending listed | Customer and privacy |
| Historical orders | Order count / totals by currency | Order count / totals by currency | Count 0; amount 0 by currency | Finance |
| Refunds and gift cards | Refund count/value / balances and usage | Target refunds/balances / usage | Within finance-approved rounding | Finance |
| SKU × location stock | Sellable, reserved, in-transit by location | Target quantity and state by location | Default 0; WMS explanation signed | Supply chain |
| URL entry points | Valuable old URL count / traffic-revenue tier | Redirect/200/deprecation destinations | Unmapped 0; exceptions approved | SEO |
Rollback: restore continuity, do not simply delete Shopify data
Separate domain rollback, continued operation on the old store, compensation for target writes, and payment/finance reversal. If cutover has already produced orders, refunds, stock deductions, or registrations, pointing DNS back does not erase those facts. Lock writes, export post-cutover events, identify the authoritative system, backfill the old store or keep the target read-only, and require finance approval for refunds or recharges.
Set a trigger threshold for every serious failure class
Examples include sustained checkout failure, a mismatch between captured payments and orders, unexplained negative stock at a location, missing orders over threshold, mass 404s on valuable URLs, an integration queue that cannot catch up, or an access-control error involving personal data. Put thresholds in the runbook before cutover. When one fires, pause traffic and downstream automation, preserve evidence, then run the smallest compensation. Do not hide differences by importing the entire dataset again.
The first 30 days: retain evidence while retiring the old stack carefully
During days 1–3, watch checkout success, payment failures, order lag, stock differences, 404/301/5xx, email, refunds, and support issues hourly. Reconcile daily through day 7, then review markets, tax, shipping, application billing, search crawling, and rollback readiness weekly through day 30. Keep the old WooCommerce system available for controlled read-only lookup, encrypted backup, and privacy response. Do not remove the only copy of historical data before approval.
Close the stabilization period with a signed checklist
At day 30, confirm zero P0/P1 issues, signed differences, an owner for every integration, a tested backup restore, revoked legacy credentials, reviewed old app and hosting charges, completed customer communications, stable sitemap and redirects, and the first full month of payment and tax reconciliation. Business, engineering, SEO, privacy, and finance should jointly approve decommissioning the old site or moving it into long-term archive.
Frequently asked questions
Can all WooCommerce data be migrated automatically to Shopify?
There is no universal guarantee. Standard products, customers, or inventory may use official CSV or API routes, while extension fields, reviews, composite products, gift cards, subscriptions, payment tokens, historical orders, and multilingual content require separate decisions. Build the ledger and hard-sample test first, then combine CSV, an app, an API, and read-only archive as appropriate.
Must the WooCommerce store be closed during the migration?
Not necessarily for a long period, but a controlled freeze or delta process is mandatory. If the old store keeps accepting orders, registrations, refunds, or stock changes, capture those deltas and reconcile them at the final watermark. Without a reliable delta method, extend the maintenance window or narrow the cutover rather than allowing two systems to write the same fact.
Can historical orders, customer passwords, and payment cards move together?
Do not assume so. Historical orders can use a migration app or API; Shopify customer CSV cannot carry an external password, so customers normally reactivate or reset access. Card numbers and payment tokens depend on the provider, compliance controls, and subscription app. Decide which history belongs in Shopify and which stays in controlled archive, with payment and privacy approval for any token or subscription path.
Will moving to Shopify automatically preserve Google rankings?
No. One-to-one redirects, equivalent content, canonicals, hreflang, sitemaps, internal links, media, status codes, and post-launch monitoring all matter. Do not send every old product, category, and article to the homepage. Continue checking crawling, 404s, redirect chains, and organic landing pages after launch and repair high-value routes from the ledger.
When is the migration actually complete?
When data, relationships, amounts, stock, payments, tax, shipping, accounts, email, SEO, integrations, and team SOPs pass written acceptance, and rollback or compensation has been rehearsed with evidence. A working domain is a publishing step, not acceptance. During the 30-day stabilization period, the old data should remain controlled, queryable, and recoverable.
First-party sources and version note
- Shopify: Migrate to Shopify
- Shopify: Migrate from WooCommerce
- Shopify: Import products with CSV
- Shopify: Product CSV field rules and inventory CSV, inventory CSV
- Shopify: Import and export customer lists
- Shopify: Create and manage URL redirects
- Shopify: Markets and international SEO
- Shopify: Payments, taxes, and shipping, taxes, shipping zones
- Shopify developer: Bulk Operations, webhooks, gift cards, and subscriptions, webhooks, giftCardCreate, subscription contracts
- WooCommerce: Back up WordPress content
- WooCommerce developer: REST API v3 and webhooks, webhooks
- WooCommerce: Customer/order/coupon export extension
- WooCommerce: Product import/export, coupons, gift cards, subscriptions, and taxes, coupons, gift cards, subscriptions, taxes