Shopify Metafields and Metaobjects Cheatsheet
Complete guide to using Shopify metafields and metaobjects for custom data and dynamic content
A comprehensive guide to using Shopify’s metafields and metaobjects system for adding custom data to collections, products, pages, and other resources.
What Are Metafields?
Metafields are custom fields that store references or values attached to Shopify resources (Collections, Products, Pages, etc.).
Key characteristics:
- Attached to specific Shopify resources
- Store references to data or direct values
- Have a namespace and key (e.g.,
custom.collection_links) - Can be single values or lists
- Enable per-resource customization without code changes
What Are Metaobjects?
Metaobjects are structured, reusable data records that exist independently of any specific resource. Think of them as custom database tables.
Key characteristics:
- Standalone structured data records
- Defined by a schema (metaobject definition)
- Reusable across multiple resources
- Have fields with specific types (text, URL, boolean, number, etc.)
- Can be referenced by metafields
Mental Model
1
2
Metaobjects = the "records" (reusable, structured content)
Metafields = the "pointer" that connects these records to Shopify resources
Example pattern:
1
Collection metafield → list of Metaobjects (Link items) → Liquid reads and renders
Creating Metaobjects
Step 1: Create a Metaobject Definition
A metaobject definition is like defining a database table structure.
Location: Settings → Custom data → Metaobjects → Create definition
Example: Collection Link Definition
- Name: Collection Link
- Type:
collection_link
Fields:
label- Single line text (e.g., “Size guide”)link- Link field (e.g.,/pages/size-guide)open_in_new_tab- Boolean (optional)icon- File (optional)sort_order- Number (optional)
Step 2: Create Metaobject Entries
After defining the schema, create actual entries:
Example entries:
- “Shipping info” →
/pages/shipping - “Returns” →
/pages/returns - “Gift guide” →
/blogs/gifts
Each entry is a structured object with fields, not just text.
Creating Metafields
Create a Collection Metafield
Location: Settings → Custom data → Collections → Add definition
Configuration:
- Name: Collection Links (display name)
- Namespace and key:
custom.collection_links - Type: List of metaobjects (NOT single reference)
- Metaobject definition: Select
collection_link
Important: You cannot convert a single-reference metafield into a list. The type is locked once created. Create a new metafield if you need to change from single to list.
Using Metafields in Admin
For each collection, you’ll see a field “Collection links” where you can:
- Click Select
- Pick existing link metaobjects (or create new ones)
- Reorder them (drag and drop)
- Leave empty for collections that should have no links
Per-collection control:
- Collection A: no links
- Collection B: 3 links
- Collection C: different set of links
Liquid Code Examples
Basic Example: List of Links
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
{% assign links = collection.metafields.custom.collection_links.value %}
{% if links != blank %}
<div class = "page-width page-width--fixed">
<ul class = "collection-links">
{% for link_obj in links %}
{% assign img = link_obj.icon.value %}
<li class = "collection-links__list-item">
<a class = "collection-links__link" href="{{ link_obj.url.value }}">
{% if img != blank %}
<img src="{{ img | image_url }}" alt="{{ link_obj.label.value | escape }}" loading="lazy">
{% endif %}
{{ link_obj.label.value }}
</a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
With Link Field Type (Recommended)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% assign links = collection.metafields.custom.collection_links.value %}
{% if links != blank %}
<ul>
{% for item in links %}
<li>
<a href="{{ item.link.url }}"
{% if item.open_in_new_tab.value %}target="_blank" rel="noopener"{% endif %}>
{{ item.label.value }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
Accessing Metafield Data in Liquid
Get the metafield:
1
collection.metafields.custom.collection_links
Get the value:
1
.value
Resolves into actual metaobject references you can loop through.
Access metaobject fields:
1
item.FIELDNAME.value
Each metaobject field is accessed via .value
Access Link fields:
1
2
item.link.url
item.link.title
Link fields have .url and .title properties (no .value needed)
Field Types: Link vs URL
Why Link Field is Better Than URL
Link Field Advantages:
- Resource-aware: Can target a collection/product/page object, not just a string
- Safer with handle changes: If you change a collection handle, Shopify keeps the reference intact
- Better editor UX: Merchants pick from a selector instead of pasting URLs
- Localization-ready: Works better with Shopify’s internal routing and multilingual setups
- Can handle external URLs too: Link fields can store external URLs
When to Use URL Field
Use URL only when:
- You need to allow any arbitrary external URL
- You don’t care about resource selection
- You’re storing something that isn’t really a “link” (e.g., webhook endpoint)
Recommended Field Structure
1
2
3
4
5
6
Metaobject: collection_link
Fields:
- label (Single line text)
- link (Link) ← Use this instead of URL
- open_in_new_tab (Boolean, optional)
- icon (File, optional)
Best Practices
Do’s
- Use metaobjects for structured data - Avoids brittle parsing
- Use Link field type for better resource awareness
- Use List of metaobjects - Allows multiple entries per collection
- Always check if metafield is blank before rendering
- Reuse metaobjects - Same objects can be used across collections
- Use conditional rendering -
{% if links != blank %}
Don’ts
- Don’t hardcode collection handles in Liquid - Use metafields
- Don’t use separate list fields for labels and URLs - Use structured metaobjects
- Don’t try to convert single reference to list - Create a new metafield
- Don’t use blocks for per-collection data - Blocks live on templates, not collections
Complete Working Example
Metaobject Definition
Name: Collection Link Type: collection_link
Fields:
label- Single line textlink- Linkopen_in_new_tab- Boolean (optional)
Collection Metafield
Name: Collection Links Namespace/Key: custom.collection_links Type: List of metaobjects References: collection_link
Liquid Template Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{% assign links = collection.metafields.custom.collection_links.value %}
{% if links != blank %}
<div class="collection-custom-links">
<h3>Helpful Links</h3>
<ul>
{% for link_obj in links %}
<li>
<a href="{{ link_obj.link.url }}"
{% if link_obj.open_in_new_tab.value %}target="_blank" rel="noopener"{% endif %}>
{{ link_obj.label.value }}
</a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
Advanced Use Cases
Nested/Grouped Links
For complex structures with grouped links:
Metaobject 1: link_item
- Fields: label, url
Metaobject 2: link_group
- Fields: title, items (list of link_item)
Collection metafield: references link_group (list)
This gives you structured groups per collection.
Shared Link Sets
Reuse the same link metaobjects across collections (great for global links like Shipping/Returns), and only add unique ones where needed.
Common Problems and Solutions
Problem: “Some collections have links, others don’t”
Solution: Use metafields with conditional rendering
1
2
3
{% if links != blank %}
<!-- render links -->
{% endif %}
Each collection has its own metafield value. Leave it empty for collections without links.
Problem: “Can only add one metaobject”
Issue: Metafield is set as single reference, not list
Solution:
- Go to
Settings → Custom data → Collections → Your metafield - Check the Type - if it says “Metaobject reference” (singular), it only allows one entry
- Create a NEW metafield with Type: List of metaobjects
- Update your Liquid to use the new namespace/key
Problem: “Links differ per collection”
Solution: Metafields are perfect for this - each collection has its own metafield value (its own list of link references)
Alternatives (Not Recommended)
Simple List Metafields
1
2
custom.link_urls (list of urls)
custom.link_labels (list of text)
Drawback: Easier to mismatch labels/urls, worse editor UX
Theme Editor Blocks
Limitation: Blocks live on the template, not on each collection. Results in multiple templates to maintain.
Hardcoded Conditional Logic
1
2
3
{% if collection.handle == 'womens-apparel' %}
<!-- hardcoded links -->
{% endif %}
Drawback: Doesn’t scale, becomes technical debt
When NOT to Use Metaobjects
If every link set is completely unique and you’ll never reuse items, a simpler approach could be a single collection metafield with “rich text” or JSON. The tradeoff is worse editor UX and brittle parsing.
Product Metafields Example
Metafields work the same way for products:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
{% assign product_links = product.metafields.custom.product_links.value %}
{% if product_links != blank %}
<div class="product-resources">
<h4>Product Resources</h4>
<ul>
{% for link in product_links %}
<li>
<a href="{{ link.link.url }}">{{ link.label.value }}</a>
</li>
{% endfor %}
</ul>
</div>
{% endif %}
Page Metafields Example
For pages with custom data:
1
2
3
4
5
6
7
{% assign page_data = page.metafields.custom.page_data.value %}
{% if page_data != blank %}
<div class="page-metadata">
<p>{{ page_data.description.value }}</p>
</div>
{% endif %}