Importing Metaobjects
The Metaobjects import creates and updates your store's metaobjects — the custom structured-data entries (color swatches, size charts, FAQ items, and so on) defined by your metaobject definitions — from a CSV/Excel file, a Google Sheet, or directly from another connected store.
⚠️ Definitions must already exist. A metaobject always belongs to a definition (its type). This import creates and updates the entries, but it cannot create the definition — set up the metaobject definition in Shopify → Settings → Custom data first, then import entries for it. A row whose
Typehas no matching definition fails with a per-row error.
Rows are matched by (Type, Handle), so running the same file twice updates the same metaobjects instead of creating duplicates.
For the wizard itself — uploading, mapping, dry runs, schedules — see Importing into EcomSolo.
The row layout — one row per field
A metaobject has a handful of fields (defined by its definition). This
import uses a tall layout: one row per field, with the object's identity
repeated on each row. Consecutive rows that share the same Type and
Handle are grouped into a single metaobject — exactly like a product's variant
rows.
- Repeat
TypeandHandleon every row of the same metaobject. - Put one field per row via
FieldKey+FieldValue. - Keep a metaobject's rows together (contiguous).
Columns
| Column | Notes |
|---|---|
| Type | The metaobject definition type (e.g. color, size_chart). Required. The definition must already exist. |
| Handle | The metaobject's unique handle within its type (e.g. ocean-blue). Required — with Type it's the upsert identity. |
| Status | ACTIVE or DRAFT (publishable status). Optional — blank leaves it unchanged. Read from the first row of each object. |
| FieldKey | The field's key as declared on the definition (e.g. name, hex). One field per row. |
| FieldValue | The value for that field, as a string. A blank value clears the field. |
Common export headers map automatically: Definition: Handle → Type,
Field / Key → FieldKey, Value → FieldValue, and so on.
Field values
Every metaobject field value is passed to Shopify as a string — that's how
the Admin API models them. For most field types you write the value plainly
(Ocean Blue, #0066cc, 42). For reference fields (a product, file,
another metaobject, …) the value is the target's GID
(gid://shopify/Product/123), and for list fields it's a JSON array string.
The value must satisfy the field's validations on the definition, or Shopify
rejects that field.
How metaobjects are matched (upsert by type + handle)
Every grouped metaobject is upserted by (Type, Handle) in the target store:
- If a metaobject with that type + handle exists, it is updated — only the fields you supply are changed.
- If none exists, a new one is created.
The dry run shows the create/update split before anything is written.
Operations
Pick the operation in Step 1. The default is Upsert — the behavior above.
- Create — only adds metaobjects. A (type, handle) that already exists fails.
- Update — only changes existing metaobjects. A missing (type, handle) fails.
- Upsert — creates missing metaobjects, updates existing ones. The safe default.
- Delete — removes metaobjects by (type, handle) (see below).
Deleting metaobjects
Pick the Delete operation in Step 1 (permission-gated) and upload a file with just the Type and Handle identity columns — no field rows needed. Each (type, handle) is resolved to its metaobject and removed from Shopify. A pair that matches no metaobject is skipped (a no-op), so re-running the same delete file is safe. Deleting a metaobject permanently removes it from Shopify and cannot be undone.
Importing from another store
On the wizard's Source step, pick From another store to copy metaobjects from a connected store — no file needed. Each source metaobject comes across as its full set of field rows, matched by (type, handle). Make sure the matching definitions exist on the target first. Combined with a schedule this becomes a recurring one-way metaobject sync.
Reference fields that point to source-store resources (a product, a file) carry the source store's GIDs, which don't exist on a different store — those field values need re-pointing on the target.
Results and freshness
Metaobjects you create or update take effect in Shopify immediately, and EcomSolo's Metaobjects dashboard refreshes within seconds of the run.
Sample file
A ready-to-run sample lives at
features/importing/examples/metaobjects-sample.csv — two color metaobjects,
two fields each:
Type,Handle,Status,FieldKey,FieldValue
color,ocean-blue,ACTIVE,name,Ocean Blue
color,ocean-blue,ACTIVE,hex,#0066cc
color,sunset,ACTIVE,name,Sunset
color,sunset,ACTIVE,hex,#ff6633
Row by row: the first two rows build the Ocean Blue color (a name and a
hex field); the next two build Sunset. Each pair shares its Type + Handle,
so it groups into one metaobject.
Troubleshooting
| Error in the report | What it means / what to do |
|---|---|
row requires a Type | Every row needs the metaobject definition type. |
row requires a Handle | Every row needs the metaobject handle; repeat it on each field row. |
Undefined type … / no definition | The Type has no metaobject definition on this store — create the definition first. |
| A field error mentioning validation | A FieldValue doesn't satisfy the field's definition (wrong format, bad reference GID, …). |
FAQ
Will re-importing create duplicates? No — rows match by (type, handle) and the operation is a native upsert, so re-runs update in place.
Can it create the metaobject definition? No. Definitions are set up in Shopify → Settings → Custom data. This import only manages entries.
Why one row per field instead of a column per field? Different definition types have different fields, so a fixed set of columns can't cover them all. The tall layout handles any type, and it matches the shape the Metaobjects export emits — so an export round-trips straight back into an import.
Does it delete metaobjects? Yes — run the Delete operation with a file of Type + Handle rows. Delete is permission-gated and irreversible; unmatched pairs are skipped.