Rich Data for Magento 2 — module reference
Rich Data adds structured data (JSON-LD) to your Magento 2 pages. It writes one linked @graph per page, so ChatGPT, Gemini, Perplexity and Google read your catalog as connected data, not as loose pieces.
Every node has a stable @id. For example, offers.seller points to the same Organization on every page, instead of repeating a name.
Schema it adds
| Schema | Pages | Main fields |
|---|---|---|
Product | Product pages | name, description, image, sku, gtin/mpn, brand, offers, aggregateRating |
ProductGroup | Configurable products | hasVariant, variesBy, productGroupID, an offer per variant |
Organization | All pages | name, description, url, logo, sameAs, contactPoint |
WebSite | Homepage | name, url, publisher |
BreadcrumbList | Product, category, CMS pages | full trail |
CollectionPage | Category pages | ItemList of the products on the current page |
FAQPage | CMS pages you choose | question and answer pairs |
Prices follow the store’s tax display setting, so the price in the markup matches the price on the page. Configurable, grouped and bundle products publish an AggregateOffer with lowPrice and highPrice.
What it fixes in AEO Audit
| Signal | Before | After |
|---|---|---|
| Product schema | Fail / warn | Pass |
| Merchant policies | Fail | Pass, once you turn it on and fill it in |
| Product rating | Warn | Pass, when reviews exist |
| JSON-LD quality — breadcrumbs | Warn | Pass |
| FAQPage schema | Warn | Pass, on the pages you choose |
Requirements
| Magento | 2.4.x (Open Source, Mage-OS or Adobe Commerce) — magento/framework >=103.0.0 |
|---|---|
| PHP | 8.2 – 8.5 — ~8.2.0||~8.3.0||~8.4.0||~8.5.0 |
Installation
composer require angeo/module-rich-data
bin/magento module:enable Angeo_RichData
bin/magento setup:upgrade
bin/magento setup:di:compile # production mode only
bin/magento cache:flush
Coming from 1.x? Read UPGRADE.md in the repository first. The markup shape changes, and prices become tax-inclusive on stores that show prices with VAT.
Example output
{
"@context": "https://schema.org",
"@graph": [
{ "@type": "Organization", "@id": "https://shop.example/#organization", "name": "Example Store" },
{
"@type": "Product",
"@id": "https://shop.example/alpine-jacket.html#product",
"name": "Alpine Jacket",
"offers": {
"@type": "Offer",
"price": "121.00",
"priceCurrency": "EUR",
"availability": "https://schema.org/InStock",
"seller": { "@type": "Organization", "@id": "https://shop.example/#organization" }
}
},
{ "@type": "BreadcrumbList", "@id": "https://shop.example/alpine-jacket.html#breadcrumb" }
]
}
Prefer one script tag per schema, as in 1.x? Set General → Output mode to One script tag per schema.
Setting it up
- Open Stores → Configuration → Angeo → Rich Data (JSON-LD).
- In Organization schema, add a one- or two-sentence description, a logo URL (512×512 PNG works well) and your social profile URLs. AI engines use this as the summary of your brand.
- In Product schema, turn on Include Brand and choose the attribute. If you have barcodes, turn on GTIN / MPN and choose those attributes too.
- Only when your real return window, shipping cost and delivery times are known, turn on Merchant policies. The default country is
US— change it to the countries you ship to. - For FAQ pages, list the CMS page identifiers. Empty means any identifier that contains “faq”.
- Check the result with the CLI command below.
Wrong policy values can hurt your eligibility in Google and ChatGPT Shopping. Leave Merchant policies off until the values are true.
FAQ markup on CMS pages
Data attributes are the reliable way:
<div data-faq-question="What is your return policy?"
data-faq-answer="We offer 30-day returns on all items in original condition.">
</div>
Without them, the module looks for an <h2> or <h3> followed by a <p>. The homepage is never treated as an FAQ page.
Google shows FAQ rich results only for government and health sites. Treat FAQPage as content for AI answer engines, not as a Google feature.
Checking the output
bin/magento angeo:rich-data:validate --store=default
bin/magento angeo:rich-data:validate --store=default --product-id=42
bin/magento angeo:rich-data:validate --category-id=11
bin/magento angeo:rich-data:validate --cms-identifier=faq
bin/magento angeo:rich-data:validate --json | jq .
| Command | What it does |
|---|---|
bin/magento angeo:rich-data:validate | Validate the JSON-LD output for a product, category or CMS page. |
The exit code is non-zero when a node has no @id, an offer is incomplete, or two nodes collide. You can use it in CI.
Configuration reference
All settings are under Stores → Configuration → Angeo → Rich Data (JSON-LD). The table shows each field, its config path (for bin/magento config:set) and its default value.
General (2)
| Setting | Config path | Default |
|---|---|---|
| Enabled | angeo_rich_data/general/enabled | Yes |
| Output mode | angeo_rich_data/general/output_mode | graph |
Product schema (15)
| Setting | Config path | Default |
|---|---|---|
| Enabled | angeo_rich_data/product/enabled | Yes |
| Include AggregateRating | angeo_rich_data/product/include_aggregate_rating | Yes |
| Include SKU | angeo_rich_data/product/include_sku | Yes |
| Include Brand | angeo_rich_data/product/include_brand | No |
| Brand attribute code | angeo_rich_data/product/brand_attribute | manufacturer |
| Item condition | angeo_rich_data/product/condition | NewCondition |
| Include GTIN / MPN identifiers | angeo_rich_data/product/include_identifiers | No |
| GTIN attribute code | angeo_rich_data/product/gtin_attribute | — |
| MPN attribute code | angeo_rich_data/product/mpn_attribute | — |
| Publish configurable products as ProductGroup | angeo_rich_data/product/include_variants | Yes |
| Maximum variants per product | angeo_rich_data/product/max_variants | 20 |
| priceValidUntil window (days) | angeo_rich_data/product/price_valid_days | 365 |
| In-stock availability URL | angeo_rich_data/product/availability_in_stock | https://schema.org/InStock |
| Out-of-stock availability URL | angeo_rich_data/product/availability_out_of_stock | https://schema.org/OutOfStock |
| Include BreadcrumbList (deprecated) | angeo_rich_data/product/include_breadcrumb | Yes |
Breadcrumb schema (1)
| Setting | Config path | Default |
|---|---|---|
| Enabled | angeo_rich_data/breadcrumb/enabled | Yes |
Merchant policies (return and shipping) (11)
| Setting | Config path | Default |
|---|---|---|
| Enable return policy | angeo_rich_data/merchant_policies/return_enabled | No |
| Return window (days) | angeo_rich_data/merchant_policies/return_days | 30 |
| Applicable country | angeo_rich_data/merchant_policies/return_country | US |
| Return fee | angeo_rich_data/merchant_policies/return_fee | FreeReturn |
| Enable shipping details | angeo_rich_data/merchant_policies/shipping_enabled | No |
| Flat shipping rate | angeo_rich_data/merchant_policies/shipping_rate | 0 |
| Shipping destination country | angeo_rich_data/merchant_policies/shipping_country | US |
| Handling time, min days | angeo_rich_data/merchant_policies/handling_days_min | — |
| Handling time, max days | angeo_rich_data/merchant_policies/handling_days_max | — |
| Transit time, min days | angeo_rich_data/merchant_policies/transit_days_min | — |
| Transit time, max days | angeo_rich_data/merchant_policies/transit_days_max | — |
Organization schema (7)
| Setting | Config path | Default |
|---|---|---|
| Enabled | angeo_rich_data/organization/enabled | Yes |
| Organization name | angeo_rich_data/organization/name | — |
| Organization description | angeo_rich_data/organization/description | — |
| Logo URL | angeo_rich_data/organization/logo | — |
| sameAs URLs | angeo_rich_data/organization/same_as | — |
| Contact telephone | angeo_rich_data/organization/contact_telephone | — |
| Contact type | angeo_rich_data/organization/contact_type | customer service |
WebSite schema (2)
| Setting | Config path | Default |
|---|---|---|
| Enabled | angeo_rich_data/website/enabled | Yes |
| Include SearchAction | angeo_rich_data/website/include_searchaction | No |
CollectionPage schema (categories) (1)
| Setting | Config path | Default |
|---|---|---|
| Enabled | angeo_rich_data/collection_page/enabled | Yes |
FAQPage schema (2)
| Setting | Config path | Default |
|---|---|---|
| Enabled | angeo_rich_data/faq/enabled | Yes |
| CMS page identifiers | angeo_rich_data/faq/cms_identifiers | — |
Notes on a few settings:
- WebSite → SearchAction is off by default. Google removed the sitelinks search box in November 2024, so it gives no Google feature. It stays for other consumers.
- CollectionPage follows paging and sort order. It does not reflect layered navigation filters, because they are not ready when the page head renders.
Adding your own schema
Implement Angeo\RichData\Api\Data\SchemaInterface and register the builder:
<type name="Angeo\RichData\Model\JsonLd\Renderer\SchemaRenderer">
<arguments>
<argument name="builders" xsi:type="array">
<item name="my_schema" xsi:type="object">Vendor\Module\Model\JsonLd\Builder\MySchemaBuilder</item>
</argument>
</arguments>
</type>
Give your root node an @id and it joins the graph like the built-in schemas.
FAQ
Will it clash with my theme’s JSON-LD?
It can, if your theme or another module also prints Product or Organization schema. Run the validate command and the AEO Audit JSON-LD quality check. Remove the duplicate source you do not need.
Why are merchant policies off by default?
Because wrong values can hurt your eligibility. Turn them on only when your return window, shipping cost and delivery times are correct.
Does it support configurable products?
Yes. They are published as ProductGroup with one offer per variant, up to the variant limit you set (hard limit 50).
Does it work with Hyvä?
Yes. The suite modules support Hyvä, and JSON-LD is printed in the page head.
Why do my prices include tax in the markup?
Prices follow the store’s tax display setting, so the markup matches the price a shopper sees. Since 2.0.0 that means tax-inclusive prices on stores that display VAT.
Related
- AEO Audit — score 20 AI-visibility signals from the command line
- llms.txt — generate llms.txt, llms.jsonl, Markdown mirrors and agents.md
- OpenAI Product Feed — the ChatGPT product feed CSV per store view, for all product types
- All module reference pages · Compatibility matrix
This page was written from the README.md, composer.json and etc/*.xml files of tag 2.0.0, read on 16 October 2026. Settings, commands and defaults come straight from that code. If a newer release is out, the README on GitHub wins.