frontend

hreflang: ce este, cum se setează corect, capcanele care strică indexarea

hreflang spune motoarelor de căutare ce versiune lingvistică să afișeze pentru fiecare audiență. Cum se setează și ce capcane te scot din index.

Cuprins

hreflang este atributul HTML prin care declari care versiune lingvistică sau regională a paginii să fie afișată fiecărei audiențe. Se setează prin tag-uri <link rel="alternate"> în <head> sau prin blocuri <xhtml:link> în sitemap. Confuzia tipică este că hreflang ar duplica conținutul (nu o face) sau ar îmbunătăți ranking-ul (nu îl îmbunătățește); rolul lui este să clarifice ce versiune se afișează unde.

Specificat de Google în 2011 și menținut consistent de atunci, hreflang este una dintre puținele unelte SEO unde Google spune limpede ce așteaptă și unde rezultatele se văd cu certitudine la verificare. Restul (canonical, schema markup, content quality) sunt mai opace.

Ce este hreflang mai exact?

O declarație simetrică prin care fiecare versiune a paginii își indică surorile. Dacă example.com/page există în trei versiuni (română, engleză, franceză), fiecare dintre cele trei pagini conține trei tag-uri hreflang: unul pentru fiecare versiune, inclusiv pentru ea însăși (self-reference).

Două principii care nu se calcă:

  • Bidirecționalitate (return tags). Dacă pagina RO declară versiunea EN ca alternativă, pagina EN trebuie să declare versiunea RO ca alternativă înapoi. Lipsa return tag-ului face Google să ignore declarația.
  • Auto-referință. Pagina RO conține și un tag pentru ea însăși (hreflang="ro" către propria URL). Pare redundant, dar e cerut de specificație.

Codurile folosite sunt ISO 639-1 pentru limbă (ro, en, fr) și opțional ISO 3166-1 alpha-2 pentru regiune (ro-RO, en-US, en-GB). Specificul regional contează doar când conținutul diferă efectiv pentru fiecare regiune (preț, monedă, regulament). Pentru același conținut servit tuturor vorbitorilor unei limbi, folosește doar codul de limbă.

Cum arată în HTML și în sitemap?

Două sintaxe echivalente. În HTML, fiecare pagină are în <head> tag-uri de forma:

<link rel="alternate" hreflang="ro" href="https://crawlerra.com/blog/articolul-meu">
<link rel="alternate" hreflang="en" href="https://crawlerra.com/en/blog/my-article">
<link rel="alternate" hreflang="x-default" href="https://crawlerra.com/blog/articolul-meu">

În sitemap, fiecare URL are blocuri <xhtml:link> imbricate care declară aceleași alternative:

<url>
  <loc>https://crawlerra.com/blog/articolul-meu</loc>
  <xhtml:link rel="alternate" hreflang="ro" href="https://crawlerra.com/blog/articolul-meu"/>
  <xhtml:link rel="alternate" hreflang="en" href="https://crawlerra.com/en/blog/my-article"/>
  <xhtml:link rel="alternate" hreflang="x-default" href="https://crawlerra.com/blog/articolul-meu"/>
</url>

Pentru detalii despre cum se compune corect un sitemap.xml care include hreflang, vezi entry-ul dedicat.

Care sunt cele cinci capcane care îți strică indexarea?

  • Return tag lipsă. Pagina RO declară EN ca alternativă, dar pagina EN nu declară RO ca alternativă. Google ignoră declarația complet. Cea mai frecventă cauză de „hreflang nu funcționează"; Search Console o flaghează direct.
  • x-default fără logică. Setezi x-default către o pagină care nu există sau către aceeași URL pentru fiecare limbă. Trebuie să fie o singură URL, identică declarată pe toate paginile alternative, către versiunea fallback.
  • Confuzie limbă vs regiune. Setezi hreflang="ro-MD" pentru un articol generic în română doar pentru că vrei să targetezi diaspora din Moldova. Google nu serveste acea versiune nimănui pentru că nu există conținut diferențiat regional. Folosește ro simplu.
  • URL-uri care redirecționează sau care răspund cu 404 în alternative. Declari ca alternativă un URL care redirecționează în altă parte sau care nu există. Google îl ignoră, dar Search Console raportează erori și poate scoate pagina din international targeting pe timp limitat.
  • Coduri invalide. Folosești cn pentru chineză (corect este zh) sau uk pentru engleza britanică (corect en-GB; uk e ucraineană). Specificația ISO este strictă; orice cod invalid e ignorat fără avertisment vizibil.

Cum îl folosim noi la crawlerra.com?

crawlerra.com servește două versiuni lingvistice: română (URL de bază /) și engleză (URL prefixat /en). Pentru paginile bilingve (homepage, privacy, contact), SeoService generează tag-urile hreflang în timpul randării SSR, cu auto-referință + cealaltă limbă + x-default către versiunea română.

Pentru articolele de blog și intrările de dicționar (care încă nu au versiune engleză), strategia este diferită: setăm hreflang="ro" și hreflang="x-default" ambele către aceeași URL în română, fără hreflang="en". Asta semnalează lui Google că nu există versiune engleză și că pagina română este fallback-ul global. Când vom publica primele articole EN (per planul nostru, după 30 de articole RO ranked în top 50), adăugăm tag-ul en către URL-ul nou și inversăm x-default-ul.

Asimetria asta este intenționată și aliniată cu cum gândește Google despre fallback: dacă utilizatorul nu se potrivește pe nicio limbă declarată, primește x-default. Pentru un site bilingv care încă nu e bilingv pe toate paginile, x-default către versiunea existentă e răspunsul corect; nu lăsa nimic gol și nu declara EN cu o URL goală. Și nu confunda asta cu canonical: canonical-ul este despre duplicate de conținut, hreflang este despre versiuni lingvistice. O pagină EN și o pagină RO nu sunt duplicate (au limbi diferite); fiecare are propriul canonical către ea însăși, iar hreflang spune cum se leagă.

Tag-urile sunt injectate în SSR direct, nu prin client-side hydration; vezi server-side rendering pentru contextul tehnic. La fiecare schimbare în prompt (în SeoService.applyArticle / applyBlogIndex), folosim un audit Search Console ca să confirmăm că noile pagini sunt interpretate corect. Detalii despre implementare în ghidul pentru SSR Angular; pilotul nostru editorial demonstrează tag-urile live la articolul despre cum scriem articolele.

Cum verifici că hreflang funcționează?

Trei verificări, în ordinea în care le rulezi după un deploy. View Source pe pagină îți arată tag-urile literal; trebuie să vezi minimum auto-referința, plus orice alternativă declarată. Dacă nu vezi tag-urile, probabil JavaScript-ul le adaugă post-hydration și pagina ta nu e SSR corect (vezi JSON-LD pentru aceeași problemă cu schema markup).

Google Search Console are o secțiune dedicată în „Legacy tools and reports" → „International Targeting". Acolo vezi numărul de hreflang-uri detectate, erorile de return tag, și conflictele de URL. Updatarea ia 1-3 zile după publish.

Pentru investigații punctuale, folosește un validator extern (Aleyda Solis' hreflang testing tool sau Ahrefs Site Audit). Acestea simulează ce vede Google și îți spun unde return tag-urile lipsesc. Pentru site-uri sub 100 de pagini, o foaie de calcul cu URL-urile RO + EN + relațiile între ele este suficientă pentru un audit lunar1; pentru site-uri mari, automatizează verificarea în CI.

  1. Strategia bilingvă a crawlerra.com folosește SeoService.applyHome() + applyPrivacy() pentru pagini cu ambele versiuni, și SeoService.applyArticle() cu removeAlternate("en") pentru articole doar în română. [crawlerra.hreflang_strategy]

Întrebări frecvente

Trebuie hreflang dacă am un singur limbaj?

Nu. hreflang există ca să dezambiguizeze între versiuni lingvistice multiple ale aceluiași conținut. Dacă ai un singur limbaj și o singură regiune țintă, nu adaugi nimic util pentru Google. Adaugă-l doar când publici primele pagini într-o a doua limbă.

hreflang merge în HTML head sau în sitemap?

În oricare, dar consistent. Tag-urile <link rel="alternate" hreflang="..."> în <head> sunt cel mai des folosite și mai ușor de verificat la nevoie. Sitemap-ul cu blocuri <xhtml:link> e util pentru site-uri mari (mii de URL-uri) unde editarea head-ului paginilor e costisitoare. Este permis să le folosești pe ambele simultan, dar trebuie să fie identice; o singură contradicție și Google ignoră ambele.

Care e diferența între "ro" și "ro-RO"?

"ro" e limba, "ro-RO" e limba + regiunea. Folosește "ro" dacă servești pe orice vorbitor de română (din România, Moldova, diasporă). Folosește "ro-RO" doar dacă ai conținut specific pentru vorbitorii din România (preț în lei, regulament local). Aceleași reguli pentru en/en-US/en-GB. Codurile sunt ISO 639-1 pentru limbă și ISO 3166-1 alpha-2 pentru regiune.

Ce e x-default și când îl folosești?

x-default e versiunea pe care Google o afișează când nu are o potrivire mai bună după limbă sau regiune. De obicei e versiunea engleză sau un selector de limbă. Pentru un site bilingv ro/en, x-default poate să fie aceeași cu versiunea engleză. Pentru un site multilingv, x-default e de obicei un homepage neutru cu opțiune de selecție.

Cât durează până Google respectă hreflang-ul nou?

De la câteva zile la șase săptămâni, în funcție de rata de re-crawl. Search Console arată în „International Targeting" cum sunt interpretate hreflang-urile tale. Pentru un site mic, vei vedea schimbarea în 1-2 săptămâni; pentru unul mare, mai mult. Nu te aștepta la efecte instant; hreflang este corectare de targeting, nu boost de ranking.