Metafield value formats for CSV import
When you import metafields from a CSV file, every value must end up in the format Shopify expects for the metafield's type: a date as 2025-12-31, a weight as {"value":2.5,"unit":"KILOGRAMS"}, a product reference as gid://shopify/Product/123. You don't have to type those formats by hand: the import recognizes and converts the usual human-friendly ways of writing a value (2.5 kg, 31.12.2025, a product handle). For how to lay out the file itself - columns, headers, and the "rows" and "columns" formats - see How to prepare a CSV file for import.
The Quick reference below is a one-screen summary. The rest of the page describes every type in detail, grouped as in the app's type selector (Text, Reference, Number, Measurement, Link, Date and time, Other, Advanced), base types first and then list types.
Quick reference
Basic rules
- The recommended format is always sent unchanged. If you aren't sure how to write a value, export a few metafields of the same type and copy the format from the
Metafield valuecolumn: an export always produces importable values (except the readable column of the Readable mode). - Numbers: use a dot for decimals and no thousands separators:
1234.56. Other styles work too, but1,500(and, in some files,1.500) is ambiguous. - Dates:
YYYY-MM-DD. Times without an offset are UTC; add one for local time:2025-12-31 13:45+02:00. - Lists: a JSON array (
["Red","Blue"]), one item per line, or items separated by semicolons or commas (Red; Blue,Red, Blue). Separators are handy but need care: an item must not contain the separator itself, otherwise it is split into several items (Red, dark, Blueis three items, not two). Use line breaks or;when items contain commas, and a JSON array when you can't be sure - see How list values are read. If any item can't be read, the whole list isn't imported. - References: a handle, SKU, email or file URL works instead of a GID, but the referenced item must already exist in the store.
- Check the Warning column of the import report: it explains every rejected value and every value the import had to interpret (an ambiguous number or date, a completed URL, repaired JSON).
Formats by type
| Type | Recommended | Also accepted |
|---|---|---|
single_line_text_field | Cotton | Any text. Preset choices in any case: small → Small |
multi_line_text_field | Text with line breaks | - |
rich_text_field | <p>Hello <strong>world</strong></p> | Shopify rich text JSON, plain text (an empty line starts a new paragraph) |
product_reference | gid://shopify/Product/123 | Handle: classic-cotton-tee |
collection_reference, page_reference, article_reference | GID | Handle: summer-sale, about-us |
variant_reference | gid://shopify/ProductVariant/123 | SKU: TEE-RED-M |
customer_reference | gid://shopify/Customer/123 | Email: jane@example.com |
company_reference, order_reference | GID | Name: Acme Inc, #1001 |
metaobject_reference | gid://shopify/Metaobject/123 | brand/acme, or just acme |
file_reference | gid://shopify/MediaImage/123 | Public file URL (the file is uploaded): https://example.com/photo.jpg |
number_integer | 42 | 1 250, 1,234,567, $42. Decimals are cut off: 12.9 → 12 |
number_decimal | 19.99 | 19,99, 1,234.56, 1.234,56, $19.99, 7.2e-3 |
money | {"amount":"19.99","currency_code":"USD"} (store currency only) | 19.99, $1,299.00, 19,99 (saved in the store currency) |
rating | {"scale_min":"0.0","scale_max":"5.0","value":"4.5"} | 4.5, 4,5 (the definition's scale, or 0-5) |
id | SKU-001 | Any text. Requires a metafield definition |
| Measurement types | {"value":2.5,"unit":"KILOGRAMS"} | 2.5 kg, 2,5kg, 5 lbs, 10", 22 °C, 60 km/h; 2.5 gets the default unit |
url | https://example.com | HTTPS://example.com; with a warning: example.com, www.example.com, support@example.com (→ mailto:) |
link | {"text":"Size guide","url":"https://example.com/size"} | Size guide https://example.com/size; with a warning: Size guide (example.com/size) |
date | 2025-12-31 | 31.12.2025, 31/12/2025, 12/31/2025, Dec 31, 2025, 31st December 2025 |
date_time | 2025-12-31T13:45:00+00:00 | 2025-12-31 13:45, 31.12.2025 13:45, Dec 31 2025 1:45 PM, 2025-12-31T13:45+02:00 |
boolean | true / false | yes/no, 1/0, y/n, on/off, t/f, in any case |
color | #ff0000 | #F00, ff0000, rgb(255, 0, 0), hsl(0, 100%, 50%), red, Dark Blue |
language | en, pt-BR | EN-us, German, Portuguese (Brazil) |
json | {"key":"value"} | {key:'value'} (repaired, with a warning). Text must be quoted: "hello" |
mixed_reference | gid://shopify/Metaobject/123 | brand/acme. Requires a metafield definition |
product_taxonomy_value_reference | gid://shopify/TaxonomyValue/123 | - |
list.* | ["Red","Blue"], [1,2] | One item per line, Red; Blue, Red, Blue. Each item takes the base type's formats: 1 kg, 500 g |
How the import processes a value
For every cell, the import does the following:
- Trims leading and trailing whitespace.
- Checks if the value is already valid for the metafield type (canonical Shopify format). If so, it's sent to Shopify as is.
- Otherwise, it tries to normalize the value using the type-specific rules described below (parse a number, a date, a unit, convert HTML to rich text, repair broken JSON, etc.).
- For reference types, it resolves identifiers (handles, SKUs, emails, file URLs) into Shopify GIDs, and uploads files from URLs to your store's Files.
- If the value can't be normalized, the original value is sent as is and the Warning column says why it couldn't be read. Shopify usually rejects such a value, and its error appears in the import report for that row; if Shopify accepts it, it's saved the way Shopify reads it, so check the warning. Nothing is silently replaced with an empty value.
- The Warning column of the import report explains what the parser did with the value: why it couldn't be read (for example, an unknown unit or text that isn't a number), or how an imported value was interpreted (for example, an ambiguous number).
Other general rules:
- Empty cells are skipped and don't change existing data. If the Empty metafields option is set to Delete, an empty cell deletes the metafield instead. You can't store an empty value in Shopify.
- Type comes from the file mapping. In the "rows" format, it's the
Metafield typecolumn (if it's empty, the type is taken from the metafield's definition or set, ormulti_line_text_fieldis used); in the "columns" format, it's the type you pick for the column during mapping. The value is parsed according to that type. - The definition type wins. If the metafield has a definition (or set), its type is used even when the
Metafield typecolumn says otherwise, and the row gets a note in the Warning column. An unknown type in that column (a typo likenumbr_integer) is replaced the same way - with the definition's type, or withmulti_line_text_fieldif there's no definition - and is noted in the Warning column too. The row is still imported. - Definition settings are respected. If the metafield has a definition (or is part of a metafield set), the import uses its rating scale and its list of allowed choices for text fields.
- Metaobject imports use exactly the same rules for each metaobject field.
JSON inside a CSV file
Many canonical values are JSON ({"amount":"19.99","currency_code":"USD"}). A CSV cell that contains double quotes must itself be wrapped in double quotes, with every inner quote doubled:
"Metafield namespace","Metafield key","Metafield type","Metafield value"
"custom","price_ref","money","{""amount"":""19.99"",""currency_code"":""USD""}"
Spreadsheet apps (Excel, Google Sheets, Numbers) do this escaping automatically when they save a CSV - just type {"amount":"19.99","currency_code":"USD"} into the cell. Only take care of it if you generate CSV files with your own code: use a proper CSV library instead of joining strings.
The import also repairs slightly broken JSON for JSON-based types: single quotes, unquoted keys, a missing closing bracket. For example, {'value':42,'unit':'KILOGRAMS'} and {value:42,"unit":"KILOGRAMS"} are both accepted. For the json type, every repair is noted in the Warning column. Don't rely on it for complex data - valid JSON is always the safest option.
How numbers are read
All number-based types (integer, decimal, money, rating, every measurement) use the same number parser. Both the US/UK style (1,234.56) and the European style (1.234,56) are supported - the parser works out which character is the decimal separator from the structure of the number:
| Input | Read as | Why |
|---|---|---|
19.99 / 19,99 | 19.99 | A single separator not followed by exactly 3 digits is decimal |
1,234.56 / 1.234,56 | 1234.56 | When both . and , are present, the last one is decimal and the other one separates thousands |
1,234,567 / 1.234.567 | 1234567 | A separator that appears several times separates thousands |
1 250 / 30 000 000 / 1'234 | 1250 / 30000000 / 1234 | Spaces (including non-breaking ones) and apostrophes between digits separate thousands |
1 234,567 | 1234.567 | If thousands are already separated by spaces, the comma is decimal |
0,500 / ,05 | 0.500 / 0.05 | A separator after 0 (or with no integer part) is decimal |
1,500 / 1.500 | depends on the column | Ambiguous - see below |
$1,005.07 / 1,005.07 € / ₡ 1,005.07 | 1005.07 | Currency symbols and other text around the number are removed |
8,71972E+12 / 7.2e-3 | 8719720000000 / 0.0072 | Scientific notation (as produced by Excel) is supported |
-1.005,07 | -1005.07 | Negative numbers are supported |
1,234,5 / 10-20 / 4.5 / 5 | not a number | Invalid digit grouping or extra characters between digits - the value is rejected |
abc | not a number | The value is rejected |
Ambiguous numbers
A number with a single separator followed by exactly three digits - 1,500 or 1.500 - can mean either one and a half or fifteen hundred. The import resolves it by looking at the other values of the same metafield in the file (the same column in the "columns" format, the same namespace and key in the "rows" format):
- if other values clearly use a comma as the decimal separator (
19,99,1.234,56),1,500is read as1.5and1.500as1500; - if other values clearly use a dot (
19.99,1,234.56),1,500is read as1500and1.500as1.5; - if the file doesn't tell (or mixes both styles), a comma is treated as a thousands separator (
1,500→1500) and a dot as a decimal separator (1.500→1.5). A value with a comma is still imported, and the row gets a note in the Warning column of the import report, so you can check it. A value with a dot gets no warning:1.500is already a valid decimal number in Shopify's format, so it's sent unchanged.
The same applies to list items: 1,000, 2,000 in a list.number_integer is read as [1000,2000], with a warning for each item.
Use a dot as the decimal separator and no thousands separators: 1234.56, 1.5. Such values never depend on the rest of the file.
Base types
Text
Single line text - single_line_text_field
- Accepts: any text.
- Line breaks are replaced with spaces, since a single line field can't contain them.
- Choices: if the definition limits the field to a list of allowed values ("Limit to preset choices"), the value is matched to a choice ignoring letter case and extra spaces, and the choice's exact spelling is saved.
| Input | Converted to |
|---|---|
Cotton | Cotton |
Line one + line break + line two | Line one line two |
small (choices: Small, Medium) | Small |
extra LARGE (choices: Extra large) | Extra large |
Multi-line text - multi_line_text_field
- Accepts: any text; line breaks are preserved. Put the value in a quoted CSV cell (spreadsheet apps do it for you) so the line breaks don't split the row.
Rich text - rich_text_field
Shopify stores rich text as a JSON document. The import accepts three formats:
- Shopify's rich text JSON - sent as is:
{"type":"root","children":[{"type":"paragraph","children":[{"type":"text","value":"Hello"}]}]} - HTML - any value that starts with an HTML tag is converted. Supported tags:
<p>,<div>,<h1>-<h6>,<ul>,<ol>,<li>,<a href="...">(withtitleandtarget),<strong>(bold),<em>(italic),<br>. Other tags (<span>,<b>,<i>,<table>, ...) are dropped but their text is kept - use<strong>/<em>instead of<b>/<i>. - Plain text - each block separated by an empty line becomes a paragraph; a single line break stays inside the paragraph.
| Input | Converted to |
|---|---|
Hello world | {"type":"root","children":[{"type":"paragraph","children":[{"type":"text","value":"Hello world"}]}]} |
<p>Hello <strong>bold</strong></p> | {"type":"root","children":[{"type":"paragraph","children":[{"type":"text","value":"Hello "},{"type":"text","value":"bold","bold":true}]}]} |
<ul><li>One</li><li>Two</li></ul> | {"type":"root","children":[{"type":"list","listType":"unordered","children":[{"type":"list-item","children":[{"type":"text","value":"One"}]},{"type":"list-item","children":[{"type":"text","value":"Two"}]}]}]} |
Reference
Reference metafields store Shopify GIDs (global IDs), for example gid://shopify/Product/8123456789. You can always import a GID, but GIDs differ between stores, so the import also accepts a human-readable identifier for most types and looks up the GID in your store. This is how the migration between stores works.
| Type | GID format | Alternative identifier |
|---|---|---|
product_reference | gid://shopify/Product/123 | Product handle: classic-cotton-tee |
variant_reference | gid://shopify/ProductVariant/123 | Variant SKU: TEE-RED-M |
collection_reference | gid://shopify/Collection/123 | Collection handle: summer-sale |
page_reference | gid://shopify/Page/123 | Page handle: about-us |
article_reference | gid://shopify/Article/123 | Blog post handle: how-to-choose-a-size |
customer_reference | gid://shopify/Customer/123 | Customer email: jane@example.com |
company_reference | gid://shopify/Company/123 | Company name: Acme Inc |
order_reference | gid://shopify/Order/123 | Order name: #1001 |
metaobject_reference | gid://shopify/Metaobject/123 | type/handle: brand/acme, or just the handle acme (see below) |
file_reference | gid://shopify/MediaImage/123 (also Video, GenericFile, Model3d, ExternalVideo) | Public file URL: https://example.com/images/photo.jpg |
product_taxonomy_value_reference | gid://shopify/TaxonomyValue/123 | - (GID only) |
Details:
- The referenced item must already exist in the store, and the app needs read access to it (for example, the customers permission for
customer_reference). Otherwise, the row fails with a "not found" or a missing-permission error. - Handle lookups ignore letter case and surrounding spaces. Product handles are also normalized the way Shopify creates them, so
Classic Cotton Teeis looked up asclassic-cotton-tee. metaobject_referencerequires a metafield definition that specifies the metaobject type. Thanks to the definition, the handle alone is enough:acmeis looked up as<definition type>/acme. You can also writebrand/acmeexplicitly.file_referencewith a URL: the file is downloaded from the URL and uploaded to your store's Files, and the new file's GID is saved. The URL must be publicly accessible. For files with an existing name, see the Duplicated images option.- A JSON array with a single item is accepted for a single reference:
["gid://shopify/Product/123"]is saved asgid://shopify/Product/123. - Old-style page GIDs (
gid://shopify/OnlineStorePage/123) are converted togid://shopify/Page/123automatically.
Number
Integer - number_integer
- Accepts: any number (see How numbers are read).
- Decimals are cut off, not rounded:
12.9→12,-3.7→-3.
| Input | Converted to |
|---|---|
42 | 42 |
1 250 | 1250 |
12.9 | 12 |
$1,005.07 | 1005 |
Decimal - number_decimal
- Accepts: any number; the decimal part is kept as written.
| Input | Converted to |
|---|---|
19.99 | 19.99 |
19,99 | 19.99 |
1,234.56 | 1234.56 |
7.2e-3 | 0.0072 |
Money - money
- Canonical format:
{"amount":"19.99","currency_code":"USD"}. - A plain number is saved in your store's currency.
- Only the store currency is accepted. Shopify rejects money values in other currencies (
must match shop currency), even as a JSON object with anothercurrency_code. Convert amounts to your store's currency before importing.
| Input (store currency: USD) | Converted to |
|---|---|
19.99 | {"amount":"19.99","currency_code":"USD"} |
$1,299.00 | {"amount":"1299.00","currency_code":"USD"} |
{"amount":"19.99","currency_code":"USD"} | sent as is |
{"amount":"19.99","currency_code":"EUR"} | rejected by Shopify - the store currency is USD |
Symbols are removed from plain numbers, not interpreted: €19.99 in a USD store is saved as 19.99 USD, without converting the amount.
Rating - rating
- Canonical format:
{"scale_min":"0.0","scale_max":"5.0","value":"4.5"}. Shopify stores the numbers with a decimal part ("1"is saved as"1.0"), but whole numbers are accepted too. - A plain number is saved with the scale from the metafield definition (
scale_min/scale_maxvalidations). Without a definition, the scale is0-5. - The value must fit the scale:
7on a0-5scale is rejected by Shopify.
| Input | Saved as |
|---|---|
4.5 (no definition) | {"scale_min":"0.0","scale_max":"5.0","value":"4.5"} |
8 (definition scale 1-10) | {"scale_min":"1.0","scale_max":"10.0","value":"8.0"} |
{"scale_min":"1","scale_max":"10","value":"8"} | {"scale_min":"1.0","scale_max":"10.0","value":"8.0"} |
ID - id
- Accepts: any text, sent as is (for example,
SKU-001orext-48213). Shopify requires the value to be unique among metafields with the same definition. - Requires a metafield definition. Shopify doesn't allow
idmetafields without one (type: 'id' cannot be used without a definition).
Measurement
Measurement types store a number together with a unit: {"value":2.5,"unit":"KILOGRAMS"}. This group includes weight, volume, dimension, and all the extended Shopify measurement types (temperature, voltage, speed, and so on - see the full table below).
The import accepts:
- A number with a unit:
2.5 kg,2.5kg,2.5 KG,30 cm,22 °C,60 km/h,512 GB. The unit is matched against the unit's symbol, short label, alias, or Shopify key - all listed in the table below - and the matching is forgiving:- letter case and a trailing dot don't matter:
KG,lb.; - a plural
sis accepted:lbs,kgs; - the degree sign is optional:
22 C,22 deg C,22 ℃; ucan replaceµ:10 uF;2/3can replace²/³:10 m2,5 ft3/h;- spaces can replace underscores:
60 kilometers per hour; - common full names, British spellings, and symbols are recognized:
kilo,gram,pound,ounce,litre,centimetre,inchor",footor',sq ft,sq m,kmh,kph,hr,sec, and so on.
- letter case and a trailing dot don't matter:
- A plain number:
2.5- saved with the default unit of the type. Forweight,volume, anddimension, the default unit is the one chosen in the app settings (falling back to the table below); for other types, it's the default from the table. - JSON:
{"value":2.5,"unit":"KILOGRAMS"}- the unit can be written in any of the ways above (KILOGRAMS,kg,kgs).
| Type | Input | Converted to |
|---|---|---|
weight | 2.5 kg | {"value":2.5,"unit":"KILOGRAMS"} |
weight | 2.5 (default unit: grams) | {"value":2.5,"unit":"GRAMS"} |
weight | {"value":2.5,"unit":"kg"} | {"value":2.5,"unit":"KILOGRAMS"} |
dimension | 30 cm | {"value":30,"unit":"CENTIMETERS"} |
volume | 1.5 L | {"value":1.5,"unit":"LITERS"} |
temperature | -40 °F | {"value":-40,"unit":"FAHRENHEIT"} |
speed | 60 km/h | {"value":60,"unit":"KILOMETERS_PER_HOUR"} |
data_storage_capacity | 512 GB | {"value":512,"unit":"GIGABYTES"} |
weight | 5 lbs | {"value":5,"unit":"POUNDS"} |
dimension | 10" | {"value":10,"unit":"INCHES"} |
area | 10 m2 | {"value":10,"unit":"SQUARE_METERS"} |
weight | 5 banana / 5 kg (net) | rejected - unknown unit |
If the text after the number isn't a unit of the metafield's type - a typo, an unsupported unit, or extra words like 5 kg (net) - the value is not imported. The row fails, and the Warning column of the import report lists the units the type supports, for example: Unknown unit "banana" for Weight. Supported units: oz, lb, g, kg. A unit is never replaced with the default unit silently; only a plain number without any unit gets the default unit.
Measurement types and units
Each unit is listed as SHOPIFY_KEY followed by the symbols and aliases the import recognizes.
| Type | Label | Default unit | Units |
|---|---|---|---|
weight | Weight | GRAMS | OUNCES (oz), POUNDS (lb), GRAMS (g), KILOGRAMS (kg) |
volume | Volume | MILLILITERS | MILLILITERS (ml), CENTILITERS (cl), LITERS (L/l), CUBIC_METERS (m³/m3), FLUID_OUNCES (fl oz/fo/us_fl_oz), PINTS (pt/us_pt), QUARTS (qt/us_qt), GALLONS (gal/us_gal), IMPERIAL_FLUID_OUNCES (imp fl oz/ifo/imp_fl_oz), IMPERIAL_PINTS (imp pt/ip/imp_pt), IMPERIAL_QUARTS (imp qt/iq/imp_qt), IMPERIAL_GALLONS (imp gal/ig/imp_gal) |
dimension | Dimension | MILLIMETERS | INCHES (in), FEET (ft), YARDS (yd), MILLIMETERS (mm), CENTIMETERS (cm), METERS (m) |
antenna_gain | Antenna gain | DECIBELS_ISOTROPIC | DECIBELS_ISOTROPIC (dBi/decibels_isotropic), DECIBELS_DIPOLE (dBd/decibels_dipole) |
area | Area | SQUARE_METERS | SQUARE_CENTIMETERS (cm²/square_centimeters), SQUARE_FEET (ft²/square_feet), SQUARE_INCHES (in²/square_inches), SQUARE_METERS (m²/square_meters), SQUARE_YARDS (yd²/square_yards) |
battery_charge_capacity | Battery charge capacity | MILLIAMP_HOURS | MILLIAMP_HOURS (mAh/milliamp_hours) |
battery_energy_capacity | Battery energy capacity | WATT_HOURS | WATT_HOURS (Wh/watt_hours) |
capacitance | Capacitance | FARADS | PICOFARADS (pF/picofarads), NANOFARADS (nF/nanofarads), MICROFARADS (µF/microfarads), FARADS (F/farads) |
concentration | Concentration | MILLIGRAMS_PER_MILLILITER | MILLIGRAMS_PER_GRAM (mg/g/milligrams_per_gram), MILLIGRAMS_PER_MILLILITER (mg/ml/milligrams_per_milliliter) |
data_storage_capacity | Data storage capacity | BYTES | BYTES (B/bytes), KILOBYTES (KB/kilobytes), MEGABYTES (MB/megabytes), GIGABYTES (GB/gigabytes), TERABYTES (TB/terabytes) |
data_transfer_rate | Data transfer rate | BITS_PER_SECOND | BITS_PER_SECOND (bps/bits_per_second), KILOBITS_PER_SECOND (kbps/kilobits_per_second), MEGABITS_PER_SECOND (Mbps/megabits_per_second), GIGABITS_PER_SECOND (Gbps/gigabits_per_second) |
display_density | Display density | PIXELS_PER_INCH | PIXELS_PER_INCH (ppi/pixels_per_inch), DOTS_PER_INCH (dpi/dots_per_inch) |
distance | Distance | KILOMETERS | KILOMETERS (km/kilometers), MILES (mi/miles) |
duration | Duration | SECONDS | NANOSECONDS (ns/nanoseconds), MICROSECONDS (µs/microseconds), MILLISECONDS (ms/milliseconds), SECONDS (s/seconds), MINUTES (min/minutes), HOURS (h/hours), DAYS (d/days), MONTHS (mo/months), YEARS (yr/years) |
electric_current | Electric current | AMPERES | MILLIAMPERES (mA/milliamperes), AMPERES (A/amperes), KILOAMPERES (kA/kiloamperes) |
electrical_resistance | Electrical resistance | OHMS | OHMS (Ω/ohms), KILOOHMS (kΩ/kiloohms) |
energy | Energy | JOULES | JOULES (J/joules), CALORIES (cal/calories), KILOJOULES (kJ/kilojoules), KILOCALORIES (kcal/kilocalories) |
frequency | Frequency | HERTZ | HERTZ (Hz/hertz), KILOHERTZ (kHz/kilohertz), MEGAHERTZ (MHz/megahertz), GIGAHERTZ (GHz/gigahertz) |
illuminance | Illuminance | LUX | LUX (lx/lux), FOOT_CANDLES (fc/foot_candles) |
inductance | Inductance | HENRIES | MICROHENRIES (µH/microhenries), MILLIHENRIES (mH/millihenries), HENRIES (H/henries) |
luminous_flux | Luminous flux | LUMENS | LUMENS (lm/lumens) |
mass_flow_rate | Mass flow rate | KILOGRAMS_PER_SECOND | GRAMS_PER_DAY (g/d), GRAMS_PER_HOUR (g/h), GRAMS_PER_MINUTE (g/min), GRAMS_PER_SECOND (g/s), OUNCES_PER_DAY (oz/d), OUNCES_PER_HOUR (oz/h), OUNCES_PER_MINUTE (oz/min), OUNCES_PER_SECOND (oz/s), POUNDS_PER_DAY (lb/d), POUNDS_PER_HOUR (lb/h), POUNDS_PER_MINUTE (lb/min), POUNDS_PER_SECOND (lb/s), KILOGRAMS_PER_DAY (kg/d), KILOGRAMS_PER_HOUR (kg/h), KILOGRAMS_PER_MINUTE (kg/min), KILOGRAMS_PER_SECOND (kg/s), TONS_PER_DAY (ton/d), TONS_PER_HOUR (ton/h), TONS_PER_MINUTE (ton/min), TONS_PER_SECOND (ton/s), TONNES_PER_DAY (t/d), TONNES_PER_HOUR (t/h), TONNES_PER_MINUTE (t/min), TONNES_PER_SECOND (t/s); each also accepts its lowercase key as an alias, e.g. grams_per_hour |
power | Power | WATTS | MILLIWATTS (mW/milliwatts), WATTS (W/watts), HORSEPOWER (hp/horsepower), KILOWATTS (kW/kilowatts) |
pressure | Pressure | BARS | POUNDS_PER_SQUARE_INCH (psi/pounds_per_square_inch), BARS (bar/bars) |
resolution | Resolution | PIXELS | PIXELS (px/pixels), MEGAPIXELS (MP/megapixels) |
rotational_speed | Rotational speed | REVOLUTIONS_PER_MINUTE | REVOLUTIONS_PER_MINUTE (rpm/revolutions_per_minute) |
sound_level | Sound level | DECIBELS | DECIBELS (dB/decibels) |
speed | Speed | METERS_PER_SECOND | KILOMETERS_PER_HOUR (km/h/kilometers_per_hour), FEET_PER_SECOND (ft/s/feet_per_second), MILES_PER_HOUR (mph/miles_per_hour), METERS_PER_SECOND (m/s/meters_per_second) |
temperature | Temperature | CELSIUS | CELSIUS (°C/celsius), FAHRENHEIT (°F/fahrenheit), KELVIN (K/kelvin) |
thermal_power | Thermal power | KILOWATTS | BRITISH_THERMAL_UNITS_PER_HOUR (BTU/h/british_thermal_units_per_hour), KILOWATTS (kW/kilowatts), TONS_OF_REFRIGERATION (TR/tons_of_refrigeration) |
voltage | Voltage | VOLTS | VOLTS (V/volts) |
volumetric_flow_rate | Volumetric flow rate | LITERS_PER_SECOND | LITERS_PER_HOUR (L/h), LITERS_PER_MINUTE (L/min), LITERS_PER_SECOND (L/s), GALLONS_PER_HOUR (gal/h), GALLONS_PER_MINUTE (gal/min), GALLONS_PER_SECOND (gal/s), CUBIC_FEET_PER_HOUR (ft³/h), CUBIC_FEET_PER_MINUTE (ft³/min), CUBIC_FEET_PER_SECOND (ft³/s), CUBIC_METERS_PER_HOUR (m³/h), CUBIC_METERS_PER_MINUTE (m³/min), CUBIC_METERS_PER_SECOND (m³/s); each also accepts its lowercase key as an alias, e.g. liters_per_minute |
Link
URL - url
- Canonical format: a full URL starting with
https:,http:,mailto:,tel:, orsms:- for examplehttps://example.com/size-guide,mailto:support@example.com,tel:+15551234567. - Cleaned up automatically: an uppercase scheme (
HTTPS://→https://), and quotes or angle brackets around the value (<https://example.com>). Spaces in the path and non-Latin domains (https://приклад.укр) are kept as is; Shopify accepts them. - Completed, with a note in the Warning column:
- a domain without a scheme gets
https://:example.com,www.example.com/size,shop.example.co.uk:8080; - a protocol-relative URL gets
https:://example.com/a; - an email address gets
mailto::support@example.com.
- a domain without a scheme gets
- Rejected, with the reason in the Warning column:
- relative paths like
/pages/size-guide(the import doesn't know which domain you mean - add it); - other schemes (
ftp:,javascript:); https://without a domain, or with a space in the domain;- anything else that isn't a URL, including phone numbers without
tel:.
- relative paths like
| Input | Converted to |
|---|---|
https://example.com/size-guide | https://example.com/size-guide |
HTTPS://Example.com | https://Example.com |
example.com/size | https://example.com/size (warning) |
support@example.com | mailto:support@example.com (warning) |
+15551234567 | rejected - write tel:+15551234567 |
/pages/size-guide | rejected - write https://your-store.com/pages/size-guide |
Link - link
A link is a URL with a label: {"text":"Size guide","url":"https://example.com/size-guide"}. Besides the JSON, the import accepts text followed or preceded by a URL; the URL can be in parentheses. The URL follows the URL type rules: the scheme is lowercased, and a missing one is completed with a warning. A URL without a scheme is recognized only where it can't be part of the label:
- the whole value is the URL:
example.com; - it's in parentheses:
Size guide (example.com/size); - it starts with
www.:Shop now www.example.com/sale.
Otherwise a dotted word stays in the label (Node.js guide has no URL, so it's rejected with a warning). In a JSON link object, a URL without a scheme is completed the same way: {"text":"Shop","url":"example.com"} → {"text":"Shop","url":"https://example.com"}.
| Input | Converted to |
|---|---|
https://example.com | {"url":"https://example.com","text":""} |
Shop now https://example.com/sale | {"url":"https://example.com/sale","text":"Shop now"} |
Size guide (https://example.com/size-guide) | {"url":"https://example.com/size-guide","text":"Size guide"} |
Call us (tel:+15551234567) | {"url":"tel:+15551234567","text":"Call us"} |
{"text":"Shop","url":"https://example.com"} | sent as is |
Size guide (example.com/size) | {"url":"https://example.com/size","text":"Size guide"} (warning) |
Contact us (support@example.com) | {"url":"mailto:support@example.com","text":"Contact us"} (warning) |
Date and time
Date - date
- Canonical format:
YYYY-MM-DD, for example2025-12-31. - Also accepts:
- year first:
2025/12/31,2025.12.31,2025 12 31; - day and month as numbers:
31.12.2025,31-12-2025,31/12/2025,12/31/2025,31/12/25(see Day or month first below); - English month names, full or short, with an optional ordinal suffix:
Dec 31 2025,31 Dec 2025,December 31, 2025,31-Dec-2025,31st December 2025; - a date with a time (
2025-12-31T10:00:00Z→2025-12-31; the time is dropped); - a label or brackets around the date:
Date: 2025-12-31,(31.12.2025).
- year first:
- Two-digit years
00-68mean 2000-2068,69-99mean 1969-1999. - Not recognized: Unix timestamps and Excel serial dates (
1704067200,45657), dates without a year (31.12), and dates that don't exist (2025-13-01,31/02/2025,2025-02-29). The Warning column of the import report explains why, and the value is sent to Shopify as is. Shopify rejects most of them, but it can read some numbers as a date of its own:1704067200is saved as2017-04-06. Convert such values toYYYY-MM-DDbefore importing.
Day or month first
When the day and the month are written as numbers, the import works out which one comes first:
- From the value itself, if one of the numbers is greater than 12:
31/12/2025and12/31/2025are both December 31. - Dotted dates are always day first:
02.01.2025is January 2. - From the other values of the same metafield in the file (the same column in the "columns" format, the same namespace and key in the "rows" format): if any of them is written like
31/12/2025,02/01/2025is read as January 2; if like12/31/2025- as February 1. - From your store's country, if the file doesn't tell: month first for stores in the United States, the Philippines, and US territories; day first for all other countries. The value is imported, and the row gets a note in the Warning column, so you can check it.
| Input | Converted to |
|---|---|
2025-12-31 | 2025-12-31 |
31.12.2025 | 2025-12-31 |
December 31, 2025 | 2025-12-31 |
31st Dec 2025 | 2025-12-31 |
02.01.2025 | 2025-01-02 |
02/01/2025 (US store, nothing else in the column) | 2025-02-01 + warning |
02/01/2025 (UK store, nothing else in the column) | 2025-01-02 + warning |
02/01/2025 (the column also has 31/12/2025) | 2025-01-02 |
31/02/2025 | rejected (warning) |
1704067200 | not recognized (warning); Shopify saves it as 2017-04-06 |
Date and time - date_time
- Canonical format:
YYYY-MM-DDTHH:mm:ss+00:00, for example2025-12-31T13:45:00+00:00. - Also accepts: any date format followed by a time:
2025-12-31T13:45,2025-12-31 13:45:30,31.12.2025 13:45,12/31/2025 07:30,Dec 31 2025 1:45 PM. Seconds are optional, milliseconds are dropped, and a date without a time means midnight. The day/month order is resolved the same way as for dates. - Times without an offset are taken as UTC:
2025-12-31 13:45is saved as13:45UTC, not in your store's time zone. If the time is in your local time zone, add the offset:2025-12-31 13:45+02:00. - Explicit offsets are converted to UTC:
Z,+03:00,-0500,+05are all supported -2025-12-31T23:59:59+03:00is saved as2025-12-31T20:59:59+00:00. - Overflowing values are rolled over, the same way Shopify does it: a day up to 31 in a shorter month moves to the next month (
2025-02-30 10:00→2025-03-02T10:00:00+00:00), and24:00or a leap second (23:59:60) moves to the next day or minute (2025-12-31 24:00→2026-01-01T00:00:00+00:00). This applies only todate_time: adatethat doesn't exist is rejected. - Other impossible values (
2025-12-32 10:00,2025-13-01 10:00,24:30,10:60,13:45 PM) are rejected with a warning.
| Input | Converted to |
|---|---|
2025-12-31T13:45:00 | 2025-12-31T13:45:00+00:00 |
31.12.2025 13:45 | 2025-12-31T13:45:00+00:00 |
Dec 31 2025 1:45 PM | 2025-12-31T13:45:00+00:00 |
2025-12-31 | 2025-12-31T00:00:00+00:00 |
2025-12-31T23:59:59+03:00 | 2025-12-31T20:59:59+00:00 |
2025-12-31T23:30:00-02:00 | 2026-01-01T01:30:00+00:00 |
2025-12-31 24:00 | 2026-01-01T00:00:00+00:00 |
2025-02-30 10:00 | 2025-03-02T10:00:00+00:00 |
2025-12-32 10:00 | rejected (warning) |
Other
True or false - boolean
| Input | Converted to |
|---|---|
true, 1, yes, y, on, t | true |
false, 0, no, n, off, f | false |
maybe, 2, any other text | rejected |
Letter case and surrounding spaces don't matter: TRUE, Yes, N are all accepted.
A value that isn't in the table is not imported: the row fails, and the Warning column of the import report lists the accepted values. Convert values in other languages or formats (ja/nein, ✓) to true/false before importing.
Color - color
- Canonical format: a 6-digit lowercase hex code,
#ff0000. - Also accepts:
- hex in any letter case, with or without
#:#FF0000,ff0000; - the 3-digit shorthand:
f00→#ff0000; - hex with transparency (
#ff000080,#f008); rgb()andrgba()with numbers0-255or percentages, separated by commas or spaces:rgb(255, 0, 0),rgb(100% 50% 0%),rgba(255, 0, 0, 0.5),rgb(255 0 0 / 50%);hsl()andhsla():hsl(0, 100%, 50%),hsl(120deg 100% 25%);- the 148 CSS color names, in any letter case and with optional spaces or dashes:
red,Navy,Dark Blue,rebeccapurple.
- hex in any letter case, with or without
- Transparency is dropped, because Shopify colors can't be transparent:
#ff000080andrgba(255, 0, 0, 0.5)are saved as#ff0000, and the import report shows a warning. - Not accepted: hex codes of other lengths (
ff,#12345),transparent, color names in other languages, and out-of-range values (rgb(300, 0, 0)). Such values are rejected, and the Warning column of the import report explains why.
| Input | Converted to |
|---|---|
#FF0000 | #ff0000 |
f00 | #ff0000 |
rgb(0, 128, 255) | #0080ff |
hsl(120deg 100% 25%) | #008000 |
Navy | #000080 |
#ff000080 | #ff0000 + warning |
reddish | rejected |
Language - language
- Canonical format: an ISO 639-1 language code with an optional region:
en,de,pt-BR. - Also accepts: any letter case (
EN-us→en-US) and the English language name (German→de,Portuguese (Brazil)→pt-BR,Chinese (Simplified)→zh-CN). - Three-letter codes (
haw) and unknown names are rejected, and the Warning column explains why.
Deprecated types - string, integer, json_string
These legacy types are still imported: string as any text, integer as an integer, and json_string with the same rules as json. Use their modern equivalents (single_line_text_field/multi_line_text_field, number_integer, json) for new metafields.
Advanced
JSON - json
- Accepts: any valid JSON value, sent as is: an object, an array, a number, a string in double quotes (
"hello"),true,false,null. true,falseandnullin any case (TRUE,Null) are lowercased.- Repaired, with a note in the Warning column: a value that starts like JSON (with
{,[or a quote) but isn't valid. Unquoted keys and single quotes are fixed, missing brackets are closed, and several objects on separate lines become an array. The warning shows the result, because a repair can hide lost data - for example, a cell cut off by a spreadsheet's length limit. - Rejected, with the reason in the Warning column: plain text (
hello,a: 1), numbers with a decimal comma (1,5),None, and JSON followed by extra text ({"a":1} trailing). To store text, wrap it in double quotes ("hello") or use a text type.
| Input | Converted to |
|---|---|
{"size":"M","fit":"slim"} | sent as is |
"hello" | sent as is |
TRUE | true |
{size:'M'} | {"size":"M"} (warning) |
{"size":"M" | {"size":"M"} (warning) |
'hello' | "hello" (warning) |
hello | rejected - write "hello" |
1,5 | rejected - write 1.5 |
Mixed reference - mixed_reference
- Accepts: a metaobject GID (
gid://shopify/Metaobject/123) ortype/handle(brand/acme). Unlikemetaobject_reference, the handle alone isn't enough, since the field can reference several metaobject types. - Requires a metafield definition that lists the allowed metaobject types, just like
metaobject_reference.
List types
Most types have a list version, named with the list. prefix: list.single_line_text_field, list.product_reference, list.weight, etc. Shopify stores a list as a JSON array, and every item follows the rules of its base type described above.
The types without a list version are: multi_line_text_field, rich_text_field, money, id, boolean, language, and json.
How list values are read
A list cell can be written in these ways:
- A JSON array (recommended, never ambiguous):
["Red","Green","Blue"]. Single quotes and small mistakes are repaired:['Red','Blue']works too. - One item per line:
If the value has line breaks, every line is an item and commas or semicolons inside a line stay part of the item: the example above isRed, darkBlue
["Red, dark","Blue"]. - Semicolon-separated values:
Red, dark; Blue. Used when the value has no line breaks but has a semicolon; commas inside items are kept. - Comma-separated values:
Red, Green, Blue. Used when the value has neither line breaks nor semicolons.
Spaces around items are trimmed. Separators inside parentheses, brackets or braces never split items: rgb(255, 0, 0), red is two items.
Every item must be readable. If any item can't be read - an unknown color, a date that doesn't exist, text in a number list - the whole list is not imported, and the Warning column names the item and says how many items failed (The list was not imported because 1 of 3 items could not be read.). The import never saves a partial list, because it would replace the full list already stored in the metafield.
Empty items are dropped: red,,blue becomes ["#ff0000","#0000ff"], and ["red",""] becomes ["#ff0000"]. A list with no items left ([], [""]) is treated as an empty cell: skipped, or deleted if the Empty metafields option is set to Delete.
Items are sent to Shopify in the form it stores them: measurements, ratings and links as objects, integers as numbers, decimals and everything else as strings.
Commas in numbers, measurements, links and dates
Items of these types can contain a comma themselves (1,5, 1,000, https://example.com/?ids=1,2, Dec 31, 2025), so comma-separated lists of them are split more carefully:
- If the value has a comma followed by a space, items are split only at a comma followed by a space:
1,5, 2,5→1,5and2,5;1,000, 2,000→1,000and2,000. - Otherwise numbers and measurements are split at commas that aren't between two digits:
1,5kg,2kg→1,5kgand2kg. - If every comma is between two digits (
1,2,3,1,5,2,5), the other values of the same metafield in the file decide (see Ambiguous numbers):- if they don't use a decimal comma, every comma separates items:
1,2,3→1,2,3; - if they use a decimal comma, a single comma is a decimal one (
1,5→[1.5]), and a value with several commas can't be split: it is rejected, and the Warning column explains why.
- if they don't use a decimal comma, every comma separates items:
Each item is then read with the rules of its base type, so 1,5 becomes 1.5 and 1,000 becomes 1000 exactly as in a single-value metafield.
Dec 31, 2025, Jan 1, 2026 can't be split by commas: the comma inside each date looks like an item separator. Put each date on its own line, separate them with ; (Dec 31, 2025; Jan 1, 2026), or use a JSON array.
Text lists
list.single_line_text_field
Each item is a single line text value. Allowed choices from the definition are matched for every item, ignoring case and extra spaces.
| Input | Converted to |
|---|---|
Red, Green, Blue | ["Red","Green","Blue"] |
["Red, dark","Blue"] | ["Red, dark","Blue"] |
small, LARGE (choices: Small, Large) | ["Small","Large"] |
Red, dark; Blue | ["Red, dark","Blue"] |
Red, dark + line break + Blue | ["Red, dark","Blue"] |
Reference lists
list.product_reference, list.variant_reference, list.collection_reference, list.page_reference, list.article_reference, list.customer_reference, list.company_reference, list.order_reference, list.metaobject_reference, list.file_reference, list.product_taxonomy_value_reference.
Each item can be a GID or the same alternative identifier as the base reference type. GIDs and identifiers can be mixed in one list.
| Type | Input | Converted to |
|---|---|---|
list.product_reference | classic-cotton-tee, wool-hoodie | ["gid://shopify/Product/111","gid://shopify/Product/222"] |
list.product_reference | ["gid://shopify/Product/111","gid://shopify/Product/222"] | sent as is |
list.variant_reference | TEE-RED-M, TEE-BLUE-L | ["gid://shopify/ProductVariant/333","gid://shopify/ProductVariant/444"] |
list.metaobject_reference | acme, brewly | ["gid://shopify/Metaobject/555","gid://shopify/Metaobject/666"] |
list.file_reference | https://example.com/1.jpg, https://example.com/2.jpg | ["gid://shopify/MediaImage/777","gid://shopify/MediaImage/888"] (files uploaded) |
If one item can't be resolved (for example, a handle doesn't exist), the whole row fails with a "not found" error.
Number lists
list.number_integer and list.number_decimal
| Type | Input | Converted to |
|---|---|---|
list.number_integer | 1, 2, 3 | [1,2,3] |
list.number_integer | [1,2,3] | [1,2,3] |
list.number_decimal | 1.5, 2, 3.25 | ["1.5","2.0","3.25"] |
list.number_decimal | [1.5,2,3.25] | ["1.5","2.0","3.25"] |
list.number_decimal | 1,5; 2,5 | ["1.5","2.5"] |
list.number_decimal | 1,5, 2,5 | ["1.5","2.5"] |
list.number_integer | 1,000, 2,000 | [1000,2000] + warning (ambiguous numbers) |
Decimal commas work when items are separated by ; , , (comma and space) or line breaks. Without spaces (1,5,2,5) the items can't be told apart; see Commas in numbers, measurements, links and dates.
list.rating
Plain numbers get the definition's scale (or 0-5), just like a single rating.
| Input (no definition) | Converted to |
|---|---|
4, 3.5 | [{"scale_min":"0.0","scale_max":"5.0","value":"4.0"},{"scale_min":"0.0","scale_max":"5.0","value":"3.5"}] |
[{"scale_min":"0","scale_max":"5","value":"4"}] | [{"scale_min":"0.0","scale_max":"5.0","value":"4.0"}] |
Measurement lists
list.weight, list.volume, list.dimension, and the list. version of every other measurement type. Each item is a number with a unit, a plain number (default unit), or a {"value":...,"unit":...} object.
| Type | Input | Converted to |
|---|---|---|
list.weight | 1 kg, 500 g | [{"value":1,"unit":"KILOGRAMS"},{"value":500,"unit":"GRAMS"}] |
list.weight | ["1 kg","500 g"] | [{"value":1,"unit":"KILOGRAMS"},{"value":500,"unit":"GRAMS"}] |
list.weight | [{"value":1,"unit":"KILOGRAMS"},{"value":500,"unit":"GRAMS"}] | sent as is |
list.dimension | 10 cm, 20 cm | [{"value":10,"unit":"CENTIMETERS"},{"value":20,"unit":"CENTIMETERS"}] |
list.weight | 1,5 kg, 2 kg | [{"value":1.5,"unit":"KILOGRAMS"},{"value":2,"unit":"KILOGRAMS"}] |
Link lists
list.url
| Input | Converted to |
|---|---|
https://a.example.com, https://b.example.com | ["https://a.example.com","https://b.example.com"] |
https://example.com/?ids=1,2, https://b.example.com | ["https://example.com/?ids=1,2","https://b.example.com"] |
list.link
Each item is text plus a URL, or a link object. Put each link on its own line or separate them with ; if the link texts contain commas; otherwise commas work too.
| Input | Converted to |
|---|---|
Size guide https://example.com/size, Care https://example.com/care | [{"url":"https://example.com/size","text":"Size guide"},{"url":"https://example.com/care","text":"Care"}] |
[{"text":"Size guide","url":"https://example.com/size"}] | [{"text":"Size guide","url":"https://example.com/size"}] |
Date and time lists
list.date and list.date_time
Each item accepts the same formats as date / date_time.
| Type | Input | Converted to |
|---|---|---|
list.date | 2025-01-01, 2025-12-31 | ["2025-01-01","2025-12-31"] |
list.date | ["2025-01-01","31.12.2025"] | ["2025-01-01","2025-12-31"] |
list.date | Dec 31, 2025; Jan 1, 2026 | ["2025-12-31","2026-01-01"] |
list.date_time | 2025-01-01 10:00, 2025-12-31T18:30:00 | ["2025-01-01T10:00:00+00:00","2025-12-31T18:30:00+00:00"] |
Other lists
list.color
| Input | Converted to |
|---|---|
#ff0000, #00ff00 | ["#ff0000","#00ff00"] |
["f00","0f0"] | ["#ff0000","#00ff00"] |
rgb(255, 0, 0), navy | ["#ff0000","#000080"] |
Advanced lists
list.mixed_reference
Each item is a metaobject GID or type/handle: brand/acme, material/cotton.
Common pitfalls
1,500and1.500are ambiguous. They're read according to the other values of the same metafield in the file; if the file doesn't tell,1,500is fifteen hundred (with a warning) and1.500is one and a half (without one). Use a dot for decimals and no thousands separators.- Unknown units make the row fail. Typos and extra words after the unit (
5 kg (net)) aren't guessed; the report's Warning column lists the supported units. Check the measurement table. - Booleans accept only
true/false,1/0,yes/no,y/n,on/off,t/f. Anything else makes the row fail. 02/01/2025depends on the file and your store's country. UseYYYY-MM-DDto avoid ambiguity.- Numbers aren't dates. Unix timestamps and Excel serial dates aren't converted; Shopify may still save them as some other date (
1704067200→2017-04-06). Check the Warning column. date_timevalues without an offset are UTC, not your store's time zone. Add an offset (+02:00) for local times.- An overflowing
date_timeis rolled over, not rejected:2025-02-30 10:00becomes March 2 and24:00becomes midnight of the next day, as in Shopify. Adatemust exist. - One bad item rejects the whole list. Check the Warning column for the item that couldn't be read.
- List items are split by line breaks first, then
;, then commas. Items with commas (text, month-name dates) need line breaks,;or a JSON array; decimal commas need;or,between items. - Colors must be opaque. Transparency in
#rrggbbaa,rgba()andhsla()is dropped with a warning; unknown color names are rejected. jsonvalues must be JSON. Plain text is rejected - wrap it in double quotes. Repaired JSON is imported with a warning; check that nothing was cut off.- URLs without a scheme get
https://(emails getmailto:) with a warning; relative paths like/pages/size-guideare rejected. Write full URLs. - Referenced items must exist in the store before the import, and the app needs access to them.
- Some types need a definition:
id,metaobject_referenceandmixed_referencecan't be imported without a metafield definition. - Money is saved in the store currency only. Values in other currencies are rejected by Shopify.
- The definition type wins over the
Metafield typecolumn; a different or unknown type is replaced with a warning. - Integers are truncated (
12.9→12), not rounded.