Get in touch
View all services

More 18

More 3

More 2

More 1

More 2

More 4
Get in touch

← All insights

Articles · SEO

Shopify schema markup, end to end

Published

Most stores already have schema markup. Almost none of them know what they have, which is why the usual advice, add structured data, is the wrong first move. The first move is finding out what your theme and your apps are already telling Google, because on a Shopify store they are usually telling it two different things.

Everything below uses one worked example: a fictional coffee roaster called Northbound Coffee. Fictional deliberately: the field names are real and the prices are not anybody's.

Anatomy of a Shopify rich result in Google A Google search result for a coffee product showing star rating, review count, price, stock status, a breadcrumb trail and three People Also Ask questions. Each element is labelled with the schema type that produces it: Product, Offer, AggregateRating, BreadcrumbList and FAQPage. whole bean coffee 1kg northboundcoffee.co.uk › products › house-blend-1kg House Blend Whole Bean Coffee, 1kg ★★★★★ 4.7 · 812 reviews £24.00 In stock Single-origin Brazilian arabica, roasted to order in Cornwall. Ships within 48 hours of roasting. SKU NB-HB-1000. Home › Coffee › Whole Bean › House Blend People also ask How long do whole beans stay fresh? + Is this coffee suitable for espresso? + Do you grind to order? + WHAT PRODUCES EACH PART Product name, sku, image, description Offer price, priceCurrency, availability AggregateRating the stars, and the review count BreadcrumbList the trail under the title FAQPage the three expandable questions Five schema types, one page. A plain blue link is what you get when none of them are present. JSON-LD · delivered in the document head · no visible change to the page itself
Five schema types, one search result. Strip them out and you get a plain blue link with no price, no stars and no breadcrumb trail. The same page, ranking in the same position, taking a fraction of the clicks.

Schema markup in plain English

A product page tells a person the price by putting it next to a button. Schema markup tells a machine the price by declaring it in a labelled field, in the head of the document, where no visitor ever sees it. It changes nothing about how the page looks. It changes what a search engine is willing to say about the page in its results, and, the newer half of the story, what an AI assistant is willing to quote.

The format is JSON-LD: a block of JSON in a script tag, describing the page in Schema.org's shared vocabulary. Google has recommended it over the older inline formats for years, and on Shopify it is the only format worth writing new markup in.

It is not the same thing as Liquid section schema

Worth clearing up before anything else, because the name collision causes real confusion on real projects. A Liquid section file contains a schema block, and that block defines the settings a merchant sees in the theme editor: headings, colour pickers, block limits. It has nothing to do with search engines.

Schema.org structured data is a different thing that happens to share a word. When a developer says the theme "has schema", find out which one they mean before you conclude anything, because the two answers point in opposite directions.

The types that matter, and the ones that do not

There are hundreds of Schema.org types. About a dozen are relevant to a store, and they are not equally worth your afternoon. The ordering below is ours, and the reason it is worth stating as an ordering is that most schema advice presents a list of twelve types as though they were twelve equal jobs.

Shopify schema priority matrix: rich-result impact against implementation effort A two by two matrix. Ship now, high impact and low effort: Product, Organization, BreadcrumbList. Worth it, high impact and higher effort: AggregateRating and Review, CollectionPage and OfferCatalog, Article and Author. Nice to have, low impact and low effort: FAQPage, VideoObject, SearchAction. Only if relevant, low impact and higher effort: LocalBusiness, HowTo, Event Recipe or Course. Where to spend your schema effort Our order for a Shopify store, 2026. Not every type is worth the same afternoon. RICH-RESULT IMPACT IMPLEMENTATION EFFORT High Low Easy Harder SHIP NOW Product price, currency, availability → the price snippet Organization logo and sameAs → the knowledge panel BreadcrumbList sitewide → tidies the URL line under the title Three types. Most of the benefit is here. WORTH IT AggregateRating + Review the stars, from your own reviews only CollectionPage + OfferCatalog collections → a signal AI shopping tools read Article + Author blog rich result, and an authorship signal Worth doing once the three on the left are clean. NICE TO HAVE FAQPage the visible rich result is rare now, but the markup still feeds AI answers VideoObject only if the product pages carry real video SearchAction the sitelinks search box ONLY IF IT IS TRUE LocalBusiness only with a real shop somebody can walk into HowTo Google narrowed where this triggers; it rarely renders on a commercial page now Event / Recipe / Course only if you genuinely sell those things
Our order for a Shopify store. Three types in the top-left quadrant carry most of the available benefit; the bottom-right quadrant is where schema projects go to consume a fortnight.

Product schema, line by line

This is the one that pays. A complete Product block is what produces the price, the stock status and the star rating in a search result, and it is also the block most themes get almost right.

An annotated JSON-LD Product block for a Shopify product page A twenty-two line JSON-LD script showing a Product with name, sku, image, an Offer carrying price, priceCurrency and availability, and an AggregateRating carrying ratingValue and reviewCount. Four callouts explain which fields Google requires, that price, currency and availability are required together, that aggregateRating is only permitted for first-party reviews, and that images should be at least 1600px on the long edge. Product schema, line by line Emitted from the theme, in the document head of a product template 123 456 789 101112 131415 161718 192021 22 <script type="application/ld+json"> { "@context": "https://schema.org", "@type": "Product", "name": "House Blend Whole Bean, 1kg", "sku": "NB-HB-1000", "image": [ "https://cdn.shopify.com/.../hb-1600.jpg" ], "offers": { "@type": "Offer", "price": "24.00", "priceCurrency": "GBP", "availability": "https://schema.org/InStock" }, "aggregateRating": { "@type": "AggregateRating", "ratingValue": "4.7", "reviewCount": "812" } } </script> WHAT EACH PART BUYS YOU "@type": "Product" The line that makes it a product rich result rather than an ignored blob of JSON. price + priceCurrency + availability All three or none. Miss one and the price stops rendering in the snippet entirely, which is the single most common fault we find. aggregateRating Only for reviews collected on your own site, by real customers. Marking up ratings you have not earned is the one error here with a penalty on it. image, as an array Shopify CDN URLs, 1600px or more on the long edge. Smaller images are quietly dropped. Before you paste any of this in Check what your theme already emits. Two Product blocks on one page is a more common fault than none, and it is the subject of the audit below.
The fields Google actually reads, and the three that have to travel together. Miss priceCurrency and the price disappears from the snippet entirely. No error, no warning, just a result that looks like everybody else's.

The trap in that block is availability. It takes a schema.org URL, not a description. It wants https://schema.org/InStock, not the words "In stock". Themes get this wrong constantly, and because the block still validates as a Product, nothing tells you the stock line is silently not rendering.

Organization and breadcrumbs, the cheap wins

Organization is one block, added once, sitewide. Name, logo, URL, and a sameAs array pointing at the social profiles you actually run. It is what a knowledge panel is assembled from, and it takes about twenty minutes on a store that has never had it.

BreadcrumbList is nearly as cheap and does one visible job: it replaces the raw URL under a result with a readable trail. On a store with deep collection nesting that is the difference between a result showing /collections/whole-bean/products/house-blend-1kg and one showing Home › Coffee › Whole Bean.

Reviews and AggregateRating, and the one rule with teeth

Star ratings in a search result come from aggregateRating, and this is the only part of schema markup where getting it wrong is treated as a policy problem rather than a technical one.

The rule: the ratings have to be from reviews collected on your own site, from real customers, and a person looking at the page has to be able to see them. Importing a supplier's average, marking up reviews of the brand rather than the product, or inventing the numbers outright are all the same offence with the same outcome. If you run a review app, it is almost certainly emitting this block already, which brings us to the audit further down.

Collections, articles and FAQs

Collection pages are the most under-marked-up surface on a typical store. A CollectionPage containing an ItemList of the products on it tells a shopping assistant what the page is a list of, which is exactly the question those tools are trying to answer.

On the blog, Article with a real author does two jobs: the blog rich result, and an authorship signal that matters more now than it did, because generative engines lean on identifiable authorship when deciding what to cite.

FAQPage is the interesting one. The visible FAQ rich result is rare in 2026 and if the SERP appearance were the only prize it would not be worth the markup. It is worth it because AI answers quote question and answer pairs more or less verbatim, and this is one of very few ways to hand a machine a fact in a form it will reproduce accurately.

Actually adding it to a Shopify theme

Three routes, and the right one depends less on the store's size than on who is going to maintain it.

Theme code. A snippet rendered into theme.liquid, built from Liquid objects so the values track the product rather than being typed once and forgotten. Full control, no monthly cost, and it needs somebody who will remember it exists at the next theme upgrade.

A schema app. Faster, maintained by somebody else, and the good ones handle the duplicate problem for you with a microdata filter. The cost is a monthly fee and a layer you do not control.

Built as part of the theme, by a developer. What we do on Plus builds, because at that size the markup has to handle Markets, B2B pricing and multiple currencies, and no app models that well.

The duplicate-schema audit, which is where to start

If you read one section of this, read this one. The most common schema fault we find on a Shopify store is not missing markup. It is two sources of the same markup, disagreeing.

Two competing sources of Product schema on one Shopify page On the left, theme microdata declaring a price of 92 pounds and OutOfStock. On the right, a schema app's JSON-LD declaring 24 pounds and InStock. The conflict panel lists three disagreements. Two likely outcomes follow: no rich result rendered at all, or the wrong fact winning. The fix is to keep one source of truth. The duplicate-schema audit When the theme and an app both emit Product schema, Google reads two different stores. SOURCE 1 · theme.liquid, microdata <div itemscope itemtype="schema.org/Product"> <meta itemprop="name" content="House Blend"/> <meta itemprop="price" content="29.00"/> <meta itemprop="priceCurrency" content="GBP"/> <meta itemprop="availability" content="OutOfStock"/> </div> SOURCE 2 · a schema app, JSON-LD <script type="application/ld+json"> { "@type": "Product", "name": "House Blend Whole Bean, 1kg", "offers": { "@type": "Offer", "price": "24.00", "availability": "InStock" } } </script> CONFLICT £29.00 against £24.00 OutOfStock against InStock and two Product entities where there is one product WHAT GOOGLE DOES NEXT Outcome A: nothing renders Handed two answers, Google declines to pick one. The listing falls back to a plain blue link and you never find out why, because nothing errored. Outcome B: the wrong one wins The stale theme value reaches the SERP. Shoppers see a price you do not charge, or Out of stock on a product you are sitting on pallets of. The fix: one source of truth Either strip the theme's microdata, or turn on the app's microdata filtering so it suppresses it. Pick one. Do not try to keep both in step by hand.
A theme and an app both declaring the same product, at two different prices, in two different stock states. Both blocks are individually valid. Together they are worse than neither.

It happens because markup accumulates. The theme has always emitted Product microdata. Someone installed an SEO app in 2023 that adds its own JSON-LD. The review app adds an aggregateRating. None of the three knows about the others, and nothing in Shopify warns you.

The audit is short: view source on a product page, search for itemtype and for application/ld+json, and count the Product entities. More than one is the job. The fix is always the same: choose which source owns it, and suppress the rest.

Validating it, and what a clean run looks like

Google's Rich Results Test takes a URL and tells you what it found. Run it on one product page and one collection page before you change anything, and again after.

A Rich Results Test run on a Shopify product page Google's Rich Results Test reporting a page eligible for rich results: five valid items detected, zero errors, one warning. Product snippets, breadcrumbs, FAQ and Organization are all marked valid. A fifth item, theme-generated Product microdata, carries a duplicate warning. Rich Results Test: a clean run search.google.com/test/rich-results · run it before you believe anything Tested URL https://northboundcoffee.co.uk/products/house-blend-1kg Page is eligible for rich results 5 valid items detected · 0 errors · 1 warning PREVIEW: HOW GOOGLE MAY RENDER IT northboundcoffee.co.uk House Blend Whole Bean Coffee, 1kg ★★★★★ 4.7 (812) · £24.00 · In stock Single-origin Brazilian arabica, roasted to order in Cornwall. Ships within 48 hours of roasting. Home › Coffee › Whole Bean DETECTED ITEMS ✓ Product snippets 1 valid item · name, sku, image, offers, aggregateRating VALID ✓ Breadcrumbs 3 list items · Home › Coffee › Whole Bean VALID ✓ FAQ 3 question and answer pairs VALID ✓ Organization logo · sameAs · contactPoint VALID ! Product, theme-generated Duplicate microdata detected: decide which source wins WARNING Zero errors is the bar. A warning is not a pass with an asterisk, it is the next job, and on Shopify it is almost always the duplicate below.
Zero errors is the bar. A warning is not a pass with an asterisk, and on Shopify the warning is nearly always the duplicate markup above.

After that, Search Console's Enhancements reports are where problems turn up at scale, because they read your whole catalogue rather than the one URL you thought to test. Worth a look once a quarter, and worth a look immediately after any theme update.

This is the part that has changed since most schema advice was written. Structured data used to be a way to get a nicer-looking search result. It is now also the most reliable way to hand a generative engine a fact it will repeat correctly.

An AI shopping answer, with each fact traced to the schema field behind it A generated shopping answer recommending a coffee product. Six facts in the answer are traced to their sources: the price to Offer.price, the stock status to Offer.availability, the rating and review count to AggregateRating, the weight to Product.weight, the roast date claim to a FAQPage answer, and the SKU to Product.sku. Schema is what an AI answer quotes from The same markup, read by a shopping assistant rather than a crawler THE QUESTION best whole bean coffee under £25 for a 1kg bag THE ANSWER Northbound Coffee’s House Blend is the closest match at £24.00 for 1kg. It is rated 4.7 out of 5 across 812 reviews, is in stock, and is roasted to order rather than held in a warehouse. The roaster ships within 48 hours. [1] northboundcoffee.co.uk Not one of those facts came from reading the page copy. Every one of them was already declared, in a machine-readable form, in the head of the document. WHERE EACH FACT CAME FROM £24.00 ← Offer.price In stock ← Offer.availability 4.7 / 812 ← AggregateRating 1kg ← Product.weight 48 hours ← FAQPage answer the product ← Product.sku A page with no structured data is not invisible to these tools. It is just harder to quote, and quoting is how they cite. We have deliberately put no percentage on this figure. The lift numbers circulating for structured data are vendor-published and we have not been able to verify any of them. The mechanism above is the part that is checkable.
Every fact in that answer was declared in the document head before the assistant ever read the page copy. We have put no percentage on this figure deliberately: see the note at the foot of it.

The practical consequence is that completeness matters more than it used to. A partial Product block still produced a decent rich result, because Google filled the gaps from the page. An assistant asked for a recommendation under twenty-five pounds either has your price as a declared number or it does not. This is the same argument our GEO work and AI SEO work rest on, approached from the plumbing rather than the strategy.

Plus, B2B and Markets

Three complications that only appear at the larger end, and all three break naive markup.

Markets. A store selling in several currencies needs the priceCurrency in the markup to match the currency the page is actually rendering, per locale. Hardcode GBP and every localised page declares the wrong currency.

B2B. Catalogue-specific pricing means the price a logged in wholesale customer sees is not the price to declare publicly. The markup should carry the retail price, or none.

Headless. If the storefront is Hydrogen or custom, the markup is your application's job entirely and no theme is emitting anything. That is more freedom and one more thing to remember at launch.

The errors we find most often

  • priceCurrency missing, so the price never renders.
  • availability set to the words "In stock" rather than a schema.org URL.
  • Two Product entities on one page, from the theme and an app.
  • Images below 1600px on the long edge, or pointing at a 404.
  • priceValidUntil left at a date that has passed.
  • Review markup for reviews that are not visible on the page.
  • Organization declared on every page with a different logo URL.

What we would actually do first

  • Run the Rich Results Test on one product page and one collection page. Read what is already there before adding anything.
  • Find every source of Product markup: the theme, the SEO app, the review app. Pick one. Suppress the rest.
  • Complete the Product block: price, priceCurrency and availability together, image at 1600px or more.
  • Add Organization once, sitewide, with logo and sameAs. It is the cheapest thing on this list.
  • Add BreadcrumbList sitewide, then stop and re-validate before going near anything else.

That is a morning on most stores, and it covers the majority of what schema markup can do for a Shopify catalogue. Everything past it has real but smaller returns. If it turns into a development job rather than an editing job, or the catalogue is large enough that the decisions have to be structural, that is where our Shopify SEO work earns its cost. The on-page half of the same subject is in product page SEO.

Common questions

Does Shopify add schema markup automatically?
Partly, and the partly is the problem. Nearly every modern theme emits some Product markup, and most emit Organization and Breadcrumb too. What themes tend to miss are the fields that actually produce the visible result: priceCurrency, a schema.org availability URL rather than the word "In stock", and review data. So the honest starting position is not "we have none", it is "we have some, and nobody has checked what".
How do I get Shopify Google rich snippets to show?
Three things have to be true at once. The markup has to be valid, which the Rich Results Test will tell you in about ten seconds. It has to be complete for the result you want, which for a price snippet means price, priceCurrency and availability all present together. And it has to be the only markup of its type on the page, because two Product blocks disagreeing about the price is the most common reason a technically valid page renders as a plain blue link. Even then Google chooses whether to show a rich result; eligibility is not a guarantee.
Schema, Shopify themes and apps: which one should own the markup?
One of them, and which one matters less than that it is only one. If you already pay for a schema app, the usual answer is to let it own everything and turn on its microdata filtering so it suppresses the theme output. If you do not, strip the app and let the theme own it, filling the gaps in the theme code. The failure mode is not having too much markup, it is having two sources that drift apart the first time a price changes.
Is FAQ schema still worth adding in 2026?
For most stores the visible FAQ rich result is rare now, so if the only reason to add it is the SERP appearance then no. The reason to add it anyway is that AI answers quote it. A well-formed question and answer pair is the easiest thing in the world for a generative engine to lift and cite, and it is one of the few places you can put a fact on a page in a form a machine will reproduce verbatim.
Can marking up reviews get a store penalised?
Marking up reviews you have not earned can, yes. The rule with actual teeth is that aggregateRating has to come from reviews collected on your own site, from real customers, and that the ratings are visible to a person on the same page. Inventing a 4.9 across 300 reviews, or importing a supplier average, is the one error in this whole area that is treated as a manual-action problem rather than a warning.
Is Liquid section schema the same thing?
No, and the name collision causes real confusion. The schema block inside a Liquid section file defines the settings a merchant sees in the theme editor. Schema.org structured data is JSON-LD in the document head and is aimed at search engines. Same word, no relationship. If a developer tells you the theme "has schema", establish which one they mean before drawing any conclusion.

Get in touch

Tell us about your store or your business and we'll reply personally. No wizard, no ten questions.

Stores we build and grow

  • Wuka
  • Art Martial Clothing
  • Citizen M
  • Black Sand
  • Waldo
  • Botanivie
  • Ebony Ivory Interiors
  • Lifestyle Home Collection
  • Nour Hammour
  • Owen Drew Candles
  • Poppy Elder
  • Sculpt Activewear
  • Snatchd
  • Venyx World
  • Tacky And Upsetting
  • Knack Snacks
  • Givino
  • Natalie's Heating Service
  • Bordeaux12
  • Ginny Litscher
  • Seko Logistics
  • La Sura Bakery
  • Meta Mortgages
  • Cream Cornwall
  • Skye McAlpine Tavola
  • The Little Shop of Olive Oils
  • Bessette
  • Powerlete
  • Fittr Nutrition
  • Smart Surfacing Solutions
  • Caorunn Gin

We'll reply personally and keep a record of your enquiry, and send the occasional ecommerce and AI email -- unsubscribe any time. See our privacy policy.

Prefer just to hear when we publish?
Get in touch