Skip to main content

Metafields

Metafields let you attach typed, namespaced data to nine resource kinds — products, variants, collections, customers, orders, pages, blogs, articles, and the shop itself. They are strongly-typed, server-validated, stored in a separate polymorphic table, and exposed in Aqua/Liquid via the standard {owner}.metafields.{namespace}.{key} access pattern. Use them to:
  • attach app-specific data to a customer, order, or product (e.g. loyalty tier, subscription status, AI-generated badge text)
  • expose structured fields to merchants under Settings → Custom data that they can fill in per resource and reference in their theme
  • store references between resources (product_reference, collection_reference, file_reference) so themes can link related items
Apps store all per-store runtime data here. The platform does not give apps a filesystem to write to — install config, feature toggles, per-resource counters, event logs, etc. all live as metafields under an app_<handle_with_underscores> namespace. See Where to store app data in the Extensions overview for the conventions.

Two API contexts

Metafields are exposed through two parallel REST surfaces with different auth and capabilities. Apps see and edit only the metafields they wrote (scoped by appId). The Admin API is what powers the admin’s Settings → Custom data and the inline editor on resource detail pages — apps cannot use it.

Owner types (nine)

The ownerType field on every metafield identifies the kind of resource it attaches to. Validation is case-sensitive lowercase — sending "PRODUCT" returns a validation error.

Supported types (22)

Each metafield carries a type that determines validation, decoding, and how it renders in Aqua/Liquid.
The full 22-type catalogue below — including list.* and all six reference types — is the Admin / merchant API. The OAuth App API (/api/v1/...) accepts only a 21-value subset: no list.* variants, and references are limited to product_reference and file_reference (not collection_reference, variant_reference, customer_reference, or page_reference). An App API write with an unsupported type is rejected with HTTP 422. See Create / Upsert Metafield for the exact App API enum.

Text

Numeric / Boolean / Color

Date / Time

Measurements

Stored as { unit, value } objects. Renders as "<value> <unit>".

Money / Rating

URL / JSON

References

Stored as id strings; the backend optionally verifies the id exists at write time. product_reference, variant_reference, collection_reference, customer_reference, page_reference, file_reference

Lists

list.<innerType> — array of items of innerType. Inner-type validations apply to each item.

Wire format

Compound types are sent as JSON in the value field:
Scalars are sent as-is:
Lists are arrays:

Validation errors

Type or validation failures return HTTP 400 with a structured errors array:

Cache invalidation

Writes to a metafield automatically expire the relevant storefront caches — both the cached copy of the owning resource and any cached page HTML that rendered it. The next storefront render will see the new value. You don’t need to poll — if you need to react to changes, register a metafields/update webhook instead.

Best practices for apps

  • Use your own namespace. Don’t write under custom (the merchant namespace). Use your app handle (e.g. subscriptions_pro, loyalty_engine) so merchants can see what’s yours and apps don’t collide on key names.
  • Pre-create definitions during app install. Apps can POST /metafield-definitions (with merchant scope, not OAuth) on first install if you want the schema to appear in the merchant admin. For OAuth-only apps, write values directly without defining first.
  • Pin definitions that merchants need to fill in — they show up on the resource detail page in admin.
  • Don’t poll. Use webhooks.

See also