Skip to main content
Back to Blog
Shopify Metafields in Liquid: Access, Types & Best Practices
Tutorial

Shopify Metafields in Liquid: Access, Types & Best Practices

How to read metafields in Shopify themes the right way — the namespace/key access path, why you almost always need .value, working with list and JSON types, and the metafield filters that save you work.

8 min read

Metafields let you attach extra information to Shopify resources — a product's care instructions, a collection's banner image, a page's author. They're how themes display custom data that doesn't fit Shopify's built-in fields, and using them well is a core theme-development skill.

This guide covers how to access metafields in Liquid, the two-layer namespace/key path, the .value gotcha that trips up nearly everyone, and how to handle list and JSON types. To look up the surrounding object syntax as you go, keep the Liquid Cheatsheet and the Liquid Objects guide handy.

The access path: namespace and key

Every metafield lives under two layers — a namespace (a grouping that prevents naming conflicts) and a key (the field name). You access one with:

{{ resource.metafields.namespace.key }}

So a product metafield in the information namespace with the key directions:

{{ product.metafields.information.directions }}

You can attach metafields to many resource types — product, variant, collection, customer, order, page, blog, article, shop, and more. The access pattern is always the same: start from the resource, go through .metafields, then namespace, then key.

The .value rule (read this twice)

Here's the single most common metafield mistake: outputting a metafield directly instead of its .value.

A metafield is an object, not a plain value. It carries the data plus type information. To get the actual content, you almost always want .value:

{# ✗ Often renders nothing useful #}
{{ product.metafields.information.directions }}

{# ✓ The actual stored value #}
{{ product.metafields.information.directions.value }}

The metafield object also exposes .type, which tells you what kind of data it holds:

Type:  {{ product.metafields.information.directions.type }}
Value: {{ product.metafields.information.directions.value }}

Always guard for missing metafields — a merchant may not have filled one in:

{% assign directions = product.metafields.information.directions %}
{% if directions != blank %}
  <p class="directions">{{ directions.value }}</p>
{% endif %}

You can't create metafields in Liquid

Worth stating plainly because it surprises people: metafields cannot be created in Liquid. They're defined and populated through the Shopify admin or an app (via the Admin API). In the theme, you only ever read them. Your job as a theme developer is to display values that already exist.

Metafield types and how to read them

The type determines how the .value behaves. The most common types:

Type .value returns Notes
single_line_text_field String Simple text
multi_line_text_field String (with line breaks) Render inside <p>/white-space: pre-line
rich_text_field Rich text object Use metafield_tag to render as HTML
number_integer / number_decimal Number Math-safe
boolean true / false Toggles
date / date_time Date string Format with the date filter
color Color string Use in inline styles or with color filters
url URL string Use as href
json Parsed object/array Access properties directly (see below)
*_reference The referenced object Product, file, metaobject, etc.

Rich text metafields

For rich_text_field, use the metafield_tag filter to render proper, safe HTML rather than dumping the raw structure:

{{ product.metafields.information.care | metafield_tag }}

There's also metafield_text for extracting plain text from a metafield (and from metaobject reference fields), e.g.:

{{ product.metafields.custom.authors | metafield_text: field: "name" }}

JSON metafields

A json metafield's .value is a real object you can navigate by property name or 0-based index, and iterate:

{% assign burn = product.metafields.information.burn_temperature.value %}
Temperature: {{ burn.temperature }}
Unit:        {{ burn['unit'] }}

{% for property in burn %}
  {{ property.first | capitalize }}: {{ property.last }}
{% endfor %}

Reference and list metafields

Reference metafields point to other Shopify resources. Because .value returns the actual object, you read its properties directly:

{% assign featured = product.metafields.custom.related_product.value %}
{% if featured != blank %}
  <a href="{{ featured.url }}">{{ featured.title }}</a>
{% endif %}

List metafields (e.g. list.product_reference, list.file_reference) return an array — loop over it like any collection, and use .count to check length or size your markup:

{% assign gallery = product.metafields.custom.gallery.value %}
{% if gallery.count > 0 %}
  <ul class="gallery">
    {% for image in gallery %}
      <li>{{ image | image_url: width: 600 | image_tag }}</li>
    {% endfor %}
  </ul>
{% endif %}

Connecting metafields to settings (dynamic sources)

You don't always have to hardcode which metafield a section reads. Shopify's dynamic sources let a merchant connect a theme setting to a metafield in the editor — so a text or image_picker setting can be backed by a product metafield without you naming it in code. This is why building flexible settings (see every input setting type) pairs so well with metafields: the merchant wires the data, your section just renders the setting.

A note on deprecated types

If you're working in an older theme, watch for the legacy integer, string, and json_string metafield types. These are older implementations that don't support the modern metafield filters or the .value properties described here. Where you can, migrate to the current typed metafields (number_integer, single_line_text_field, json, etc.).

Common metafield mistakes

  • Forgetting .value — outputs the object, not the data. The number-one issue.
  • No != blank guard — breaks layouts when a metafield is empty or the reference was deleted.
  • Rendering rich text as a raw string — use metafield_tag.
  • Trying to create metafields in Liquid — not possible; define them in admin or via an app.
  • Assuming a list metafield is a single value — it's an array; loop it.

For a broader catalog of theme pitfalls, see 15 Common Shopify Development Mistakes.

Next steps

Metafields are the foundation of custom, data-driven Shopify themes. Once you're comfortable reading them, build sections that surface them with the Schema Builder, convert your HTML mockups into metafield-ready sections with the HTML to Liquid converter, and keep the cheatsheet open for the exact object and filter syntax.

Found this helpful?

Share it with your network!

Ready to Convert HTML to Liquid?

Try our free HTML to Liquid converter and build your Shopify themes faster.

Try HTML2Liquid Now