Nel mio articolo precedente ti ho raccontato di quando ho tradotto della documentazione in nove lingue: ogni check tornava verde e molte cose erano rotte. Questa storia nasce dallo stesso periodo di lavoro e punta esattamente dalla parte opposta, e secondo me è la più scomoda delle due:
Non era rotto niente. E qualcosa non aveva comunque mai funzionato.
Ti spiego la situazione. Il mio sito è in inglese e in italiano. Ogni pagina ha la sua gemella. Nell’HTML c’è un tag il cui unico lavoro è dire a Google “questa pagina e quella sono la stessa pagina, in due lingue” — si chiama hreflang, ed è il motivo per cui chi cerca in italiano finisce sulla versione italiana invece che su quella inglese.
Sulla mia homepage non aveva mai funzionato. Non “funzionava male”. Mai funzionato, dal giorno in cui l’ho messo, che git dice essere il 2026-07-12. Trentatré giorni.
E in quei trentatré giorni non c’era assolutamente niente che sembrasse sbagliato. Entrambe le homepage erano online. Entrambe si vedevano perfettamente. Ogni link del sito portava dove diceva di portare. Nessun errore, nessun avviso, nessuna build fallita, niente di rosso da nessuna parte. Avevo quattro check automatici che giravano ad ogni build ed erano verdi tutti e quattro — uno dei quali l’avevo scritto proprio per proteggere l’indicizzazione.
L’ho scoperto solo perché avevo collegato il sito a Google Search Console pochi giorni prima, e finalmente aveva raccolto abbastanza dati per dire qualcosa.
La versione breve
- Search Console mi diceva che 228 delle mie 254 pagine erano indicizzate — il 90%. Sembrava una buona notizia, e stavo per chiudere la scheda.
- Delle 26 che mancavano, sei erano archiviate sotto “pagina con reindirizzamento”. Sono quelle sei ad aver portato a tutto il resto.
- La causa era uno slash mancante in fondo ai miei link. Il mio host risponde a
/aboutrimbalzandoti su/about/. Nel browser non lo vedi succedere, quindi nessuno se ne accorge — ma io pubblicavo nove indirizzi che facevano tutti quel giro. - Otto di quei nove erano link normali, di quelli che si cliccano. Il nono stava dentro il tag che accoppia la mia homepage inglese e quella italiana — e quel tag vale solo se l’indirizzo che nomina risponde diretto. Il mio nominava la deviazione, quindi a Google non è mai stato detto davvero che le due pagine fossero una coppia.
- La mia pagina 404 annunciava due indirizzi che non esistono —
/404/e/it/404/— come se fossero vere pagine tradotte. Due dei tre errori “non trovato” nel report erano opera del mio stesso sito. - Tutti e nove gli indirizzi uscivano da una funzione sola, quindi una correzione di due righe li ha sistemati tutti insieme. Compreso quello invisibile, che a mano non avrei mai trovato.
- E il check che ho scritto dopo è fallito al primissimo giro, prendendo una copia dello stesso errore rimasta nell’unico posto in cui mi ero dimenticato di guardare.
Un redirect non è un bug, ed è esattamente questo il problema
Partiamo dalla meccanica noiosa, perché tutto il resto viene da lì.
Quando hai un sito statico, una pagina come about di solito vive in una cartella come about/index.html. Chiedi /about/ e la ottieni. Chiedi /about — senza slash — e quasi tutti gli host, il mio compreso, ti rimandano un redirect: “qui non c’è, prova /about/”.
Non è un errore. È il comportamento giusto, standard, e funziona così da sempre. Scrivi /about nel browser e atterri sulla pagina About, immediatamente, senza il minimo segno che sia successo qualcosa.
Così quando ho scritto i link della navigazione senza lo slash finale, niente me l’ha detto. Non la build. Non il browser. Non una singola persona che gira il sito. I link funzionavano. Facevano solo un salto in più prima, ogni singola volta, e un salto che nessuno vede è un salto di cui nessuno parla.
Nove URL, su ogni pagina del sito: /about, /blog, /learn, /privacy, la gemella italiana di ciascuno, più /it stesso.
Google l’ha notato. Google lo archivia sotto “pagina con reindirizzamento” e, ragionevolmente, non indicizza la versione che rimanda: indicizza quella che risponde. Che va benissimo! È il sistema che funziona. Sei scansioni sprecate sono un’inezia e ci avrei fatto una spallucciata.
Poi ho guardato dove viveva il nono.
Quello che non era un link
Otto di quegli URL erano link per le persone. Voci di menu, footer, bottoni.
Il nono era /it — e compariva nel tag hreflang della mia homepage.
Quel tag non è un link che qualcuno clicca. Niente nella pagina lo indica. Non è navigazione, non è contenuto, non ha alcun aspetto visibile. È una dichiarazione su una relazione: la homepage inglese e la homepage italiana sono la stessa pagina in due lingue.
E una dichiarazione così ha una condizione attaccata: l’indirizzo che nomini deve essere quello vero — l’URL canonico, quello che risponde diretto. Se al suo posto nomini un redirect, la dichiarazione non viene onorata. Non hai fatto un’affermazione debole. Non hai fatto alcuna affermazione.
Quindi per trentatré giorni la mia homepage inglese diceva “la mia gemella italiana sta a /it”, /it diceva “in realtà, /it/”, e l’accoppiamento silenziosamente non avveniva.
Ora fermati su come si presentava tutto questo dal mio lato. Entrambe le pagine esistevano. Entrambe erano nella sitemap. Entrambe venivano servite, correttamente, a chiunque le chiedesse. Se mi avessi dato il sito dicendo “qui una cosa non ha mai funzionato, trovala”, avrei potuto cliccare ogni link, leggere ogni pagina in entrambe le lingue, far girare ogni check che ho, e non trovare niente — perché non c’era niente da trovare. Le due pagine stavano bene. Era la linea tra loro che non esisteva.
Una cosa la puoi guardare. Una relazione no.
Questa è la parte che ti voglio davvero lasciare, e mi è servito un giorno per dirla così semplice.
Una pagina ha un aspetto. Se è rotta, qualcosa sembra rotto — un buco, un colore sbagliato, una frase che si interrompe. Quello lo prendi guardando, e guardare costa poco, ed è per questo che quasi tutti i nostri istinti sul “controllare il proprio lavoro” sono in realtà istinti sul guardare le cose.
Una relazione tra due pagine non ha aspetto. Non c’è niente da renderizzare. Non vive su nessuna delle due in una forma che un essere umano legge; vive in un’affermazione che una pagina fa sull’altra, rivolta a una macchina che passerà più tardi e deciderà se crederci. Se l’affermazione è malformata, entrambe le pagine continuano a sembrare perfette, perché entrambe le pagine sono perfette. Il difetto non sta in nessuna delle due.
E quindi l’intera categoria è invisibile al guardare. Non “difficile da vedere”. Strutturalmente invisibile — non esiste una vista in cui compaia.
Una volta trovata quella frase, sono andato a farmi la lista di tutto quello che sul mio sito ricade in questa categoria, ed è più lunga di quanto pensassi:
hreflang— una relazione tra due pagine. Questa.canonical— un’affermazione su quale indirizzo sia quello vero, quando più indirizzi potrebbero servire la stessa pagina.- I dati strutturati — una descrizione della pagina scritta per le macchine, che nessun visitatore vede mai. Nel mio caso è un blocco di JSON nell’
<head>. Potrebbe descrivere un sito completamente diverso e la pagina si vedrebbe identica. - I redirect — cose che funzionano, solo non necessariamente per lo scopo per cui ti servivano.
- Le direttive
robots— qui una sola parola sbagliata ti toglie dalla ricerca, nel giro di settimane, senza sintomi visibili in nessun momento. Questa mi spaventa abbastanza da avere un check tutto suo.
Tutto quello che sta in quella lista ha la stessa forma. Niente di tutto ciò è contenuto. È tutto un messaggio sulla pagina, indirizzato a un motore di ricerca.
Ed è per questo che aprire il tuo sito non ti dice niente su nessuna di queste cose. Quello che vedi nel browser è la pagina. Queste cose non stanno sulla pagina: sono biglietti attaccati alla pagina perché li legga qualcun altro, e quel qualcun altro non sei tu. Puoi fissare una pagina renderizzata alla perfezione per tutto il giorno senza scoprire niente su quel biglietto — se fosse corretto, se si contraddicesse, se indicasse un indirizzo che non esiste.
Quindi l’unico che può dirtelo è il destinatario. Per me è Google Search Console — gratis, e riferisce con circa una settimana di ritardo. L’avevo collegato all’inizio dello stesso mese e non l’avevo ancora letto, di proposito: una proprietà appena creata non ha dati dentro, e non c’era davvero niente da vedere. Questa è stata la prima volta che aveva abbastanza storia per dire qualcosa, e la prima cosa che ha detto è che c’era qualcosa di sbagliato da sempre.
La correzione era una funzione, ed è tutta la ragione per cui è stata piccola
Ecco la parte che è stata bella, ed è l’unico consiglio di ingegneria ordinaria di questo articolo.
Tutti e nove gli URL uscivano dallo stesso posto. Ho esattamente una funzione che costruisce un percorso per una data lingua — la usa il menu, la usa il footer, la usano i bottoni, la usano i breadcrumb, e la usano i tag hreflang. Era così:
// L'inglese non ha prefisso; le altre lingue prendono il loro.
export function localizePath(path, lang) {
const clean = path === '/' ? '' : path;
return lang === defaultLang ? path : `/${lang}${clean}`;
}
Leggila e vedi tutto il bug. Passa fedelmente qualunque cosa le dai, e io le stavo dando /about. E per la homepage fa una cosa un filo peggiore: path === '/' diventa una stringa vuota, quindi / in italiano esce come /it, senza slash del tutto. È il caso della homepage. È quello che è costato trentatré giorni.
La correzione sono due righe:
export function localizePath(path, lang) {
const withSlash = path.endsWith('/') ? path : `${path}/`;
return lang === defaultLang ? withSlash : `/${lang}${withSlash}`;
}
Una funzione, e il menu, il footer, i bottoni, i breadcrumb e i tag hreflang di 240 pagine sono tornati corretti tutti nello stesso momento.
Voglio essere chiaro sul perché te lo racconto, perché “mettilo in un posto solo” è un consiglio che hai già sentito fino a farci la tappezzeria. Il punto non è che centralizzare sia elegante. Il punto è come sarebbe andata l’alternativa su questo bug preciso. Se quei percorsi fossero stati scritti a mano in nove componenti, avrei corretto i sei che Search Console mi ha nominato, mi sarei sentito a posto, e avrei lasciato lì l’hreflang — il solo che contasse davvero. Perché è quello che non potevo vedere.
Ecco quindi la ragione che vale più dell’ordine. Il bug che potevo vedere e quello che non potevo vedere erano lo stesso bug, nelle stesse due righe. Correggere quello di cui Google si lamentava — un link del menu — ha riparato l’hreflang nello stesso istante, senza che io sapessi che era quella la parte importante. Ho ottenuto gratis la correzione che non avrei saputo trovare, come effetto collaterale di quella che sapevo fare.
E funziona solo perché a costruirli era una funzione sola. Con nove copie scritte a mano avrei corretto i sei di cui mi avevano parlato e mi sarei fermato lì.
Il check che ho scritto, e cosa ha preso nei primi dieci secondi
Ho aggiunto un check che gira ad ogni build. Legge il sito finito e, per ogni URL che punta al mio dominio — nei link, nel canonical, negli hreflang e dentro i dati strutturati — verifica due cose: che l’indirizzo finisca con lo slash, e che ci sia davvero qualcosa.
L’ho lanciato aspettandomi di passare, perché avevo già corretto tutto a mano e controllato.
È fallito subito.
La mia pagina 404 — che avevo appena rivisto, proprio per togliere gli URL sbagliati — stava ancora annunciando /404/ dentro i suoi dati strutturati. Avevo sistemato i tag nell’<head> e non avevo mai pensato al blocco di JSON più sotto, che descrive la pagina nominando il proprio indirizzo. Stesso URL sbagliato, secondo nascondiglio, e gli ero passato accanto.
C’è un dettaglio nel perché gli sono passato accanto che ti passo, perché è una trappola con il mio nome sopra. Quando ho controllato i dati strutturati a mano, ci ho cercato dentro un pattern. Il pattern era scritto come si presenta il JSON quando è formattato per le persone, con uno spazio dopo i due punti. Il mio sito lo minifica, quindi lo spazio non c’è. La mia ricerca non ha trovato nulla, non ha stampato nulla, e io ho letto quel silenzio come un certificato di buona salute.
Se questo errore ti suona familiare è perché è il tema del mio articolo precedente — avevo fatto la cosa identica con un’altra ricerca su un altro progetto, e ci ho pubblicato sopra un pezzo intero pochi giorni prima di rifarlo qui. Quindi non te lo rispiego: sta là, e in versione migliore.
Quello che voglio dirti è che scriverlo non mi ha fermato. Avevo descritto questo identico errore nel dettaglio, in pubblico, nell’articolo subito prima di questo, e l’ho fatto lo stesso. Capire una trappola, a quanto pare, non protegge quasi per niente dal caderci dentro. Ed è proprio questo l’argomento a favore del check: non perché non lo sappia, ma perché saperlo dimostrabilmente non basta.
Ed è anche il motivo per cui il check fa il lavoro in modo diverso da come l’ho fatto io. Io ho cercato un pattern nel testo; il check legge i dati strutturati come dati. Li trasforma in un oggetto vero e percorre ogni indirizzo che ci trova dentro. È tutta lì la differenza: una ricerca testuale che non trova niente è indistinguibile da una ricerca testuale che non ha trovato niente di sbagliato, e da fuori non puoi dire quale delle due sia. Un parser non può farti questo scherzo. O legge la struttura e controlla ogni indirizzo, o fallisce rumorosamente perché la struttura non era quella che si aspettava. Non esiste una via di mezzo silenziosa, vuota e rassicurante.
E poi ho fatto l’unica cosa che ho davvero imparato a fare: ho rotto il sito di proposito, per vedere se il check se ne accorgeva. Ho messo in una pagina un link senza slash — preso. Ho puntato un hreflang a una pagina che non esiste — preso. Ho tolto uno slash da un URL che compare solo dentro i dati strutturati, da nessun’altra parte — preso. Poi ho rimesso tutto a posto.
Dieci minuti. Senza quelli avrei una spunta verde che non avevo alcun motivo di credere.
Quindi cosa ti direi di fare
Tre cose, e sulla prima sola insisterei.
Vai ad aprire Search Console. Adesso, prima di finire di leggere. Non per sistemare niente — solo per guardare il report di indicizzazione e vedere cosa dice di pagine che davi per buone. È gratis, probabilmente l’hai già collegato, ed è l’unica cosa che possiedi capace di vedere la categoria di problemi che ti ho descritto. E se l’hai appena installato, mettiti un promemoria fra un paio di settimane: una proprietà vuota non ti dice niente, ed è facile guardarla una volta, non vedere nulla e non tornarci più. Novanta per cento indicizzato non è la stessa cosa di qui non c’è niente da vedere — te l’avrei detto anch’io, fino al momento in cui ho letto l’altro 10%.
Quando trovi qualcosa, seguilo oltre la prima spiegazione. Sei URL che rimandano è una scoperta noiosa. Stavo per archiviarla, e la cosa interessante stava sotto — non nelle sei pagine che Google mi ha nominato, ma nel nono URL con la stessa causa che Google non aveva modo di segnalare, perché dal suo lato non c’era niente da segnalare. Semplicemente non gli era mai stato detto che le due pagine fossero collegate.
Fatti la tua lista delle cose senza sintomi. È questa la generalizzazione vera e va molto oltre l’hreflang. Per non farti partire da zero, ecco una lista concreta — ognuna di queste può essere sbagliata su un sito che sembra perfetto:
- Il codice di stato della tua pagina 404. Una schermata “pagina non trovata” può essere servita con un
200 OK, che ai motori di ricerca dice che ogni indirizzo sbagliato del tuo sito è una pagina vera. All’occhio è identica nei due casi. Il mio sito ha fatto così per mesi e l’ho scoperto per caso. - La tua sitemap, che elenca in silenzio pagine che hai cancellato, o che si dimentica quelle che hai aggiunto.
- L’anteprima che vede chi condivide il tuo link — immagine, titolo, descrizione. Sei l’unica persona che non la vede mai.
- I redirect dopo uno spostamento. Funzionano per i tre URL che hai provato a mano.
- Se l’email del tuo form di contatto arriva davvero. Il form dice grazie in ogni caso.
- Le regole
robots, ilcanonical, i dati strutturati, l’hreflang— quelle di cui parla questo articolo.
Passale in rassegna e controlla quelle che ti riguardano. Non guardando il tuo sito: andando a cercare la cosa dall’altra parte che può davvero risponderti. A me è servita circa un’ora per tutte, e le stavo trattando tutte quante come se fossero il genere di cosa che puoi semplicemente vedere.
La versione comoda di questa storia è che ho trovato un bug e l’ho corretto. La versione vera è che una cosa piccola e invisibile è stata sbagliata per trentatré giorni mentre ogni strumento che possiedo diceva che andava tutto bene — e il solo motivo per cui lo so è che uno strumento nuovo ha finalmente avuto abbastanza dati per dire il contrario, e che mi è venuta curiosità per un numero che sembrava buono.
Le cose di cui parla questo articolo
Il check è uno scriptino che legge il sito costruito; non c’è niente di furbo dentro, e tutto il suo valore sta nel fatto che falla. Se vuoi il pezzo compagno — lo stesso modo di sbagliare dall’altro lato, dove ogni check passava e le pagine erano piene di buchi — è Ogni check è passato. Molte cose erano rotte. →
E se preferisci leggere di come si sbaglia in pubblico in un senso più letterale, una volta ho pubblicato nove identificatori che non esistono: Nove nomi sbagliati →
Se da qui ti porti via una cosa sola: un check verde ti dice che una cosa sta bene. Non può dirti che due cose sono collegate. Vai a chiederlo a qualcosa fuori dal tuo progetto.
Buon viaggio,
Francesco