惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
A
About on SuperTechFans
Engineering at Meta
Engineering at Meta
宝玉的分享
宝玉的分享
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 叶小钗
WordPress大学
WordPress大学
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
Stack Overflow Blog
Stack Overflow Blog
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 聂微东
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Blog — PlanetScale
Blog — PlanetScale
T
Tailwind CSS Blog
Recent Announcements
Recent Announcements
Jina AI
Jina AI
大猫的无限游戏
大猫的无限游戏
Apple Machine Learning Research
Apple Machine Learning Research
J
Java Code Geeks

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
Magento 2 Product JSON-LD Schema for AI Search — Complete...
Ievgenii Gry · 2026-05-05 · via DEV Community

Even if your Magento store ranks well in Google, it may still not appear in AI-generated product results (ChatGPT, Gemini, Perplexity).

A common reason is missing or incomplete Product schema.

AI systems rely on structured data to extract pricing and availability. When that data is missing or inconsistent, products may not be eligible for inclusion. This guide covers what is typically missing, why, and how to fix it.

TL;DR:

  • Magento 2 outputs microdata by default; JSON-LD is generally more reliable and easier for parsers to consume
  • Missing offers.availability is a common issue that breaks product eligibility for AI-powered shopping results
  • Schema injected via GTM is often not visible to non-JavaScript crawlers
  • Hyvä Theme does not include product schema out of the box

What is AI Search?

By "AI search" we refer to systems like ChatGPT browsing (via OAI-SearchBot), Google AI Overviews, Gemini, and Perplexity that extract structured data from pages to generate answers and product listings.

Unlike traditional search engines that primarily rank links, these systems rely more heavily on structured data like JSON-LD to understand product details — price, availability, ratings — rather than inferring them from HTML layout.

Magento 2 Product JSON-LD Schema for AI Search — Complete Guide

Before vs After: Schema and AI Eligibility

Setup ChatGPT Shopping Gemini Perplexity
No schema ❌ Not eligible / rarely shown ❌ Not eligible ❌ Rarely cited
Microdata only (Luma default) ⚠️ Partially parsed ⚠️ Inconsistent ⚠️ Inconsistent
JSON-LD, missing offers.availability ⚠️ Often fails eligibility check ⚠️ May appear ⚠️ May appear
Full JSON-LD + availability + rating ✅ Eligible for Shopping results ✅ Product results ✅ Cited with price

Why Magento 2 Falls Short for AI Schema

Default Luma theme outputs microdata — the older itemscope/itemprop HTML format:

<!-- Default Magento Luma — often insufficient for AI search -->
<div itemscope itemtype="http://schema.org/Product">
  <span itemprop="name">Product Name</span>
  <div itemprop="offers" itemscope itemtype="http://schema.org/Offer">
    <span itemprop="price">49.99</span>
    <!-- offers.availability not present -->
  </div>
</div>

Enter fullscreen mode Exit fullscreen mode

Three issues worth addressing for AI search:

1. Microdata vs JSON-LD. JSON-LD is generally more reliable because it is self-contained and easier to parse compared to microdata embedded in HTML. Microdata is also more fragile when themes or extensions modify markup.

2. offers.availability is missing. This field tells AI systems whether a product can actually be purchased. Without a valid value, products may not pass eligibility checks for AI-powered shopping results.

3. JavaScript-rendered schema may not be indexed. While Google Search processes JS-rendered content reasonably well, many AI crawlers rely on the initial HTML response. Schema injected after page load (e.g. via GTM) is often not visible to these crawlers.

On GTM specifically: While Google Search may process JavaScript-rendered schema, many AI crawlers rely on the initial HTML response. If all your structured data comes from GTM, there's a good chance AI systems aren't seeing it — even if Google Rich Results Test passes.


Real Example

A Magento store with correct pricing but missing offers.availability:

  • Passed Google Rich Results Test ✅
  • Had valid microdata with price and name ✅
  • Did not appear consistently in AI-generated product listings ❌

After adding JSON-LD with "availability": "https://schema.org/InStock" and validating via curl (server-side output), the product became eligible for AI Shopping results.

This is the most common schema issue across Magento stores — and it takes about five minutes to fix.


The Copy-Paste Product JSON-LD

A spec-compliant block that covers all the fields AI systems look for:

<script type="application/ld+json">
{
  "@context": "https://schema.org/",
  "@type": "Product",
  "name": "Alpine Hiking Jacket",
  "description": "Waterproof 3-layer shell for alpine conditions.",
  "sku": "WB-004",
  "image": ["https://yourstore.com/media/catalog/product/jacket.jpg"],
  "brand": { "@type": "Brand", "name": "TrailMaster" },
  "offers": {
    "@type": "Offer",
    "priceCurrency": "EUR",
    "price": "189.99",
    "priceValidUntil": "2026-12-31",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition",
    "url": "https://yourstore.com/alpine-hiking-jacket.html",
    "seller": { "@type": "Organization", "name": "Your Store Name" }
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.6",
    "reviewCount": "38",
    "bestRating": "5",
    "worstRating": "1"
  }
}
</script>

Enter fullscreen mode Exit fullscreen mode


Required and Recommended Fields

Field Status Common mistake
@type: Product ✅ Required
name ✅ Required HTML tags in name string
offers.availability ✅ Required Text string instead of URI
offers.price ✅ Required "€189" instead of "189.99"
offers.priceCurrency ✅ Required Symbol instead of code EUR
image ⚠️ Recommended Relative URL instead of absolute
sku ⚠️ Recommended Often missing entirely
aggregateRating ⚠️ Recommended Including when reviewCount is 0 — causes validation error
brand ⚠️ Recommended Plain string instead of {"@type":"Brand","name":"..."}

offers.availability — full URI required

Status ✅ Correct ❌ Often rejected
In stock https://schema.org/InStock "In Stock" / "instock"
Out of stock https://schema.org/OutOfStock "Out of Stock"
Pre-order https://schema.org/PreOrder "preorder"
Back order https://schema.org/BackOrder "backorder"

The full schema.org URI is what the spec requires. Short strings are technically invalid — parsers may accept them or silently ignore them depending on the implementation.


Configurable Products — Use AggregateOffer

When individual variants have different availability states, it's cleaner to use AggregateOffer so AI systems can understand the full option matrix:

{
  "@type": "Product",
  "name": "Running Shoe",
  "offers": {
    "@type": "AggregateOffer",
    "offerCount": 8,
    "lowPrice": "89.99",
    "priceCurrency": "EUR",
    "availability": "https://schema.org/InStock",
    "offers": [
      {
        "@type": "Offer",
        "sku": "RS-42-BLK",
        "name": "Size 42 / Black",
        "availability": "https://schema.org/InStock",
        "price": "89.99",
        "priceCurrency": "EUR"
      },
      {
        "@type": "Offer",
        "sku": "RS-43-BLK",
        "name": "Size 43 / Black",
        "availability": "https://schema.org/OutOfStock",
        "price": "89.99",
        "priceCurrency": "EUR"
      }
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode


Hyvä Theme — No Schema Out of the Box

Hyvä Theme is built on Alpine.js and does not include Luma's product templates. This means Hyvä Theme does not include product schema out of the box in its default templates — neither microdata nor JSON-LD.

Verify quickly:

curl -s https://yourstore.com/sample-product.html | grep -c 'application/ld+json'
# Returns 0 → no JSON-LD

curl -s https://yourstore.com/sample-product.html | grep -c 'itemscope'
# Returns 0 → no microdata either

Enter fullscreen mode Exit fullscreen mode

The fix is to inject JSON-LD via layout XML so it's server-side rendered. Create Vendor_Theme/layout/catalog_product_view.xml:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <block class="Magento\Framework\View\Element\Template"
               name="product.json.ld"
               template="Vendor_Module::product/json-ld.phtml"/>
    </head>
</page>

Enter fullscreen mode Exit fullscreen mode

Schema in <head> via layout XML is part of the initial HTML response — visible to crawlers that don't execute JavaScript.

Alternatively, you can use an open-source module like angeo/module-rich-data (MIT) to generate schema automatically for both Luma and Hyvä.


Diagnosing Your Current Schema

This one-liner checks what schema your product pages actually output:

curl -s https://yourstore.com/sample-product.html | \
  python3 -c "
import sys, json, re
body = sys.stdin.read()
blocks = re.findall(r'<script[^>]+type=\"application/ld\+json\"[^>]*>(.*?)</script>', body, re.DOTALL)
for b in blocks:
    try:
        d = json.loads(b)
        items = d if isinstance(d, list) else [d]
        for item in items:
            nodes = item.get('@graph', [item])
            for n in nodes:
                if n.get('@type') in ('Product', 'IndividualProduct'):
                    print('FOUND Product schema')
                    offers = n.get('offers', {})
                    if isinstance(offers, list): offers = offers[0] if offers else {}
                    print('availability:', offers.get('availability', 'MISSING'))
                    print('price:', offers.get('price', 'MISSING'))
                    print('aggregateRating:', 'present' if n.get('aggregateRating') else 'MISSING')
    except: pass
  "

Enter fullscreen mode Exit fullscreen mode

Output Meaning Next step
No output No JSON-LD schema Add it or install a module
availability: MISSING Offers block incomplete Fix the offers object
availability: InStock Text string (non-spec) Change to full URI
availability: https://schema.org/InStock ✅ Correct Validate at schema.org

Implementation Options

Option 1 — Module (5 min)

composer require angeo/module-rich-data
bin/magento setup:upgrade && bin/magento cache:flush

Enter fullscreen mode Exit fullscreen mode

MIT licensed, works on Luma and Hyvä. Adds Product, Organization, BreadcrumbList, WebSite, FAQPage schema — all server-side rendered.

Option 2 — Manual phtml

Create Magento_Catalog/templates/product/json-ld.phtml:

<?php
$product = $block->getProduct();
$schema = [
    '@context' => 'https://schema.org/',
    '@type'    => 'Product',
    'name'     => $product->getName(),
    'sku'      => $product->getSku(),
    'offers'   => [
        '@type'         => 'Offer',
        'price'         => (string) $product->getFinalPrice(),
        'priceCurrency' => $block->getCurrencyCode(),
        'availability'  => $product->isAvailable()
            ? 'https://schema.org/InStock'
            : 'https://schema.org/OutOfStock',
        'itemCondition' => 'https://schema.org/NewCondition',
    ],
];
?>
<script type="application/ld+json">
<?= json_encode($schema, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) ?>
</script>

Enter fullscreen mode Exit fullscreen mode

Option 3 — GTM

Worth mentioning because it comes up a lot: GTM-injected schema works for Google Search, which processes JavaScript. For AI crawlers that rely on the initial HTML response, GTM schema may not be seen. If you're specifically targeting AI search visibility, server-side rendering is safer.


Validation Checklist

  • [ ] JSON-LD format (not microdata)
  • [ ] offers.availability — full schema.org URI
  • [ ] offers.price — number string, no currency symbol
  • [ ] offers.priceCurrency — ISO 4217 code (EUR, USD, GBP)
  • [ ] image — at least one absolute URL
  • [ ] aggregateRating omitted if reviewCount is 0
  • [ ] Schema present in raw curl output (server-side rendered)
  • [ ] Hyvä: schema injected via layout XML <head>
  • [ ] Configurable products use AggregateOffer with per-variant Offer
  • [ ] Zero errors at validator.schema.org

Common Errors

"The value of offers.availability is not valid"
Using a text string. Change to "https://schema.org/InStock".

"Missing field: offers.priceCurrency"
Add "priceCurrency": "EUR" to the offers object.

"ratingValue out of range"
Value must be between 1 and bestRating. A value of 0 is invalid — omit aggregateRating entirely if no reviews yet.


Full AEO Check

Product schema is one of 13 signals that affect AI search visibility in Magento. To check all of them at once:

composer require angeo/module-aeo-audit
bin/magento setup:upgrade && bin/magento cache:flush
bin/magento angeo:aeo:audit

Enter fullscreen mode Exit fullscreen mode

Free CLI tool — weighted score across 13 signals, exact fix command for each failure.


If you're debugging Magento schema issues, the CLI audit tool above can save a lot of manual checking.

Originally published at angeo.dev