frontend

JSON-LD: ce este, ce scheme contează, cum îl injectezi în SSR

JSON-LD este formatul prin care Google citește datele structurate ale paginii. Cinci scheme acoperă 95% din cazuri. Plus capcanele frecvente.

Cuprins

JSON-LD (JavaScript Object Notation for Linked Data) este formatul în care declari semnificația paginii tale pentru motoarele de căutare. Este un bloc JSON pe care îl injectezi în pagină și care îi spune lui Google „acesta este un articol cu acest titlu, scris de această persoană, la această dată". Pentru SEO, este principala unealtă prin care obții rich results (snippet-uri îmbogățite cu rating, imagini, breadcrumbs, FAQ-uri).

Formatul a fost standardizat de W3C în 2014 și a devenit recomandarea oficială Google pentru date structurate în 20151. De atunci, schema.org (vocabularul folosit) a crescut la peste 1.000 de tipuri și 1.500 de proprietăți. În practică, vei folosi cinci scheme; restul sunt cazuri foarte specifice.

Ce este JSON-LD mai exact?

Un bloc <script type="application/ld+json"> care conține un obiect JSON conform vocabularului schema.org. Spre deosebire de Microdata (atribute pe elemente HTML) sau RDFa (atribute namespaced), JSON-LD trăiește separat de marcajul vizual, ceea ce înseamnă că poți schimba template-ul fără să atingi datele structurate, și invers.

Structura minimă a unui obiect JSON-LD are trei chei obligatorii:

  • @context: aproape mereu "https://schema.org". Spune validatorului de unde să citească definițiile.
  • @type: numele schemei (de exemplu "Article", "Product", "DefinedTerm").
  • @id sau url: URL-ul canonic al entității, ca să poată fi identificată stabil.

Restul proprietăților depind de tipul ales. Validatorul Google îți spune dacă lipsește ceva critic; restul sunt sugestii.

Care sunt cele cinci scheme care contează cu adevărat?

Pentru un site editorial sau comercial obișnuit, aceste cinci scheme acoperă majoritatea cazurilor de rich results:

  • Article (sau BlogPosting, NewsArticle). Pentru orice piesă de conținut editorial. Câmpuri cheie: headline, datePublished, dateModified, author, publisher cu logo, image. Generează rich results cu data publicării și autor.
  • BreadcrumbList. Lista de pași către pagină. Afișează breadcrumbs în SERP în loc de URL crud. Simplu, profitabil.
  • FAQPage. Pagini cu întrebări și răspunsuri. Câteodată afișează FAQ-urile direct în SERP, ocupând spațiu suplimentar.
  • Product + Offer + AggregateRating. Pentru pagini de produs. Afișează preț, stoc, rating cu stele.
  • Organization (sau LocalBusiness). Pe homepage și pagini „despre". Hrănește knowledge graph-ul Google despre marca ta.

Pentru intrările de dicționar (cum este aceasta), folosim DefinedTerm împachetat într-un DefinedTermSet. Tip mai puțin spectaculos vizual în SERP, dar e semnal de claritate semantică pentru crawlere.

Cum îl injectezi corect cu SSR?

Pe partea de tehnică, regula de aur este: JSON-LD trebuie să fie în răspunsul HTML al serverului, nu adăugat de JavaScript după hydration. Dacă schemele tale apar doar după ce browserul execută bundle-ul, Googlebot le poate vedea (face render JavaScript), dar le poate vedea cu ore de întârziere. Restul crawlerelor (Bingbot, motoarele de social media) nu le vor vedea deloc.

Practic, în server-side rendering, fluxul corect este:

  • Componenta de rută primește datele necesare (titlu, descriere, autor, data publicării).
  • În timpul randării pe server, un serviciu SEO compune obiectul JSON și creează un element <script type="application/ld+json"> în <head>.
  • Procesul SSR trimite HTML-ul complet, cu blob-ul JSON-LD inclus, ca primă cerere.
  • La hydration, același serviciu re-rulează pe client și înlocuiește în loc (nu duplică) același tag, identificat printr-un atribut data-managed.

Lipsa unui atribut de identificare pe script-ul JSON-LD este o capcană clasică: la fiecare navigare, hydration-ul adaugă încă un blob în head, iar pagina ajunge cu cinci versiuni de Article schema după zece minute de navigare. Google e suficient de tolerant ca să nu te penalizeze, dar Search Console va semnala avertismente confuze.

O a doua capcană legată de același flux: JSON-LD-ul trebuie să fie consistent cu ce vede vizitatorul. Dacă schema declară headline diferit de titlul vizibil al articolului, sau dacă author arată „echipa redacțională" pe schemă și „Lucian Coanda" în corpul paginii, Google interpretează asta ca semnal de manipulare și scoate pagina din eligibilitatea pentru rich results. Regula simplă: dacă utilizatorul vede „X", JSON-LD-ul trebuie să spună tot „X", nu o variantă optimizată pentru crawler.

Cum îl folosim noi la crawlerra?

Pe crawlerra.com folosim SeoService (în src/app/core/seo/seo.service.ts) care injectează două tipuri de scheme principale: Article pentru piese de blog (cu publisher.logo + dateModified separat de datePublished, ambele cu offset UTC) și DefinedTerm pentru intrările de dicționar. Blob-ul este marcat cu data-managed="seo-service"2, ceea ce înseamnă că la navigarea între articole, scriptul vechi e înlocuit în loc, nu duplicat.

Pentru articolul nostru de manifestare editorială, JSON-LD-ul are exact aceste câmpuri în <head>: @context, @type: "Article", headline, description, mainEntityOfPage, url, datePublished, dateModified, inLanguage: "ro-RO", author, publisher cu obiect logo propriu, și image. Verifică deschizând „View Source" și căutând application/ld+json sau, mai elegant, prin Rich Results Test direct pe URL.

Cum verifici că funcționează și ce te scoate din rich snippets?

Trei unelte, fiecare pentru o întrebare diferită. Google Rich Results Test îți spune ce rich result-uri poate produce pagina ta și unde e ambiguitate. Schema.org Validator îți spune dacă structura JSON e validă chiar și pentru scheme care nu sunt suportate de Google. Search Console agregă erorile pe site la nivel de zile, util pentru a vedea regresii după un deploy.

Patru greșeli care te scot din eligibilitatea rich results, în ordinea în care le vezi cel mai des:

  • Date inconsistente cu conținutul vizibil. Declari datePublished: "2024-01-15" dar pagina spune „Publicat ieri". Google scoate pagina din rich results.
  • Câmpuri obligatorii lipsă. Article fără publisher.logo. Product fără price. Validatorul îți spune exact ce.
  • Schema markup pentru conținut absent. Declari FAQPage pe o pagină fără secțiune de întrebări vizibilă. Spammy pattern, penalizat.
  • Date randate doar prin client. Schema injectată după hydration nu intră în HTML initial. Vezi server-side rendering pentru fluxul corect.

În paralel cu JSON-LD, asigură-te că sitemap.xml include toate URL-urile schema-tagged și că hreflang-ul e consistent dacă servești în mai multe limbi; Google folosește toate trei împreună ca să-și formeze imaginea despre pagină. Detaliile complete de injectare în Angular SSR sunt în ghidul nostru pentru SSR pe produse reale.

  1. Recomandarea oficială Google pentru date structurate este JSON-LD, exprimată explicit pe Search Central din 2015. [seo.google_jsonld_recommendation]
  2. SeoService din src/app/core/seo/seo.service.ts injectează blob-ul JSON-LD în <head> cu atributul data-managed="seo-service" pentru a permite re-injectarea idempotentă la navigare. [crawlerra.seo_service]

Întrebări frecvente

JSON-LD, Microdata sau RDFa, care merită folosit?

JSON-LD, în 99% din cazuri. Google a recomandat explicit JSON-LD din 2015 încoace pentru că separă datele structurate de marcajul HTML și nu murdărește template-urile. Microdata și RDFa sunt încă suportate, dar sunt mai grele de menținut și fără avantaj real. Dacă ai deja microdata în pagini vechi, nu le rescrie, doar adaugă JSON-LD în plus pentru pagini noi.

Pot pune JSON-LD oriunde în pagină?

Tehnic da, dar pune-l în <head>. Atât head cât și body sunt acceptate de Google, dar head ține datele structurate aproape de meta tag-uri (care sunt vizate de aceleași crawlere) și menține template-urile vizibile curate. Pe crawlerra.com toate blob-urile JSON-LD sunt injectate în <head> de către SeoService înainte ca pagina să ajungă la browser.

Câte scheme pot folosi pe aceeași pagină?

Toate cele care descriu corect conținutul, fără să se contrazică. Un articol de blog poate avea simultan Article, BreadcrumbList, Person (autor), Organization (publisher) și FAQPage. Fiecare schemă răspunde la o întrebare diferită despre pagină. Ce te scoate din rich results nu e cantitatea, ci minciuna: să declari o schemă care nu se potrivește cu conținutul vizibil.

Schema markup garantează rich snippets?

Nu, niciodată. Schema este eligibilitatea, nu garanția. Google decide dacă afișează rich results în SERP pe baza unei combinații de calitate a paginii, query-ul căutat, dispozitivul utilizatorului, și diversitatea SERP-ului. Schema corectă te face eligibil; conținutul bun te face afișat. Site-uri cu schema impecabilă rămân fără rich snippets dacă sunt nou-publicate sau au autoritate scăzută.

Cum verifici că JSON-LD-ul tău e corect?

Cu Google Rich Results Test (search.google.com/test/rich-results) și cu Schema.org Validator. Primul îți spune ce rich result-uri poate produce; al doilea îți spune dacă schema e validă la nivel de format. Rulează ambele la fiecare schimbare structurală. Pentru monitorizare continuă, Search Console arată erori de schema agregat pe site.