Metafields were the go-to solution for custom data in Shopify for a long time. But there was a problem: they were flat, disproportionate, and unsuitable for complex structures. With Metaobjects, Shopify delivered a more elegant answer.
After five years of Shopify development, we see projects every day where Metaobjects form the foundation for compelling storefront experiences. In this article, we show you what matters.
What Are Metaobjects? The Core Concept
Metaobjects are structured data types that Shopify introduced in 2023. Unlike Metafields, which are tied to a resource (e.g., a product), Metaobjects are standalone records with their own fields and relationships.
Imagine you sell wines. With Metafields, you could add a note to each product ("Tannins: Medium, Acidity: High"). With Metaobjects, you create a "WineProfile" type with structured fields: Tannins (number), Acidity (number), Flavor Notes (multi-line), Origin Region (link to Region Metaobject).
Metafields vs. Metaobjects: The Difference
| Aspect | Metafields | Metaobjects |
|---|---|---|
| Structure | Flat, limited field types | Hierarchical, custom types |
| Binding | Tied to products, collections, orders | Standalone records |
| Relationships | Limited | Native relationship fields |
| Management | Admin UI or API | Admin UI with custom apps |
| Reusability | Defined per resource | Defined once, usable everywhere |
For many simple cases (e.g., "manufacturer delivery number"), Metafields are sufficient. But as soon as you need complex structures, Metaobjects are more elegant.
When Do You Actually Need Metaobjects?
Not every project needs Metaobjects. There are a few clear indicators:
1. Standard Fields Are Not Enough Your product has 50+ custom fields? The admin UI becomes cluttered. Metaobjects enable dedicated management interfaces for related data.
2. Multilingual Content With Metaobjects, you can structure language-specific content — for example, different descriptions for the German and English storefront, without needing external tools.
Metaobject Type: "ProductDescription"
- Field: title (Text, multilingual)
- Field: shortDescription (Text, multilingual)
- Field: longDescription (Rich Text, multilingual)
- Field: seoKeyword (Text)
3. Content Management Without External Apps Many stores use external headless CMS for flexible content. With Metaobjects, you can manage much of it directly in Shopify — cheaper, faster, more integrated.
4. Complex Relationships Between Records Say you have "Certifications" for your products. Each certification has a logo, a description, and validity dates. With Metaobjects, you define it once and link it to many products.
Real Use Cases From Our Practice:
- JClay: Collections with storytelling — each collection had associated articles, image galleries, and author profiles. Metaobjects made management clear and organized.
- Fashion Brand: Size charts with size names, measurements, and videos per item
- Food Manufacturer: Nutrition tables, allergens, and certifications as structured data
How to Build Metaobjects
Step 1: Define the Metaobject Type
This is done in the Shopify Admin under Settings → Data Models → Metaobject Definitions.
For our wine example:
Name: Wine Profile
Plural: Wine Profiles
Description: Flavor profiles for wines
Add fields:
| Field Name | Type | Required? | Notes |
|---|---|---|---|
| Tannins | Integer | Yes | Scale 1-10 |
| Acidity | Integer | Yes | Scale 1-10 |
| Flavor Notes | List | No | Text array |
| Origin Region | Link (Collection) | No | Link to region |
| Aging Duration | Text | No | e.g., "5-10 years" |
Step 2: Create Metaobject Instances
In the Admin under Content → Metaobjects:
Display Name: "Pinot Noir 2019"
Tannins: 7
Acidity: 6
Flavor Notes: ["Cherries", "Mushrooms", "Earth"]
Origin Region: Burgundy Region
Aging Duration: "8-12 years"
Step 3: Connect to the Storefront
The magic part: every product can now have a Wine Profile Metaobject.
With GraphQL (API):
query {
products(first: 1) {
edges {
node {
id
title
metafield(namespace: "custom", key: "wine_profile") {
reference {
... on Metaobject {
type
field(key: "tannine") {
value
}
field(key: "sauere") {
value
}
field(key: "geschmacksnoten") {
value
}
}
}
}
}
}
}
}
With Liquid (Theme):
{% assign wine_profile = product.metafields.custom.wine_profile.reference %}
{% if wine_profile %}
<div class="wine-profile">
<h3>{{ wine_profile.field.tannine.value }} / 10 Tannins</h3>
<p>{{ wine_profile.field.sauere.value }} / 10 Acidity</p>
<p>Flavor Notes: {{ wine_profile.field.geschmacksnoten.value | join: ", " }}</p>
</div>
{% endif %}
That is the core. Metaobjects are not complicated — they are simply well-structured.
Practical Examples & Code
Example 1: Custom Product Attributes (Fashion)
Many fashion stores need additional attributes beyond size and color: material composition, care instructions, country of origin.
Define Metaobject Type: "FabricInfo"
Fields:
- material (Text): "100% Cotton"
- composition (List): ["60% Cotton", "40% Polyester"]
- careInstructions (Rich Text)
- sustainabilityBadge (Link to Badge Metaobject)
- manufacturingCountry (Text)
GraphQL for Frontend:
query GetProductWithFabric($handle: String!) {
productByHandle(handle: $handle) {
title
variants(first: 10) {
edges {
node {
id
title
metafield(namespace: "custom", key: "fabric_info") {
reference {
... on Metaobject {
field(key: "material") { value }
field(key: "careInstructions") { value }
field(key: "sustainabilityBadge") {
reference {
... on Metaobject {
field(key: "name") { value }
field(key: "icon") { value }
}
}
}
}
}
}
}
}
}
}
}
Liquid Output:
{% assign fabric = variant.metafields.custom.fabric_info.reference %}
<div class="fabric-details">
<h4>Material & Care</h4>
<p><strong>Material:</strong> {{ fabric.field.material.value }}</p>
<div class="care-instructions">
{{ fabric.field.careInstructions.value }}
</div>
{% if fabric.field.sustainabilityBadge.reference %}
<span class="badge">
{{ fabric.field.sustainabilityBadge.reference.field.name.value }}
</span>
{% endif %}
</div>
Example 2: Testimonials Without an External App
Instead of an external testimonial app, you can use Metaobjects:
Metaobject Type: "CustomerTestimonial"
Fields:
- customerName (Text)
- customerTitle (Text): "CEO of XYZ"
- testimonialText (Rich Text)
- rating (Integer): 1-5
- productLink (Link to Product)
- image (File): Customer profile photo
- datePublished (Date)
- featured (Boolean): Highlight on homepage
Admin Experience: Your team creates testimonials directly in the Admin under Content → Metaobjects. No external services, no API integrations.
Storefront Query:
query GetFeaturedTestimonials {
metaobjects(type: "customer_testimonial", first: 10) {
edges {
node {
id
field(key: "customerName") { value }
field(key: "testimonialText") { value }
field(key: "rating") { value }
field(key: "featured") { value }
field(key: "image") { reference { ... } }
}
}
}
}
Example 3: Complex Product Bundles
A bundle with multiple products, tiered discounts, and storytelling.
Metaobject Type: "ProductBundle"
Fields:
- bundleName (Text)
- bundleDescription (Rich Text)
- bundleImage (File)
- products (List of Product Links): [Prod1, Prod2, Prod3]
- bundlePrice (Number): Optional bundle price
- discountPercentage (Integer): 0-100
- validFrom (Date)
- validUntil (Date)
Liquid for Bundle Page:
{% assign bundle = page.metafield.reference %}
<div class="bundle-card">
<h2>{{ bundle.field.bundleName.value }}</h2>
<img src="{{ bundle.field.bundleImage.reference.url }}" alt="Bundle">
<div class="bundle-products">
{% for product_link in bundle.field.products.value %}
{% assign product = product_link.reference %}
<div class="bundle-item">
<p>{{ product.title }}</p>
<span class="price">{{ product.priceRange.minVariantPrice.amount }}</span>
</div>
{% endfor %}
</div>
<div class="bundle-discount">
<strong>{{ bundle.field.discountPercentage.value }}% bundle discount</strong>
</div>
</div>
Performance & Best Practices
When Metaobjects Are Faster Than Apps
Apps add latency. They need to call external APIs, cache data, and then return it to Shopify. Metaobjects are part of Shopify — the data is local.
Comparison:
- With App: Storefront request → Shopify → App server (100ms+) → Shopify → Browser
- With Metaobjects: Storefront request → Shopify → Browser
For frequently accessed data (product descriptions, attributes, certifications), Metaobjects are significantly faster.
Scalability
Metaobjects scale excellently up to 10,000+ entries per type. Beyond that, you should use pagination:
query GetMetaobjects($first: Int, $after: String) {
metaobjects(type: "wine_profile", first: $first, after: $after) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
id
field(key: "title") { value }
}
}
}
}
SEO Implications
Structured data is critical for SEO. Metaobjects help you generate clean schema markup.
Example: Structured Data for Product with Wine Profile
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "{{ product.title }}",
"description": "{{ product.description }}",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{{ wine_profile.field.tannine.value }}",
"reviewCount": "{{ reviews.size }}"
}
}
</script>
Search engines understand your data better when it is structured. This leads to better rich snippets and higher click-through rates.
Common Mistakes
Too Many Fields Per Metaobject Problem: Poor admin UX. Solution: Split large Metaobjects into multiple smaller ones.
No Pagination for Large Volumes Problem: Timeouts with 5,000+ objects. Solution: Use cursor-based pagination.
Circular References Problem: Metaobject A references B, B references A. Solution: Establish a clear hierarchy.
Stale Metaobject Updates Problem: Admin changes data, frontend shows old values. Solution: Think through caching strategies (ISR with Next.js, TTL with Liquid).
Conclusion
Metaobjects are not just a technical improvement over Metafields — they change how you think about data architecture in Shopify. Instead of keeping everything flat, you can now define structured, reusable data types.
Our rule of thumb after years of practice: Use Metaobjects when your data has a clear structure and is reused multiple times.
Need help with the setup? We have implemented Metaobjects in over 50 projects — from small attribute sets to complex content management systems built on Shopify. Get in touch.
About the Author
Claudio Gerlich is the founder of smplx. and a technical Shopify partner since 2020. Based in Munsterland, NRW, he has brought his deep understanding of Shopify architecture to hundreds of projects — from early-stage stores to six-figure revenue businesses. He loves elegant technical solutions that solve real business problems.