Magento to Shopify: converting a product CSV export

Magento exports a configurable product as a parent row plus one simple product per variation, and encodes the relationship as a string. Shopify expresses the same thing with repeated handles. Translating between them is the job.

Open the converter with this presetField names verified against a published export spec.

Where the file comes from

In the Magento or Adobe Commerce admin go to System → Data Transfer → Export, set Entity Type to Products and Export File Format to CSV. Every column is documented in Adobe’s product data attributes reference, which also states the one hard rule: sku “is the only required value”, and it “should be the first column”.

Headers are lowercase snake_case: sku, attribute_set_code, product_type, categories, product_online, name, description, short_description, weight, price, special_price, qty, base_image, additional_images, url_key, configurable_variations. Columns beginning with an underscore hold service data for complex attributes and are not product fields.

Pitfall 1: configurable_variations is the variant matrix, in one cell

This is the defining difference. Adobe documents the structure exactly:

sku=MH01-XS-Black,size=XS,color=Black|sku=MH01-XS-Gray,size=XS,color=Gray

Each variation is separated by a pipe, each attribute within one by a comma, and the values are attribute codes rather than labels. Adobe warns that “the string of data in the configurable_variations column can be long” — for a large matrix it is thousands of characters.

Shopify has nowhere to put that. Its model is: one handle, one row per variant, option names on the first row. The good news is that the information is also present as ordinary rows — the export writes each variation as its own product_type: simple row with its real SKU, price and qty. So the conversion is to use the simple rows and ignore the parent’s encoded cell, which is what this preset does. Mapping the cell anywhere produces a variant whose option value is a comma-separated program listing.

Pitfall 2: the parent row is not a variant, and its children are hidden

A configurable row carries the title, description and images but no stock and no single option value. Its children carry visibility: Not Visible Individually — they exist only through the parent.

Copy the parent through as a variant and you get a phantom purchasable item with no options, or a duplicate blank combination and the Validation failed: options are not unique rejection. Conversely, import the children as standalone products and you publish nine near-identical product pages where there should be one. Neither is what you want: the parent should contribute product-level fields and the children should become its variant rows, grouped under one handle. Set grouping in step 2 to the column that ties them — the shared SKU prefix, or a parent-reference column if your export template includes one — and check the preview before downloading.

Pitfall 3: base_image is a Magento path, not a URL

Adobe documents base_image as “the relative path for the main image”, noting that “Commerce stores files internally in an alphabetical folder structure”. That is why real exports contain /h/o/hood-01.jpg and /t/e/tee.jpg — the first letters of the file name become the directory.

Shopify downloads images over HTTP at import time and cannot resolve a path. Prefix every value with your media base URL — typically https://yourdomain/media/catalog/product — so /h/o/hood-01.jpg becomes a fetchable address, and do it while the old store is still serving those files. The validator reports “/t/e/tee.jpg” is not an http(s) URL for anything still relative. additional_images is a comma-separated list of the same kind of path and needs the same treatment before the splitter can use it.

Pitfall 4: qty is decimal in Magento and integer in Shopify

Magento supports decimal quantities — is_qty_decimal is a real attribute, for goods sold by weight or length. Shopify’s Inventory quantity is a whole number and the import fails the row with “Inventory quantity is not a number”.

The validator reports Inventory quantity “14.5” is not a whole numberbefore you upload. Decide per product whether to round or to re-express the unit; there is no correct automatic answer, which is why the converter does not silently truncate it. Note too that qty is single-source stock — a multi-source-inventory store has its real quantities elsewhere, and Shopify wants the separate inventory CSV for multi-location anyway.

Pitfall 5: product_online and visibility are two different things

product_online is 1 or 0 and maps cleanly onto Published on online store, which Shopify writes as TRUE/FALSE; the converter normalises it. visibility is the other axis — Catalog, Search, Not Visible Individually — and has no Shopify equivalent at all.

That second column is how you tell a configurable’s children apart from real standalone products, so read it before you decide what each row becomes; just do not map it. Likewise special_price (with its from/to dates) is a scheduled discount: Shopify expresses a sale as a lower Price with the former price in Compare-at price, and schedules nothing from the CSV.

What the preset maps

name → Title, description → Description, url_key → URL handle, categories → Type, sku → SKU, price → Price, qty → Inventory quantity, weight → Weight value (grams) with the kg conversion, base_image → Product image URL, and product_online → Published on online store. Status is draft.

attribute_set_code, product_type, visibility, configurable_variations and product_websites are all deliberately unmapped. They are structural — they tell you how to interpret the file — and Shopify has no column for any of them. additional_attributes is a packed key=value cell that would need splitting into metafields, which the product CSV cannot create.

Before you upload to Shopify

  • Import into a development store or a draft-status batch first. Set the default status to draft in the tool and nothing goes live by accident.
  • Shopify caps a product CSV at 15 MB. Bigger catalogues are split into numbered parts, and a product is never split across two files.
  • Overwriting existing products by handle is destructive: a blank cell can erase data that is currently there. Export your live products first if you are updating rather than creating.

Full column contract: the Shopify product CSV format, column by column. Nexum Gate is not affiliated with Shopify Inc.