Metaobjects
Create custom structured content types and render them in Liquid templates or query via the GraphQL Storefront API.
Overview
Metaobjects are standalone custom content types. Unlike Metafields (which attach to an existing entity like a product), Metaobjects are schemas you design from scratch — a designer, a faq_item, a store_location. Each definition declares a type (snake_case), an access level, and a set of typed fields. Entries are instances of the definition.
Definitions API
GET /admin/metaobject-definitions— list all definitions for the shopPOST /admin/metaobject-definitions— create a definition (type, name, access, fields). Field order is persisted and can be changed by sending a reordered fields array in PUT.GET /admin/metaobject-definitions/:id— fetch one definition with its full field schemaPUT /admin/metaobject-definitions/:id— update name, access level, or field order; drag-to-reorder in the admin saves hereDELETE /admin/metaobject-definitions/:id— delete definition and all its entries
Entries API
GET /admin/metaobjects/:type— list entries. Supports?status=active|draft|archived,?q=(full-text on handle),?sort=created_at|updated_at|handle&order=asc|desc,?page=&?limit=. Response includespaginationmeta,created_at, andupdated_attimestamps per entry.POST /admin/metaobjects/:type— create an entry. Body:{handle, status, fields: {key: value}}.GET /admin/metaobjects/:type/:id— fetch one entry by UUID or handle (same route, resolved by format).PUT /admin/metaobjects/:type/:id— update fields or status.POST /admin/metaobjects/:type/:id/duplicate— clone entry; new handle gets a-copysuffix automatically.DELETE /admin/metaobjects/:type/:id— delete a single entry.POST /admin/metaobjects/:type/bulk-action— bulk delete or bulk status-change on a set of entry IDs. Body:{ids: [...], action: "delete"|"set_status", status?: "active"|"draft"|"archived"}.GET /admin/metaobjects/:type/:id/storefront-usage— returns the Liquid templates and sections that reference this entry's handle. Run before archiving or deleting to confirm the entry is not live in a theme.GET /admin/metaobjects/:type/export?format=json|csv— stream all entries as JSON (full field objects) or CSV (flat key-value columns).
Field Types and Entry Form Widgets
The admin entry form renders a purpose-built input for each field type:
single_line_text,multi_line_text— plain text inputsrich_text— Tiptap WYSIWYG (bold, italic, links, ordered/unordered lists, headings h2–h4)integer,decimal,money— numeric inputs with type coercionboolean— toggle switchdate,date_time— date/datetime pickersurl,color— validated string inputsjson— raw JSON textareafile_reference— opens the shared media library picker; stores the media file UUID as valueproduct_reference,collection_reference— search-and-select pickers scoped to the shop's own catalogpage_reference— pick a CMS page by titlemetaobject_reference— pick an entry from another (or the same) definition. Requires ametaobject_typevalidation declaring which definition to load.list.<base>— array variant of any base type (e.g.list.single_line_text,list.product_reference). Rendered as a dynamic add/remove list; values stored as JSON array strings.
Validations
Each field definition accepts an optional validations array:
{name: "choices", value: ["S","M","L"]}— restrictssingle_line_text/multi_line_textto a fixed set. The entry form renders a<select>dropdown instead of free text.{name: "metaobject_type", value: "designer"}— required onmetaobject_referencefields; specifies which definition type's entries to show in the picker.
GraphQL Storefront API
query {
metaobjects(type: "designer", limit: 10) {
handle
fields { key value type }
}
metaobject(type: "designer", handle: "alice-chen") {
id
fields { key value }
}
}Definitions with access: admin_only return an empty list from the storefront API. The metaobject_reference field value resolves to the referenced entry's handle string.
Liquid Rendering
{% for entry in metaobjects.designer.entries %}
<div>{{ entry.fields.name | escape }}</div>
{{ entry.fields.bio }}
{% endfor %}Safety limits: 50 entries per type, 250 total per render. Redis version counter invalidates Liquid cache on every mutation. Gcore CDN surrogate-key purge fires asynchronously.
Admin UI — What Was Added
- Entries list — status tabs (Active/Draft/Archived), full-text search, multi-column sort, pagination, created/updated timestamps, per-row inline status toggle, and bulk select with bulk delete or bulk status change.
- Entry form — media picker, product/collection/page/metaobject reference pickers, Tiptap rich_text editor, list fields with dynamic add/remove rows, and choices+metaobject_type validations.
- Definition editor — drag-to-reorder fields via drag handle; order is persisted on save.
- Row actions — Duplicate entry (handle gets -copy suffix), JSON view dialog (raw API shape), Storefront usage scanner.
- Export — JSON and CSV export from the entries list toolbar.