Skip to main content

Use metafields in Liquid

After a metafield is created, you can read and display its value in your theme with Liquid. This guide covers the access syntax, how to render each metafield type, and how to handle missing values.

For what metafields are and how they're structured, see Overview. For the full list of types, see Types.

Access a metafield

Access a metafield through its parent resource, namespace, and key:

{{ resource.metafields.namespace.key }}
  • Parent resource — the object the metafield is attached to. In Liquid you read metafields from objects that expose a metafields property, reached through the relevant page: product on a product page and collection on a collection page. Whether an object exposes metafields is listed on that object's reference page.
  • Namespace — a container that groups related metafields so their keys don't collide (for example, custom).
  • Key — the metafield's own name (for example, spec_text).

This returns a metafield object, not the stored value. To output the value, append .value.

For example, suppose a product has a single_line_text_field metafield named spec_text in the custom namespace, holding 100% cotton:

{{ product.metafields.custom.spec_text.value }}
100% cotton

🚧 Caution

Accessing a metafield always returns a metafield object, even when the metafield doesn't exist — the result is never nil. Test .value for presence, not the metafield itself. See Handle missing values.

Render each type

How you read .value depends on the metafield type. Each example below assumes the product has the named metafield in the custom namespace.

Text, number, date, boolean, color, and URL

These scalar types return the value directly from .value. For example, the spec_text single-line text field above (100% cotton):

{{ product.metafields.custom.spec_text.value }}
100% cotton

The same pattern applies to multi_line_text_field, number_integer, number_decimal, date, date_time, boolean, color, and url.

JSON

For a json metafield, .value is a parsed object. Access nested properties by name. Suppose details_json holds {"foo": "bar"}:

{{ product.metafields.custom.details_json.value.foo }}
bar

Measurement (weight, volume, dimension)

These return a measurement object. Read the number and unit separately. For a weight metafield net_weight holding 20 kilograms:

{{ product.metafields.custom.net_weight.value.value }} {{ product.metafields.custom.net_weight.value.unit }}
20 KILOGRAMS

Rating

A rating metafield returns a rating object. For a review_score rated 4 on a scale that tops out at 10:

{{ product.metafields.custom.review_score.value.value }} / {{ product.metafields.custom.review_score.value.scale_max }}
4 / 10.0

File (image)

A file_reference metafield holds the file under value.image. For a spec_file holding an image, output the image URL directly, or pass value to the img_url filter to resize it:

<img src="{{ product.metafields.custom.spec_file.value.image.src }}">

<img src="{{ product.metafields.custom.spec_file.value | img_url: '400x' }}">

Handle missing values

Because accessing a metafield never returns nil, guard your output on .value:

{% if product.metafields.custom.spec_text.value != blank %}
<p>Material: {{ product.metafields.custom.spec_text.value }}</p>
{% endif %}

Render with metafield filters

Instead of reading .value and building the markup yourself, the metafield_tag and metafield_text filters output a metafield based on its type:

  • metafield_tag wraps the value in an HTML element suited to the type, with a metafield-<type> class — ready to drop into the page.
  • metafield_text returns the value as plain text, for when you need the raw string.

For the spec_text field above (100% cotton):

{{ product.metafields.custom.spec_text | metafield_tag }}
{{ product.metafields.custom.spec_text | metafield_text }}
<span class="metafield-single_line_text_field">100% cotton</span>
100% cotton

Next steps