Lezioni SEO da una correzione del nostro sito
Per alcuni giorni abbiamo letto il nostro sito come lo legge un motore di ricerca, e abbiamo trovato sei cose da sistemare. Ogni pagina dichiarava due blocchi FAQ, Google usava come miniatura un alone decorativo dello sfondo, alcune pagine modello comparivano per ricerche a cui non rispondevano, e una nuova sezione del sito era bloccata dal nostro stesso edge in staging. Niente di drammatico, ma tutto costava visibilità in silenzio.
Il sito in un paragrafo
mythex.ai è un'app a pagina singola che pre-renderizziamo in fase di build: uno script percorre ogni rotta, scrive un file HTML statico per ciascuna e inserisce titolo, descrizione e dati strutturati della pagina (il blocco JSON-LD che dice ai motori di ricerca di cosa tratta una pagina; vedi cos'è il markup strutturato). Gran parte di quello che segue sta in quel passaggio di pre-rendering, perché è l'HTML che un crawler legge davvero.
1. Ogni pagina si dichiarava la pagina delle FAQ
Sintomo. Il nostro template HTML conteneva un blocco FAQPage valido per tutto il sito, con l'URL che puntava a /faq. Il pre-rendering aggiungeva poi il FAQPage di ciascuna pagina. Quindi ogni pagina del sito ne conteneva due, e la nostra informativa sulla privacy diceva a Google di essere la pagina delle FAQ.
Perché conta. Google si aspetta al massimo un FAQPage per pagina. Un secondo blocco che punta altrove è il tipo di cosa che fa scontare il markup di una pagina, non solo lo fa ignorare.
Soluzione. Il blocco globale è stato eliminato. Il markup FAQ di ogni pagina ora arriva da un solo punto, compresa la stessa /faq, che lo costruisce dall'elenco completo delle domande. Le pagine senza FAQ ora non dichiarano nulla, che è la risposta onesta. E il pre-rendering fa fallire la build se una pagina ne porta di nuovo più di una. Una regola che vive solo nella memoria di qualcuno prima o poi viene infranta; una regola imposta dalla build no.
2. Google usava l'immagine sbagliata
Sintomo. Nei risultati di ricerca, la miniatura di Mythex era il bagliore pulsante che sta dietro l'hero della homepage, un'immagine decorativa, invece della nostra scheda di condivisione.
Perché è successo. Non avevamo detto a Google quale immagine rappresentasse una pagina, quindi ne ha scelta una che ha trovato.
Soluzione. Due lati dello stesso problema:
- Indica qual è l'immagine della pagina. La homepage ora ha un nodo
WebPagecon unprimaryImageOfPageche punta alla scheda di condivisione, e i dati strutturati di ogni pagina pre-renderizzata portano una propria immagine (l'immagine di condivisione della pagina, o quella predefinita). - Nascondi la decorazione. Le immagini di sfondo ora sono vietate in
robots.txte servite con un headernoindex, noimageindex, così restano fuori dalla ricerca immagini e dalle miniature.
3. I motori di ricerca conoscevano solo il nostro logo
Il markup Organization aveva un nome, un logo e alcuni link social: solo branding. I motori di ricerca costruiscono il pannello di conoscenza di un'azienda a partire da dati di tipo registro, quindi abbiamo aggiunto quelli della nostra licenza commerciale: ragione sociale, data di fondazione, fondatore e sede legale. Il numero di telefono l'abbiamo lasciato fuori di proposito.
4. Le pagine modello rispondevano alla domanda sbagliata
Sintomo. Search Console mostrava tre pagine modello con impressioni e nessun clic. Una compariva per «content strategist portfolio» e varianti, una per «best italian restaurant website design», una per un gruppo di ricerche intorno ad «agile board». Metà di quelle ricerche includeva la parola «free». Le posizioni andavano dalla 20ª alla 50ª circa.
Perché. Ogni pagina rispondeva a una domanda diversa da quella posta. Chi voleva vedere com'è un buon sito per un ristorante italiano finiva su una pagina che vendeva un costruttore.
Soluzione. Ognuna delle tre ora ha una sezione scritta per la ricerca anziché per il prodotto, un titolo e una descrizione con le parole che la gente digita, e FAQ che valgono il markup che già emettevano.
Lo stesso commit ha risolto un problema più silenzioso. Il blocco «modelli correlati» prendeva i primi quattro modelli di una categoria, quindi ogni modello di portfolio puntava agli stessi quattro portfolio, e il resto della categoria non aveva alcun link interno. Lo abbiamo sostituito con un anello ordinato per sottocategoria: ogni pagina modello ora ha esattamente quattro link in entrata e quattro in uscita. Anche l'HTML pre-renderizzato ora stampa quei link: prima esistevano solo dopo che girava il JavaScript, cosa che un crawler potrebbe non fare mai.
5. Avvisare Bing delle pagine nuove appena vengono pubblicate
Google ignora IndexNow, un protocollo per segnalare ai motori di ricerca che un URL è cambiato. Lo usano Bing, Yandex e Seznam, e l'indice di Bing è quello che legge la ricerca di ChatGPT. Un costruttore di app con IA che gli assistenti IA non riescono a trovare è un tipo particolare di fallimento.
L'approccio ovvio, inviare l'intera sitemap a ogni deploy, è il modo in cui una chiave viene limitata, e la maggior parte dei deploy non cambia nulla che interessi a un motore di ricerca. Quindi uno script confronta la sitemap che il sito sta servendo ora con quella appena costruita e invia solo la differenza.
Due dettagli hanno fatto funzionare la cosa:
- Fai lo snapshot prima del deploy. La base di confronto va catturata prima che la nuova build vada online. Dopo, la sitemap «in produzione» è già quella nuova e ogni differenza risulta vuota.
- Solo pagine nuove, per ora. La nostra sitemap non ha date
lastmod, quindi lo script segnala le pagine nuove ma non le riscritture. Assegnare a ogni URL la data della build farebbe risultare cambiato l'intero sito a ogni deploy: esattamente lo spam che stavamo evitando.
Gira solo sui deploy di produzione e non fa mai fallire la build: quando viene eseguito il sito è già online, e un ping a un motore di ricerca non vale un deploy rosso.
6. Il nostro edge diceva «non trovato»
Quando abbiamo lanciato le pagine /ai (ne parliamo in una landing page per ogni tipo di attività), lo staging mostrava «Not found» per tutte, mentre l'host statico le serviva correttamente.
Il servizio davanti ai nostri host di marketing inoltra solo un elenco consentito di percorsi; tutto il resto riceve un 404 secco. /ai era nuovo e non stava nell'elenco. Abbiamo aggiunto /ai e /ai/*, con un test che verifica che passino. Un bug piccolo, ma proprio del tipo che rende una nuova sezione invisibile ai crawler senza che nessuno se ne accorga.
Cosa ci siamo portati a casa
- Leggi l'HTML che legge un crawler. La maggior parte di questi problemi era invisibile nel browser e ovvia nel file pre-renderizzato.
- Trasforma le regole SEO in controlli di build. «Un solo FAQPage per pagina» ora è imposto, non ricordato.
- Di' ai motori di ricerca cosa intendi. Se non dici quale immagine o quali dati ti rappresentano, li indovineranno.
- Search Console ti dice quale domanda si è posta la gente. Impressioni senza clic di solito significano che la pagina rispondeva a un'altra domanda.
- Invia le differenze, non tutto. Segnalare solo ciò che è cambiato ti tiene al riparo dai limiti di frequenza.
Se fai lo stesso per un sito che hai costruito tu, le nostre guide su SEO per i siti costruiti con l'IA e come configurare Google Search Console coprono le basi.