Shopify decides the shape of your URLs. Products live under /products/, collections under /collections/, pages under /pages/ and blog posts under /blogs/, and only the last part, the handle, is yours to choose. So a move onto Shopify changes almost every URL on the old site, and a move off it means rebuilding redirects that only ever worked inside Shopify. Both directions also change who controls robots.txt, canonicals, structured data and hreflang. This post covers what Shopify fixes, what its redirect feature can and cannot do, what carries over, and a checklist for either direction.
The general method for any move, from benchmarking to rollback, is in the website migrations guide. Catalogue questions that are not specific to Shopify, such as faceted navigation, are in the ecommerce SEO guide.
The URL patterns Shopify fixes for you
Shopify's own documentation shows the patterns. A product URL is /products/ plus the handle, and its within filter turns that into a collection-aware URL such as /collections/sale-potions/products/draught-of-immortality.1 Pages sit under /pages/, as in /pages/about-us,2 and articles sit under the blog's handle, as in /blogs/potion-notions/ followed by the article.3 A variant adds a query parameter: /products/[product-handle]?variant=[variant-id].4
Shopify's help centre calls /products, /collections and /collections/all fixed Shopify paths.5 On a standard theme, plan on keeping every prefix. What you control is the handle after it, so spend the mapping effort there: keep the old slug as the handle wherever it still reads well, and the redirect map becomes a pattern instead of a list of guesses.
A worked example: a tea shop moving onto Shopify
Illustrative. Fernbrook Tea is a fictional shop on a custom PHP platform. Its old URLs and their Shopify equivalents show most of the problems you will meet.
| Old URL | New Shopify URL | What to watch |
|---|---|---|
/tea/green/sencha.php | /products/sencha | Straightforward. Keep the handle the same as the old slug. |
/green-tea.html | /collections/green-tea | Shopify treats a URL ending in .html as the same URL without it, so the old and new paths must differ in more than the extension.5 |
/category.php?id=12 | /collections/green-tea | Query string URLs might not work as expected with Shopify's redirects.5 Test every one. |
/shop/gift-sets | /collections/gift-sets | Shopify cannot redirect URLs that begin with /shop.5 Its redirect feature will not catch this one. |
/about.html | /pages/about-us | A page, so it moves under /pages/. |
/journal/brewing-guide | /blogs/journal/brewing-guide | Name the blog to match the old folder and the paths stay recognisable. |
The /shop row is the one that hurts. Shopify will not redirect URLs that begin with /apps, /application, /cart, /carts, /orders, /services or /shop, or URLs that use collection tag filtering.5 If an old site used any of those prefixes for pages with traffic or backlinks, find them in the inventory early and decide what you will accept, because the redirect feature will not catch them.
What you can and cannot control on Shopify
| Setting | What Shopify does | What you can change |
|---|---|---|
| URL prefixes | Fixed: /products, /collections and the other patterns above5 | The handle only |
| robots.txt | A default file Shopify describes as optimal for SEO6 | Add or remove rules in a robots.txt.liquid template |
| Canonical tags | Generated automatically to prevent duplicate content7 | Theme code, with care |
| Structured data | A Liquid filter that outputs JSON-LD for products and articles | Whether and how the theme uses it |
| hreflang | Added automatically for stores using Shopify Markets | Turn the automatic tags off and manage them yourself |
| XML sitemap | Generated automatically7 | Nothing directly |
robots.txt.liquid
Shopify's default robots.txt blocks admin, cart, checkout and account paths, filtered collection pages with Disallow: /collections/*+* and sorted ones with Disallow: /collections/*sort_by*.6 To change it you add a robots.txt.liquid template, which replaces the default output.8 Shopify recommends editing through the Liquid objects so the defaults keep updating, and its developer docs show request.host being used to set different rules per domain for stores selling into several markets.8
Shopify calls this an unsupported customisation and warns that incorrect use can result in loss of all traffic.6 One detail matters during a migration: uploading a theme from the Themes section of the admin does not import robots.txt.liquid, while ThemeKit or command line changes preserve it.6 If you launch on a new theme, check the live robots.txt again.
Collection-aware product URLs and canonicals
Shopify adds canonical tags automatically to keep duplicate content out of results.7 The duplicates it is guarding against include collection-aware product URLs. Shopify's own within documentation cautions that a standard product page and a product page in a collection context have the same content on separate URLs, and asks you to consider the SEO implications.1 Two checks are worth doing on the new theme:
- View the source of a collection-aware product URL and confirm the canonical points to the plain
/products/URL. - Check what the collection grid links to. If every product link goes through
/collections/.../products/..., crawlers find the duplicate first and rely on the canonical to sort it out. I would link to/products/directly where the theme allows it.
Variants follow the same logic. How variant URLs, canonicals and Merchant Center fit together is covered in product variants: URLs, canonicals, ProductGroup markup and Merchant Center.
Shopify's redirect feature and its limits
Shopify's URL redirects are managed under Content, then Menus, then URL redirects. They start working immediately, can point to a relative URL within the primary domain or a full URL elsewhere, and accept Liquid in both fields.5 They are 301s. Under the HTTP standard a 301 can be cached unless headers say otherwise,9 and Shopify notes that browsers and search engines do cache them, so a removed redirect can keep working in a visitor's browser until the cache expires.5 The limits are where migrations go wrong.
- A redirect only works from a broken URL. If a page still loads at the old path, the redirect does nothing.5 Hiding a product or collection makes its URL return a 404 so a redirect can take over, but making it visible again deletes that redirect automatically.5
- A store can hold up to 100,000 redirects, or 20,000,000 on the Plus plan.5 A large catalogue with years of retired products and old campaign URLs can approach the lower figure.
- Prefixes such as
/shop,/cartand/apps, the fixed paths, and collection tag URLs cannot be redirected.5 - URLs with query strings might not work as expected.5
- Market subfolders need testing. The help page says a redirect applies to all language or market subfolders, and in its list of limitations also says redirects do not automatically apply to all market subfolders.5 With two statements pulling in different directions, test a sample of
/en-ca/-style URLs yourself.
Importing redirects in bulk
Build the map in a spreadsheet first, as described in how to build a redirect map. Shopify imports it as a CSV with two columns, Redirect from and Redirect to, through the Import button on the URL redirects screen, and the help centre links a sample template.5 Keep the redirect-from values relative, such as /tea/green/sencha.php. Before you transfer the domain, Shopify's migration guide suggests setting up redirects in advance for pages customers may have bookmarked.10
Once the domain points at Shopify, test every row against the live site. In bash, this prints the status, the target and the row's intended target side by side:
- Bash:
tail -n +2 redirects.csv | while IFS=, read -r from to; do curl -s -o /dev/null -w "%{http_code} %{redirect_url} expected $to\n" "https://www.example.com$from"; done - Windows PowerShell 5.1:
Import-Csv redirects.csv | ForEach-Object { $r = Invoke-WebRequest -Uri ("https://www.example.com" + $_.'Redirect from') -MaximumRedirection 0 -UseBasicParsing -ErrorAction SilentlyContinue; "$($r.StatusCode) $($r.Headers.Location) expected $($_.'Redirect to')" }
Every row should return a 301 to its mapped target, and that target should return a 200. If scripted requests get a verification page instead of the store, run the check from a crawler in list mode, or spot-check in a browser.
What carries over, and what does not
Shopify's migration guide lists what can be moved onto the platform: products, customers, historical orders, gift cards and store credit, blogs, and pages. Import products first, then customers, then orders, so the orders connect to both.10 Its Store Migration app supports moves from platforms including Amazon, Etsy, eBay, Squarespace, Wix and WooCommerce.10 The search signals around that content are a different matter.
| Item | Moving onto Shopify | Moving off Shopify |
|---|---|---|
| Product, page and blog content | Imported, then checked template by template | Exported, then rebuilt in the new platform's structure |
| Redirects | Imported by CSV, within the limits above | Export them by CSV first.5 They only run while Shopify serves the domain. |
| Reviews | Usually held by a review app, so they move only if that app can import them | Depend on the review app's export |
| Structured data | Whatever the new theme outputs | Whatever the new platform outputs |
| hreflang | Automatic with Shopify Markets | Rebuilt from scratch |
Collection-aware and ?variant= URLs | Not relevant on the way in | Need their own redirect rules on the new platform |
Reviews and structured data
Reviews are where rich results most often disappear after a move. Review content usually lives in a third-party app, so the questions are whether that app can export everything, including dates and ratings, and whether the new setup shows them on the product page. Google's guidelines say structured data must be a true representation of the page, that you should not mark up content readers cannot see, and that fake reviews are misleading content.11 Markup carried over without the visible reviews breaks the first rule.
Shopify's structured_data filter outputs JSON-LD for products, as Product or as ProductGroup when there are variants, and for articles as Article.12 Themes and apps differ in whether they use it, add their own, or both. Save the JSON-LD from one product, one collection and one article on the old site, then compare it with the new templates before launch. Where a theme and a review or SEO app both output markup, look for duplicate Product blocks.
hreflang through Shopify Markets
If the store uses Shopify Markets, Shopify adds hreflang tags automatically through content_for_header in the theme layout. The tags reflect each market's languages and regions and stay in sync with each page's canonical URL.13 Shopify warns that adding your own tags on top can produce duplicate or conflicting annotations, and lets you turn the automatic tags off under Online store, then Preferences.13 On a move onto Shopify, remove any hreflang an old theme or app outputs. On a move off, you rebuild every annotation yourself, so audit the result with the method in how to audit hreflang.
A migration checklist for moves onto and off Shopify
Moving onto Shopify, in order
Inventory
Collect every old URL with traffic, links or rankings, from a crawl, analytics, Search Console, backlinks and logs.
Shopify's migration guide puts SEO as an optional last step, after shipping, taxes, payments and the domain.10 I would move it to the start, because the URL inventory and the redirect map decide how much of the old site's search traffic survives. Google's site move guidance applies in full: map old URLs to new ones, use permanent server-side redirects, do not send many old URLs to the homepage, and keep the redirects for as long as possible, generally at least a year.14
Moving onto Shopify
Moving off Shopify
The Migrations skill in my open-source pack plans the redirect map and verifies each mapping on the served output, which suits either direction. The work that decides the outcome is the same in both: an inventory nobody skipped, a map that respects Shopify's patterns, and a test of every row on the live domain.
Common questions
01Can I remove /products/ or /collections/ from Shopify URLs?
02How many URL redirects can a Shopify store have?
03Why is my Shopify redirect not working?
04Does Shopify add hreflang tags automatically?
05Do product reviews carry over when I migrate a Shopify store?
Sources
- Platform docs13
- Regulator1
- 01Liquid filters: withinShopify Dev DocsPlatform docs
- 02Liquid objects: pagesShopify Dev DocsPlatform docs
- 03Liquid objects: articleShopify Dev DocsPlatform docs
- 04Liquid objects: variantShopify Dev DocsPlatform docs
- 05Creating and managing URL redirectsShopify Help CenterPlatform docs
- 06Editing robots.txt.liquidShopify Help CenterPlatform docs
- 07SEO overviewShopify Help CenterPlatform docs
- 08Customize robots.txtShopify Dev DocsPlatform docs
- 09RFC 9110: HTTP SemanticsIETFRegulator
- 10Migrate to ShopifyShopify Help CenterPlatform docs
- 11General structured data guidelinesGoogle Search CentralPlatform docs
- 12Liquid filters: structured_dataShopify Dev DocsPlatform docs
- 13Use hreflang tags in your themeShopify Dev DocsPlatform docs
- 14Site Moves and MigrationsGoogle Search CentralPlatform docs
Written by Mani Bharij, SEO & AI Search Consultant in London. More on this subject in the Website migrations guide.