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
!= blankguard — 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.



