# 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.

Page: https://lintelagency.com/resources/graphql/storefront-metafields-and-metaobjects

## 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.

## Facts

- **API:** Storefront API
- **Operations:** product.metafield, metaobjects
- **Access scopes:** unauthenticated_read_product_listings, unauthenticated_read_metaobjects
- **API version:** 2026-10
- **Last checked:** 2 November 2026

## How to use it

1. Make sure the metafield and metaobject definitions have storefront access PUBLIC_READ.
2. Send ProductCustomData; aliases (fabric, sizeChart) let you read several metafields in one query.
3. For a reference, select reference { ... on Metaobject { … } } and pick fields by key.
4. Send StoreFaq to list entries of a type, and page with after while hasNextPage is true.

## Code

### product-custom-data.graphql

```graphql
query 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

```json
{
  "handle": "linen-shirt"
}
```

### product-custom-data.response.json

```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.graphql

```graphql
query StoreFaq($type: String!, $first: Int!) {
  metaobjects(type: $type, first: $first) {
    nodes {
      handle
      fields {
        key
        value
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}
```

### metaobjects-by-type.variables.json

```json
{
  "type": "faq",
  "first": 20
}
```

### metaobjects-by-type.response.json

```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=="
      }
    }
  }
}
```

## 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

- [Storefront API metaobjects query](https://shopify.dev/docs/api/storefront/latest/queries/metaobjects)
- [Storefront API metaobject query](https://shopify.dev/docs/api/storefront/latest/queries/metaobject)

## Related

- [Create a metaobject definition and upsert entries](https://lintelagency.com/resources/graphql/metaobject-definition-and-upsert)
- [Create a metafield definition](https://lintelagency.com/resources/graphql/create-metafield-definition)
- [Hydrogen vs Liquid: when headless pays for itself](https://lintelagency.com/journal/shopify-hydrogen-vs-liquid)

License: MIT. Free to use in your own store and in client work.
