The Adstic Orb product CSV format, column by column

Adstic Orb imports products from a flat CSV with 64 fixed columns plus an optional tail of translation and attribute columns. This page is the whole contract: format v2, the same specification the Adstic Orb importer reads and its exporter writes, so an export can be edited and re-imported unchanged. Nexum Gate writes this file.

v2 is v1 plus columns. The first 31 columns keep their names and their positions, and all 33 new ones are appended after variant_stock — so a v1 file is a valid v2 file, and a file written today still opens in a tool that only knows v1. Every new column is optional; missing means not set, never zero and never false. The two exceptions are requires_shipping and charge_tax, whose blank means TRUE, because that is the default in Adstic Orb’s own database.

Convert a spreadsheet into this format in the browser — free, with no product limit, because Nexum Gate and Adstic Orb are both made by ADSTIC INTERACTIVE LTD.

File requirements

  • UTF-8 with a BOM. The byte-order mark is required, not optional: it is what makes Excel open a Cyrillic or Greek catalogue without mangling every name.
  • CRLF line endings, comma delimiter, RFC 4180 quoting. Cells may contain commas, quotes and newlines, so the file can never be split line by line — it has to be parsed.
  • The first line is the header. The order below is canonical for writers; readers match by header name, case-insensitively and trimmed, and ignore columns they do not know.

One row per variant

A product with no variants is a single row. A product with four variants is four rows that share the same handle and must be contiguous.

  • The first row of a handle group carries every product field — name, description, price, categories, images, SEO, variant_label — plus the first variant.
  • Every later row carries handle plus the variant_* columns and nothing else. Other cells are ignored there, so filling them only creates doubt about which row owns the data.

There are no image rows in this format: additional images live in one pipe-separated gallery cell on the product row.

Required columns

handle on every row, and name and price on the first row of each group. price is required and must be zero or more — unlike Shopify, a blank price is an error rather than a silent 0.00.

The 64 columns

All 64 Adstic Orb product CSV columns with type, scope, rules and an example value
Column#TypeScopeRulesExample
handlerequired1handlekeyGroups the rows of one product, which must be contiguous. Any text; it seeds the slug when the product is created. Required on every row.ceramic-mug
id2uuidproductAdstic Orb product uuid. Blank creates a product; filled updates that product, which must belong to your tenant.—
namerequired3textproductThe product title. Required on the first row of each handle group.Ceramic mug
subtitle4textproductShort line shown under the title. Optional.100% cotton
description5longtextproductPlain text or HTML. May contain commas, quotes and newlines — the cell is RFC 4180 quoted, so never split the file by line.Soft tee. Wash at 30°, inside out.
status6enumproductactive or draft. Blank means active. A digital product is always imported as draft regardless of this cell.draft
product_type7enumproductphysical or digital. Blank means physical.digital
pricerequired8moneyproductRequired, >= 0. Major units with a dot decimal mark — 19.90, never 1990 and never a comma. Stored as price_cents.29.90
compare_at_price9moneyproductThe reference ("was") price. Must be strictly greater than price when set.34.90
cost_price10moneyproductYour cost, stored as cost_cents. Never shown to customers.11.20
currency11textproductISO 4217 code. Blank means EUR.EUR
sku12textproductProduct-level SKU, used when the product has no variants.TSH
barcode13textproductEAN / UPC / ISBN or your own reference. Text, so leading zeros survive.0012345678905
stock14integerproductWhole number. Blank means stock is not tracked (NULL), which is not the same as 0.40
continue_selling15booleanproductTRUE keeps selling at zero stock. Blank means FALSE.FALSE
weight_grams16integerproductInteger grams, no unit text and no decimals.350
brand17textproductFree text.Adstic
categories18categoriesproductPipe-separated list of paths; levels inside a path are joined with " > ". Maximum depth 3. Categories that do not exist yet are created.Home > Kitchen > Mugs|Sale
tags19listproductPipe-separated. Tags that do not exist yet are created.cotton|summer
image_url20urlproductMain image, http(s). Stored as given — Adstic Orb does not re-host it.https://example.com/t.jpg
video_url22urlproductOptional product video, http(s).—
seo_title23textproductUp to 70 characters.Logo T-shirt
seo_description24textproductUp to 160 characters.Soft cotton t-shirt.
variant_label25textproductThe NAME of the choice, on the product row: "Size", or "Color / Size" when several Shopify options were combined into one axis.Color / Size
variant_name26textvariantThis variant's value: "L", or "Red / L" for a combined axis. Blank on every row of a product means the product has no variants.Black / M
variant_sku27textvariantSKU of this variant.TSH-BK-M
variant_barcode28textvariantBarcode of this variant. Text, so leading zeros survive.0012345678912
variant_price29moneyvariantMajor units. Blank falls back to the product price.31.90
variant_compare_at_price30moneyvariantReference price for this variant. Must exceed the price that applies to it.—
variant_stock31integervariantWhole number. Blank means this variant is not stock-tracked.5
image_altnew in v232textproductAlt text for the main image. From Shopify's "Image alt text" on the product's first image row.Black t-shirt with the logo on the front
requires_shippingnew in v234booleanproductFALSE for something that is never posted. Blank means TRUE, unlike most columns here — so a Shopify FALSE has to be written out, not left empty.TRUE
weight_display_unitnew in v235enumproductDisplay unit only; weight_grams stays the stored value.g
unit_price_measurenew in v236decimalproductPack quantity for the EU unit price, greater than zero. All four unit-price columns go together or none do.500
unit_price_measure_unitnew in v237enumproductUnit of the pack quantity. Must measure the same thing as the base unit — 500 ml cannot be quoted per 1 kg.g
unit_price_base_measurenew in v238decimalproductThe base the price is quoted per, greater than zero.1
unit_price_base_unitnew in v239enumproductUnit of the base measure, same kind as the pack unit.kg
vat_ratenew in v240decimalproductPer-product VAT percent, 0 or more and under 100. BLANK means the shop's own rate, which is not the same as 0 — 0 is a zero-rated supply.20
charge_taxnew in v241booleanproductFALSE marks a VAT-exempt supply. Blank means TRUE.TRUE
tax_codenew in v242textproductAvalara or Shopify Tax code, straight from Shopify's own column.A9277
package_lengthnew in v243decimalproductPacked length, expressed in package_dimension_unit. The importer converts to millimetres, so the unit is required as soon as any dimension is set.30
package_widthnew in v244decimalproductPacked width, in package_dimension_unit.20
package_heightnew in v245decimalproductPacked height, in package_dimension_unit.3
package_dimension_unitnew in v246enumproductThe unit the three packed dimensions are in. Required once any of them is filled: "30, 20, 3" in centimetres and in inches are parcels that differ by a factor of 2.54.cm
google_categorynew in v247textproductGoogle product category: a numeric id or the full "A > B > C" path.Apparel & Accessories > Clothing > Shirts & Tops
google_gendernew in v248enumproductmale, female or unisex, lowercase. Shopify's own cell is free text, so "Unisex" is normalised; anything outside the list is dropped to "not set" rather than stored.unisex
google_age_groupnew in v249enumproductnewborn, infant, toddler, kids or adult. Shopify writes prose like "Adult (13+ years old)", which is mapped to adult.adult
google_mpnnew in v250textproductManufacturer part number.TSH-12345-BK
google_conditionnew in v251enumproductnew, refurbished or used, lowercase.new
google_custom_productnew in v252booleanproductTRUE means no GTIN or MPN exists for this product (handmade, custom). The Adstic Orb feed then sends Google identifier_exists=no.FALSE
google_custom_label_0new in v253textproductGoogle Ads custom label 0. The five labels are positional.Top Seller
google_custom_label_1new in v254textproductGoogle Ads custom label 1.—
google_custom_label_2new in v255textproductGoogle Ads custom label 2.—
google_custom_label_3new in v256textproductGoogle Ads custom label 3.—
google_custom_label_4new in v257textproductGoogle Ads custom label 4.—
variant_image_urlnew in v260urlvariantThis variant's own picture, http(s). Falls back to the product's. From Shopify's "Variant image URL".https://example.com/t-bk-m.jpg
variant_image_altnew in v261textvariantAlt text for the variant image. Shopify has no column for it — it only alt-texts product images — so this is blank from a Shopify export.Black t-shirt, size M
variant_weight_gramsnew in v262integervariantInteger grams for this variant; blank falls back to the product's. Shopify's weight IS per variant, so this is where it belongs.180
variant_cost_pricenew in v263moneyvariantWhat this variant cost you, major units. Never shown to customers. From Shopify's per-variant "Cost per item".11.20
variant_unit_price_measurenew in v264decimalvariantPack size of this variant for the unit price, greater than zero. The UNITS stay on the product: a 500 g and a 1 kg bag share a base (per 1 kg) but not a pack size.500

Translation and attribute columns

After variant_unit_price_measure, in any order, the file may carry:

  • name_<lang> and description_<lang> — a translation, where <lang> is a two-letter code: name_en, description_bg.
  • attr_<key> — a value for one of your own product attributes, with | separating multiple values: attr_material.

Unknown columns are ignored rather than rejected, so an extra column is never fatal.

Value rules that reject a product

Prices are major units with a dot

19.90 means nineteen ninety. Not 1990, not 19,90, no currency symbol and no thousand separator; the importer converts to cents itself. price is required and compare_at_price, when set, must be strictly greater than the price it refers to — it is the “was” price.

Blank stock is not zero

A blank stock or variant_stock means “not tracked” (NULL). A 0 means tracked and out of stock. The two behave differently in the shop, so the distinction is worth getting right in the source file.

Multi-values use the pipe, hierarchy uses “ > ”

categories, tags, gallery and attr_* are pipe-separated. Inside one category path the levels are joined with > , as in Home > Kitchen > Mugs|Sale. Maximum depth is 3 levels; categories and tags that do not exist yet are created on import.

Length limits

seo_title 70 characters, seo_description 160. Adstic Orb refuses the product when either is too long — it does not truncate. Shopify allows 320 characters of SEO description, twice the limit here, so Nexum Gate shortens an over-long value at a word boundary on the way out and tells you which products it shortened. Without that, Shopify’s own template file loses two of its three products on import.

The unit price is all four columns or none

unit_price_measure, unit_price_measure_unit, unit_price_base_measure and unit_price_base_unit go together. A pack size with no unit cannot be priced, and Adstic Orb refuses the partial set rather than printing a guessed figure — a unit price is a legally required number in the EU, and a wrong one is worse than none. The two units must also measure the same thing: 500 ml quoted per 1 kg is not a conversion that exists.

A blank VAT rate is not zero

vat_rate blank means “whatever this shop charges”. vat_rate 0 means a zero-rated supply the seller has decided on. They are different statements and Adstic Orb keeps them apart, so leaving the column empty on an import is not the same as writing a 0 into it. The accepted range is 0 or more and under 100.

A parcel size needs its unit

package_length, package_width and package_height are expressed in package_dimension_unit, and the importer converts them to millimetres for storage. The unit is required as soon as any of the three is filled: “30 × 20 × 3” in centimetres and in inches are parcels that differ by a factor of 2.54, which is the difference between a correct courier quote and a wrong one. Adstic Orb takes mm, cm, m and in; Shopify only ever writes cm or in.

Alt texts are positional with their pictures

gallery_alt is read against gallery by position: entry 2 describes gallery URL 2. An empty entry is a picture with no alt text, which is perfectly legitimate — so Front||Seam detail is three entries, not two, and compacting it would attach the last alt to the wrong image. More alt texts than pictures is an error rather than a truncation, because it means a URL was deleted and its alt was not.

Google fields are a closed vocabulary

google_gender, google_age_group and google_condition take only Google’s own lowercase values. Shopify’s equivalents are unstructured metafields — its own sample file writes Adult (13+ years old) — so Nexum Gate maps the obvious prose forms (Unisex → unisex, that age group → adult) and drops anything it cannot recognise to “not set”. Adstic Orb would drop it anyway: a typo stored today is a Merchant Center rejection weeks later.

Known limits, stated rather than hidden

  • Variants are single-axis. Adstic Orb has one choice per product, so a Shopify product with Color and Size is combined: variant_label = "Color / Size" and variant_name = "Red / L". That is lossy — the two axes cannot be filtered separately afterwards.
  • Digital files cannot travel in a CSV. A row with product_type: digital imports as a draft; attach the files in Adstic Orb, then publish.
  • Image URLs are stored as given. Adstic Orb does not re-host them, so a URL that stops working takes the image with it.
  • Rows of one product must be contiguous. The product fields are read from the first row of the block, so a file sorted by SKU rather than by handle will import the wrong data.
  • Eight Shopify columns still have nowhere to go. Option1/2/3 Linked To are metafield references and Adstic Orb options are plain text; Gift card cannot be created by import in Shopify either, and Adstic Orb sells gift cards as vouchers rather than products; Inventory tracker and Fulfillment service describe systems Adstic Orb does not have; the colour metafield belongs in an attr_color column if you want it; and Image position is not lost at all — the order of the gallery cell is the position. When your file actually has values in any of those, the converter names them in a note instead of dropping them quietly.
  • Packed dimensions round-trip through millimetres. Adstic Orb stores mm, so a value given in inches comes back rounded to two decimals: 1 in is 25.4 mm is 1 in, but an exotic fraction of an inch will shift slightly.
  • Shopify has no alt text for a variant image. Its Image alt text belongs to a product image row, so variant_image_alt comes out of a Shopify export empty — filling it would be writing alt text nobody wrote.
  • Shopify has no VAT rate. It stores a taxable flag and a tax code; the rate lives in the store’s tax settings, not in the product CSV. So vat_rate is always blank from a Shopify conversion, which Adstic Orb reads as “use the shop’s own rate” — the right answer.

What the importer does

Parse, validate every row, then show a preview — N products to create, N to update, N rows in error with their row numbers — and write only after you confirm. The tenant comes from your session and never from the file, and a row error blocks only that product, not the whole file.

The sample file

adstic-orb-sample-v2.csv is the golden fixture for format v2: four products in seven rows, exercising a quoted description with a newline and escaped quotes, a three-variant product with per-variant images and costs, a product priced per kilogram, a VAT-exempt digital product that is never posted, the Google Shopping fields, a gallery_alt list with a deliberate gap in the middle, Cyrillic text, a leading-zero barcode, and one product that sets none of the v2 columns at all. Nexum Gate’s test suite asserts byte-for-byte that it writes this file’s header and round-trips its rows. The same file is byte-identical in the Adstic Orb repository.

How to import into Adstic Orb

  1. Open Dashboard → Shop → Products → Import CSV in your Adstic Orb dashboard.
  2. Choose the CSV this tool generated. The file is read, not stored.
  3. Read the preview: how many products will be created, how many updated, and which rows failed with why. Nothing is written yet.
  4. Confirm. Rows that errored are skipped product by product; the rest import.
  5. For digital products, attach the files to each draft and publish it.

To update existing products rather than create new ones, fill the id column with the Adstic Orb product uuid — easiest by exporting your products first and editing that file, which is exactly the round-trip this format guarantees.

Selling with Adstic Orb

Adstic Orb — online shop, booking and email marketing for small businesses is the platform this format belongs to: a shop with products and variants, bookings with their own calendar, and email marketing to the customer list the shop builds — in one account instead of three.

Because the importer reads the format on this page, a catalogue you already have as a spreadsheet goes in without retyping: map it here, download, import. Nexum Gate and Adstic Orb are both made by ADSTIC INTERACTIVE LTD. That is also why this conversion has no product limit and costs nothing — it is not a third-party integration we charge to maintain.

Nexum Gate and Adstic Orb are both made by ADSTIC INTERACTIVE LTD. The format on this page is that company’s own specification, not a reverse-engineered guess — which is why Nexum Gate can promise the file imports and ADSTIC INTERACTIVE LTD can keep both sides in step.