Key takeaways

  • Variable products need a parent row plus one row per variation, linked by SKU.
  • Attributes need three flags set correctly or the variations import but never display.
  • Category hierarchy uses > to nest and , to separate. Spaces matter.
  • meta: columns write anywhere, with no validation. Powerful and unforgiving.

WooCommerce's importer is more flexible than Shopify's and correspondingly easier to get subtly wrong. It accepts almost any column order, auto-detects standard headers, and will happily write custom fields you invented. It also fails quietly when a flag is missing.

This is the field reference, with the rules that are not obvious from the column names.

Core product columns

ColumnAcceptsNotes
IDIntegerExisting post ID. Leave blank for new products.
Typesimple, variable, variation, grouped, externalAlso accepts modifiers: variable, virtual
SKUTextThe matching key for updates. Must be unique site-wide.
NameTextProduct title
Published1, 0, -11 published, 0 private, -1 draft
Is featured?1 or 0Featured product flag
Visibility in catalogvisible, catalog, search, hiddenWhere the product appears
Short descriptionHTMLThe excerpt, shown next to the price
DescriptionHTMLThe main tab content
Regular priceDecimalNo currency symbol, no thousands separator
Sale priceDecimalMust be lower than regular price to apply
Tax statustaxable, shipping, none
Tax classTextBlank means standard rate
In stock?1, 0, backorderIndependent of the Stock number
StockIntegerOnly used when stock management is on
Backorders allowed?1, 0, notify
Weight (kg)DecimalUnit follows your store settings despite the header
Length/Width/Height (cm)DecimalSame caveat
CategoriesTextSee hierarchy rules below
TagsComma separatedCreated if they do not exist
ImagesComma separated URLsFirst is the featured image, rest are the gallery
ParentSKU or id:123Links a variation to its variable parent
PositionIntegerMenu order for sorting

Published uses -1 for draft, not 0. Zero means private, which is published but visible only to logged-in admins. Importing a test batch with 0 expecting drafts leaves you with products that are live in a sense you did not intend.

Category hierarchy

Nest with a greater-than sign, separate with commas:

Clothing > Shirts > Long Sleeve, Sale, New Arrivals

That assigns the product to three categories and creates the entire Clothing tree if it does not already exist. Only the deepest term in each chain is actually assigned; the ancestors are created as structure.

Two things that silently duplicate your taxonomy:

  • Inconsistent spacing. Clothing >Shirts and Clothing > Shirts produce different terms. Normalise before importing.
  • A comma inside a category name. "Shoes, Boots & Sandals" splits into three categories. Escape the cell or rename the category.

Attributes, and the three flags

Attribute columns come in numbered sets. For each attribute N:

ColumnValueWhat it controls
Attribute N nameText, e.g. SizeThe label
Attribute N value(s)Comma separated on parents, single value on variationsThe options
Attribute N visible1 or 0Shows in the Additional Information table
Attribute N global1 or 01 uses a site-wide taxonomy, 0 is product-specific
Attribute N defaultTextPre-selected option on the product page

The critical, invisible one is in variations. In the WooCommerce exporter's own output this appears as part of the attribute configuration rather than as a plainly named column, and it is the flag that tells WooCommerce this attribute is a customer choice rather than a specification.

Without it, variation rows import successfully and attach to nothing. The product renders as a simple item with a spec table and no dropdowns, which is exactly the symptom described in 12 WooCommerce import errors and how to fix them.

Structuring a variable product

A shirt in three sizes and two colours is seven rows: one parent, six variations.

Type,SKU,Name,Parent,Regular price,Attribute 1 name,Attribute 1 value(s),Attribute 1 visible,Attribute 1 global
variable,SHIRT-01,Oxford Shirt,,,"Size","Small, Medium, Large",1,1
variation,SHIRT-01-S-BLU,,SHIRT-01,49.99,"Size","Small",1,1
variation,SHIRT-01-M-BLU,,SHIRT-01,49.99,"Size","Medium",1,1
variation,SHIRT-01-L-BLU,,SHIRT-01,49.99,"Size","Large",1,1

Rules:

  • The parent carries every possible value for each attribute, comma separated.
  • Each variation carries one value per attribute.
  • Parent on the variation is the parent's SKU, or id:123 if you are matching on post ID.
  • The parent's price columns are ignored. Price lives on variations.
  • Variations do not need a Name. WooCommerce derives it.
  • Order matters. The parent must appear before its variations in the file. Sort by SKU or Parent.

Let the format be someone else's problem

Scrapify writes WooCommerce-schema CSV directly from any store URL, with parent and variation rows, attribute flags and category hierarchy already correct.

Generate a Woo CSV Or skip CSV entirely

The meta: escape hatch

Any column named meta:key writes its value to that post meta key. This is how plugin data and ACF fields survive an import.

meta:_yoast_wpseo_title
meta:_yoast_wpseo_metadesc
meta:_custom_ingredient_list
meta:_wc_cog_cost

It is completely unvalidated. A typo in the key does not error, it creates orphaned meta that nothing reads. Underscore-prefixed keys are hidden from the custom fields UI, so you cannot easily spot the mistake afterwards either.

The reliable way to get these right: export one existing product that already has the data, look at the exact key names WooCommerce emits, and copy them.

Downloadable and external products

ColumnApplies toNotes
Download limitDownloadableBlank means unlimited
Download expiry daysDownloadableBlank means never
Download N nameDownloadableLabel shown to the customer
Download N URLDownloadableMust be reachable at import time
External URLExternal/AffiliateWhere the button sends the customer
Button textExternal/AffiliateDefaults to "Buy product"
Grouped productsGroupedComma separated child SKUs or id: refs
Upsells / Cross-sellsAllComma separated SKUs. Targets must already exist.

Upsells and cross-sells need two passes. They reference other products by SKU, and those products must exist when the row is processed. Import everything once, then re-import with "update existing products" ticked and the relationship columns populated.

File rules

  • UTF-8, ideally with BOM. Without it, WooCommerce sometimes guesses Latin-1 and mangles accented characters.
  • Comma delimiter. The importer does offer a delimiter setting, but sticking to commas avoids a class of problems.
  • Standard header names. Order is irrelevant, spelling is not. Exact names skip the manual mapping step.
  • Parents before variations. The one ordering rule that does exist.
  • Absolute image URLs. Relative paths are silently skipped.

The safest way to produce a file WooCommerce will definitely accept is to export two or three existing products first and use that as your template. The importer and exporter share a schema, so anything the exporter emits is by definition importable.

Frequently asked questions

How do I write category hierarchy in a WooCommerce CSV?
Use a greater-than sign to nest and a comma to separate multiple categories. Clothing > Shirts > Long Sleeve creates the whole tree if it does not exist. Watch for stray spaces, because Clothing >Shirts and Clothing > Shirts are treated as different terms.
How are variable products structured in a WooCommerce CSV?
One row for the parent with Type set to variable, then one row per variation with Type set to variation and Parent set to the parent's SKU or an id: reference. Each attribute column on the parent needs its visible and global flags set, and the variation rows carry the specific value for each attribute.
What do the meta: columns do?
Any column named meta:something writes directly to that post meta key. This is how you carry custom fields and third-party plugin data through an import. It is powerful and unvalidated, so a typo in the key silently creates orphaned meta rather than throwing an error.
Does the WooCommerce importer care about column order?
No. The importer shows a mapping screen where you match each CSV column to a WooCommerce field, and it auto-detects the standard names. Order is irrelevant, but exact header spelling matters for auto-detection, so keep the canonical names if you want to skip the mapping step.

Keep reading

WooCommerce How to Bulk Import Products into WooCommerce Without a Spreadsheet WooCommerce 12 WooCommerce Product Import Errors and How to Fix Each One WooCommerce How to Export All WooCommerce Products to CSV: 5 Methods Compared