ABAR
Data Modeling

Metafields: The Complete Guide (2026)

Everything merchants and developers need to know about metafields — definitions, types, storefront rendering, bulk editing, GraphQL access and the Metaobjects that replaced most theme customizations.

ABAR Editorial Updated July 11, 2026 16 min read 10 sections

Metafields: The Complete Guide (2026)

Quick answer

Shopify metafields are structured custom fields attached to products, variants, collections, customers and orders. Define them in Settings → Custom data, populate them via the admin, CSV, Admin API or apps, and render them on the storefront via {{ product.metafields.namespace.key }} in Liquid. Metaobjects are reusable multi-field records — the modern replacement for hardcoded theme content.

Key takeaways
  • Always define metafields explicitly in Settings → Custom data before writing to them.
  • Standard metafields (e.g. `descriptors.subtitle`) enable native theme integrations.
  • Metaobjects unlock reusable content blocks that non-devs can edit.
  • Metafield type mismatches silently corrupt data — validate before bulk imports.
  • GraphQL is the only supported API for JSON and reference-type metafields.
20+
Metafield types
text, number, JSON, references, files…
unlimited
Per-resource limit
practical: keep under 200/resource
reserved
Definition namespaces
avoid `custom` — it's the default bucket
TL;DR

Metafields = structured custom data on any resource. Metaobjects = reusable records referenced by metafields. Together they replace 80% of theme customizations and app dependencies.

What metafields actually are

A metafield is a typed key–value pair attached to a Shopify resource — a product, variant, collection, customer, order, blog, article, page, market or shop. Unlike a tag (a single unstructured string) a metafield has a namespace, a key, a validated type, and can hold structured or referenced data. When you define a metafield in Settings → Custom data, Shopify enforces the type at write time — try to write text into a `number_decimal` metafield and the mutation fails cleanly instead of corrupting your data. This is the difference between a professional Shopify catalog and a fragile one.

The type system

Types are not cosmetic — they change what the admin editor looks like, what the storefront receives, and which apps can consume the field. Pick the narrowest type that fits the data.

TypeBest forStorefront output
single_line_text_fieldSKU codes, short labelsString
multi_line_text_fieldLong descriptions, care instructionsString with newlines
rich_text_fieldFormatted marketing copyJSON — render via `metafield_tag`
number_integer / number_decimalQuantities, weights, ratingsNumber
booleanToggle flags (`hasWarranty`)true / false
file_referencePDFs, spec sheets, videosFile object with URL
product_reference'Frequently bought together'Product object
metaobject_referenceReusable content (authors, sizing charts)Metaobject with fields
jsonComplex nested dataParsed object

Defining before writing

Never populate an undefined metafield. Shopify accepts it, but the admin won't expose it in editors, the storefront can't type-check it, and CSV imports will silently create duplicates under slightly different namespaces. Always start in Settings → Custom data → Add definition. Pick a namespace that matches the domain (`specs`, `care`, `seo`) — avoid the default `custom` bucket because that's where every third-party app dumps its own data.

The `custom.` namespace is a landfill

Every app that writes metafields defaults to `custom.*`. If you follow suit your store's data becomes indistinguishable from third-party garbage. Reserve a short namespace like `abar.` or `shop.` for your own definitions.

Rendering on the storefront

Once defined and populated, metafields become available in Liquid at `{{ product.metafields.namespace.key }}`. For rich text and metaobject references, use the built-in filters and object accessors — never try to render them as raw strings.

Rendering common metafield types in Liquidliquid
{% comment %} Simple text {% endcomment %}
<p>{{ product.metafields.specs.material }}</p>

{% comment %} Rich text — must use metafield tag {% endcomment %}
{{ product.metafields.marketing.pitch | metafield_tag }}

{% comment %} Metaobject reference — access fields {% endcomment %}
{% assign chart = product.metafields.abar.size_chart.value %}
<h3>{{ chart.title }}</h3>
{{ chart.body | metafield_tag }}

{% comment %} File reference — resolve to URL {% endcomment %}
<a href="{{ product.metafields.docs.spec_sheet.value.url }}">
  Download spec sheet
</a>

Bulk-editing metafields

The native bulk editor gained metafield support in 2024, but with caveats: only simple types (text, number, boolean) work reliably, and you must add each metafield as a column manually. For JSON, references or media metafields, CSV is the only reliable admin path — and CSV rules are strict.

  • The column header must be exactly `Metafield: namespace.key [type]` (case-sensitive).
  • The `type` in brackets must match the definition; a mismatch silently skips the row.
  • For reference types, the cell value is a `gid://shopify/Product/12345` global ID — not a handle.
  • For JSON, the cell must be minified JSON on a single line, no linebreaks.
  • Empty cells clear the field; whitespace-only cells write literal spaces.
Reference metafields via CSV lose linkage silently

If the referenced product is deleted or its ID changes, the CSV import succeeds but the metafield returns null on the storefront. Always re-export and diff after an import touching references.

The Admin API path (GraphQL)

REST metafields are legacy — use GraphQL for anything new. The `productUpdate` mutation accepts a `metafields` array where each item is namespace, key, type and value. For JSON metafields the value is a stringified JSON. For reference types the value is the global ID of the referenced resource.

Writing a metafield via GraphQLgraphql
mutation UpdateProductSpecs($id: ID!) {
  productUpdate(input: {
    id: $id
    metafields: [{
      namespace: "specs"
      key: "material"
      type: "single_line_text_field"
      value: "Organic cotton"
    }]
  }) {
    product { id }
    userErrors { field message }
  }
}

Metaobjects: the reusable layer

A metaobject is a typed record with multiple fields — think of it as a lightweight database table inside Shopify. Define a metaobject type (`author`, `size_chart`, `feature_block`), populate instances in the admin, then reference them from products or the theme via metafields. Metaobjects power the modern 'headless-lite' pattern: content teams edit metaobjects, developers reference them in Liquid, and the site stays fast because everything ships in the Shopify response — no external CMS round-trip.

Common metafield patterns

These are the highest-leverage metafield definitions we deploy for merchants.

  • `specs.material`, `specs.weight`, `specs.dimensions` — structured product attributes that unlock filtered navigation and Google Shopping attributes.
  • `docs.spec_sheet` — file reference for PDFs, shown as a native download button.
  • `marketing.pitch` — rich text for the copy that lives above the fold, editable without touching Liquid.
  • `abar.related_products` — product reference list for cross-sell blocks that respect merchandiser intent instead of algorithmic guesses.
  • `abar.badges` — metaobject reference for reusable trust badges (Made in EU, Vegan, Certified) that render consistently across every product.

Performance and limits

There is no hard cap on metafields per resource, but the storefront GraphQL query for a product returns metafields lazily — every field you access adds to page render time. Keep the top-of-product-page metafields under ~10, and lazy-load spec sheets and long-form content into tabs or accordions. For collection pages, expose only the metafields you actually use in cards; querying every metafield 'just in case' is the #1 cause of slow collection pages on otherwise-fast themes.

Debugging metafields that don't render

When a metafield is populated in the admin but blank on the storefront, walk this checklist before blaming the theme.

  1. 1
    Verify the definition

    Settings → Custom data → your definition exists with the exact namespace and key your Liquid references.

  2. 2
    Confirm the type

    Rich text renders differently from text — `{{ … }}` outputs `[object Object]` for rich text. Use `| metafield_tag`.

  3. 3
    Check publication scope

    Some metafield definitions default to hidden from the Storefront API. Toggle 'Storefronts' access in the definition.

  4. 4
    Rebuild theme cache

    Themes cache metafield definitions. After a definition change, save the theme once to trigger a rebuild.

  5. 5
    Query via GraphiQL

    If Storefront API returns null, the issue is data. If it returns the value, the issue is Liquid.

Frequently asked questions

The most common questions merchants ask us about data modeling.

No — they live in the Shopify database and are queried at render time.

Keep reading

A
ABAR Editorial
The editorial team at ABAR writes about practical Shopify operations, grounded in real API and admin behaviour.