How to show a Shopify metafield on the live product page and in its JSON-LD
A Shopify metafield reaches the live product page only if a template in the published theme prints it: connected as a dynamic source in the theme editor, written in Liquid, or rendered by an app's app embed. It reaches the JSON-LD by a different road: the documentation for the filter Shopify's themes use to generate product markup never mentions metafields, so your data gets into the markup only if someone writes it there. Here are six steps to follow a value all the way to the page source.
Key takeaways
- Saving a metafield does not publish it. A template in the published theme prints it: as a dynamic source in the editor, with a line of Liquid, or from an app's app embed.
- Dynamic sources need a theme with JSON templates, such as an Online Store 2.0 theme, and a setting compatible with the metafield's type. A boolean or a JSON has no compatible setting: it goes through code.
- A connection made in one template reaches only the products that use that template, and only in the theme where you made it.
- Shopify's Dawn and Horizon themes generate product JSON-LD with the structured_data filter, whose documentation never mentions metafields. For a metafield to get into the markup, someone has to write it, and whatever is marked up has to be visible on the page.
- The proof is the source code of the live product page, not the admin or the theme editor preview.
You put a T-shirt's material in one of its metafields, save, open the product page and it isn't there. Or it's on the page and not in the JSON-LD. Both are normal on Shopify, because saved data and published data live in different places: the first in the admin, the second in the HTML your store sends. This guide follows one value of a product metafield from its definition to the source code of the live product page, with the rules as Shopify writes them, and at every step it tells you how to check that it happened.
Where the data travels, and where it gets lost
A product metafield's value covers four stretches before a person or a web crawler reads it:
| Stretch | What has to happen | Where it usually gets lost | Where you check it |
|---|---|---|---|
| 1. Saved | The product has a value in a metafield that has its definition | The product is empty, or the data sits in another namespace | The product, in the admin |
| 2. In the template | A template in the published theme reads it | Connected in another template, in another theme, or nowhere | The theme editor or the theme code |
| 3. In the HTML | The value is written into the server's response | An app renders it and its app embed is off, or JavaScript adds it | The page source |
| 4. In the JSON-LD | The value is inside the product markup | The theme's markup doesn't include it | The application/ld+json block |
The first three decide whether the data is visible; the fourth, whether it goes into the structured data. They are independent: data can be visible without being in the markup, and it can be in the markup without being visible, which is exactly what Google asks you to avoid. Don't mark up content that the page's readers can't see.[1]Google Search Central. General structured data guidelines
Step 1: check the definition and the value
A metafield has an identifier, which is the namespace plus the key (custom.material, for example), a value, and a type, which says what kind of data it is and how it gets interpreted. The metafield's definition comes first, and the definition is what provides validation, the editor in the admin and access control. Shopify also offers standard definitions for common cases, such as ingredients or care instructions.[2]Shopify.dev. About metafields
Open the definition under Custom data in your admin settings and write down three exact things: the namespace, the key and the type. You'll need them in steps 3 and 6. Then open the product and check that the metafield has a value: a product with no value prints nothing, however well it's connected.
The namespace also tells you whose data it is. Metafields the merchant creates use unreserved namespaces, such as custom; an app's go in its reserved namespace, $app, and Shopify's usually start with shopify--.[2]Shopify.dev. About metafields If an app wrote the value in its own namespace, check first whether that app is the one publishing it: that's step 4.
One setting you don't need to touch: the definition's Storefront API access. Shopify says that permission is for headless and custom storefronts, and that it doesn't affect Liquid templates: from Liquid, metafields are always accessible.[2]Shopify.dev. About metafields Turn it on only if your storefront is headless.
Step 2: find out which template and which theme render the page
When you edit a template, the change reaches every page that uses that template, and only those.[3]Shopify Help Center. Templates A product can be assigned an alternate template instead of the default product template: you choose it on the product itself, in the Theme template drop-down.[3]Shopify Help Center. Templates Those templates are saved as product.<suffix>.json, and you can view any product with one of them by adding ?view=<suffix> to its URL.[4]Shopify.dev. Alternate templates If you work in the code, Liquid's template object returns the suffix of the template in use, or nil if it's the default.[5]Shopify.dev. Liquid objects: template
Check which theme you're editing, too. JSON templates are theme files that store which sections render and with which settings,[6]Shopify.dev. JSON templates so a connection made in a copy of the theme is not in the published theme until you publish that copy.
Before moving on, have two answers ready: which template the page you want to fix uses, and whether the theme you have open is the published one.
Step 3: connect the metafield in the template
There are two roads, and your theme's type decides which ones you have.
With a dynamic source, from the theme editor. A dynamic source connects a section or block setting to a piece of store data, such as a product attribute or a metafield's value.[7]Shopify.dev. Dynamic data sources It needs a theme that supports JSON templates.[8]Shopify Help Center. Sections and blocks: use metafields and metaobjects with dynamic sources Online Store 2.0 themes have them; older themes, which Shopify calls vintage, don't.[9]Shopify Help Center. Theme architecture versions To find out which one you have, Shopify suggests opening the theme editor, going to the default product template and looking for the button to add a section below the list of sections: if it's there, the theme supports sections on every page.[9]Shopify Help Center. Theme architecture versions
The steps, according to Shopify: open the theme editor, choose the template that holds the section or block, click the Dynamic source button on the setting you want to fill, pick the metafield and save.[8]Shopify Help Center. Sections and blocks: use metafields and metaobjects with dynamic sources Their example is a candle store that adds a text block to the main section of the product template and connects it to the burn time metafield. When the connection icon shows a +, you can add up to 20 metafields to a single template, one at a time.[10]Shopify Help Center. Displaying metafields on your online store
Not every metafield fits every setting. This is the compatibility Shopify publishes, summarized:[7]Shopify.dev. Dynamic data sources
| Block setting | Metafield types it accepts |
|---|---|
Text (text) |
Single-line text and its list, integers and decimals, date, date and time, weight, volume, dimension, rating, money |
Rich text (richtext) |
The same, plus multi-line text, rich text and link |
Image (image_picker) |
File reference |
Color (color) |
Color |
URL (url) |
URL |
| Product and product list | Product reference and list of product references |
| Metaobject and metaobject list | A metaobject reference and its list, from the same definition the setting asks for |
Two practical consequences. Multi-line text doesn't go into a plain text setting: it needs a rich text one (richtext). And anything not in the table, such as a boolean or a JSON, can't be connected from the editor: for the types the editor doesn't support, Shopify points you to editing the theme code.[7]Shopify.dev. Dynamic data sources[8]Shopify Help Center. Sections and blocks: use metafields and metaobjects with dynamic sources
With Liquid, in the theme code. This is the road for vintage themes, for types with no compatible setting, and for anyone who wants control over the exact HTML. Shopify warns you to edit theme code only if you have coding experience.[10]Shopify Help Center. Displaying metafields on your online store In Liquid, you read a metafield with product.metafields.namespace.key, and its value property returns the data formatted by its type: a string for text, a number for numbers, a measurement object for weight.[11]Shopify.dev. Liquid objects: metafield A fictitious example, for the product section:
{% if product.metafields.custom.material %}
<p class="material">Material: {{ product.metafields.custom.material.value }}</p>
{% endif %}
Three details from the Liquid reference that save you an afternoon. If your metafield's key is size, first or last, read it with square brackets (product.metafields.custom["size"]): with a dot, if the metafield doesn't exist, Liquid applies the filter of the same name, and size returns how many metafields there are instead of nothing. The legacy types integer, json_string and string don't have these properties and don't accept the metafield filters.[11]Shopify.dev. Liquid objects: metafield And if you'd rather not write the HTML by hand, the metafield_tag filter outputs a different element depending on the type, such as a <time> for a date.[12]Shopify.dev. Liquid filters: metafield_tag
Whichever road you take, Liquid is resolved on the server: Shopify recommends rendering the initial content with Liquid and HTML, so the server responds with the complete HTML and the browser shows it as soon as it arrives.[13]Shopify.dev. Render essential content in Liquid and HTML, not JavaScript That's server-side rendering, and it's why a value printed this way is in the source code any crawler downloads.
Step 4: if an app publishes the data, turn on its app embed
An app gets into your theme in three ways: as an app block, which you place in a section; as an app embed, which adds code without a fixed spot on the page; or by injecting code directly into the theme.[14]Shopify Help Center. Extend your theme with apps Of the two block types, the one that goes into the page head is the app embed: Shopify inserts app embeds before the closing </head> or </body> tag, and they come deactivated after you install the app. You turn them on in the theme editor, under App embeds in the theme settings.[15]Shopify.dev. Configure theme app extensions
When you turn one on, watch for two things Shopify's help puts in writing. If you sell in several markets and don't pick one from the editor's Market drop-down, the change applies to the store's default settings. And if you change your published theme, the apps you activated in the old one won't be active in the new one: you have to turn them back on.[14]Shopify Help Center. Extend your theme with apps App embeds work with any theme version; app blocks only work with compatible themes.[14]Shopify Help Center. Extend your theme with apps
If you'd rather check it in the theme code: an app embed is added to config/settings_data.json the first time it's activated, and if it's deactivated later, it stays there with "disabled": true.[15]Shopify.dev. Configure theme app extensions
Step 5: find out where your JSON-LD comes from
The Product markup on a Shopify product page can come from several places, and it's worth knowing which one before you ask why it doesn't carry your metafield:
- The theme. In the two Shopify themes whose code we read on GitHub on October 7, 2026, the product markup is written by the product section in a single line:
product | structured_datain Dawn'smain-product.liquidandclosest.product | structured_datain Horizon'sproduct-information.liquid.[16]Shopify, GitHub repository. Dawn: sections/main-product.liquid[17]Shopify, GitHub repository. Horizon: sections/product-information.liquid - An app, with an app embed in the
head[15]Shopify.dev. Configure theme app extensions or with code it has injected into the theme.[14]Shopify Help Center. Extend your theme with apps - JavaScript, after the page loads. Google warns that Product markup generated this way can make Shopping crawls less frequent and less reliable, a problem for price and availability.[18]Google Search Central. Generate structured data with JavaScript
The structured_data filter turns the product into a Schema.org Product if it has no variants, and into a ProductGroup if it has one or more. The example in its documentation includes the brand, the category, the description, the image, the name, the offer and the URL, and the documentation never mentions metafields at all.[19]Shopify.dev. Liquid filters: structured_data So don't assume your material metafield is in there: the published block is the proof, and you look at it in step 6.
If you want the data inside the markup, someone has to write it: your theme, in Liquid, or an app. In Schema.org, material is a Product property for the material something is made of, such as leather, wool, cotton or paper.[20]Schema.org. material A fictitious fragment of hand-written markup, not complete markup, since it's missing the offer, the images and the rest:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": {{ product.title | json }},
"material": {{ product.metafields.custom.material.value | json }}
}
</script>
The json filter adds the quotation marks and escapes any inside the value,[21]Shopify.dev. Liquid filters: json so a quote in the metafield's text doesn't break the block. Two conditions before you copy it. If your theme already renders its own Product with structured_data, a second block like this describes the same product twice; how two nodes relate is explained in the entry on @id in JSON-LD. And the material has to be visible on the page too, with the block from step 3: Google asks you not to mark up content the reader can't see.[1]Google Search Central. General structured data guidelines
Step 6: check it in the published HTML
Open the public URL of the product page, not the theme editor preview, which shows whichever theme you have open. If the product uses an alternate template, that URL is the one that counts (step 2). Ask for the source code, with View page source or view-source: in front of the URL, not the inspector, which shows the page after JavaScript has run. To save a copy and compare it later, one line in the terminal will do, such as curl -s -o product-page.html https://your-store.example/products/example (the URL is fictitious). In that code, look for:
- The metafield's literal value. If it's there, it travels in the HTML the server sends. If you only see it on the page and not here, JavaScript put it there.
application/ld+json. Count how many blocks there are and which@typeeach one declares.- Your value inside those blocks. If you were looking for it in the markup and it isn't there, go back to step 5.
- The app's code, if there is an app, before
</head>or</body>.[15]Shopify.dev. Configure theme app extensions
Repeat the check every time you change theme, template or app, and whenever another tool writes to the same metafield, which is the case of field overwrite. To see what Google's renderer paints, the steps are in what an AI crawler sees in your store; to audit the markup itself, in auditing a product page's structured data. And keep the two apart: validating the markup is not the same as verifying it gets published, which is what publication verification does.
What gets mixed up
Storefront API access has nothing to do with your theme. Turning it on doesn't make a metafield show up on the product page, and turning it off doesn't hide it from Liquid: that permission only counts for headless and custom storefronts.[2]Shopify.dev. About metafields What publishes the data is a template that prints it.
What we tested
Tested on: store, theme and version, date.
| Case | In the admin? | In the page source? | In the JSON-LD? |
|---|---|---|---|
| 1. Dynamic source in a text block of the default product template | |||
| 2. The same product assigned to an alternate template without that connection | |||
| 3. The connection made in an unpublished copy of the theme | |||
| 4. The metafield printed with Liquid in the product section | |||
| 5. A boolean metafield: does the editor offer it as a dynamic source? | |||
6. The theme's JSON-LD, with structured_data: does the material appear? |
|||
| 7. The fragment from step 5 added to the product section | |||
| 8. A structured data app embed, off and then on |
The limits, as they are: one store, one theme and one date. Themes change versions, and what one theme does says nothing about what the others do.
Where to go next
The publishing by platform path puts the rest of the terms in order, and the guide from widget to published page makes this same journey on BigCommerce.
Clione follows the road of steps 4 and 5 on Shopify: it writes its signals into metafields and renders them with two app embeds, "Clione SEO", with the JSON-LD graph in the head, and "Clione FAQ", with the question accordion in the body, which you turn on from its dashboard in one click. Its Product node carries a stable @id and sits next to the theme's instead of duplicating it. Then it does step 6 for you: it reads the live product page and tells you, signal by signal, what was published and what couldn't be read on the store.
Sources
- [1] Google Search Central. General structured data guidelines. Accessed . ↑ ↑
- [2] Shopify.dev. About metafields. Accessed . ↑ ↑ ↑ ↑
- [3] Shopify Help Center. Templates. Accessed . ↑ ↑
- [4] Shopify.dev. Alternate templates. Accessed . ↑
- [5] Shopify.dev. Liquid objects: template. Accessed . ↑
- [6] Shopify.dev. JSON templates. Accessed . ↑
- [7] Shopify.dev. Dynamic data sources. Accessed . ↑ ↑ ↑
- [8] Shopify Help Center. Sections and blocks: use metafields and metaobjects with dynamic sources. Accessed . ↑ ↑ ↑
- [9] Shopify Help Center. Theme architecture versions. Accessed . ↑ ↑
- [10] Shopify Help Center. Displaying metafields on your online store. Accessed . ↑ ↑
- [11] Shopify.dev. Liquid objects: metafield. Accessed . ↑ ↑
- [12] Shopify.dev. Liquid filters: metafield_tag. Accessed . ↑
- [13] Shopify.dev. Render essential content in Liquid and HTML, not JavaScript. Accessed . ↑
- [14] Shopify Help Center. Extend your theme with apps. Accessed . ↑ ↑ ↑ ↑
- [15] Shopify.dev. Configure theme app extensions. Accessed . ↑ ↑ ↑ ↑
- [16] Shopify, GitHub repository. Dawn: sections/main-product.liquid. Accessed . ↑
- [17] Shopify, GitHub repository. Horizon: sections/product-information.liquid. Accessed . ↑
- [18] Google Search Central. Generate structured data with JavaScript. Accessed . ↑
- [19] Shopify.dev. Liquid filters: structured_data. Accessed . ↑
- [20] Schema.org. material. Accessed . ↑
- [21] Shopify.dev. Liquid filters: json. Accessed . ↑
Change history
- First English version.
More questions
Why isn't my metafield showing up in my store?
Does Shopify add my metafields to the structured data?
structured_data filter, which Dawn and Horizon use to generate product JSON-LD, never mentions metafields: its example includes the brand, the category, the description, the image, the name, the offer and the URL. If you want a metafield inside the markup, your theme has to write it in Liquid or an app has to, and the proof is the application/ld+json block on the live product page.Do I have to turn on Storefront API access to show a metafield in my theme?
Can I show metafields with an older theme?
Related terms
Metafields
What Shopify metafields are, what parts they have, how they get from the admin to the product page's HTML and how to check your theme publishes them.
Liquid
What Liquid is, Shopify's template language: objects, tags and filters, how it writes your product page data on the server and how to check it.
Shopify app embed
What a Shopify app embed is, how it differs from an app block, why it comes switched off after you install the app, and how to check that it works.
JSON-LD
What JSON-LD is, what @context, @type, @id and @graph mean, why Google recommends it and how to find and check the block on your product page.
Product
What the Schema.org Product type is, which properties it carries, what Google requires for product snippets and merchant listings, and how to check it.
Shopify metaobject
What a Shopify metaobject is, how it differs from a metafield, how it links to your products and how to check that your theme publishes it on the product page.
Keep reading
Guide
From widget to live product page on BigCommerce, step by step
How data reaches a live BigCommerce product page: Stencil template, Page Builder widget, Script Manager or Catalyst, and the HTML that proves it.
Read article →
The Corpus
Everything we learned, in one report.
A year of reading the signals AI assistants use on tens of thousands of websites, in a 100-page report plus the dataset behind it.
Request it for free →
Comparison
SEO vs AEO vs GEO: what changes for an online store
SEO vs AEO and GEO for an online store: what each one wins, what it asks of your product pages, how it's measured, and what Google and Bing say.
Read article →Make your catalog easy for bots to read
Clione fills every product page with what bots read best: the JSON-LD graph with its structured data, the meta description and the FAQs. You review and press Push; then we check your live store so it all stays published.