Shopify SEO + Structured Data
Shopify metaobject SEO
and structured data
How to turn your Shopify metaobject definitions into reusable JSON-LD sources for FAQPage, LocalBusiness, Review, and Product schema — without hardcoding content in Liquid files.
application/ld+json blocks. Merchandisers edit the data in Admin — no developer needed for content updates.
What are Shopify metaobjects?
Metaobjects are merchant-defined structured objects inside your Shopify store — like custom database tables where you define the schema (definition) and fill in the rows (entries). Each definition has a type (e.g. faq_item, store_location, ingredient) and a set of typed fields.
Unlike metafields, which attach additional data to existing Shopify objects (products, variants, collections), metaobjects are standalone entities. You can link them to products via a metafield of type metaobject_reference or list.metaobject_reference, making them reusable across multiple products or pages.
Metaobject vs. metafield — which to use for structured data?
| Use case | Best tool | Reason |
|---|---|---|
| Single piece of data per product (e.g., GTIN, material) | Metafield | Simpler: one field, one product, one value |
| List of FAQ items shared across many products | Metaobject | Write once, link to many; edit in one place |
| Store location with address, hours, geo | Metaobject | Multiple fields per location; maps to LocalBusiness type |
| Author bio with name, image, credentials | Metaobject | Reusable across blog posts; maps to Person type |
| Product specification table (dimensions, weight, etc.) | Metaobject or metafield group | Metaobject if specs are reused across variants/products |
| Shipping delivery estimate per region | Metaobject | Multiple fields (min days, max days, region) per rule |
Schema.org types that map naturally to metaobjects
| Metaobject definition type | Schema.org type | Key fields to include |
|---|---|---|
faq_item |
Question + Answer (FAQPage) | question (text), answer (rich_text) |
store_location |
Store or LocalBusiness | name, address, city, zip, country, phone, hours (JSON), lat, lng |
team_member / author |
Person | name, job_title, bio (rich_text), image, social_url |
ingredient |
DefinedTerm or ItemList | name, description, allergen_flag (boolean) |
specification |
PropertyValue (additionalProperty) | spec_name, spec_value, unit |
shipping_zone |
OfferShippingDetails | region (list.country), min_days, max_days, free_threshold |
review_highlight |
Review | reviewer_name, rating (integer), review_text, review_date |
FAQPage schema from metaobjects (complete example)
This is the most common and highest-impact metaobject structured data pattern. FAQ Rich Results appear in Google Search and in Google AI Mode summaries. Each question-answer pair you add in Shopify Admin automatically appears in structured data.
Step 1: Create the metaobject definition
In Shopify Admin → Content → Metaobjects → Add definition:
- Type:
faq_item - Field 1: Key
question, Type: Single line text - Field 2: Key
answer, Type: Multi-line text (or Rich text) - Check "Has web presence" if you want /faq URLs to be accessible
Step 2: Create a metafield on products/pages to link FAQ entries
In Shopify Admin → Settings → Custom data → Products → Add definition:
- Name: FAQ items
- Namespace and key:
custom.faq_items - Type: List of metaobjects (select
faq_itemas the referenced type)
Step 3: Liquid JSON-LD output
{% assign faq_items = product.metafields.custom.faq_items.value %}
{% if faq_items.size > 0 %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{% for item in faq_items %}
{
"@type": "Question",
"name": {{ item.question.value | json }},
"acceptedAnswer": {
"@type": "Answer",
"text": {{ item.answer.value | strip_html | json }}
}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
}
</script>
{% endif %}
LocalBusiness schema from a store_location metaobject
For Shopify stores with physical retail locations, a store_location metaobject lets store managers update hours, address, and phone numbers in Admin without touching Liquid code — and every change automatically flows into the JSON-LD for Google AI Mode's local shopping results.
Metaobject definition fields
| Field key | Type | Schema.org mapping |
|---|---|---|
| name | single_line_text_field | name |
| street_address | single_line_text_field | address.streetAddress |
| city | single_line_text_field | address.addressLocality |
| state | single_line_text_field | address.addressRegion |
| zip | single_line_text_field | address.postalCode |
| country | single_line_text_field | address.addressCountry |
| phone | single_line_text_field | telephone |
| latitude | number_decimal | geo.latitude |
| longitude | number_decimal | geo.longitude |
| monday_hours | single_line_text_field | openingHoursSpecification |
Liquid JSON-LD output for a location page
{% assign loc = metaobject %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Store",
"name": {{ loc.name.value | json }},
"url": "{{ shop.url }}/locations/{{ loc.handle }}",
"telephone": {{ loc.phone.value | json }},
"address": {
"@type": "PostalAddress",
"streetAddress": {{ loc.street_address.value | json }},
"addressLocality": {{ loc.city.value | json }},
"addressRegion": {{ loc.state.value | json }},
"postalCode": {{ loc.zip.value | json }},
"addressCountry": {{ loc.country.value | json }}
},
"geo": {
"@type": "GeoCoordinates",
"latitude": {{ loc.latitude.value | json }},
"longitude": {{ loc.longitude.value | json }}
},
"openingHoursSpecification": [
{% assign days = "Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday" | split: "," %}
{% assign keys = "monday_hours,tuesday_hours,wednesday_hours,thursday_hours,friday_hours,saturday_hours,sunday_hours" | split: "," %}
{% for day in days %}
{% assign key = keys[forloop.index0] %}
{% assign hours = loc[key].value %}
{% if hours != blank and hours != "Closed" %}
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": "https://schema.org/{{ day }}",
"opens": "{{ hours | split: '-' | first | strip }}",
"closes": "{{ hours | split: '-' | last | strip }}"
}{% unless forloop.last %},{% endunless %}
{% endif %}
{% endfor %}
],
"parentOrganization": {
"@type": "Organization",
"name": {{ shop.name | json }},
"url": {{ shop.url | json }}
}
}
</script>
Product specification tables via metaobjects
Technical products (electronics, hardware, apparel with materials) benefit significantly from structured additionalProperty values in their JSON-LD. AI shopping agents use these to answer specification queries: "which headphones have 40-hour battery life", "shoes made from recycled materials", "monitors with 4K resolution under $400".
Instead of hardcoding spec values into metafields per product (which requires creating dozens of individual metafields), a specification metaobject lets you create reusable spec entry objects and attach a list of them to each product.
Specification → additionalProperty output
{% assign specs = product.metafields.custom.specifications.value %}
{% if specs.size > 0 %}
"additionalProperty": [
{% for spec in specs %}
{
"@type": "PropertyValue",
"name": {{ spec.spec_name.value | json }},
"value": {{ spec.spec_value.value | json }}
{% if spec.unit.value != blank %}
,"unitCode": {{ spec.unit.value | json }}
{% endif %}
}{% unless forloop.last %},{% endunless %}
{% endfor %}
]
{% endif %}
Metaobject URL pages and canonical tags
When you enable "Has web presence" for a metaobject definition, Shopify creates accessible URLs for each entry based on the URL template you define (e.g., /locations/{handle}). These pages are crawled and indexed by default. There are two SEO considerations:
- Canonical tags — Shopify automatically adds a
<link rel="canonical">tag with the metaobject entry's URL. Verify it is correct withcurl -s URL | grep canonical. If your metaobject pages have duplicate content (e.g., multiple location entries sharing similar descriptions), addnoindexto low-value entries or ensure each entry has unique content in at least one field. - Sitemap inclusion — Metaobject pages are included in Shopify's auto-generated
/sitemap.xmlas of Shopify platform version 2024-01. If you want to suppress them (e.g., for internal-only metaobjects), set the entry to "Not available online" in the metaobject definition settings.
FAQ
What are Shopify metaobjects and why do they matter for SEO?
Shopify metaobjects are merchant-defined structured content objects — like custom database tables inside your store. They matter for SEO because they provide a clean, admin-editable data source that your Liquid templates can read to generate valid schema.org JSON-LD, without hardcoding content in template files. FAQ answers, store hours, author bios, and product specifications stored in metaobjects become reusable structured data sources.
Can I use metaobjects to generate FAQPage schema automatically?
Yes. Create a metaobject definition with type faq_item and fields question and answer. In your product template, use a list metaobject_reference metafield to link FAQ entries to products. Loop through them in Liquid JSON-LD to output FAQPage schema. Merchandisers can add and edit FAQ entries in Admin without touching any code.
Do Shopify metaobject pages get indexed by Google?
Metaobject entries with "Has web presence" enabled are served at URLs like /locations/san-francisco and are indexed by Google and AI crawlers the same as any other Shopify page. Add LocalBusiness or other relevant JSON-LD to the metaobject page template using the entry's field values. Ensure each location page has unique and complete structured data.
What is the Liquid syntax for accessing metaobject fields in JSON-LD?
Assign the metaobject reference value: assign items = product.metafields.custom.faq_items.value. This returns an array of metaobject entries. For each entry, access fields via entry.field_key.value (e.g., entry.question.value). Use | json to serialize values safely into JSON-LD, preserving quotes and special characters.
Are metaobject-sourced structured data blocks faster than hardcoded Liquid?
Performance is identical — both are rendered server-side before the HTTP response is sent. The advantage of metaobjects is editorial: content editors can update FAQ answers, store hours, or specification values without involving a developer. For AI agent readiness, the important thing is that the JSON-LD appears in the initial HTML response, which both approaches guarantee (unlike JavaScript-injected schema).
Scan for structured data completeness
CatalogScan checks whether your Shopify store's product pages include FAQPage, additionalProperty specification values, and other rich schema types — including data sourced from metaobjects. Get a full report of which structured data your AI shopping agents can read.
Related: Shopify metafields and AI agents · Metafields guide (blog) · Schema markup overview