# Using metafields in your Aqua theme

USING METAFIELDS IN YOUR AQUA THEME

Once you’ve defined a metafield and set a value, exposing it in your storefront
takes a single line of Aqua. This guide covers the access pattern, type-aware
rendering, lists, fallbacks, and the most common pitfalls.


THE ACCESS PATTERN

Every resource drop in Aqua exposes a .metafields attribute, namespaced by
definition:

{{ owner.metafields.<namespace>.<key> }}

If the metafield exists, this prints the type-correct string. If it does not, it
prints an empty string — no exception, so it is safe to use unconditionally in
your templates.


A REAL EXAMPLE

Say you defined three metafields on the product resource:

 * custom.warranty_years — number_integer
 * custom.care_instructions — rich_text_field
 * custom.tags — list.single_line_text_field

Render them on the product page like this:

{% if product.metafields.custom.warranty_years %}
  <p>Warranty: {{ product.metafields.custom.warranty_years }} years</p>
{% endif %}

<div class="care-instructions">
  {{ product.metafields.custom.care_instructions }}
</div>

<ul class="tags">
  {% for tag in product.metafields.custom.tags %}
    <li>{{ tag }}</li>
  {% endfor %}
</ul>


TYPE-AWARE RENDERING

The drop chooses its output based on the metafield type. You don’t need to
coerce values yourself:

 * text → the string itself.
 * rich_text_field → raw HTML (do not pipe through escape).
 * number_integer / number_decimal → numeric string.
 * boolean → true or false.
 * color → #RRGGBB.
 * weight / dimension / volume → <value> <unit>, e.g. 1.5 KILOGRAMS.
 * money → object — always pipe through money.
 * list.* → iterable of value drops.
 * references → the resolved drop (you can access its fields directly).


WORKING WITH MONEY VALUES

<p>Deposit required: {{ product.metafields.custom.deposit | money }}</p>

The money filter respects the shopper’s current currency and locale, so the same
metafield renders correctly across every storefront.


WORKING WITH REFERENCES

A product_reference metafield resolves to a full product drop:

{% assign related = product.metafields.custom.related_product %}
{% if related %}
  <a href="{{ related.url }}">Pairs with {{ related.title }}</a>
{% endif %}

The same pattern works for variant_reference, collection_reference,
customer_reference, page_reference and file_reference.


INSPECTING TYPE AND VALUE EXPLICITLY

If your block needs to branch on the type, the drop exposes both .value and
.type:

{{ product.metafields.custom.warranty_years.type }}   {# 'number_integer' #}
{{ product.metafields.custom.warranty_years.value }}  {# 5 #}


FALLBACK HANDLING

An unset metafield returns an empty string — not nil — so use {% if %} or the
default filter:

{{ product.metafields.custom.badge | default: 'NEW' }}


WHERE IT DOESN’T WORK

 * Inside checkout extensions you must request the data through the App Bridge —
   the storefront drop is not available there.
 * Inside section schemas (the JSON block of a section file) you cannot
   reference metafields — schemas are static.

For everything else — product, collection, blog, cart, page, order — the access
pattern above works.


FAQ


WHY DOES MY METAFIELD PRINT BLANK IN THE THEME?

Three common causes: (1) the value is genuinely empty, (2) the namespace/key in
Aqua doesn’t match the definition exactly, or (3) you saved the value but the
page cache is stale. After saving a metafield, hard-refresh the storefront or
wait up to 60 seconds for caches to expire.


HOW DO I ESCAPE RICH TEXT OUTPUT?

You don’t. rich_text_field is intentionally raw HTML. If you want to print it as
plain text, pipe through strip_html: {{ product.metafields.custom.notes |
strip_html }}.


CAN I READ ANOTHER RESOURCE’S METAFIELDS FROM A PRODUCT PAGE?

Yes — shop.metafields is always available. For other resources, use a reference
metafield or fetch them via a section AJAX call.


HOW DO I SORT A LIST METAFIELD?

List metafields preserve the order you entered them in. Use the sort filter if
you need a different order: {% assign sorted = product.metafields.custom.tags |
sort %}.


DO METAFIELDS WORK IN CUSTOMIZER PREVIEW?

Yes. The customizer preview uses the same storefront pipeline, so any metafield
set on the resource appears in the preview immediately after save.


WHAT’S THE RIGHT NAMESPACE FOR AN APP I’M BUILDING?

Pick a unique namespace tied to your app’s handle, e.g. my_app or
foundry_reviews. Avoid custom — that’s reserved for merchant-defined fields and
clashes are likely.