Browse documentation

Import products from CSV

Bring an existing catalog in as one file — with the exact column spec, how updates are matched, and what the console rejects before writing anything.

Adding products one at a time is fine for ten. For a hundred, put them in a CSV and import it. Coming from Shopify? Import its export directly — see Move a Shopify catalog to CordeliaApps. The importer validates the entire file before writing anything, so a row with a bad price or an unknown brand costs you a re-upload rather than a half-imported catalog.

Open Products → Import CSV in the console.

The dialog has a Download sample button. It produces a valid file with your store's own categories and brands already in it — start from that rather than from a blank spreadsheet.

Prepare your categories and brands first

A product row references categories and brands by name, and the importer will not invent one that doesn't exist. Create them before importing, or every row referencing a missing name fails validation.

Categories and brands have CSV importers of their own, so a full catalog migration is three files in order: categories, brands, then products.

The columns

ColumnRequiredWhat it holds
nameYesProduct name. Also the match key when id is blank.
priceYesWhat the shopper pays, in the store's currency. Must be above 0.
original_priceNoPre-discount price. Blank means not discounted.
unit_valueNoPack size as a number, e.g. 500. Leave blank for non-packaged goods.
unit_typeNoOne of g, ml, pcs. Blank means g.
stockYesA whole number, 0 or more.
descriptionNoShown on the product's details screen.
prep_timeNoFree text, e.g. 10 mins.
image_urlNoPublic https URL of the product photo.
categoriesNoExisting category names, separated by |.
brandNoAn existing brand name. Blank means unbranded.
is_popularNotrue/false — feeds the storefront's popular rail.
skuNoYour stock-keeping code.
barcodeNoEAN / UPC / ISBN.
external_idNoThe id another system knows this product by (a Shopify handle, an ERP code). The match key before name — see below.
idNoAn existing product id. Present means update that exact product.
option1_nameoption3_nameNoFor a product that comes in choices (Size, Colour): the option names. Only on the product's first row.
option1_valueoption3_valueNoThis row's value for each option (M, Red). One row per variant, all sharing the product's name or external_id; price, stock, sku and barcode on a variant row belong to that variant.
pack_sizeNoFor a pack-size variant: the size in unit_type units, so weight labels keep working.
attributesNoDetails shown on the product page: Material=Cotton|Origin=India.

Column order doesn't matter; the header row is matched by name. Any column not listed above is ignored.

A minimal file

csv
name,price,original_price,unit_value,unit_type,stock,categories,brand,is_popular
Amul Gold Milk,34,,500,ml,120,Dairy & Eggs|Breakfast,Amul,true
Tata Salt,28,30,1000,g,80,Staples,Tata,false
Bananas (Robusta),49,59,6,pcs,40,Fruits & Vegetables,,true

Note the third row: an empty brand is unbranded, and original_price above price is what makes a product show a discount.

A product with variants

One row per variant, sharing the product's name (or external_id). The option names go on the first row; every row carries its own value, price and stock:

csv
name,external_id,price,stock,sku,categories,option1_name,option1_value,option2_name,option2_value
Classic Tee,tee-classic,499,3,TEE-M-RED,Clothing,Size,M,Colour,Red
Classic Tee,tee-classic,499,5,TEE-L-RED,,,L,,Red
Classic Tee,tee-classic,549,2,TEE-XL-RED,,,XL,,Red

The product's own price becomes the cheapest variant's, and its stock the sum.

How rows are matched

The importer decides create-or-update per row, and reports the split before you commit:

If the row has an id

That exact product is updated. Use this when you are keeping a spreadsheet alongside your catalog and pushing changes back to specific products.

If the id is blank but external_id is set

The row is matched on external_id. This is the key to use for anything that lives in another system — a rename in either place still updates the same product.

Otherwise

The row is matched against existing products by name. A match updates it; no match creates a new product.

Because name is the fallback match key, renaming a product in your spreadsheet and re-importing creates a second product rather than renaming the first. Keep the id column when you intend to edit.

Validation

Every row is checked before anything is written. The dialog lists each failure with its line number and the reason, and the import button stays disabled until the file is clean. The common rejections:

  • price must be a number greater than 0 — a blank, a currency symbol, or a thousands separator in the cell.
  • original_price is below price — a discount cannot be negative.
  • unit_type must be one of g, ml, pcs (or blank) — anything else, including kg and litre. Convert the units: 1 kg is 1000 + g.
  • stock must be a whole number — decimals aren't stock.
  • A category or brand name that doesn't exist in this store.
  • An alcohol or tobacco product — banned platform-wide, and refused on import exactly as it is in the product form. See What you can't sell.
My spreadsheet exports prices as ₹1,299.00

Strip the symbol and the separator before importing — the cell must be a bare number like 1299. In Google Sheets, set the column's format to Number → Plain text before exporting; in Excel, format it as Number with no thousands separator.

Can I import product images?

Yes, as URLs — put a public https link in image_url and the storefront loads it directly. The importer doesn't upload files, so images hosted only on your own machine need to go somewhere public first. Images added through the console's product form are uploaded and hosted for you.

How big can a file be?

Keep a single import at or under 500 rows. Up to that size the whole import commits as one batch — it either all lands or none of it does. Above it, the importer writes in chunks of 500, so a failure part-way through leaves the earlier chunks already written and reports Import stopped after N of M. Validation still covers the whole file first either way; it is only the writing that stops being all-or-nothing. Split large catalogs into files of 500 rows or fewer.

Can I export my existing catalog to a CSV?

Not from the console — there is no export button today. The Download sample button in the import dialog gives you a valid file with your store's own categories and brands in it, which is the closest thing: use it as the header row and fill in your products. If you need a full copy of your data, ask us and we'll provide one.

What's next