JSON-LD structured data is de directe lijn tussen jouw productpagina en ChatGPT, Perplexity én Google Rich Results. Zonder het zijn je producten een raadsel voor AI. Met de juiste implementatie word je geciteerd, gevonden en gekocht. In deze gids: werkende code voor elk groot e-commerce platform.
AI-zoekmachines zoals ChatGPT, Perplexity en Google AI Overviews beantwoorden vragen door webpagina's te begrijpen — niet alleen te indexeren. Ze "lezen" je productpagina en proberen te ontdekken: wat kost dit product? Wat zijn de reviews? Is het op voorraad? Welk merk maakt het?
Als die informatie verborgen zit in HTML-tabellen, JavaScript-laadlogica of gewoon niet aanwezig is, geeft de AI een vaag antwoord of — erger — verwijst door naar een concurrent die zijn data wél netjes aanbiedt.
JSON-LD lost dit op. Het is een klein stukje code in de <head> van je pagina dat machine-leesbaar vertelt: "Dit is een product, het heet X, kost Y euro, heeft 4,8 sterren van 247 reviews, en is op voorraad." Voor AI is dat het verschil tussen een vage hint en een directe bevestiging.
De impact op je GEO-score is direct: de dimensie "Structured Data" weegt voor 30% mee in onze scoring. Een webshop zonder enige JSON-LD scoort hier standaard een 0. Met een volledige implementatie spring je direct naar 80–100 punten op dit onderdeel.
Schema.org definieert tientallen velden voor een Product. Niet alle velden zijn even waardevol voor GEO. Hieronder de prioriteitstabel — van essentieel tot nice-to-have:
| Veld | Prioriteit | GEO Impact | Google Rich Results |
|---|---|---|---|
| name | Verplicht | Hoog | Vereist |
| description | Verplicht | Hoog | Aanbevolen |
| image | Verplicht | Middel | Vereist |
| offers.price | Verplicht | Hoog | Vereist voor prijs-resultaten |
| offers.availability | Belangrijk | Hoog | Vereist |
| brand | Belangrijk | Hoog | Aanbevolen |
| aggregateRating | Belangrijk | Hoog | Vereist voor sterren in SERP |
| sku | Aanbevolen | Middel | Aanbevolen |
| gtin / gtin13 (EAN) | Aanbevolen | Hoog voor AI | Aanbevolen |
| category | Aanbevolen | Middel | Aanbevolen |
| review (individueel) | Bonus | Hoog voor citaties | Bonus |
Het GTIN/EAN-nummer is bijzonder waardevol voor AI. ChatGPT en Perplexity gebruiken het om je product te koppelen aan externe databronnen: vergelijkingssites, productdatabases, andere shops. Dat vergroot de kans op vermeldingen enorm.
Dit is het ideale JSON-LD Product schema. Kopieer dit als startpunt:
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Productnaam hier",
"description": "Uitgebreide productomschrijving. Minimaal 150 woorden voor maximale GEO-score.",
"image": [
"https://example.nl/images/product-vooraanzicht.jpg",
"https://example.nl/images/product-zijaanzicht.jpg"
],
"sku": "ARTIKEL-001",
"gtin13": "1234567890123",
"brand": {
"@type": "Brand",
"name": "Merknaam"
},
"category": "Categorie > Subcategorie",
"offers": {
"@type": "Offer",
"url": "https://example.nl/product/productnaam",
"priceCurrency": "EUR",
"price": "49.95",
"priceValidUntil": "2026-12-31",
"availability": "https://schema.org/InStock",
"itemCondition": "https://schema.org/NewCondition",
"seller": {
"@type": "Organization",
"name": "Naam van je winkel"
}
},
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "4.7",
"reviewCount": "128",
"bestRating": "5",
"worstRating": "1"
}
}
</script>
Hieronder de concrete implementatiemethode per platform — inclusief code snippets die je direct kunt gebruiken.
WooCommerce heeft ingebouwde schema markup via Yoast SEO of RankMath, maar beide plugins missen often het gtin13 veld en genereren geen reviewdata. De meest flexibele oplossing: voeg een custom PHP-snippet toe aan je child theme's functions.php.
/**
* GEO-geoptimaliseerd JSON-LD Product schema voor WooCommerce
* Toevoegen aan: child-theme/functions.php
*/
function geo_product_jsonld() {
if ( ! is_product() ) return;
global $product;
$product = wc_get_product();
if ( ! $product ) return;
$rating = $product->get_average_rating();
$reviews = $product->get_review_count();
$gtin = $product->get_meta('_gtin'); // Vereist ACF of custom meta
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $product->get_name(),
'description' => wp_strip_all_tags( $product->get_description() ),
'image' => wp_get_attachment_url( $product->get_image_id() ),
'sku' => $product->get_sku(),
'brand' => [
'@type' => 'Brand',
'name' => $product->get_attribute('pa_merk') ?? get_bloginfo('name'),
],
'offers' => [
'@type' => 'Offer',
'url' => get_permalink(),
'priceCurrency' => get_woocommerce_currency(),
'price' => $product->get_price(),
'availability' => $product->is_in_stock()
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
'itemCondition' => 'https://schema.org/NewCondition',
'seller' => [
'@type' => 'Organization',
'name' => get_bloginfo('name'),
],
],
];
// EAN/GTIN toevoegen als aanwezig
if ( $gtin ) {
$schema['gtin13'] = $gtin;
}
// Reviews toevoegen als aanwezig
if ( $rating && $reviews > 0 ) {
$schema['aggregateRating'] = [
'@type' => 'AggregateRating',
'ratingValue' => number_format( (float)$rating, 1 ),
'reviewCount' => (int)$reviews,
'bestRating' => '5',
'worstRating' => '1',
];
}
echo '<script type="application/ld+json">'
. wp_json_encode( $schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES )
. '</script>';
}
add_action( 'wp_head', 'geo_product_jsonld' );
_gtin via ACF (Advanced Custom Fields) of het gratis WooCommerce plugin "GTIN, UPC, EAN for WooCommerce". Dit veld wordt dan automatisch meegenomen in de JSON-LD output.
Shopify genereert automatisch Product schema via de product.json Liquid template. De standaard output mist echter reviews, GTIN en adequate beschrijving. Pas je product.json.liquid (of de schema sectie in je main-product.liquid) aan.
application/ld+json in je thema-bestanden. In de meeste moderne themes zit dit in sections/main-product.liquid of templates/product.json.
{% comment %} GEO-geoptimaliseerd Product JSON-LD voor Shopify {% endcomment %}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": {{ product.title | json }},
"description": {{ product.description | strip_html | truncate: 500 | json }},
"image": [
{% for image in product.images limit: 3 %}
"https:{{ image.src | img_url: 'master' }}"{% unless forloop.last %},{% endunless %}
{% endfor %}
],
"sku": {{ product.selected_or_first_available_variant.sku | json }},
{% if product.metafields.custom.gtin != blank %}
"gtin13": {{ product.metafields.custom.gtin | json }},
{% endif %}
"brand": {
"@type": "Brand",
"name": {{ product.vendor | json }}
},
"category": {{ product.type | json }},
"offers": {
"@type": "Offer",
"url": "{{ shop.url }}{{ product.url }}",
"priceCurrency": {{ shop.currency | json }},
"price": "{{ product.price | divided_by: 100.0 }}",
"priceValidUntil": "{{ 'now' | date: '%s' | plus: 7776000 | date: '%Y-%m-%d' }}",
"availability": {% if product.available %}
"https://schema.org/InStock"
{% else %}
"https://schema.org/OutOfStock"
{% endif %},
"itemCondition": "https://schema.org/NewCondition",
"seller": {
"@type": "Organization",
"name": {{ shop.name | json }}
}
}
{% if product.metafields.reviews.rating != blank %}
,"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "{{ product.metafields.reviews.rating.value }}",
"reviewCount": "{{ product.metafields.reviews.rating_count }}",
"bestRating": "5",
"worstRating": "1"
}
{% endif %}
}
</script>
custom en key gtin. Vul het daarna in voor elk product via het product-beheerscherm.
Magento 2 heeft geen ingebouwde JSON-LD Product schema output. De aanbevolen aanpak: maak een custom module of voeg een PHTML-bestand toe via je theme. Hieronder de minimale implementatie via een theme template override.
Maak het bestand aan op: app/design/frontend/[Vendor]/[Theme]/Magento_Catalog/templates/product/geo-jsonld.phtml
<?php
/**
* GEO Tool — JSON-LD Product Schema voor Magento 2
* Template: Magento_Catalog/templates/product/geo-jsonld.phtml
*/
/** @var \Magento\Catalog\Block\Product\View $block */
$product = $block->getProduct();
$helper = $block->helper(\Magento\Catalog\Helper\Data::class);
$imageHelper = $this->helper(\Magento\Catalog\Helper\Image::class);
$imageUrl = $imageHelper->init($product, 'product_page_image_large')->getUrl();
$price = $product->getFinalPrice();
$inStock = $product->isAvailable();
// EAN opgeslagen in custom attribute 'ean'
$ean = $product->getData('ean');
$schema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $product->getName(),
'description' => strip_tags($product->getDescription() ?: $product->getShortDescription()),
'image' => $imageUrl,
'sku' => $product->getSku(),
'brand' => [
'@type' => 'Brand',
'name' => $product->getAttributeText('manufacturer') ?: '',
],
'offers' => [
'@type' => 'Offer',
'url' => $product->getProductUrl(),
'priceCurrency' => 'EUR',
'price' => number_format($price, 2, '.', ''),
'availability' => $inStock
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
'itemCondition' => 'https://schema.org/NewCondition',
],
];
if ($ean) {
$schema['gtin13'] = $ean;
}
// Reviews via Magento rating
$ratingSummary = $product->getRatingSummary();
if ($ratingSummary && $ratingSummary->getReviewsCount() > 0) {
$ratingValue = round(($ratingSummary->getRatingSummary() / 100) * 5, 1);
$schema['aggregateRating'] = [
'@type' => 'AggregateRating',
'ratingValue' => (string)$ratingValue,
'reviewCount' => (string)$ratingSummary->getReviewsCount(),
'bestRating' => '5',
'worstRating' => '1',
];
}
?>
<script type="application/ld+json">
<?= json_encode($schema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) ?>
</script>
Registreer de template via een layout XML update in je theme:
<?xml version="1.0"?>
<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\Catalog\Block\Product\View"
name="product.geo.jsonld"
template="Magento_Catalog::product/geo-jsonld.phtml"
after="-"/>
</head>
</page>
Shopware 6 genereert standaard minimale schema markup. De meest schone aanpak voor Shopware is een Twig block extension in je custom thema of plugin.
Voeg dit toe aan je thema in: Resources/views/storefront/page/product-detail/index.html.twig
{% sw_extends '@Storefront/storefront/page/product-detail/index.html.twig' %}
{% block page_product_detail_schema_org %}
{{ parent() }}
{%- set product = page.product -%}
{%- set currency = context.currency -%}
{%- set baseUrl = app.request.schemeAndHttpHost -%}
{%- set price = product.calculatedPrice.unitPrice -%}
{%- set inStock = (product.availableStock > 0) -%}
{%- set ean = product.ean -%}
{%- set manufacturerName = product.manufacturer ? product.manufacturer.name : '' -%}
{%- set reviewAvg = product.ratingAverage -%}
{%- set reviewCount = product.reviewCount -%}
{%- set imageUrl = '' -%}
{%- if product.cover.media -%}
{%- set imageUrl = baseUrl ~ '/thumbnail/' ~ product.cover.media.id ~ '/' ~ product.cover.media.fileName -%}
{%- endif -%}
{% endblock %}
ean veld op producten. Vul dit in via het productbeheer (Catalogus → Producten → [product] → Maten & verpakking → EAN). Dit wordt automatisch meegenomen in bovenstaand template.
Op basis van duizenden scans zien we telkens dezelfde JSON-LD fouten terugkomen. Hier zijn de zeven meest impactvolle:
Fout: "price": 49.95 — Goed: "price": "49.95". Schema.org verwacht een string voor prijs. Google's Rich Results Test geeft een warning bij numerieke waardes.
priceValidUntilGoogle vereist dit veld om pijlen bij prijzen in Rich Results te tonen. Stel minimaal in op een datum in de toekomst (bijv. "priceValidUntil": "2026-12-31"). Vergeet niet dit jaarlijks te updaten of dynamisch te genereren.
Dit moet exact https://schema.org/InStock zijn — met hoofdletter en zonder trailing slash. Fouten als http://schema.org/in-stock of InStock worden niet herkend.
Een product description van 10 woorden helpt AI niets. Richt je op minimaal 150 woorden per product. AI-tools citeren pagina's met uitgebreide, informatieve beschrijvingen significant vaker.
Als je Trustpilot, Google Reviews of eigen reviews hebt, maar ze niet opneemt in je JSON-LD, mist AI die informatie volledig. Voeg aggregateRating toe zodra je ook maar één review hebt.
Als je zowel een SEO-plugin (Yoast, RankMath) als custom code gebruikt, krijg je twee conflicterende Product blokken. Google kiest er één — niet altijd de juiste. Zet de plugin-output uit of gebruik uitsluitend de plugin met customisaties via hooks.
Sommige implementaties voegen "gtin13": "0" of "gtin13": "" toe als er geen EAN bekend is. Dit schaadt meer dan het helpt. Voeg het veld alleen toe als er een valide 13-cijferig EAN is.
Offer hebben met bijbehorende prijs en availability. Een enkel Offer voor alle varianten is technisch onjuist en kan leiden tot fouten in Google Search Console.
Na implementatie wil je weten of het werkt. Er zijn twee niveaus van testen:
Ga naar search.google.com/test/rich-results en voer je product-URL in. Je ziet direct:
Dit test alleen Google-compatibiliteit — niet hoe AI-tools als ChatGPT je pagina zien.
Voor een volledig beeld — inclusief hoe ChatGPT, Perplexity en Google AI Overviews je pagina interpreteren — gebruik de gratis GEO Tool scan. Die controleert niet alleen structured data maar ook alle 5 GEO-dimensies.
Ontdek je GEO-score op alle 5 dimensies — inclusief structured data analyse. Geen account vereist.
Gratis scan starten →JSON-LD (JavaScript Object Notation for Linked Data) is de aanbevolen manier van Google en schema.org om gestructureerde data aan webpagina's toe te voegen. Het vertelt zoekmachines én AI-tools precies wat een product kost, welke reviews het heeft en wat de eigenschappen zijn — zonder dat ze de HTML hoeven te "raden". Resultaat: rijke resultaten in Google, hogere GEO-score en meer kans op vermeldingen in ChatGPT.
JSON-LD staat los van de HTML-structuur en is makkelijker te onderhouden. Microdata is ingebouwd in de HTML-tags zelf. Google geeft de voorkeur aan JSON-LD. Voor nieuwe implementaties is JSON-LD altijd de betere keuze — het is makkelijker te testen, te debuggen en te automatiseren.
Voor Google Product Rich Results zijn verplicht: name, image, en minimaal één van: offers (met price en priceCurrency), aggregateRating, of review. Voor maximale GEO-score voeg je ook toe: description, sku, brand, gtin13 (EAN), en availability.
Nee. De platform-specifieke code in dit artikel genereert automatisch JSON-LD voor elke productpagina vanuit je bestaande productdata. Eenmalige implementatie, directe werking op alle producten.
Gebruik de Google Rich Results Test (search.google.com/test/rich-results) voor Google-compatibiliteit. Voor een volledige GEO-score analyse — inclusief hoe ChatGPT en Perplexity je pagina zien — gebruik de GEO Tool gratis scan.