Shopify to Shopify migration: moving stores without data loss
How to migrate from one Shopify store to another using Graftport — covering products, customers, orders, URL redirects, handle conflicts, and the cut-over sequence.
How to migrate from one Shopify store to another using Graftport — covering products, customers, orders, URL redirects, handle conflicts, and the cut-over sequence.
A Shopify-to-Shopify migration sounds deceptively simple — both stores speak the same platform. In practice it is one of the more nuanced migration types. The source and destination share the same data model, but handle collisions, existing URL redirects, and Shopify's idempotency guarantees all require deliberate handling. This guide covers when and why you'd run a Shopify-to-Shopify migration and exactly how Graftport handles the move.
Consolidating multiple stores. An agency running a rebrand might merge two regional Shopify stores into a single international store on Shopify Plus. Or a brand group that acquired a sister brand wants to bring that brand's product catalogue onto a shared platform. In both cases, you're moving products, customers, and orders from one Shopify store into another Shopify store that may already have records.
Store rebranding or domain migration. A merchant is retiring an old Shopify store and launching a net-new one under a different brand or domain. They want the product catalogue, customer accounts, and order history to move with them — not start from scratch.
Migrating to a different Shopify plan. Moving from Shopify Standard
to Shopify Plus changes your store's URL (from myshopify.com to a
custom domain), your plan capabilities, and often the store slug. The
data doesn't move automatically. See Migrating to Shopify Plus with
Graftport for the Plus-specific
considerations; this guide covers the underlying store-to-store move.
Separating a multi-currency store. A merchant running multiple currencies on one store wants to split into per-region stores. You'd use a scoped migration to move the relevant customer and order subset to each regional destination.
The Shopify source connector reads from the Shopify Admin REST API. The following resource types are supported:
| Resource | What migrates |
|---|---|
| Products | Title, description, variants with prices and SKUs, images, tags, metafields, product type |
| Collections | Smart and custom collections, title, description, collection image, product membership |
| Customers | Name, email, addresses, tags, customer notes, marketing consent status |
| Orders | All orders — line items, tax, shipping, fulfilment status, financial status |
| URL redirects | All existing URLRedirect rows on the source, plus historical handle redirects |
URL redirects are particularly important in a Shopify-to-Shopify migration. If the source store has accumulated redirects over years of product renames and collection restructuring, those redirects protect inbound links and Search Console indexed URLs. Graftport carries them across as-is to the destination.
Source Shopify store. Install a custom app on the source store
(Settings → Apps and Sales Channels → Develop Apps). Issue an access
token with read scopes for every resource you're migrating:
read_products, read_customers, read_orders, read_fulfillments,
read_url_redirects, read_inventory.
Destination Shopify store. Install a custom app on the destination store and issue an access token with read + write scopes for each resource type. The full scope list per resource is on the destination setup page in the Graftport engineering docs.
Paste both tokens into the New migration wizard. The wizard validates both before proceeding.
In Shopify, every product has a handle — the URL slug used in
/products/{handle}. If the destination store already has products
(because it was an existing store before the migration), handles from
the source may collide with handles on the destination.
By default, if a product with the same handle already exists on the destination and the conflict strategy is overwrite, Graftport updates that record in place. This is the right behaviour when you're moving the source store onto the destination and want the destination's version to be replaced by the source version.
If you want to keep the destination's existing product for a colliding handle and only load net-new products from the source, use the skip conflict strategy. Skipped records are counted but not billed.
For consolidation scenarios — where the destination is an already-live
store and you're adding the source store's catalogue as a new set of
products — consider adding a prefix to the source handles in the
products mapping (for example, "brand-a-" & $.handle) to avoid any
collisions entirely.
If the same customer email exists on both the source and destination, Shopify will reject the second create with a duplicate-email error. The practical approach:
The sequence is the same as any Graftport migration:
Extract. Graftport pulls all enabled resources from the source Shopify store via the Admin API. Large stores (100k+ products) take longer at extract time due to Shopify's API rate limits; Graftport handles the back-off automatically.
Transform. The mapping converts source records into destination-ready payloads. For Shopify-to-Shopify migrations, the transform is mostly a pass-through — the data model is the same. The primary mapping work is around handle adjustments, tag normalisation, and metafield namespace mapping if source and destination apps use different metafield namespaces.
Dry run. Always run with dry-run on first. Inspect product and customer counts, check for handle collision warnings in the run items, and confirm URL redirect counts look right. Fix any surprises in the mapping before the real load.
Load. With dry-run off, records are written to the destination. The load is idempotent — Graftport tracks each source record by its Shopify ID, so re-running the load never creates duplicates. Records already on the destination from a prior load run are skipped at zero cost.
At go-live — when you flip DNS from the source store to the destination store — the destination needs URL redirects in place for any URLs that changed between the two stores. Graftport migrates the source store's existing redirect table as part of the redirects resource.
If you changed product handles during the migration (e.g. by adding a brand prefix), you also need redirects from the old handles to the new ones. The redirects mapping is configurable — it can generate redirects for handle changes in addition to carrying over the source store's existing table.
The SEO preservation guide covers the Search Console verification routine for the crawl window after DNS flip.
If you're running two or more Shopify stores into a single destination, create a separate Graftport migration per source store. Each migration has its own source credentials, runs independently, and loads into the same destination store. Handle and customer deduplication decisions apply per migration.
The Consolidating Shopify stores with Graftport guide covers the multi-source workflow in detail, including how to sequence the migrations and avoid loading conflicts between them.
Once DNS is pointing at the destination and the final load run has completed, run a 24-hour delta extract and load. This picks up any orders placed on the source store during the DNS propagation window. Because Graftport's load is idempotent, everything already on the destination is skipped — only the new orders from that window are added.
Ready to try it?
Connect a source store, dry-run the move, and see the exact destination state before committing a single record.
Start a migration at app.graftport.com
Related reading:
Connect a source store, dry-run a migration, see the exact Shopify result before a single record lands. The same platform your team will use on go-live night.