Skip to content
New Webhooks added: Inventory and Order modifications. Check the changelog →
Cartly Developers

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 shop
  • POST /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 schema
  • PUT /admin/metaobject-definitions/:id — update name, access level, or field order; drag-to-reorder in the admin saves here
  • DELETE /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 includes pagination meta, created_at, and updated_at timestamps 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 -copy suffix 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 inputs
  • rich_text — Tiptap WYSIWYG (bold, italic, links, ordered/unordered lists, headings h2–h4)
  • integer, decimal, money — numeric inputs with type coercion
  • boolean — toggle switch
  • date, date_time — date/datetime pickers
  • url, color — validated string inputs
  • json — raw JSON textarea
  • file_reference — opens the shared media library picker; stores the media file UUID as value
  • product_reference, collection_reference — search-and-select pickers scoped to the shop's own catalog
  • page_reference — pick a CMS page by title
  • metaobject_reference — pick an entry from another (or the same) definition. Requires a metaobject_type validation 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"]} — restricts single_line_text/multi_line_text to a fixed set. The entry form renders a <select> dropdown instead of free text.
  • {name: "metaobject_type", value: "designer"} — required on metaobject_reference fields; 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.