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.

TL;DR Metaobjects (GA: Oct 2023) are Shopify's structured content layer. Create a metaobject definition for each semantic type (FAQ, Store Location, Author, Spec Sheet), link entries to products/pages via metaobject_reference metafields, then loop through them in Liquid to generate 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 caseBest toolReason
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 typeSchema.org typeKey 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:

Step 2: Create a metafield on products/pages to link FAQ entries

In Shopify Admin → Settings → Custom data → Products → Add definition:

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 keyTypeSchema.org mapping
namesingle_line_text_fieldname
street_addresssingle_line_text_fieldaddress.streetAddress
citysingle_line_text_fieldaddress.addressLocality
statesingle_line_text_fieldaddress.addressRegion
zipsingle_line_text_fieldaddress.postalCode
countrysingle_line_text_fieldaddress.addressCountry
phonesingle_line_text_fieldtelephone
latitudenumber_decimalgeo.latitude
longitudenumber_decimalgeo.longitude
monday_hourssingle_line_text_fieldopeningHoursSpecification

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:

  1. Canonical tags — Shopify automatically adds a <link rel="canonical"> tag with the metaobject entry's URL. Verify it is correct with curl -s URL | grep canonical. If your metaobject pages have duplicate content (e.g., multiple location entries sharing similar descriptions), add noindex to low-value entries or ensure each entry has unique content in at least one field.
  2. Sitemap inclusion — Metaobject pages are included in Shopify's auto-generated /sitemap.xml as 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.

Scan your store free

Related: Shopify metafields and AI agents · Metafields guide (blog) · Schema markup overview