Skip to content
Back to all articles
Shopify Migration Expert
Technical SEO
301 Redirects
Matrixify
Case Study

Shopify Migration Expert Notes: Moving URLs Without Losing SEO

The redirect ordering rule Shopify does not document, URL inventories, rollback asymmetry, and what a platform migration leaves behind years later. Field notes from repeatable Shopify migrations.

August 20, 2026 12 min readBy Matheus Abrahão

Migrations are not a project, they are a process

Most migration advice assumes you do it once: leave Magento, arrive on Shopify, cry, celebrate.

The migrations that taught me the most are the ones that happen every three to four weeks. On a US building-products manufacturer's storefronts, an old product line is progressively retired and replaced with a new one — old SKUs out, new SKUs in, URLs redirected, across two stores. Same operation, dozens of times.

Repetition is what turns migration from an art into a runbook. Here is the runbook.

The atomic operation

Per SKU pair, three things happen:

  • Old product → Draft
  • New product → Active
  • Old URL → 301 to the new URL

Three operations, two stores, in a fixed order. And the order is not arbitrary.

The ordering rule Shopify does not put in a warning box

Upload Active first, then Draft, then Redirects.

The reason: Shopify ignores a URL redirect while the source URL still resolves to a live product. The redirect record exists, it appears in the admin, and it does nothing. The live product wins.

So if you create redirects before drafting the old products, your redirects silently do not fire. You will not get an error. You will find out from Search Console six weeks later, after the equity has already leaked.

Draft the old product first. Then the redirect takes effect.

The mechanics, concretely

Per round, six import files — three per store, times two stores:

  • Two XLSX files (activate, draft) with a sheet named exactly Products, containing only ID and Status. Not Sheet1. Not Products (1).
  • One CSV: Redirect from,Redirect to, with full absolute URLs on the destination side, using that store's own domain.

Three things that will bite you:

Product IDs are store-specific. A consumer-store ID used against the wholesale store gives "product not found." The two stores have entirely separate ID spaces.

Scientific notation silently corrupts IDs. A 13-digit product ID pasted into Excel becomes 1.05E+13. Format the column as Text before pasting. This is the single most common cause of a migration import that reports success against zero rows.

Parent and child products are not variants. Variants are finishes inside one product. Children are separate products with separate IDs and separate URLs — multi-unit versions, kit bundles, cut-down sizes. Activating a "mother" product activates its children. If your redirect list only covers parents, every child leaves an orphaned live URL behind.

Verification, and the audit trail Shopify does not give you

Verification is thirty seconds and non-negotiable: open two or three old URLs in incognito and confirm the 301 lands where it should. Then confirm the new pages are live on both stores.

Incognito matters because your logged-in admin session can render draft products.

And a detail worth knowing: Shopify records a product's creation date, not its activation date. If you will ever need to answer "when did this SKU go live?" — for a retailer, for a warranty claim, for a marketing post-mortem — you have to log it yourself, out of band. We keep a workbook with activation dates and a release-schedule legend. The platform does not remember, so you do.

Batching, because the cost is fixed

The whole process takes 20–30 minutes whether you migrate one pair or six. That fixed cost drives an explicit decision rule:

  • 4–6+ pairs ready → run the round.
  • 1–3 slow movers → hold and batch them with the next round.
  • 1 fast mover → run it alone as a deliberate exception, because the revenue justifies the overhead.

Making that rule explicit stops the process from being run ad hoc every time someone asks nicely.

Automating the file generation

The six files per round are mechanical, which means they should not be made by hand.

I wrote a Python generator that reads the redirect-mapping workbook read-only, takes an approved list of parent SKUs, filters to those parents (children included automatically), de-duplicates variant SKUs down to product IDs, resolves old SKUs to old product IDs, keeps the two stores' ID spaces separate, and emits all six files.

How I validated it: regenerated a historical round that had already been run manually and byte-matched the output. One parent expanded to 90 variant SKUs which collapsed to 3 product IDs — exactly the kind of arithmetic a human gets wrong at 6pm.

Redirect safety rules

Live ads point at existing URLs. A wrong redirect in a bulk file breaks paid traffic silently — the ad still runs, the click still costs, the landing page is now something else. Never generate a redirect file without showing the before/after pairs for review first.

The asymmetry rule. This is the thing I want people to internalise:

  • Deleting a wrong SKU is reversible in five minutes.
  • A broken redirect on a fast-selling product is lost revenue and lost SEO instantly, and no rollback un-loses it.

So price files and redirect files get line-by-line human review. Description and tag files get a spot check. Review effort should follow blast radius, not row count.

Always export current state before importing. That export is your rollback. Test 5 rows before 200.

URL inventory: the artifact you build before you move anything

For a genuine site split or replatform, the pre-work is an inventory, not a plan.

We built a full crawl-and-classify inventory of roughly 2,072 URLs per store — about 4,144 across both — with columns for store, page type, title, URL and last-modified date. Then joined it against organic performance data to produce three artifacts:

  • A master URL → traffic map: organic traffic per month, keyword count, traffic share, top query with its volume and position, and primary intent, per URL. This is what tells you which redirects are load-bearing.
  • A "ranking but not in inventory" list. 33 URLs earning organic traffic that the inventory did not know existed — including legacy product URLs from a discontinued material line and a bare http:// homepage. These are the URLs a migration loses, because nobody redirects a page they do not know they have.
  • A query-opportunity list: high-volume terms sitting at positions 11–19. Page-two risk. A migration can push these either direction, so you want them identified before you move.

That triad is the artifact set. If you are quoted a migration and nobody mentions a URL inventory, the quote is for something else.

What a migration leaves behind, years later

The store I work on migrated from another platform long before I arrived. The residue is still measurable, and every item on this list is a real bug I found:

  • Dead conversion metrics in the email platform — a <old platform> Placed Order metric still selectable in dropdowns, recording 0 every day. Any flow pointed at it reports $0 revenue forever.
  • Legacy customer tags: <old platform> Group:1, migrated. Still being written by nothing, still matched by segments.
  • Legacy product metafields with the old platform's namespace, still on the schema, still populated on old products and empty on new ones.
  • Products with no compare-at price, because the old platform did not have that field and the migration had nowhere to put MSRP.

Budget a post-migration cleanup sprint at 90 days. Nobody does, and this is what it costs.

The failure mode that follows every activation

Products get flipped to Active and the Online Store sales channel is never added. They are active, in stock, correctly priced, and completely unbuyable.

The first audit for this across two stores found 164 of them — 86 on one store, 78 on the other. 35 were carrying inventory. One had 5,469 units sitting idle.

Detection is cheap: export read-only, filter to Status = Active, then one query for rows where active AND published = false, sorted by inventory descending. I run it over the CSV with DuckDB in about ten seconds.

One caveat that matters: the Published column reflects only the Online Store channel. A true "published to N of 8 channels" audit needs the Admin API publications query. If you syndicate to retail channels, the CSV will tell you a comfortable half-truth.

If you are migrating to a new domain

The hardest migration is not the catalog. It is moving a logged-in, revenue-generating audience.

Every bookmark, every saved login link, every email flow URL, every sales-rep email signature and every paid campaign points at the current address. The position I hold on this: the redirect map is built before anything moves, it is its own workstream with its own owner, and it does not get absorbed into whoever happens to be building the new pages.

Migrations fail in the gaps between people's job descriptions, not in the technology.


I run Shopify migrations and URL restructures on stores where downtime and lost rankings are not acceptable. See [Shopify migration services](/shopify-migration-expert) or [hire a Shopify developer](/hire-shopify-developer).

Direct: [WhatsApp +55 11 98851-2788](https://wa.me/5511988512788) · [contato.matheusabrahao@gmail.com](mailto:contato.matheusabrahao@gmail.com)

Need a senior engineer who thinks like an operator?

I take on a small number of Shopify operations and senior engineering engagements each quarter. If your store needs catalog hygiene, technical SEO, performance, or marketing automation done right — let's talk.

Continue reading

Vamos conversar