WooCommerce to Shopify Product Import: Variants and Redirects With AI

Coding Liquids tutorial cover featuring Sagnik Bhattacharya for WooCommerce to Shopify Product Import: Variants and Redirects With AI.
Coding Liquids tutorial cover featuring Sagnik Bhattacharya for WooCommerce to Shopify Product Import: Variants and Redirects With AI.

Export your WooCommerce products to CSV, ask AI to map each column to Shopify's product import file, and have it flag variable products, category paths and image lists that need restructuring. Then ask it for a redirect table, and spot-check 20 products in Shopify before you point the domain across. AI drafts the mapping; you verify it.

Most failed migrations go wrong in the same three places: variations that flatten into one product, category paths that become tags nobody planned, and old addresses that quietly start returning "page not found". All three are cheap to catch on a 20-product test import and expensive to catch after the domain moves, so the prompts and the sample audit below concentrate on them.

Follow me on Instagram@sagnikteaches

What the two systems store differently

WooCommerce keeps a variable product as one parent row plus one row per variation. Its exporter lists variable and variation as values in the Type column, and variation rows point back to the parent through a Parent column that uses the SKU where it can. Attributes sit in numbered column groups: name, value or values, default, visible and global.

Connect on LinkedInSagnik Bhattacharya

Shopify's product file works the other way round. The first row for a product carries every product-level field and the first image. Each further variant gets its own row that repeats the URL handle, leaves Title, Description, Vendor and Tags empty, and fills in the variant details. A product can have three options at most, and a product with a single option uses "Default Title" as the option name.

Subscribe on YouTube@sagnikteaches

Shopify's help pages also tell you to check your headers against its own sample CSV. They are case-sensitive, and if the format does not match or headers are missing, the import fails. Download the current sample from the Import screen before you start, because the names AI remembers from older guides may be out of date. The help page for the file format currently names fields such as URL handle, Option1 name, Option1 value, SKU, Product image URL, Image position and Status; compare these with your downloaded sample and use whatever your sample says.

That gap between a parent-and-children layout and a repeated-handle layout is the reason a plain copy-and-paste into the template rarely works. It is also the job AI does well, because the task is pattern matching across a table you can show it. If your source data is untidy before it reaches either platform, cleaning supplier data first saves time on both sides.

The Complete Excel Course with AI Integration thumbnail

The Complete Excel Course with AI Integration

From formulas and pivot tables to Power Query, DAX, VBA and AI with Copilot, ChatGPT and Claude — hands-on from the first lesson.

By Sagnik Bhattacharya and Virginia Thorn, Primetime Emmy Award winner

Buy now

Prepare the export before any AI sees it

In WooCommerce go to Products, All Products, then Export. The default is every column, which is what you want for a migration. Choose the product types and categories to include, and choose "Yes, export all custom meta" if plugins hold data you care about; those columns arrive with a meta: prefix. Export drafts and private products too if you plan to carry them over, since you can set them to draft in Shopify afterwards.

Then do the dull jobs a person should do first:

  • Save a copy of the untouched export and never edit it. Every later step works on a copy.
  • Delete columns you know you will not use, such as cross-sell IDs and upsell IDs, but keep a note of which ones went.
  • Count the rows by Type: how many simple products, how many variable parents, how many variations. You will compare these numbers to Shopify later.
  • Remove customer, order and review data from anything you plan to paste into a chat tool. Product data is fine to share; personal data is not.

Large stores should send AI a sample, not the whole file. Thirty to fifty rows that include every product type, a variable product with three attributes, a product with a missing SKU and a product with an awkward category give it enough pattern to work with. For the full file, use the mapping it produces as a rule set, not as a thing to retype.

Ask for a column map, then argue with it

Start with the map. Give the AI two things: the header row of your WooCommerce export, and the header row of the sample file you downloaded from Shopify. Ask for a table, not code.

Below are two CSV header rows. The first is a WooCommerce product export. The second is Shopify's product import sample.

For every Shopify column, tell me which WooCommerce column(s) fill it, what transformation is needed, and mark anything with no source as "NO SOURCE". Then list every WooCommerce column that has no Shopify home and say whether to drop it, turn it into a tag, or turn it into a metafield.
Do not invent column names. If a name is ambiguous, ask me.

WooCommerce headers:
[paste]

Shopify headers:
[paste]

Illustrative output for a small shop selling workwear might look like this:

Shopify fieldWooCommerce sourceTransformation
TitleNameParent rows only; blank on variant rows
URL handleName (or Slug if exported)Lower-case, hyphens, repeat on every row of the product
DescriptionDescriptionKeep the HTML; strip shortcodes in square brackets
TagsTags, plus CategoriesJoin; categories become tags only if you do not rebuild collections
Option1 name and valueAttribute 1 name, Attribute 1 value(s)Split a multi-value attribute across variant rows
SKUSKUCopy; flag duplicates and blanks
Price and Compare-at priceSale price, Regular priceRegular goes to compare-at only if a sale price exists
Product image URLImagesSplit the comma list into one row per image
StatusPublished1 (published) becomes active; 0 (private), -1 (draft) and 2 (pending review) need a decision, usually draft

Now argue with it. Three mistakes turn up often in this kind of output. The model may map the sale price to the main price without remembering the regular price needs to go to compare-at. It may treat the WooCommerce Categories column as a single tag. And it may gloss over the Shopify column that has no WooCommerce source at all, such as the product category taxonomy. Ask a follow-up for each: "Which Shopify columns will be blank for every product, and does that matter?"

Read the whole table once yourself against the sample file. If AI names a Shopify column that is not in your downloaded header row, it has guessed; delete that line.

Variants: the part that breaks most imports

Take a variable product, say a hi-vis jacket sold in three sizes and two colours. WooCommerce exports one parent row and six variation rows. In Shopify that becomes one product with two options and six variant rows sharing a handle. The parent row's data folds into the first variant row, and the other five rows leave Title, Description, Vendor and Tags blank.

Ask AI to do the reshaping on your 30-row sample and show its working:

Here are rows from a WooCommerce export: one variable product (Type = variable) and its variations (Type = variation, Parent = the SKU).

Rebuild them as Shopify import rows:
- first row carries all product-level fields plus the first variant
- each other variant is its own row with the same handle, and Title, Description, Vendor, Tags left empty
- Option1 name/value and Option2 name/value come from the Attribute columns
- keep SKU, price, weight and stock quantity per variant
Return a table with these columns only: Handle, Title, Option1 Name, Option1 Value, Option2 Name, Option2 Value, SKU, Price. Then list any product that has more than three attributes, since Shopify allows three options.

A typical illustrative result: the model correctly builds six rows for the jacket but writes the colour in the wrong option slot for half of them, so "Navy" appears under Size. That is why you read the output instead of trusting a row count. Check that Option1 holds the same kind of value on every row of a product.

Where a store runs out of options

Some WooCommerce products have four attributes: size, colour, material and length. Shopify allows three options, so one has to give way. Three ways to handle it, in order of how much I'd trust each:

  1. Merge two attributes into one option value, such as "Navy / Long". Fine when only some combinations exist.
  2. Split the product into two products that share a collection. Fine when the fourth attribute defines a genuinely different item.
  3. Move the fourth attribute to a line-item property or a separate customisation app. Only if the customer chooses it freely.

Ask AI to list the affected products and propose one of the three for each, then make the call yourself; it cannot know which combinations you actually stock.

Why option values matter after launch

Shopify's help page warns that changing Option1, Option2 or Option3 values on a later import deletes the existing variant IDs and creates new ones, which can break connected apps. Moving a value from one option position to another can also produce an error saying specific lines are invalid, with no further detail. So settle your option names and order on the first import, because correcting them later is messier than getting them right now.

Another trap sits in the same help page: variant-related columns such as SKU or weight need Option1 name and value present. Leave those out and Shopify creates a default variant and removes existing ones. On a fresh store that costs you nothing, but it is a nasty surprise if you re-import to fix a typo. Always keep the option columns in the file.

Categories become collections, not tags

WooCommerce stores categories as a comma-separated list, with a greater-than sign marking hierarchy, so one cell might read "Clothing > Jackets, Sale". Shopify does not import that tree. You get collections, which are lists of products, and a separate product category field whose value must come from Shopify's Standard Product Taxonomy and which Shopify uses, among other things, to work out tax rates.

Ask AI to propose three things from the unique category paths in your export:

  • A short list of collections to create, with the rule that fills each (a tag, a product type, or a manual list).
  • A mapping from each WooCommerce path to a tag name you can import now.
  • A best-guess match to Shopify's product category, flagged "needs checking" where the match is loose.

Say a four-person accountancy-supplies shop has 140 categories because staff added them freely over six years. AI will usually cluster these into 12 to 20 collections, and, just as usefully, it will point out near-duplicates such as "Folders" and "Folder". Accept the clusters you recognise. For the taxonomy side, fixing Shopify taxonomy at scale covers the matching in more depth.

One import-specific point: Shopify's file format allows one extra column called Collection without breaking the format, and exports do not include it. Treat it as a convenience for the first load, and still confirm in the admin that each collection holds the right count.

Images: the quiet failure

Shopify pulls images from URLs during the import. Per its help page, each image needs its own row with the handle repeated, the image position starts at 1 and ascends, and the URL must be reachable over https with no password in front of it. File names should not include markers such as _thumb, _small or _medium, so WooCommerce's resized copies are the wrong thing to link to.

That has practical consequences for a WooCommerce export, where the Images column lists URLs separated by commas with the first as the featured image. Ask AI to split that list into rows, but then run three checks of your own:

  1. Open ten of the URLs in a private browser window. If the old site is behind a maintenance page or login, none will load.
  2. Look for URLs ending in a size suffix such as -300x300, and strip it so the original upload is fetched. Ask AI for a find-and-replace pattern, then test it on five rows.
  3. Sort your file only before you build the image rows. Shopify warns that sorting a CSV in a spreadsheet editor can break image links and lose images.

Alt text is the other loss. WooCommerce's core importer cannot add or edit alt text, so the export may not carry it. Shopify has an alt text column (512 characters maximum, 125 or fewer recommended). If you want it filled, ask AI for a draft per image from the title and option, and keep each under 125 characters. Read twenty before you accept the batch, because generic drafts such as "product image" add nothing.

A worked run: 412 products, 3 hours of checking

Illustrative numbers for a small architecture-supplies shop moving to Shopify. The export holds 412 product rows: 168 simple products, 61 variable parents and 183 variation rows. That means Shopify should end with 168 + 61 = 229 products and 168 + 183 = 351 variants.

The plan, with rough time for each step:

  1. Export and back up (15 minutes).
  2. Column map with AI, two rounds of corrections (30 minutes).
  3. Variant reshaping on a 40-row sample, then the rule applied to the full file in the spreadsheet (60 minutes).
  4. Category clusters and image URL clean-up (45 minutes).
  5. Test import of 20 products to a development or trial store (20 minutes).
  6. Full import, split in two because the file passed Shopify's 15 MB limit once image URLs were added (20 minutes).

After the full import, the counts say 229 products and 349 variants. Two variants are missing. Filtering the original file for variation rows whose Parent SKU did not match any parent shows two orphaned variations left over from deleted products. They never belonged in the store; the check found what the row count alone would have hidden. That is the value of reconciling the numbers, and it costs ten minutes.

Redirects: the list that protects your traffic

Shopify product pages live under /products/handle and collections under /collections/handle. WooCommerce stores usually use /product/name or a shop-and-category path, so almost every address changes. A redirect sends the old address to the new one, so visitors and search engines land on the right page instead of an error.

Build the list in four steps.

  1. Get the old addresses. Export them from WooCommerce (the permalink or slug), and add the addresses that earn traffic or links from your search console or analytics reports. Do this before the old site goes offline.
  2. Build the new addresses. Shopify generates the handle from the title unless you set it, so use the handle column in your file to predict them.
  3. Ask AI to pair them and show you the weak matches.
  4. Import the finished pairs into Shopify's URL redirect list.
I have two lists. OLD is the WooCommerce product URL path with its SKU. NEW is the Shopify handle with its SKU.
Match by SKU first. Where there is no SKU, match by closest title and mark the row "CHECK".
Output a CSV with two columns, "Redirect from" and "Redirect to", using relative paths that start with a slash.
Also list OLD rows with no match, and NEW rows with no old address.

Shopify's help page says you can import redirects from a CSV through Content, Menus, then the URL redirects list, and offers a sample file as a template. It does not spell out the header names on that page, so use the headers in the sample you download. Redirects work immediately once saved.

Things the redirect page warns about that affect a migration:

  • You cannot redirect from addresses that start with /apps, /application, /cart, /carts, /orders, /services or /shop, nor from the fixed paths /products, /collections and /collections/all. A WooCommerce /shop/ address is on that list, so plan for the main shop page and any /shop/... product addresses to need a different answer, such as a new navigation link, or a redirect only from addresses that do not use the blocked prefix.
  • A redirect only works from an address that returns "page not found". If the old address still loads a page in Shopify, the redirect does nothing.
  • The limit is 100,000 redirects on standard plans.
  • Query strings might not behave as expected, so avoid relying on them.
  • A 301 redirect is cached by browsers and search engines, so a wrong pair lingers after you delete it. Test before you save in bulk.

If your domain moves too, or the old store keeps running on another address for a while, that work happens at the domain level and sits outside Shopify's redirect table.

The 20-product spot-check

This is the step that earns its keep. Before you switch the domain, pick 20 products and compare them against the old store, side by side. Pick them deliberately rather than at random:

  • 4 simple products (the easy case should be perfect).
  • 6 variable products, including your biggest and one with three options.
  • 2 products with a sale price.
  • 2 products with long descriptions that contain tables, lists or embedded shortcodes.
  • 2 products with many images.
  • 2 products that were out of stock or hidden on the old store.
  • 2 of your best sellers by revenue.

For each one check the same ten things: title, handle, description rendering, price and compare-at price, every variant label and its SKU, stock count, image count and order, weight, collection membership. Then test the redirect for that product from the old address.

AI helps with the comparison. Paste the old row and the matching new row from the two files and ask it to list differences:

Compare these two product records. The first is the WooCommerce export row(s), the second is the Shopify import row(s) for the same product. List every difference in title, price, variants, image count, tags and status. Ignore column order. Mark differences that look intended (for example regular price moved to compare-at) separately from those that look like errors.

Illustrative result for one jacket: the model reports the old regular price of 64.00 and sale price of 49.00 became a Shopify price of 49.00 with a compare-at of 64.00, which is intended; and that the Large variant has no SKU in the new file, which is an error. You then trace that blank SKU back to a source cell with a trailing space that broke your lookup.

Log what you find in a plain sheet with columns for product, field, expected, found and fix. If three or more of the twenty show the same kind of fault, fix the rule and re-import the lot instead of patching individually.

Descriptions, shortcodes and leftover plugin clutter

WooCommerce descriptions often contain page-builder markup, shortcodes in square brackets and plugin tabs that do not exist in Shopify. They show up on the new site as raw text such as [vc_row]. Ask AI to list every distinct shortcode pattern in the description column with a count, then decide each one's fate: delete, replace with plain text, or recreate by hand.

Resist the urge to rewrite 229 descriptions with AI in the same pass. Move first, improve later. Rewrites carry their own checks, and doing both at once makes errors hard to trace. When you are ready, bulk descriptions from CSV rows covers keeping them unique and accurate.

Product data that depended on a plugin deserves a note of its own: gift options, custom fields, product add-ons, wholesale price tiers and bundles. None of these map to a plain Shopify column. List them early, since each may need a Shopify app or a different design. AI is good at making that list from your meta columns; it is not a reason to assume Shopify has the same feature.

When a mapping looks right and is not

Here are failure patterns worth checking for after the test import, each with the symptom you will see.

  • Decimal commas or thousands separators. Prices of 1.299,00 become 1.299 or fail. Look at the highest-priced product first.
  • Curly quotes. Shopify says quotation marks and commas that are not UTF-8 encoded cause an illegal quoting error, and wants the file saved as UTF-8. Spreadsheet programs love to insert curly quotes in descriptions.
  • Duplicate handles. Two products called "Safety Boots" merge or overwrite each other. Ask AI to list duplicate handles before import.
  • Weight units. WooCommerce uses the store's unit; Shopify's file has its own weight column in grams and a display unit. A bag marked 0.5 can import as half a gram.
  • Stock on multi-location stores. Shopify says inventory quantity in the product file applies to single-location stores only; use its inventory CSV otherwise.
  • Overwrite surprises. If you re-import with "Overwrite products with matching handles" ticked, blanks in non-required columns clear existing values. Include every column you care about, or turn overwrite off.

Each of these is cheap to catch on 20 products and expensive to catch on 2,000 customers' orders.

Go-live sequence

Once the spot-check passes, run the full import, reconcile the counts (products, variants, images), re-run the spot-check on five fresh products, then load the redirects. Switch the domain last. Keep the old store reachable on a temporary address for a few weeks so you can look up anything that went missing.

After launch, watch for 404 errors for two to four weeks. Your search console's page-not-found report and your analytics will show old addresses people still request. Feed that list back to AI with your product list and ask it to propose the missing pairs, then add them. If you want the whole process mapped with someone who has done it, that is the sort of thing my AI implementation consultation covers; you can reach me through the contact page.

The same approach will serve you after the move too: when new supplier sheets arrive, the column map you wrote today is a template, and turning a supplier sheet into an import file reuses most of it.

Questions that come up mid-migration

Should I paste my customer or order data into an AI tool?

No. Product data is the safe part: titles, SKUs, prices, attributes and image links. Customer names, addresses and order histories are personal data, so move those with Shopify's own import routes or a migration app, and keep them out of chat tools altogether.

Can I just let a migration app do all of this?

Apps can move a lot in one go, and they are worth pricing. They still map your messy attributes and categories by guesswork, so the spot-check and the redirect list below apply either way. AI is a cheap second pair of eyes on whatever route you pick.

What if the CSV fails halfway through the import?

Shopify says an import cannot be cancelled once it starts, so test with 20 products first. For a failed full import, split the file, since Shopify caps a product CSV at 15 MB, and compare the confirmation email against your row count before retrying.

Do I need redirects if my product addresses stay the same?

Shopify builds its own addresses under /products/, so WooCommerce addresses such as /product/name or /shop/category/name will almost always change. Each old address that earned visits or links needs a redirect, or it becomes a dead page.

Further reads

Sources: Shopify help pages on importing products with a CSV file, the product CSV format and URL redirects; WooCommerce documentation for the product CSV importer and exporter.

Moving stores without losing search traffic?

On a 1:1 call we'll map your WooCommerce attributes and categories to Shopify, decide which checks AI can do for you, and set up a repeatable spot-check before go-live.

Book a 1:1 call with me