Metaobjects are Shopify's answer to a long-standing request: the ability to model reusable, structured content — think author bios, ingredient tables, team members, or size guides — without reaching for a third-party headless CMS. Introduced in 2022, they let you define a custom content type with typed fields, create instances in the Shopify admin, then reference those instances from product metafields and render them in Liquid. This tutorial walks through one of the most common real-world use cases: attaching an Author bio to product pages.
What you'll build
You'll define an author metaobject definition with fields for name, bio, avatar image, and a website URL. You'll create a couple of sample Author entries in the Shopify admin, add a metafield on product resources to reference an Author, then render the author bio card in a product page section using Liquid. The result is a reusable author card that any product can point to — change the author's headshot once in the metaobject, and every linked product page updates automatically.
Before you start
You'll need Shopify CLI 3.x, a development store on a plan that includes Online Store 2.0 (all non-trial plans qualify), and a theme that supports section rendering (Dawn or any other OS 2.0 theme). Familiarity with the Shopify admin's Content section and basic Liquid template structure is assumed.
Define the Author metaobject in the Shopify admin
Navigate to Settings > Custom data > Metaobject definitions and click Add definition. Name it "Author" — Shopify will auto-generate the API type handle author. This handle is what you'll use to query entries in Liquid.
Add the following fields to the definition: a name field of type single_line_text_field (required); a bio field of type multi_line_text_field; an avatar field of type file_reference filtered to images; and a website field of type url (optional).
Under Display name field, select name so the admin list view shows author names rather than generic IDs. Enable "Storefronts" under access to make entries available to Liquid and the Storefront API. Save the definition.
{
"type": "author",
"name": "Author",
"field_definitions": [
{ "key": "name", "type": "single_line_text_field", "required": true },
{ "key": "bio", "type": "multi_line_text_field" },
{ "key": "avatar", "type": "file_reference" },
{ "key": "website", "type": "url" }
],
"access": { "storefront": "PUBLIC_READ" }
}Expected outcome: The Author metaobject definition appears under Content > Metaobjects in your admin, ready to accept entries.
Create sample Author entries
Navigate to Content > Metaobjects in the Shopify admin and select the Author type. Click Add entry. Fill in the name (e.g. "Dr. Sarah Chen"), a short bio paragraph, upload a headshot image, and optionally add a website URL. Create at least two authors so you can test the reference relationship from multiple products.
Each entry gets a system-generated handle like dr-sarah-chen and a unique GID. You'll never need to reference these directly in Liquid — the metafield reference resolves the entry for you — but they're visible in the admin URL if you need to link to an entry via the Admin API.
# Verify entries exist via the Admin API
query {
metaobjects(type: "author", first: 10) {
nodes {
id
handle
field(key: "name") { value }
field(key: "bio") { value }
}
}
}Expected outcome: Two or more Author entries are visible in Content > Metaobjects, each with name, bio, and avatar populated.
Add a product metafield definition to reference an Author
In Settings > Custom data > Products, click Add definition. Name it "Author" and set the namespace and key to custom.author. Select the type "Metaobject" and then pick "Author" from the metaobject type selector. This creates a typed reference — Shopify will validate that any value assigned to this metafield is a valid Author metaobject ID.
Once saved, open any product in the admin. Scroll to the Metafields section at the bottom of the product detail page. The "Author" field will appear with a picker that lets you search and select from your Author entries. Assign an author to at least two products.
The metafield type metaobject_reference stores a single GID. In Liquid, when you access product.metafields.custom.author, the platform automatically resolves that GID to the full metaobject entry, giving you access to all its fields without any additional API calls.
{%- comment -%}
Verify the metafield is accessible in Liquid
(put this in a temporary snippet or section for testing)
{%- endcomment -%}
{%- assign author_ref = product.metafields.custom.author -%}
{% if author_ref %}
Type: {{ author_ref.type }}
{%- comment -%} Should output: metaobject_reference {%- endcomment -%}
Value ID: {{ author_ref.value.id }}
Author name: {{ author_ref.value.name }}
{% endif %}Expected outcome: The debug snippet outputs the author's metaobject ID and resolves the name field, confirming the reference chain works end-to-end.
Create the author-bio snippet in Liquid
Create snippets/author-bio.liquid. The snippet expects a single variable author to be passed via render. The snippet accesses fields on the metaobject using dot notation: author.name, author.bio, author.avatar, and author.website.
Note that the avatar field is of type file_reference, so it resolves to a MediaImage object. You access its image property, then pipe through image_url as usual. The chain is: author.avatar.image | image_url: width: 80 | image_tag.
{%- comment -%}
Usage: {% render 'author-bio', author: product.metafields.custom.author.value %}
{%- endcomment -%}
{%- if author != blank -%}
<div class="author-bio">
{%- if author.avatar != blank -%}
{{ author.avatar.image | image_url: width: 80 | image_tag:
loading: 'lazy',
class: 'author-bio__avatar',
alt: author.name | escape
}}
{%- endif -%}
<div class="author-bio__text">
<p class="author-bio__name">
{%- if author.website != blank -%}
<a href="{{ author.website }}" target="_blank" rel="noopener">
{{ author.name | escape }}
</a>
{%- else -%}
{{ author.name | escape }}
{%- endif -%}
</p>
{%- if author.bio != blank -%}
<p class="author-bio__description">{{ author.bio | escape }}</p>
{%- endif -%}
</div>
</div>
{%- endif -%}Expected outcome: The snippet renders an author card with avatar image, linked name, and bio paragraph when an author is assigned to the product.
Wire the snippet into a product section
Open sections/main-product.liquid (or whichever section renders your product details). Find an appropriate location — typically below the product description — and add a render call. The key detail is accessing .value on the metafield before passing it: product.metafields.custom.author.value returns the resolved metaobject entry, while product.metafields.custom.author returns the metafield object itself (which has properties like .type and .value). This distinction trips up most developers the first time.
Because the snippet guards against a nil author variable, products without an assigned author will simply not show the card. This is the intended behaviour — no conditional needed at the call site.
{%- comment -%} Place after the product description block {%- endcomment -%}
{%- assign author = product.metafields.custom.author.value -%}
{% render 'author-bio', author: author %}Expected outcome: Products with an assigned Author metafield display the author bio card below the description. Products without an author show nothing.
Expose author as a dynamic source in the theme editor
To let merchants control whether the author bio block appears — and where it sits — you can wrap the render call in a block schema. Add a new block type author_bio to your section's {% schema %} definition. With blocks enabled, merchants can drag the author card above or below the Add to Cart button in the theme editor without touching code.
You can also add a section setting of type metaobject (filtered to the author type) to let merchants override the product's assigned author from within the theme editor. This pattern is useful for featured pages where editorial control matters.
{
"name": "t:sections.main-product.name",
"blocks": [
{
"type": "author_bio",
"name": "Author bio",
"limit": 1,
"settings": [
{
"type": "paragraph",
"content": "Displays the author linked via the product's Author metafield."
}
]
}
]
}Expected outcome: The theme editor shows an Author bio block that merchants can add, remove, and reorder within the main product section.
What's next
The Author pattern scales to any structured, reusable content type: Brand definitions, Certifications, Ingredients, Fabric specifications. The decision of when to use a metaobject (reusable, structured, relational) versus a plain metafield (product-specific, single value) is the subject of its own deep dive — but the core rule is: if the same data needs to appear on multiple resources and be managed in one place, reach for a metaobject definition.
