Read metafields and metaobjects with the Storefront API
Read a product’s metafields, follow a metaobject reference such as a size chart, and list all metaobjects of a type like FAQs.
- API
- Storefront API
- Operations
- product.metafield, metaobjects
- Access scopes
- unauthenticated_read_product_listings, unauthenticated_read_metaobjects
- API version
- 2026-10
- Last checked
In short
To read custom data in a headless storefront, select product.metafield(namespace, key) for single values, and use reference with an inline fragment on Metaobject to follow a metaobject reference. To list entries of one type, such as FAQs, query metaobjects(type: "faq"). Both only return data whose definition has storefront access set to PUBLIC_READ.
How to use it
- Make sure the metafield and metaobject definitions have storefront access PUBLIC_READ.
- Send ProductCustomData; aliases (fabric, sizeChart) let you read several metafields in one query.
- For a reference, select reference { ... on Metaobject { … } } and pick fields by key.
- Send StoreFaq to list entries of a type, and page with after while hasNextPage is true.
Code
product-custom-data.graphqlquery ProductCustomData($handle: String!) {
product(handle: $handle) {
title
fabric: metafield(namespace: "custom", key: "fabric") {
value
}
sizeChart: metafield(namespace: "custom", key: "size_chart") {
reference {
... on Metaobject {
handle
title: field(key: "title") {
value
}
rows: field(key: "rows") {
value
}
}
}
}
}
}
product-custom-data.variables.json{
"handle": "linen-shirt"
}
product-custom-data.response.json{
"data": {
"product": {
"title": "Linen shirt",
"fabric": {
"value": "Linen"
},
"sizeChart": {
"reference": {
"handle": "shirts",
"title": {"value": "Shirts"},
"rows": {"value": "[{\"size\":\"S\",\"chest\":96},{\"size\":\"M\",\"chest\":102},{\"size\":\"L\",\"chest\":108}]"}
}
}
}
}
}
metaobjects-by-type.graphqlquery StoreFaq($type: String!, $first: Int!) {
metaobjects(type: $type, first: $first) {
nodes {
handle
fields {
key
value
}
}
pageInfo {
hasNextPage
endCursor
}
}
}
metaobjects-by-type.variables.json{
"type": "faq",
"first": 20
}
metaobjects-by-type.response.json{
"data": {
"metaobjects": {
"nodes": [
{
"handle": "shipping-time",
"fields": [
{"key": "question", "value": "How long does shipping take?"},
{"key": "answer", "value": "Two to four working days within the EU."}
]
}
],
"pageInfo": {
"hasNextPage": false,
"endCursor": "eyJsYXN0X2lkIjoxMTExMTExMTExfQ=="
}
}
}
}
Written by Lintel. MIT license: free to use in your own store and in client work.
Limits and edge cases
- A metafield with no storefront access returns null, as if it didn’t exist.
- To read several metafields without aliases, use metafields(identifiers: [{namespace, key}, …]).
- Values are strings; parse json and list types yourself.
- To read a single entry by handle, use metaobject(handle: {type, handle}); handles are only unique within a type.
Questions
- How do I get product metafields with the Storefront API?
- Select metafield(namespace: "custom", key: "your_key") { value } on the product. The metafield definition must have storefront access PUBLIC_READ.
- How do I query metaobjects in Hydrogen?
- Use the metaobjects query with the type, or follow a metaobject reference from a product metafield. Hydrogen’s storefront client runs the same Storefront API queries.
- Why does my metafield return null in the Storefront API?
- Usually its definition doesn’t allow storefront access, or the namespace or key is different. Set storefront access to PUBLIC_READ in the definition.
Shopify documentation
- Validated against the Admin or Storefront API schema for version 2026-10 on the date shown. Check the version in your request URL.
- IDs and store addresses in the examples are placeholders. Replace them with your own.
- Admin API calls need an access token from your app. Never put an Admin API token in a storefront or theme.
- MIT license. Use the code in your own store or in client work.
Need this built, tested and maintained for your store? See API integrations.
