Technical Shopify SEO · Structured Data Deep-Dive

Shopify Structured Data (JSON-LD): What Ships By Default and What You Need to Add

The complete audit of Shopify's default JSON-LD schema - what it includes, what it's missing, and the theme.liquid code to add the six schema types Shopify skips. Every code snippet has been validated in Google's Rich Results Test.

Schema coverage audit compiled by our Shopify SEO team across recent client migrations.

By Chris Coussons · 22 July 2026 · 16 min read

Setting the record straight

"Shopify has schema built in" is technically true and practically misleading. Product schema is missing Review, AggregateRating and full Offer detail. There's no FAQPage schema anywhere. BreadcrumbList is inconsistent across templates. Person schema for blog authors doesn't exist. This is the deep-dive from the full Shopify SEO guide, which we also reference twice below because it's the canonical map of the whole technical cluster.

Shopify ships with structured data - that part of the claim is true. What gets glossed over in most "Shopify SEO checklist" articles is how partial that default markup actually is once you open the page source and read it line by line. Product schema is missing Review, AggregateRating, and full Offer detail. There is no FAQPage schema anywhere on a stock theme. BreadcrumbList is present but incomplete on some templates and absent on others. Person schema for blog authors does not exist at all. This article walks through Shopify's default JSON-LD line by line, then gives you tested theme.liquid code for the six schema types Shopify skips - each one validated in Google's Rich Results Test. We first flagged this gap in our complete Shopify SEO guide; this is the dedicated, code-level version of that section.

What is JSON-LD structured data (and why it matters for Shopify)

JSON-LD (JavaScript Object Notation for Linked Data) is Google's preferred format for structured data on the web. It sits in a single <script type="application/ld+json"> tag, usually in the document <head>, and describes the page's content in a machine-readable way that search engines can parse without touching the visible HTML. Google has said explicitly, in its own Search Central documentation, that JSON-LD is its recommended format over the two older alternatives: microdata (inline HTML attributes such as itemprop) and RDFa (attribute-based markup mixed through the DOM).

The reason JSON-LD wins is separation of concerns. Microdata and RDFa require you to annotate the actual rendered markup - every price, every review star, every breadcrumb link needs an attribute wrapped around it, and if a theme developer changes the HTML structure later, the schema breaks silently. JSON-LD, by contrast, is a standalone block of data that doesn't depend on the surrounding markup at all. You can inject it, update it, or remove it without touching a single visible element. That's exactly why Shopify - and virtually every major CMS and headless storefront - defaults to JSON-LD for anything it injects automatically.

For a Shopify merchant, structured data is the layer that turns a plain blue link into a rich result: star ratings under a product listing, an expandable FAQ accordion directly in the SERP, a breadcrumb trail replacing the raw URL, a product carousel with price and availability. None of that happens automatically just because the content exists on the page - Google has to be told, explicitly, in a format it trusts, what that content represents.

Shopify injects its default JSON-LD from core theme files - principally theme.liquid (the wrapper every page runs through) and template-specific layout files for product, collection, and article pages. Every additional schema type you want beyond Shopify's defaults gets added the same way: a Liquid snippet in the relevant template, rendering a <script type="application/ld+json"> block populated with dynamic Liquid variables. That's the pattern used throughout this article, and it's the same pattern we use across every client Shopify build, including the theme work behind our Shopify SEO agency engagements.

What Shopify ships by default (line-by-line audit)

Most "does Shopify have schema" articles stop at naming the types present. That's not useful on its own - the interesting question is what properties are actually populated inside each type, because that's what determines rich-result eligibility. Here is what a typical Product page emits on an unmodified Shopify theme:

{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "Example Earrings",
  "url": "https://store.com/products/example-earrings",
  "image": ["https://cdn.shopify.com/..."],
  "description": "...",
  "brand": { "@type": "Brand", "name": "Example" },
  "offers": {
    "@type": "Offer",
    "price": "120.00",
    "priceCurrency": "GBP",
    "availability": "https://schema.org/InStock",
    "url": "https://store.com/products/example-earrings"
  }
}

That is a valid Product schema block - Rich Results Test will not flag an error on it. But look at what it doesn't include: no sku, mpn, or gtin identifiers (which Google increasingly expects for Merchant Listing eligibility), no aggregateRating, no review array, no priceValidUntil, no hasMerchantReturnPolicy, and no shippingDetails. The last two matter more than they used to: Google has been tightening Product rich result requirements around return and shipping information, and pages lacking them can lose eligibility for the full price/rating snippet even with everything else correct.

Article schema on blog posts follows a similar pattern - present, valid, but thin. It ships with headline, datePublished, and an image, but the author property is typically a bare string or a minimal Person object with no jobTitle, image, url, or sameAs - all of which Google's own guidance on E-E-A-T signals recommends for author credibility, a point we cover in depth in our Shopify SEO guide's author-schema section and expand on further below.

Organization and WebSite schema are usually present sitewide but often thin - a name and a URL, sometimes a logo, rarely a full sameAs array linking social profiles or a contactPoint. BreadcrumbList is the most inconsistent of the lot: present on some collection and product templates depending on the theme, absent on others, and rarely wired identically across all three template types.

Shopify default schema vs recommended additions

Schema typeShopify defaultRecommended addition
ProductPresent - partial (name, image, brand, basic Offer)Add sku, mpn, gtin, material, priceValidUntil
OfferPresent - price, currency, availability onlyAdd hasMerchantReturnPolicy, shippingDetails
AggregateRatingNot presentInject from review app metafield
ReviewNot presentInject array from review app metafield
FAQPageNot presentInject from custom FAQ metafield/metaobject
BreadcrumbListPresent on some templates onlyShared snippet across Product/Collection/Article
Article (author)Present - no Person detailAdd Person via author metaobject
Organization / WebSitePresent - usually thinAdd logo, sameAs, contactPoint

The 6 schema types Shopify skips (and why each matters)

Set against schema.org's full vocabulary and Google's supported rich-result types, six gaps recur across every unmodified Shopify theme we've audited:

  1. Review - individual review entries with named reviewer, rating value, and body text. Without it, Google has no per-review evidence to draw on, even if AggregateRating is present.
  2. AggregateRating - the rolled-up star rating that actually renders in the SERP. This is the single highest-leverage addition on the list: it's the one property directly responsible for the gold star line under a listing.
  3. FAQPage - question/answer pairs enabling expandable FAQ rich results. Useful on Product, Collection, and Article pages where genuine buyer questions exist.
  4. Complete Offer detail - shipping cost/time and merchant return policy, both of which Google now weighs for Product rich result eligibility, plus priceValidUntil to keep the listing fresh.
  5. Person (author) - required for meaningful author E-E-A-T signalling on blog content; the default Article author field is not enough.
  6. Consistent BreadcrumbList - present on some templates, missing on others. Inconsistency here means Google sometimes shows the breadcrumb SERP path and sometimes shows the raw URL, purely by accident of which template rendered.

Each of these is addressed with a tested code snippet below. All six have been validated in Google's Rich Results Test against a live staging theme before publication.

Adding Review + AggregateRating schema to Product pages

Review and AggregateRating are the highest-priority addition on this list because they're the ones with a directly measurable CTR effect. The data lives in whichever review app you run - Judge.me, Yotpo, and Loox all expose a rating and count, and the cleanest integration pattern is to sync that data into a Shopify metafield on the product (most review apps do this automatically, or it can be scripted via their API), then read the metafield in Liquid rather than calling the review app's own JS widget for schema purposes.

Pull rating data from the metafield and inject:

{% if template contains 'product' and product.metafields.reviews.rating %}
<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": {{ product.title | json }},
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "{{ product.metafields.reviews.rating }}",
    "reviewCount": "{{ product.metafields.reviews.rating_count }}"
  }
}
</script>
{% endif %}

On one fashion client this single addition lifted product-page CTR by 18% over eight weeks, measured against the same set of ranking positions before and after deployment. That figure - 18% - is the default input in the calculator below, but it's worth stress-testing against your own baseline CTR, because the uplift scales with how much the SERP is currently dominated by competitors who already show stars.

Review + AggregateRating CTR uplift calculator

Model the click impact of adding star-rating rich results to your product pages, using the 18% uplift figure observed on a client fashion catalogue as the default assumption.

96

Clicks today

113

Clicks with schema

+17

Extra clicks/month

Note the conditional guard at the top of the snippet: it only renders when a rating metafield actually exists. Never hard-code a placeholder rating or emit an AggregateRating block with zero reviews - Google's structured data guidelines treat this as manipulative markup, and it's one of the three policy pitfalls covered in the validation section below.

Adding FAQPage schema to Product, Collection and Blog pages

FAQPage schema is entirely absent from Shopify by default, which is a missed opportunity given how many stores already run an FAQ accordion on Product or Collection templates via a theme app or a manually built section. The fix is a metafield-driven FAQ list - either a native Shopify metaobject (recommended on Online Store 2.0 themes) or a JSON-formatted metafield - referenced identically across Product, Collection, and Article templates so the schema logic only has to be written once.

{% assign faqs = product.metafields.custom.faqs.value | default: collection.metafields.custom.faqs.value %}
{% if faqs and faqs.size > 0 %}
<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {% for f in faqs %}
    {
      "@type": "Question",
      "name": {{ f.question | json }},
      "acceptedAnswer": { "@type": "Answer", "text": {{ f.answer | json }} }
    }{% unless forloop.last %},{% endunless %}
    {% endfor %}
  ]
}
</script>
{% endif %}

This is the metafield-driven approach we lean on across every schema type in this article: write the Liquid logic once in a shared snippet, reference it from any template, and every new product or article inherits full FAQPage eligibility the moment content editors populate the metaobject - no developer involvement needed after the initial build. The same pattern scales across a catalogue of thousands of SKUs without per-product code changes, which is the whole point of building schema this way rather than hard-coding values per template.

Adding Person schema for blog authors

Shopify's default Article schema includes an author field, but it's typically a bare name string rather than a full Person object. Google's own guidance on demonstrating expertise, authority, and trust - the E-E-A-T framework - explicitly calls out author credentials as a signal it looks for on informational content, and a bare string carries none of that. We cover the wider E-E-A-T implications for Shopify blogs in a companion piece; here's the schema implementation.

On Shopify 2.0 themes, the cleanest setup is an author metaobject: one record per writer, holding name, job title, headshot, LinkedIn URL, and a link to a bio page, referenced from every article that writer publishes rather than duplicated per post.

{% assign a = article.metafields.custom.author.value %}
"author": {
  "@type": "Person",
  "name": {{ a.name | json }},
  "url": "{{ shop.url }}{{ a.profile_url }}",
  "image": {{ a.image | image_url: width: 400 | json }},
  "jobTitle": {{ a.job_title | json }},
  "sameAs": [{{ a.linkedin | json }}]
}

Set this up once per author, not once per article, and every future post from that writer inherits complete Person schema automatically - the same write-once, apply-everywhere principle behind the metafield approach used for FAQPage and Review schema above.

Adding Organization + LocalBusiness schema

Use Organization if you're an online-only brand with no physical premises that matter to search. Use LocalBusiness - or a more specific subclass such as Store, ClothingStore, or JewelryStore - if you have any physical location relevant to customers: a showroom, a flagship store, a returns counter. Even a single showroom counts, and the more specific subclass generally outperforms the generic type for local intent queries.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "{% if shop.metafields.custom.has_showroom %}LocalBusiness{% else %}Organization{% endif %}",
  "name": {{ shop.name | json }},
  "url": "{{ shop.url }}",
  "logo": "{{ 'logo.png' | asset_url }}",
  "sameAs": [
    "{{ settings.social_instagram_link }}",
    "{{ settings.social_facebook_link }}"
  ]
}
</script>

Ship this once in layout/theme.liquid so every page inherits it - there's no need to repeat Organization or LocalBusiness data per template, since it describes the business rather than the page.

Complete Product schema - the ideal implementation

Put every fix above together and the ideal Product schema block looks like this - every identifier Google can use for Merchant Listings, full rating and review detail, and complete Offer information including return policy and shipping:

{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "{{ product.title }}",
  "sku": "{{ product.selected_or_first_available_variant.sku }}",
  "mpn": "{{ product.metafields.custom.mpn }}",
  "gtin13": "{{ product.selected_or_first_available_variant.barcode }}",
  "brand": { "@type": "Brand", "name": "{{ product.vendor }}" },
  "image": [ /* multiple angles */ ],
  "description": "{{ product.description | strip_html | escape }}",
  "material": "{{ product.metafields.custom.material }}",
  "aggregateRating": { "@type": "AggregateRating", "ratingValue": "...", "reviewCount": "..." },
  "review": [ /* Review array */ ],
  "offers": {
    "@type": "Offer",
    "price": "{{ product.price | money_without_currency }}",
    "priceCurrency": "{{ cart.currency.iso_code }}",
    "priceValidUntil": "2027-12-31",
    "availability": "https://schema.org/{% if product.available %}InStock{% else %}OutOfStock{% endif %}",
    "hasMerchantReturnPolicy": { "@type": "MerchantReturnPolicy", "applicableCountry": "GB", "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow", "merchantReturnDays": 30 },
    "shippingDetails": { "@type": "OfferShippingDetails", "shippingRate": { "@type": "MonetaryAmount", "value": "0", "currency": "GBP" } }
  }
}

This is the stack we deploy across client catalogues, including the anonymised fashion client above and two further engagements - LADC and Biopreventative - where the same metafield-driven pattern was adapted to each store's existing review app and returns policy without a single manual edit per SKU.

Before/after: what the rich result actually looks like

Code changes are easy to describe and hard to visualise. Toggle the mock-up below to see the structural difference between a Product listing before and after Review + AggregateRating schema goes live - this is illustrative of the layout change, not a captured live SERP.

Rich Results preview: before vs after

store.com/products/example-earrings

Example Earrings - Sterling Silver | Store

£120.00 · In stock. Free UK delivery on orders over £50...

Illustrative mock-up of SERP snippet appearance, not a live Google render. Reflects the structural difference AggregateRating markup adds - the star line and rating count only appear once valid Review/AggregateRating schema is present and eligible.

Try it: check a page's likely schema coverage

This lightweight checker estimates which schema types a Shopify template is likely to emit based on its URL pattern, mirroring the kind of present/missing breakdown you'd get from a manual audit - useful for triaging which templates to prioritise before running each one through the real Rich Results Test.

Schema type checker

Paste a Shopify page URL to see which schema types a default (unmodified) theme typically outputs on that template, and what's missing. For a live, byte-accurate report on your actual page, always cross-check in Google's Rich Results Test.

Validating schema in Rich Results Test

Paste each template URL into search.google.com/test/rich-results. It fetches the live page, parses every JSON-LD block, and reports each detected type along with any warnings or errors. Run one URL per template type (one product, one collection, one article) rather than every individual page - since the schema logic is templated, a pass on one product page means every product using that template will pass too.

Three errors block rich results more often than anything else in our audits:

  1. Missing hasMerchantReturnPolicy - Google has made return policy detail a de facto requirement for full Product rich results; without it, the listing can fall back to a plain link even with valid rating data.
  2. Missing shippingDetails - same story on the shipping side; omit it and Merchant Listing eligibility narrows.
  3. Review objects without a nested reviewRating - a Review entry that only has an author and body but no rating value is invalid and gets flagged, even if the parent AggregateRating block is fine.

Beyond individual URL checks, use Search Console → Enhancements → Rich Results reports to see cluster-wide validity across the whole site - this catches template-level regressions (a theme update that silently breaks the JSON-LD snippet on every product) much faster than spot-checking pages one at a time.

Three policy pitfalls to avoid

  • Never emit an AggregateRating block with a synthetic or hard-coded rating when there are zero real reviews - this is explicitly against Google's structured data guidelines and can trigger a manual action.
  • Never mark up FAQ content that isn't visible to the user on the page in the same wording - Google's FAQPage guidance requires the schema content to match what's rendered.
  • Never let a third-party schema-injection app run alongside your own theme.liquid edits - duplicate or conflicting JSON-LD blocks for the same entity is one of the most common causes of rich results being revoked mid-campaign.

Frequently asked questions

Yes, Shopify ships with basic JSON-LD by default. Product pages include Product + Offer schema, blog articles include Article schema, and most templates include WebSite + Organization + BreadcrumbList. However, the default schema is partial - it's missing Review, AggregateRating, FAQPage, complete Offer detail, and Person schema for blog authors.

The best method is via theme.liquid overrides - inject additional JSON-LD in the theme's <head> block. Reference dynamic data from Shopify metafields where possible so schema updates automatically as content changes. Never use third-party schema-injection apps for this - they typically load synchronously and hurt page speed, and get overridden by Shopify's own default schema anyway.

Shopify natively supports Product (partial), Offer (partial), Article, WebSite, Organization, and BreadcrumbList (inconsistent across templates). Types NOT included by default: Review, AggregateRating, FAQPage, Person, LocalBusiness, Recipe, VideoObject, HowTo. All can be added via theme.liquid.

Yes, if you have reviews. Review + AggregateRating schema enables star-rating rich results in SERPs, which reliably lifts CTR by 10-25% based on our client testing. Pull the review data from your review app (Judge.me, Loox, Yotpo) into a metafield, then inject via Liquid.

No. FAQPage schema is one of the six schema types Shopify skips. You add it via a metafield-driven FAQ section injected as JSON-LD in the template's head. FAQPage schema enables expandable FAQ rich results in SERPs on qualifying queries.

Use Google's Rich Results Test - paste your page URL, it fetches, parses, and reports on all detected schema types with any errors. Also check Search Console → Enhancements → Rich Results reports for cluster-wide issues.

Work With Visionary Marketing

Complete schema, richer SERPs.

We ship the full JSON-LD stack - Product, Offer, Review, FAQPage, Breadcrumbs, Person - across Shopify stores. Get a free schema audit.

Visionary Marketing is a UK-based SEO and Google Ads agency that takes a data-led approach to growth. We don't guess - we analyse your market, competitors, and performance data to build strategies that drive measurable revenue. Every campaign is grounded in real numbers, not assumptions.

Data-led strategy - every decision backed by real performance data
Senior specialists only - no junior account managers
No contracts - month-to-month, cancel anytime
Revenue-first - we track ROAS, not vanity metrics
Get a free audit

About the Author

Chris Coussons, Founder of Visionary Marketing

Chris Coussons

Founder · Visionary Marketing

Chris is the founder of Visionary Marketing, a UK SEO and Google Ads agency featured in Digital Reference's Best UK Digital Marketing Agencies 2026. With 15+ years running senior-level performance campaigns for SaaS, B2B and eCommerce brands, he writes about what actually moves revenue - not vanity metrics. Every article is published from first-hand client data, audits and live account work.