Layers fully supports Shopify metaobjects, allowing you to leverage custom data structures defined in your Shopify admin. When a product metafield references a metaobject, Layers automatically resolves the complete metaobject data from a local cache, giving you access to all fields defined on the metaobject — including nested metaobject references up to 5 levels deep.
All reference-type metafields are normalized into a consistent, predictable structure. This means you always receive the same shape of data regardless of how Shopify returns the raw reference, making it easier to build reliable storefront experiences.
Supported reference types
The schema supports the following reference types with full data normalization:
| Reference Type | Description |
|---|
metaobject_reference | Single reference to a custom metaobject |
list.metaobject_reference | List of references to custom metaobjects |
file_reference | Reference to a file asset (image, video, or document) |
product_reference | Single reference to another product |
list.product_reference | List of references to other products |
variant_reference | Single reference to a product variant |
collection_reference | Single reference to a collection |
page_reference | Single reference to a Shopify page |
Normalized reference shapes
Each reference type is normalized into a small, consistent object. Transport-only fields like __typename are always removed. The shape you receive depends on the type of referenced resource.
Metaobject references are resolved into a structure with the metaobject’s core identifiers and a key-value map of its fields:
| Field | Type | Description |
|---|
id | String | The Shopify GID of the metaobject |
type | String | The metaobject definition type |
handle | String | The metaobject handle |
display_name | String or null | The display name of the metaobject |
fields | Object | Key-value map of resolved field data |
Media image references (including file_reference metafields that point to images) are normalized to:
| Field | Type | Description |
|---|
id | String | The Shopify GID of the media image |
url | String | The CDN URL of the image |
alt | String or null | The alt text for the image |
Taxonomy value references are normalized to:
| Field | Type | Description |
|---|
id | String | The Shopify GID of the taxonomy value |
name | String | The display name of the taxonomy value |
Video references are normalized to:
| Field | Type | Description |
|---|
id | String | The Shopify GID of the video |
url | String | The URL of the first video source |
When a metaobject field references another metaobject (via metaobject_reference or list.metaobject_reference), Layers automatically resolves the nested reference from its local cache. This happens recursively up to 5 levels deep, with circular reference protection to prevent infinite loops.
This is useful for data models where metaobjects reference other metaobjects. For example, a “Product Spec” metaobject that references a “Material” metaobject, which in turn references a “Certification” metaobject.
Non-reference fields are returned as their plain values (strings, numbers, etc.). If a referenced metaobject is not found in the cache, the reference data from Shopify is still normalized into the standard shape.
{
"metafields": {
"custom": {
"color_swatch": {
"id": "gid://shopify/Metaobject/123456",
"type": "color_swatch",
"handle": "midnight-blue",
"display_name": "Midnight Blue",
"fields": {
"color": "#191970",
"name": "Midnight Blue",
"hex_code": "#191970"
}
}
}
}
}
{
"metafields": {
"custom": {
"available_colors": [
{
"id": "gid://shopify/Metaobject/111",
"type": "color_swatch",
"handle": "red-swatch",
"display_name": "Red",
"fields": {
"color": "#FF0000",
"name": "Red"
}
},
{
"id": "gid://shopify/Metaobject/222",
"type": "color_swatch",
"handle": "blue-swatch",
"display_name": "Blue",
"fields": {
"color": "#0000FF",
"name": "Blue"
}
}
]
}
}
}
{
"metafields": {
"custom": {
"hero_image": {
"id": "gid://shopify/MediaImage/123456",
"url": "https://cdn.shopify.com/s/files/hero-image.jpg",
"alt": "Product hero image"
}
}
}
}
In this example, a product has a “material” metafield that references a Material metaobject, which itself has a “certification” field referencing a Certification metaobject:
{
"metafields": {
"custom": {
"material": {
"id": "gid://shopify/Metaobject/500",
"type": "material",
"handle": "organic-cotton",
"display_name": "Organic Cotton",
"fields": {
"name": "Organic Cotton",
"weight": "150gsm",
"certification": {
"id": "gid://shopify/Metaobject/600",
"type": "certification",
"handle": "gots-certified",
"display_name": "GOTS Certified",
"fields": {
"name": "Global Organic Textile Standard",
"level": "Grade A",
"url": "https://example.com/gots"
}
}
}
}
}
}
}
Metaobject data is resolved from a local cache that is kept in sync with Shopify via webhooks. If a referenced metaobject is not found in the cache, Layers normalizes the original reference data from Shopify’s GraphQL response into the standard shape, or falls back to the numeric ID if no reference data is available.
See also