export function buildCanonicalUrl(pathname: string, searchParams: URLSearchParams): string {
const baseUrl = 'https://eduardweb.ro';
const allowedParams = ['page']; // Păstrăm doar parametrii esențiali de indexare
const cleanParams = new URLSearchParams();
for (const param of allowedParams) {
if (searchParams.has(param)) {
cleanParams.set(param, searchParams.get(param)!);
}
}
const queryString = cleanParams.toString();
return `${baseUrl}${pathname}${queryString ? `?${queryString}` : ''}`;
}Tag-ul rel="canonical" este probabil cel mai prost înțeles instrument din SEO tehnic. Am văzut zeci de magazine online care au pierdut 30-40% din traficul organic doar pentru că cineva a decis din greșeală să canonicalizeze paginile 2, 3 și 4 direct pe pagina principală a categoriei.
Canonical-ul nu este o directivă strictă (cum e un 301 redirect sau robots noindex), ci un hint puternic pe care Google îl poate ignora cu grație dacă semnalele din pagină îl contrazic.
Parametri de URL: tracking vs. filtrare
Cea mai simplă problemă o reprezintă parametrii de tracking (utm_source, fbclid, gclid). Aici regula e bătută în cuie: pagina cu parametri trebuie să aibă canonical către URL-ul curat, fără query string. Dacă ai un URL de forma site.ro/produs?utm_campaign=blackfriday, canonical-ul trebuie să fie strict site.ro/produs.
La filtre (fațete) povestea se complică:
- Filtre triviale (sortare după preț, număr de produse pe pagină): canonicalizezi către categoria de bază (
/telefoane). - Căutări cu intenție clară de volum (
/telefoane/apple/culoare-negru): creezi URL dedicat, cu conținut optimizat, meta tags unice și self-referencing canonical.
Greșeala clasică este să pui canonical către rădăcină pe pagini filtrate care conțin zeci de produse unice. Google va vedea că produsele diferă masiv de pagina de bază, va considera canonical-ul greșit și va alege el singur un URL arbitrar.
Paginarea: capcana paginii 1
Acum câțiva ani, Google recomanda rel="prev" și rel="next". În 2019 au anunțat oficial că nu le mai folosesc ca semnal de indexare. De atunci, mulți devi fac o gafă masivă: pun canonical de pe /blog?page=2 către /blog.
Ce se întâmplă în realitate? Googlebot nu va mai indexa articolele sau produsele care apar exclusiv pe pagina 2 sau 3, pentru că îi spui că acele pagini sunt identice cu prima. Paginile paginate trebuie să aibă self-referencing canonical (/blog?page=2 are canonical pe /blog?page=2). Nu canonicaliza niciodată o pagină paginată către prima pagină decât dacă prima pagină este o versiune "View All" care conține absolut toate elementele.
Cross-domain syndication
La un proiect anterior, publicam articolele tehnice pe blogul companiei și le republicam integral pe Medium și Dev.to pentru reach. Dacă lași platformele externe să fie indexate fără canonical cross-domain, domeniul lor (având autoritate mult mai mare) îți va fura poziția în SERP.
Soluția e simplă: pe Dev.to sau Medium setezi canonical_url exact către articolul tău original (https://domeniultau.ro/blog/articol). Google va acorda creditul SEO domeniului tău, chiar dacă versiunea de pe Medium adună mai multe vizualizări.
Trade-off-uri reale
Canonical-ul rezolvă crawl budget-ul și diluarea de PageRank, dar are costuri de procesare dacă ai generare dinamică greșită. Nu uita: un canonical prost configurat ascunde conținut util de la indexare. Dacă Googlebot găsește link-uri interne care trimit către URL-ul necanonicalizat, tag-ul tău va fi deseori ignorat.
Voi cum gestionați generarea dinamică de canonical la stack-urile moderne cu SSR (Next.js / Nuxt)? Folosiți middleware sau logica din controller?