JSON-LD : composants réutilisables, jamais inline
Le JSON-LD doit être dans le HTML brut crawlé. Donc : émis côté serveur (ou pré-rendu), jamais via next/script ou un useEffect. Sur un projet Vite + pré-rendu, c'est un injecté par le composant racine ou par Helmet/SSG.
Wrapper unique : JsonLdScript
export function JsonLdScript({ data }: { data: object }) {
const json = JSON.stringify(data).replace(/</g, "\\u003c");
return <script type="application/ld+json" dangerouslySetInnerHTML={{ __html: json }} />;
}L'échappement est obligatoire — sinon faille XSS si un champ contient .
16 composants typés
Un composant par type Schema.org : OrganizationJsonLd, WebSiteJsonLd (+ SearchAction), BreadcrumbJsonLd, ServiceJsonLd, FaqJsonLd, HowToJsonLd, ItemListJsonLd, BlogPostingJsonLd, VideoObjectJsonLd, SoftwareApplicationJsonLd...
Chacun prend des props typées et appelle JsonLdScript. Zéro chance de produire un blob invalide.
@id cross-référencés
Organization et WebSite sont émis une seule fois au layout racine, avec un @id stable (https://site.com/#organization). Toutes les autres entités les référencent via { "@id": "..." }. Résultat : Google reconstruit le knowledge graph proprement, zéro duplication d'entité.
Anti-pattern fatal
JSON-LD inline dans une page :
<script dangerouslySetInnerHTML={{ __html: `{...}` }} />→ Pas de typage, pas de réutilisabilité, pas de validation CI. Bannir.
À retenir
JsonLdScript SSR + composants typés + @id cross-référencés. C'est non négociable pour un projet qui veut être cité par les IA et obtenir des rich results.
Partager