SEO GEO E-commerce Practical guide
Structured data for an e-shop: what to add, in what order
Organization, Product/Offer, BreadcrumbList, FAQPage, Review: what Google gives an online store today, which fields are required, with copy-paste JSON-LD.
On this page
- The short answer
- What Google gives an online store today
- 1. Organization: one, the same everywhere
- 2. Product and Offer: the page that sells
- 3. BreadcrumbList: cheap, and usually already there
- 4. FAQPage: what’s left after the retirement
- 5. Review and AggregateRating: only with genuine reviews
- Five mistakes we find often
- What about PrestaShop modules?
- What to do tomorrow
Structured data is one of the few parts of SEO that feels like a setting: it goes into the theme once and works for every product. That is also why it attracts so many overpromises. Someone promises stars Google won’t show, someone else promises FAQ snippets that no longer exist. And a plugin adds a second Product on top of the one the platform already outputs.
In this article we put an e-shop’s schema in order of priority, based on Google’s documentation as it stood in September 2026. For each one you get copy-paste JSON-LD. We also show what a real PrestaShop store, antoniadis.com.cy, actually outputs, mistakes included. A real store’s mistakes teach more than a perfect example.
The short answer
- The order: Organization → Product/Offer → BreadcrumbList → FAQPage → Review. The first two do most of the work.
- Product with an Offer matters most. Required for merchant listings:
name,image, andofferswithpriceandpriceCurrency. Everything else is “recommended”, but without it you lose information Google shows in results. - FAQ rich results are gone. Since 7 May 2026 Google shows them on no site at all. FAQPage costs little and does no harm, but it changes nothing about how you appear in Google.
- No schema is “for AI”. Google says no special markup is needed for AI Overviews. What helps is correct data that matches the page.
- The most common mistake isn’t missing markup. It is markup declared twice, or markup that says something different from the page.
What Google gives an online store today
Before you write a line of code, it’s worth knowing what you get back. From Google’s documentation on merchant listings, product snippets, review snippets, Organization and the changelog:
| Schema | What it gives you in Google | Required fields | Status (09/2026) |
|---|---|---|---|
| Organization / OnlineStore | Logo, details in the merchant knowledge panel, store-wide return and shipping policy | None, but the more the better | Active |
| Product + Offer (merchant listing) | Price, availability, shipping and returns in results and the Shopping tab | name, image, offers.price, offers.priceCurrency | Active, last updated 07/2026 |
| Product (product snippet) | Stars, price, availability under the title | name plus one of offers, review, aggregateRating | Active |
| BreadcrumbList | Category trail instead of the URL | itemListElement with position, name, item | Active |
| AggregateRating / Review | Stars on the product | ratingValue plus ratingCount or reviewCount | Active, not for reviews of the business itself |
| FAQPage | Nothing in Google any more | — | Rich result retired 7 May 2026 |
Two notes. First, merchant listings only apply to pages where the customer can buy directly. If your site is a catalogue without a cart, you’re in product snippets. Second, Google notes that the price must be greater than zero. A “price on request” product marked up with price: 0 doesn’t qualify.
1. Organization: one, the same everywhere
This is the schema that says who is selling. Google suggests putting it on the homepage or the About page. If your theme outputs it on every page, that’s fine, as long as it’s identical everywhere. Since June 2024 Google accepts your store’s return policy here, and since November 2025 your shipping policy too. So you don’t have to repeat them on every Offer. For an e-shop, use the OnlineStore subtype:
{
"@context": "https://schema.org",
"@type": "OnlineStore",
"@id": "https://www.example.com.cy/#organization",
"name": "The Store",
"url": "https://www.example.com.cy/",
"logo": "https://www.example.com.cy/img/logo.png",
"sameAs": ["https://www.facebook.com/thestore"],
"contactPoint": {
"@type": "ContactPoint",
"contactType": "Customer Service",
"email": "[email protected]",
"telephone": "+357-22-000000"
},
"vatID": "CY00000000X",
"hasMerchantReturnPolicy": {
"@type": "MerchantReturnPolicy",
"applicableCountry": "CY",
"returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
"merchantReturnDays": 14,
"returnMethod": "https://schema.org/ReturnByMail",
"returnFees": "https://schema.org/ReturnShippingFees",
"refundType": "https://schema.org/FullRefund"
}
}
The @id is what lets other schema point to this entity without writing it out again. That’s how we do it on pythia.works: the Organization is written in one place, the shared layout, with the @id https://pythia.works/#organization, and the homepage’s WebSite points to it as publisher instead of repeating it. Put in your own return window and fees. If the policy page says 14 days and the schema says 30, the mistake is yours, not Google’s.
2. Product and Offer: the page that sells
This is the schema worth the most time. PrestaShop, WooCommerce and Shopify already output some version of it. So the job is rarely to add it. The job is to check what’s missing. A complete product page looks like this:
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Arduino UNO R4 Minima",
"description": "Arduino UNO R4 Minima board with an RA4M1 Cortex-M4 at 48MHz, 256kB Flash, CAN bus and USB-C.",
"image": [
"https://www.example.com.cy/img/arduino-uno-r4-minima-1.jpg",
"https://www.example.com.cy/img/arduino-uno-r4-minima-2.jpg"
],
"sku": "ARD017",
"mpn": "ABX00080",
"gtin13": "0000000000000",
"brand": { "@type": "Brand", "name": "Arduino" },
"category": "Arduino boards",
"offers": {
"@type": "Offer",
"url": "https://www.example.com.cy/arduino-uno-r4-minima",
"price": "29.95",
"priceCurrency": "EUR",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"seller": { "@id": "https://www.example.com.cy/#organization" }
}
}
gtin13 is the product’s EAN barcode. Include it only if you know it, not with zeros as in the example. price uses a dot and no currency symbol, even if the page shows “€29,95”.
What does a store actually output? On the page for this exact product on antoniadis.com.cy, PrestaShop’s native Product has name, description, image, sku, mpn, brand, category, and an Offer with price, currency, availability and priceValidUntil. That’s a good base. Missing are itemCondition, the GTIN, and any return or shipping policy, on either the Offer or the Organization. And the policies are exactly what Google can show next to the price.
3. BreadcrumbList: cheap, and usually already there
The trail “Home › Robotics › Arduino › Boards” helps Google understand your category structure and show it in place of the URL. Most themes already output it. What’s worth checking is whether they output it once:
{
"@context": "https://schema.org",
"@type": "BreadcrumbList",
"itemListElement": [
{ "@type": "ListItem", "position": 1, "name": "Home", "item": "https://www.example.com.cy/" },
{ "@type": "ListItem", "position": 2, "name": "Robotics & STEM", "item": "https://www.example.com.cy/robotics/" },
{ "@type": "ListItem", "position": 3, "name": "Arduino UNO R4 Minima" }
]
}
The last item, the page you’re on, doesn’t need an item. On pythia.works the BreadcrumbList is generated by the same component that draws the trail on the page. So the visible and the structured version can never disagree, because they have one source.
4. FAQPage: what’s left after the retirement
This needs honesty, because there are still guides promising FAQ snippets. In August 2023 Google limited FAQ rich results to well-known government and health sites. On 8 May 2026 it announced that they would stop appearing entirely from 7 May 2026, and in June it removed their documentation. Today FAQPage produces no rich result, on any site.
Is it still worth it? It costs little, it is valid schema.org, and nobody penalises you for having it. The only value left is that it makes your questions and answers machine-readable for whatever tool reads them. That’s part of GEO. But be careful: no major AI provider has stated that it uses FAQPage, and Google’s guide to AI features says explicitly that no special schema is needed. What counts is the visible text of the questions on the page, as we explain in the guide on how to prepare your site for AI search. The schema is just the label on top.
{
"@context": "https://schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": "Is it compatible with UNO R3 shields?",
"acceptedAnswer": {
"@type": "Answer",
"text": "Yes, it has the same form factor and pin layout as the UNO R3."
}
}
]
}
5. Review and AggregateRating: only with genuine reviews
Stars are the most visible rich result a product has left, and so the most misunderstood. Google’s rules: ratings must come from users, must be visible on the page, and fake or undisclosed incentivised reviews are prohibited. On top of that, reviews of the business itself, managed on your own site, don’t earn stars for the Organization. Google treats them as self-serving. On a Product, though, they work as normal:
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.6",
"reviewCount": "23"
}
This block goes inside the Product. If you don’t have a review system, don’t add it. It comes last precisely because it depends on something you can’t write in code.
Five mistakes we find often
We found 1, 2 and 4 on antoniadis.com.cy, and 3 is the risk we watch for when we work on it. They aren’t a developer’s mistakes. They’re what the theme and the platform produce if nobody checks them.
- The same thing declared twice. The theme outputs BreadcrumbList as JSON-LD and, at the same time, as microdata on the visible menu. Google accepts both formats, so it isn’t a violation. But it’s two sources for the same data, and the day one of them changes they’ll disagree. Keep only the JSON-LD.
- An empty
"description": "". PrestaShop takes the Product description from the product’s short description. Where that’s missing, it outputs an empty string instead of leaving the field out. The fix isn’t in the code: write short descriptions. It’s also the first thing the customer reads. - A second Product on top of the native one. An SEO module that “adds rich snippets” to a PrestaShop store that already outputs Product creates two Products on the same page, often with different prices or availability. Before installing one, open the source of a product page and search for
"@type": "Product". If it’s already there, fix the existing one instead of adding another. - HTML entities inside JSON. On the same page, the Greek breadcrumb reads
"Ρομποτική & STEM". JSON-LD isn’t HTML, so whatever parses it sees a literal&. It’s a small error, but it shows the template escapes text for HTML instead of JSON. - Markup that disagrees with the page. A sale price on the page and the old price in the schema, “In stock” in the schema and “Sold out” on the button, stars with no visible reviews. Google requires markup to describe what the visitor sees, and a mismatch can make you ineligible for rich results. It usually comes from caching, or from a module that rewrites the price only in the visible part.
For the last two, the simplest check is Google’s Rich Results Test on three or four pages: a product on sale, a sold-out one, and one with variants.
What about PrestaShop modules?
None of our ready-made PrestaShop modules touch structured data. So they won’t create a second Product for you. For the schema itself, in most cases you don’t need a module. You need a fix in the theme template, which survives updates if it’s done in a child theme.
What to do tomorrow
Open one product page in the Rich Results Test and count how many Products you see. If it’s one, check that it has an image, price, currency and availability, and that the price matches the page. Then add your return policy to the Organization. It’s the one piece most stores don’t have at all.
If you’d rather have someone else look, the free mini-audit checks five product pages, and the full €390 audit includes a structured data review. Fixing it in your theme costs from €290. If you’re building a store from scratch, ask your developer which of the above is included before you sign. It’s one of the things behind the spread of prices in our article on how much a website costs in Cyprus. And once you’ve decided which AI crawlers get to read this data, the guide to llms.txt and AI crawlers is the next step.