
The 43 WooCommerce columns with the Type, Parent and attribute pairs set out, so variable products group the way you intended.
Download the templateThe WooCommerce product CSV importer is more forgiving than Shopify's, and more confusing as a result. It will accept almost anything, report a successful import, and leave you working out why the variations do not appear as choices on the product page.
Three columns decide whether that happens: Type, Parent, and the attribute pairs. Everything else in the file is ordinary.
Forty three columns matching WooCommerce's own importer field names, with a worked variation row. Two attribute pairs are included, which covers most catalogues, and a Meta: _gtin column for barcodes.
The columns group into product basics (ID, Type, SKU, Name, Published, visibility, descriptions), tax and stock, physical dimensions, pricing, taxonomy (Categories, Tags, Shipping class), relationships (Parent, Grouped products, Upsells, Cross-sells), images, and then the attribute pairs.
Leave the ID column empty on a first import. WooCommerce assigns it. Filling it in is how you accidentally overwrite an unrelated product.
A variable product in WooCommerce is two kinds of row.
One parent row with Type set to variable. It carries the shared content: the name, both descriptions, the categories, the tags, the images, and the full attribute list. It has no price and no stock of its own.
Then one row per variation with Type set to variation, and the Parent column holding the parent's SKU. Each variation row carries its own SKU, its own price, its own stock, its own weight and dimensions, and the single attribute value that variation represents.
Order matters. Import the parent before its variations, or the Parent references have nothing to resolve against. If the file is sorted alphabetically by name this usually happens by accident, and when it does not, it fails quietly.
This is the part that catches people out, and it is worth reading twice.
Each attribute uses four columns: name, value, visible, global. On the parent row, the value column holds every option separated by commas: "300mm, 400mm, 500mm". On each variation row, the same column holds the single value that variation has: "300mm".
Get that the wrong way round, put the full list on the variations or a single value on the parent, and the variations import successfully and do not appear as selectable options. The products exist. The dropdown is empty. Nothing in the import log mentions it.
Attribute visible controls whether the attribute shows in the Additional Information table on the product page. Set to 1 for anything a customer would want to read, 0 for internal values.
Attribute global decides whether the attribute uses a site wide taxonomy or one created just for that product. Global, set to 1, is almost always what you want, because layered navigation and filter widgets only work on global attributes. Product specific attributes are fine for one off details and useless for filtering.
Weight and dimensions carry no unit. The columns are Weight (kg), Length (cm), Width (cm) and Height (cm) in the template, but WooCommerce itself uses whatever the store is configured to use. A file built in millimetres loaded into a store set to centimetres imports without a single warning and produces shipping quotes that are wrong by a factor of ten. Check the store setting before the import, not after.
Regular price and Sale price are separate columns. Putting the discounted figure into Regular price loses both the discount and the original, and there is no way to recover the original from the import file once it is live.
In stock? and Stock. Two columns doing different jobs. In stock? is the boolean the product page reads. Stock is the number. Setting the number without the boolean produces a product with stock that shows as unavailable.
Backorders allowed? Takes 0, 1 or notify. Anything else is read as 0.
Recent WooCommerce versions have a native GTIN field. Older stores, and a lot of stores running feed or marketplace plugins, expect it as post meta instead, which is why the template carries a Meta: _gtin column.
Check which one your store uses before importing. A barcode written to the wrong field is invisible to every feed plugin that needs it, and the symptom appears later, as a Google Merchant Center disapproval rather than an import error.
If you are unsure, add the barcode to a single product by hand through the admin, export that product, and see which column it lands in. Two minutes, and it settles the question for the whole catalogue.
Categories use a greater than sign for hierarchy: Brackets > Shelf Brackets. WooCommerce creates any level that does not already exist, which is convenient and is also how stores accumulate near duplicate categories differing by a plural or a trailing space.
Multiple categories are separated by commas within the same cell. A product in three categories is one cell, not three rows.
Fix the taxonomy before the import. Cleaning up sixty categories that should have been twenty, after products are attached to all sixty, is a considerably worse afternoon than getting the list right first.
The WooCommerce importer runs in the browser and times out on large files. Split anything over roughly two thousand rows, and run the batches in order so parents always land before their variations.
A file that imports halfway is worse than one that fails outright, because the catalogue is then in a state where you cannot simply re-run the same file: some products exist, some do not, and the ones that exist may be parents with no children. Take a database backup before a large import, and keep the split files so you know exactly where it stopped.
Run five products first. The same rule applies on every platform and it is ignored most often on WooCommerce, because the importer feels forgiving right up to the point where it is not.
A WooCommerce product CSV is a destination format. Keeping the catalogue inside the export is what leads to a spreadsheet nobody trusts, a store that disagrees with it, and a monthly reconciliation that somebody does by eye.
Holding the product record once and generating the WooCommerce file from it removes that: the Type and Parent columns are derived from the variant model rather than typed, the attribute lists on parent and variation rows are produced from the same attribute data, and the GTIN goes wherever your store expects it. That is the job SKULaunch does, and the template stays useful for the first load and for one off ranges.
Free to use and adapt. No sign-up, no email required.
DownloadRequired columns are marked in red. Delete the worked example row before you use the file.
Upload a supplier file and watch SKULaunch turn it into complete, structured, sales-ready records. Two weeks free, no card, no consultants.