Titles, prices and images move between Shopify and WooCommerce in an afternoon. Variants, collections, metafields and URLs do not, and the redirects have to exist before DNS changes. What maps, what has to be rebuilt, and the order to do it in.
By Rehan Idrisi · · 7 min read
Part of: Shopify, WooCommerce
A catalog move between Shopify and WooCommerce looks like a CSV export followed by a CSV import. We have done it in both directions, for an electronics accessories store leaving Shopify over app costs and for an apparel brand going the other way to stop running servers, and the import is the shortest part of either project. The time goes into the fields that have no counterpart, and into the URLs. What follows is the map of both, and the order of work that keeps search traffic off a 404 page.
Shopify's Title is WooCommerce's Name. Body (HTML) becomes Description, and it is HTML on both sides. Variant SKU becomes SKU. Image Src holds a URL the WooCommerce importer downloads, and Shopify's importer does the same with a WooCommerce Images column.
Price needs one decision first. Shopify's Price is the selling price and Compare At Price is the struck-through original. WooCommerce's Regular price is the original and Sale price is the selling price. A discounted product therefore needs Compare At to become Regular price and Price to become Sale price; a full-price product needs Price to become Regular price with Sale price empty. Get it backwards and every discounted product displays its sale price crossed out.
Tax is the second trap. An Indian store usually enters prices inclusive of GST, and both platforms have a store-level switch for that: Shopify's include tax in prices, WooCommerce's prices entered with tax. They have to agree before a single price row is imported. If one side is inclusive and the other exclusive, every price shifts by the GST rate on import day. Weight is the same problem in miniature. Shopify exports Variant Grams, always in grams, and WooCommerce stores weight in the store's configured unit, kilograms by default.
Shopify writes one row per variant and repeats the Handle down the group, with product-level fields on the first row only and extra rows carrying nothing but a Handle and an Image Src for gallery images. WooCommerce writes one parent row typed variable and one variation row per combination, each pointing at the parent through the Parent column. Converting between them is regrouping, in either direction.
Two things do not line up. Shopify allows three option axes per product; WooCommerce has no fixed limit on attributes, so a product varying on four cannot become one Shopify product. And a single-variant Shopify product still carries a placeholder option, Title with the value Default Title, which should become a simple WooCommerce product with no attribute at all. Our Shopify to WooCommerce CSV converter does the regrouping both ways and lists every column it dropped, with a count of how many cells held data, so the loss is visible before the import runs.
Shopify's product export has no collection column. Collections are a separate object, and an automated collection is a set of rules evaluated at request time, so membership is never stored on the product. The export carries Type, one free-text value, and Tags. WooCommerce has hierarchical categories, several per product, plus flat tags. Type maps to one category and Tags map to tags. The collection structure, which is usually where the navigation and the ranking landing pages live, has to be rebuilt as categories with products reassigned. A rules-based collection like under 999 becomes a manual category or a price filter. Going the other way, the tree flattens: Type holds one value, so a product in three categories keeps one, and the other two become collections built from tags.
Shopify metafields with a definition appear in the export as their own columns. WooCommerce reads any column prefixed Meta: into a custom field of that name. A fabric composition or a care instruction therefore crosses as text. The type and the display do not. A metafield typed as a list or a product reference arrives as a string, and a WooCommerce theme shows a custom field only when a template asks for it. Budget for that template change, or the data lands and never appears on a page.
Shopify products live at /products/handle and collections at /collections/handle. WooCommerce products live at /product/slug/ by default and categories at /product-category/slug/. Even when the handle and the slug are the same string, the prefix changes and the trailing slash changes. Every product and category URL on the old store needs a permanent redirect on the new one, and the map is built from the old store's URLs, never guessed from the new store's.
The order matters because crawlers do not wait. A domain that moves before the map exists serves a 404 for every indexed URL, and positions lost that way take months to earn back. WordPress will guess a redirect for an unknown URL from similar slugs. That is not a redirect map, and it sends some visitors to the wrong product.
Images follow the same rule. A Shopify export points at Shopify's CDN, and those URLs stop resolving when the store is closed, so import the images and check the media library before closing the account. In the other direction, the old WooCommerce host stays up until Shopify's importer has finished fetching.
Neither platform's product importer touches orders or customers. The first question about order history is whether it should move at all. GST returns have already been filed against the old store's invoice numbers. Those numbers cannot become order IDs on WooCommerce, where the ID is a post ID, without a sequential numbering plugin, and Shopify assigns its own numbers to imported orders. Keeping the old order export as the read-only record for the financial year, and starting clean on the new platform, is often the honest answer.
Customers move as records, never as logins. Password hashes do not transfer in either direction, so every customer resets a password or accepts an account invitation. Saved cards and UPI mandates are tokens held by the payment gateway against the old store's account, and they do not follow the customer. Tell customers before the move, not after the first failed login.
Build the redirect map before the domain moves. Export every old product, collection and page URL, generate the matching new slug, load old-to-new 301 redirects on the new store, and test them on a temporary hostname. Change DNS only once every old URL redirects, in one hop, to a page that returns 200.
Convert a product CSV between Shopify and WooCommerce column formats in either direction, with every dropped column listed explicitly.
Check a WooCommerce product CSV before you import it: missing columns, duplicate SKUs, orphaned variations and malformed prices, by row.
Generate clean, search engine optimized slugs from title strings or written copy.
Check a sitemap.xml against the sitemap protocol - well-formed XML, valid URLs, lastmod/changefreq/priority formats, duplicate entries, and the 50,000-URL limit.