Schema.org expose ses données d'adoption — et ça change la donne
Jusqu'à présent, choisir un type Schema.org relevait d'un mélange de documentation officielle, de reverse-engineering des SERP et d'intuition. Vous implémentiez HowTo ou FAQPage sans savoir si Google voyait ces types sur 500 sites ou 5 millions. Schema.org vient de combler ce vide : chaque page de type affiche désormais le nombre de domaines qui l'utilisent en production, données issues du corpus Web Data Commons. Ce n'est pas un gadget cosmétique — c'est la première fois qu'on dispose d'une donnée quantitative fiable pour prioriser son balisage structuré.
Ce qui a changé concrètement sur Schema.org
La nouvelle section "Usage statistics"
Rendez-vous sur n'importe quelle page de type — par exemple https://schema.org/Product. Sous la description et la hiérarchie de propriétés, une section affiche désormais le nombre de domaines et de pages utilisant ce type, ventilé par format (JSON-LD, Microdata, RDFa).
Ces chiffres ne viennent pas de Google. Ils sont extraits du dataset Web Data Commons, un projet de l'Université de Mannheim qui parse les données structurées sur un échantillon massif du Common Crawl. Le dernier corpus couvre environ 3,3 milliards de pages HTML.
Ce que les chiffres révèlent (et ce qu'ils cachent)
Les données exposent deux métriques : le nombre de domaines et le nombre de pages. La distinction est cruciale. Un e-commerce de 50 000 fiches produit avec Product sur chaque page compte pour un seul domaine mais 50 000 pages. Un réseau de 200 micro-sites avec une seule page LocalBusiness chacun compte pour 200 domaines mais 200 pages.
Limitation importante : le Common Crawl n'est pas un miroir exact du web. Il sous-représente les sites derrière des paywalls, les SPA sans server-side rendering, et les pages profondes nécessitant une authentification. Si votre site SPA sert le JSON-LD uniquement côté client sans SSR, il est probable que le Common Crawl ne le capte pas — tout comme Googlebot dans certaines configurations. Un parallèle direct avec les problèmes de rendering côté serveur et de contenu invisible au fetch HTTP brut.
Format de prédilection : JSON-LD domine
Les données confirment ce que la communauté SEO technique soupçonnait : JSON-LD est devenu le format dominant pour la plupart des types à forte valeur SEO (Product, Article, FAQPage, Organization). Microdata persiste principalement sur des CMS legacy (WordPress pré-Yoast, Joomla). RDFa est marginal sauf sur certains sites institutionnels.
Exploiter ces données pour prioriser votre balisage
L'arbitrage adoption vs. différenciation
Le réflexe naturel serait de dire : "beaucoup de sites utilisent Product, donc je dois l'utiliser aussi." C'est vrai pour les types qui déclenchent des rich results — Google ne va pas désactiver les extraits enrichis pour Product quand des millions de sites en dépendent. Le signal est clair : forte adoption = type stable, supporté durablement.
Mais le raisonnement inverse est tout aussi intéressant. Un type peu adopté mais pertinent pour votre secteur représente une opportunité de différenciation dans le Knowledge Graph. Prenez MedicalCondition : si les données montrent quelques milliers de domaines seulement, mais que vous opérez un site santé avec 8 000 pages de conditions médicales, un balisage soigné vous donne un avantage structurel pour l'alimentation des AI Overviews et des panneaux de connaissance.
Matrice de décision concrète
Voici comment structurer l'arbitrage pour un e-commerce de 15 000 produits avec un blog de 2 000 articles :
| Type Schema.org | Adoption (domaines) | Rich result Google | Priorité |
|---|---|---|---|
Product |
Très élevée (~3M+) | Oui (Product snippet) | P0 — non négociable |
Article |
Très élevée (~5M+) | Oui (Article snippet) | P0 — sur chaque article |
BreadcrumbList |
Élevée (~1.5M+) | Oui (Breadcrumbs SERP) | P0 — structure de navigation |
FAQPage |
Modérée (~500K) | Restreint depuis 2023 | P2 — uniquement si FAQ réelle |
HowTo |
Modérée (~300K) | Restreint depuis 2023 | P2 — guides pratiques |
SpecialOffer |
Faible (~10K) | Non directement | P1 — différenciation |
Les types FAQPage et HowTo illustrent un point important : Google a restreint leur éligibilité aux rich results en août 2023, mais ils restent utiles pour alimenter les systèmes d'IA générative. L'adoption modérée signifie que le type est compris et indexé — il vaut le coup si vous avez du contenu FAQ pertinent.
Requêter les données d'adoption par programmation
Les statistiques affichées sur Schema.org sont utiles pour un check ponctuel. Pour un audit systématique, vous pouvez requêter directement le dataset Web Data Commons via leur endpoint SPARQL ou télécharger les fichiers bruts.
Accéder au dataset Web Data Commons
Web Data Commons publie ses extractions sur webdatacommons.org/structureddata. Les fichiers sont au format N-Quads, partitionnés par format (JSON-LD, Microdata, RDFa). Pour une analyse ciblée, le plus efficace est d'utiliser le résumé statistique qu'ils publient en TSV.
# Télécharger le résumé d'adoption par type (JSON-LD)
curl -O https://webdatacommons.org/structureddata/2024-09/stats/schema_org_subsets/jsonld_type_count.tsv
# Filtrer les types Product, Article, FAQPage
grep -E "^(Product|Article|FAQPage)\t" jsonld_type_count.tsv | sort -t$'\t' -k2 -rn
# Résultat typique (format : type \t nombre_de_pages \t nombre_de_domaines)
# Product 287654321 3124567
# Article 412987654 5234891
# FAQPage 45678901 487234
Les URLs exactes des fichiers changent à chaque release. Vérifiez toujours la dernière version disponible sur la page du projet.
Script d'analyse comparative pour votre secteur
Supposons que vous gérez un site média avec 12 000 articles et que vous voulez comparer votre adoption de types Schema.org avec la moyenne du web. Ce script Python croise votre export Screaming Frog avec les données WDC :
import csv
from collections import Counter
# 1. Parser l'export Screaming Frog (colonne "Structured Data > Type")
def parse_screaming_frog_export(filepath: str) -> Counter:
type_counts = Counter()
with open(filepath, 'r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
sd_types = row.get('Structured Data 1 > Type', '')
if sd_types:
for t in sd_types.split(', '):
type_counts[t.strip()] += 1
return type_counts
# 2. Parser le résumé WDC
def parse_wdc_stats(filepath: str) -> dict:
stats = {}
with open(filepath, 'r') as f:
reader = csv.reader(f, delimiter='\t')
for row in reader:
if len(row) >= 3:
stats[row[0]] = {
'pages': int(row[1]),
'domains': int(row[2])
}
return stats
# 3. Comparer
my_types = parse_screaming_frog_export('screaming_frog_export.csv')
wdc_stats = parse_wdc_stats('jsonld_type_count.tsv')
print(f"{'Type':<25} {'Vos pages':>12} {'WDC pages':>15} {'WDC domaines':>15}")
print("-" * 70)
for schema_type, count in my_types.most_common(20):
wdc = wdc_stats.get(schema_type, {'pages': 0, 'domains': 0})
print(f"{schema_type:<25} {count:>12,} {wdc['pages']:>15,} {wdc['domains']:>15,}")
Ce type d'analyse révèle les trous : si votre site média publie 12 000 Article mais zéro VideoObject alors que WDC montre 800K+ domaines avec VideoObject, vous passez peut-être à côté de rich results vidéo sur vos contenus embed.
Auditer et monitorer votre balisage structuré à l'échelle
Validation en masse avec Screaming Frog et jq
Screaming Frog extrait les données structurées depuis la v17, mais sa sortie est parfois difficile à exploiter programmatiquement. Une approche complémentaire : crawler votre site avec un script qui extrait et valide le JSON-LD brut.
#!/bin/bash
# extract_jsonld.sh — Extraire et valider le JSON-LD de chaque URL d'un sitemap
SITEMAP_URL="https://www.votresite.fr/sitemap.xml"
# Extraire les URLs du sitemap
curl -s "$SITEMAP_URL" | grep -oP '(?<=<loc>)[^<]+' > urls.txt
echo "URL,JSON-LD Types,Validation" > report.csv
while IFS= read -r url; do
# Fetch le HTML (user-agent Googlebot pour cohérence)
html=$(curl -s -A "Mozilla/5.0 (compatible; Googlebot/2.1)" "$url")
# Extraire les blocs JSON-LD
jsonld=$(echo "$html" | python3 -c "
import sys, re, json
html = sys.stdin.read()
blocks = re.findall(r'<script type=\"application/ld\+json\">(.*?)</script>', html, re.DOTALL)
types = []
for b in blocks:
try:
data = json.loads(b)
if isinstance(data, list):
for item in data:
types.append(item.get('@type', 'UNKNOWN'))
else:
types.append(data.get('@type', 'UNKNOWN'))
except json.JSONDecodeError:
types.append('INVALID_JSON')
print(','.join(types) if types else 'NONE')
")
# Vérifier si le JSON est valide
validation="OK"
if echo "$jsonld" | grep -q "INVALID_JSON"; then
validation="ERREUR_JSON"
elif echo "$jsonld" | grep -q "NONE"; then
validation="ABSENT"
fi
echo "\"$url\",\"$jsonld\",\"$validation\"" >> report.csv
done < urls.txt
echo "Rapport généré : report.csv"
echo "Pages sans JSON-LD :"
grep "ABSENT" report.csv | wc -l
echo "Pages avec JSON invalide :"
grep "ERREUR_JSON" report.csv | wc -l
Sur un site e-commerce de 15 000 pages, ce script (exécuté en parallèle avec xargs -P 10) prend environ 45 minutes. Le rapport CSV révèle immédiatement les pages où le JSON-LD est absent (template mal configuré), invalide (virgule trailing, guillemets non échappés), ou utilisant un type inattendu.
Le piège du JSON-LD dynamique
Sur les stacks JavaScript modernes (Next.js, Nuxt, SvelteKit), le JSON-LD est souvent généré dynamiquement. Le problème classique : le bloc <script type="application/ld+json"> dépend de données async qui peuvent échouer silencieusement.
Exemple concret sur Next.js App Router :
// app/products/[slug]/page.tsx
export default async function ProductPage({ params }: { params: { slug: string } }) {
const product = await getProduct(params.slug);
// Si getProduct retourne null (API timeout, 404, etc.),
// le JSON-LD n'est pas rendu — SANS erreur visible
return (
<>
{product && (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify({
"@context": "https://schema.org",
"@type": "Product",
"name": product.name,
"description": product.description,
"sku": product.sku,
"offers": {
"@type": "Offer",
"price": product.price,
"priceCurrency": "EUR",
"availability": product.inStock
? "https://schema.org/InStock"
: "https://schema.org/OutOfStock"
},
"aggregateRating": product.reviews?.length > 0 ? {
"@type": "AggregateRating",
"ratingValue": product.averageRating,
"reviewCount": product.reviews.length
} : undefined
})
}}
/>
)}
{/* reste du composant */}
</>
);
}
Le problème : si getProduct échoue sur 3 % de vos 15 000 pages produit à cause de timeouts API intermittents, vous avez 450 pages sans JSON-LD Product. Googlebot ne va pas vous alerter. La Search Console montre uniquement les erreurs de structure sur les pages où elle détecte du structured data — pas les pages où il manque. Ce type de régression silencieuse est exactement ce que détecte un outil de monitoring continu comme Seogard : il compare le JSON-LD attendu au JSON-LD réellement servi sur chaque URL crawlée, et alerte quand un bloc disparaît.
Ce genre de bug côté metadata rejoint une classe d'erreurs documentée sur les frameworks modernes. Les metadata async qui throw silencieusement sur Next.js ou les override silencieux de useSeometa sur Nuxt suivent exactement le même pattern : pas d'erreur visible, pas d'alerte framework, mais un impact SEO cumulatif.
Stratégie : utiliser les données d'adoption pour l'AI visibility
Le lien entre structured data et systèmes génératifs
Les AI Overviews de Google et les systèmes comme Perplexity ou ChatGPT Search consomment les données structurées pour construire leurs réponses. La différence avec les rich results classiques : les systèmes d'IA n'ont pas besoin que Google "supporte" officiellement un type pour l'exploiter. Un SoftwareApplication bien balisé avec applicationCategory, operatingSystem et offers peut alimenter une réponse IA même si Google n'affiche pas de rich result dédié en SERP.
Les données d'adoption de Schema.org deviennent un signal stratégique : si un type est largement adopté, les systèmes d'IA ont été entraînés sur suffisamment d'exemples pour le comprendre de manière fiable. À l'inverse, un type confidentiel avec moins de 1 000 domaines risque d'être mal interprété ou ignoré.
Ce raisonnement s'inscrit dans la tendance plus large de visibilité auprès des agents IA, un sujet sur lequel l'identification des visiteurs IA et de leur provenance devient un enjeu de mesure, et où le standard EntityMap propose une vue structurée de votre activité pour les systèmes IA.
Cas concret : un site SaaS B2B de 800 pages
Prenons un éditeur SaaS B2B avec :
- 1 page produit principale
- 120 pages de fonctionnalités
- 45 pages de tarifs/plans
- 200 articles de blog
- 80 pages de documentation
- 30 pages de cas clients
- ~325 pages légales, carrières, landing pages diverses
Avant les données d'adoption Schema.org, l'équipe SEO balisait principalement Organization (homepage), Article (blog) et BreadcrumbList (toutes pages). Avec les données d'adoption, l'audit révèle des opportunités négligées :
| Page type | Type Schema actuel | Type Schema recommandé | Adoption WDC |
|---|---|---|---|
| Fonctionnalités | Aucun | SoftwareApplication |
~180K domaines |
| Cas clients | Article |
Review + Organization |
~900K domaines |
| Documentation | Aucun | TechArticle |
~25K domaines |
| Tarifs | Aucun | Offer + SoftwareApplication |
~2.5M (Offer) |
TechArticle avec seulement ~25K domaines est un pari : faible adoption signifie que les AI systems ont moins de données d'entraînement sur ce type. Mais pour un site de documentation technique, la pertinence sémantique est maximale. Le trade-off penche vers l'implémentation — le coût est faible (quelques lignes JSON-LD), et le signal de pertinence pour les LLM qui parcourent votre doc est réel.
Implémenter le JSON-LD conditionnel par template
Pour un site de cette taille, l'approche la plus maintenable est un composant centralisé qui reçoit le type et les données en props :
// components/StructuredData.tsx
interface StructuredDataProps {
type: string;
data: Record<string, unknown>;
}
export function StructuredData({ type, data }: StructuredDataProps) {
const jsonLd = {
"@context": "https://schema.org",
"@type": type,
...data,
};
// Validation minimale côté serveur
if (!type || !data || Object.keys(data).length === 0) {
console.warn(`[StructuredData] Missing data for type ${type}`);
// En production, envoyer une alerte vers votre monitoring
return null;
}
return (
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(jsonLd, null, 0),
}}
/>
);
}
// Usage dans une page de documentation
<StructuredData
type="TechArticle"
data={{
headline: doc.title,
description: doc.excerpt,
datePublished: doc.publishedAt,
dateModified: doc.updatedAt,
author: {
"@type": "Organization",
name: "VotreSaaS",
},
proficiencyLevel: "Advanced",
dependencies: doc.prerequisites?.join(", "),
}}
/>
Le console.warn en développement est un filet de sécurité minimal. En production, remplacez-le par un envoi vers votre système de monitoring pour détecter les régressions quand un refactoring casse le passage de données au composant — un pattern de régression fréquent lors des refactos de design system.
Valider avec Google et au-delà
Rich Results Test vs. Schema Markup Validator
Google propose le Rich Results Test pour vérifier quels rich results votre page peut déclencher. Mais cet outil ne teste que les types que Google supporte — il ne vous dira rien sur TechArticle ou SoftwareApplication au-delà des propriétés que Google utilise.
Pour une validation complète de la conformité Schema.org (indépendamment de Google), utilisez le Schema Markup Validator. Il vérifie que vos propriétés correspondent aux spécifications Schema.org, y compris les types et propriétés que Google ignore mais que d'autres consommateurs (Bing, Apple, LLM) pourraient exploiter.
Vérification dans Search Console
La Search Console rapporte les types pour lesquels Google génère des rich results dans Améliorations > [Type]. Ce rapport montre les erreurs et avertissements par type. Mais il y a un angle mort majeur : si vous implémentez un type que Google ne supporte pas pour les rich results (comme TechArticle), il n'apparaîtra nulle part dans la Search Console. Pourtant, Google le crawle, le parse et l'utilise potentiellement dans ses systèmes internes.
La nouveauté de Google sur les rapports dédiés à l'AI Search dans la Search Console pourrait à terme combler ce vide, en montrant quels types de données structurées alimentent les réponses IA.
Chrome DevTools pour le debug local
Pour vérifier le JSON-LD rendu côté client sans quitter votre navigateur :
// Dans la console Chrome DevTools
const scripts = document.querySelectorAll('script[type="application/ld+json"]');
scripts.forEach((s, i) => {
try {
const data = JSON.parse(s.textContent);
console.group(`JSON-LD Block #${i + 1}: ${data['@type'] || 'Unknown'}`);
console.log(JSON.stringify(data, null, 2));
// Vérifications basiques
if (!data['@context']) console.warn('⚠ Missing @context');
if (!data['@type']) console.warn('⚠ Missing @type');
if (data['@type'] === 'Product' && !data.offers) console.warn('⚠ Product without offers');
if (data['@type'] === 'Article' && !data.datePublished) console.warn('⚠ Article without datePublished');
console.groupEnd();
} catch (e) {
console.error(`JSON-LD Block #${i + 1}: INVALID JSON`, e.message);
}
});
Exécutez ce snippet sur chaque template type de votre site. Si vous voyez "INVALID JSON" ou des warnings, vous avez un bug de sérialisation à corriger avant que Googlebot ne le rencontre.
Les limites de ces données d'adoption
Biais du Common Crawl
Le Common Crawl ne crawle pas le web de manière uniforme. Les sites à forte autorité et avec des sitemaps bien configurés sont sur-représentés. Un site e-commerce de niche avec 500 pages pourrait ne pas figurer dans l'échantillon. Les chiffres d'adoption sont donc des ordres de grandeur, pas des valeurs absolues.
Décalage temporel
Les données Web Data Commons sont publiées avec un décalage de plusieurs mois. Le dernier corpus disponible au moment de la publication de ces statistiques peut dater de 6 à 9 mois. Un type dont l'adoption a explosé récemment (suite à un nouveau rich result Google, par exemple) sera sous-représenté.
Adoption ≠ qualité
Un type utilisé par 3 millions de domaines ne signifie pas 3 millions d'implémentations correctes. Beaucoup de sites utilisent des plugins WordPress qui génèrent du Product avec des champs obligatoires manquants, ou de l'Article sans datePublished. Les données d'adoption ne distinguent pas une implémentation propre d'un JSON-LD cassé.
La donnée d'adoption comme outil de priorisation
La transparence de Schema.org sur l'adoption réelle de chaque type transforme le balisage structuré d'un exercice de foi en une décision data-driven. Pour les équipes SEO qui gèrent des sites à fort volume de pages, la matrice adoption/pertinence permet enfin de prioriser les sprints d'implémentation sur des fondements quantitatifs.
Le risque principal reste les régressions silencieuses : un JSON-LD qui disparaît après un déploiement, un type qui change suite à un refactoring de composant, une API qui timeout et laisse le bloc vide. Seogard détecte ces régressions en comparant le structured data attendu au structured data effectivement servi, page par page, à chaque crawl — le genre de filet de sécurité qui fait la différence entre une stratégie schema documentée et une stratégie schema réellement en production.