C’è un momento, nella vita di chi lavora profittevolmente sul web da moltissimi anni, in cui ti senti assolutamente sicuro di fare sempre tutto nel migliore dei modi possibili. Questo perché, di solito, tutto quello a cui metti mano funziona subito al primo colpo – il vantaggio dell'esperienza 😄 – e continua a funzionare perfettamente nel tempo.

E invece, può anche succedere che a volte qualcosa si rompa in silenzio, senza che tu te ne accorga, se non quando è ormai troppo tardi e devi quindi correre ai ripari.

Nel mio caso, quel momento è arrivato alcuni mesi fa e a rompersi è stato proprio il mio blog professionale — esattamente, proprio quello dove ti trovi ora.

Un giorno Google ha semplicemente smesso di indicizzarlo. Nessun errore, nessun messaggio, nessun avviso in Search Console. Zero. Il vuoto assoluto. Semplicemente sparito da Google in un … poff!

Ma, se sono qui a scriverne, significa che ho trovato la causa del problema ed elaborato una soluzione che penso ti possa interessare. Quindi, ora ti racconto tutta la storia dall’inizio — mettiti comodo 🍿

L’inizio: una improvvisa e apparentemente inspiegabile deindicizzazione

Quando il problema si è presentato, il sito era tecnicamente impeccabile: Ghost aggiornato, sitemap regolari, performance ottime – i miei server sono imbattibili 😎 –, HTTPS perfetto, contenuti originali, nessun malware, eccetera eccetera — e ci mancherebbe altro: è il mio lavoro praticamente da sempre (!!!).

Eppure, nel giro di poche settimane, tutto è sparito. Gli articoli non comparivano più neanche cercando il titolo esatto e nella Search Console ovunque dominava la scritta:

“URL controllato, ma non indicizzato”

La prima ipotesi era la più ovvia: un problema di canonical o redirect.

Poco tempo prima, avevo infatti semplificato il dominio passando da https://www.ivan.agliardi.pro a https://ivan.agliardi.pro, idea apparentemente innocua e altrettanto priva di alcun beneficio, se non quello di rendere più semplice ricordare l’URL di questo sito.

Google, per qualche settimana, sembrava avere recepito la variazione. Poi, il silenzio, all’improvviso.

E quando ho deciso di fare marcia indietro ripristinando il www, la situazione non è affatto migliorata.

Allora, seguendo la logica del tipo di fraintendimento che il mio cambio di URL poteva avere indotto in Google, ho impostato un redirect 301 riparatore:

curl -I https://ivan.agliardi.pro
# → 301 Moved Permanently → https://www.ivan.agliardi.pro

Niente da fare. Il tempo passava e nessun cenno di ripristino dell’indicizzazione in Google Search Console.

Tutto il resto del server — decine di altri siti Ghost sullo stesso host — perfettamente indicizzati e super vivi.

Solo il mio blog invisibile … poff! 😭

Il momento della scoperta: i log non mentono mai

Dopo settimane in cui nulla sembrava cambiare e durante le quali avevo ben altre cose a cui pensare, ho deciso di guardare oltre la Search Console.

Ho aperto i log di accesso di Nginx e ho eseguito un semplice comando:

grep -E "Googlebot|bingbot" /var/log/nginx/access.log | tail -n 50

E ciò che ho scoperto è stato imbarazzante ma chiarissimo: non c’era traccia dei crawler di Google. Nessuna richiesta a sitemap.xml, nessuna visita alle pagine, nessun “GET” dai bot ufficiali. Era come se il dominio fosse stato “parcheggiato” da Google — esisteva ancora, ma non valeva più la pena di essere scansionato.

In quel momento ho realizzato che non era più un problema di contenuti o pubblicazione. Stavo regolarmente producendo nuovi articoli, aggiornando temi, creando link: ma Google non rilevava più attività significativa.

La causa era più sottile:

  • un cambio di host/dom ain (senza dichiarazione formale)
  • redirect multipli e temporanei
  • sitemap coerenti ma considerati “vecchi”
  • nessun segnale tecnico forte che dicesse “torna su questo sito”.

In pratica, Google aveva sospeso il crawling del sito, non per mancanza di contenuti, ma per instabilità strutturale.

Prima della svolta: tutti i tentativi (quelli sbagliati)

Prima di arrivare alla conclusione che i crawler non mi stessero più scansionando, ho passato giorni a fare quello che chiunque, al mio posto, avrebbe fatto: verifiche DNS incrociate, controlli ossessivi sui redirect 301 tra dominio nudo e www, test ripetuti con curl, analisi delle sitemap, confronto con altri siti Ghost sullo stesso server.

Ho riletto la documentazione di Ghost, rimesso mano alle API, ricontrollato le chiavi admin, rigenerato token JWT più volte, convinto che il problema fosse un errore di configurazione o di autenticazione.

Tutto era tecnicamente corretto, tutto rispondeva come previsto — e proprio questo è stato il primo vero campanello d’allarme: il problema non era ciò che rispondeva, ma ciò che non veniva più chiamato.

La soluzione tecnica: un “heartbeat” automatico

Serviva a questo punto un segnale chiaro, un messaggio inequivocabile da inviare ai server di Google che decidono quali siti scansionare e quali no, una cosa del tipo:

Hey! Guarda che il sito è di nuovo stabile, puoi toglierlo dalla lista dei cattivi e riprendere le scansioni!

Non volevo pubblicare articoli finti o modifiche inutili: volevo una azione tecnica discreta, efficace e automatizzata.

Ecco quindi che cosa ho messo in campo:

  1. Ho creato una chiave Admin API in Ghost per il dominio.
  2. Ho realizzato uno script in bash (ghost-freshping.sh) che fa quanto esegue:
    - genera un token JWT firmato correttamente per Ghost 6.x;
    - crea una pagina (“Fresh Ping”) via API (non un post visibile nella home);
    - pinga immediatamente Google e Bing con le sitemap aggiornate;
    - (opzionale) invia anche una richiesta a IndexNow.
  3. Ho schedulato lo script in cron perché venga eseguito ogni domenica mattina alle 5:
0 5 * * 0 /bin/bash /usr/local/ghost-freshping.sh >> /var/log/ghost-freshping.log 2>&1

In questo modo, ogni settimana il mio sito manda un piccolo “ping” tecnico che i motori di ricerca leggono come segnale di vita e stabilità.

Il codice completo dello script ghost-freshping.sh

Ecco il tuo script pronto per essere adattato e usato anche da altri (assicurati di sostituire ADMIN_API_KEY con la tua chiave reale):

#!/bin/bash
# Ghost Fresh Ping – SEO Revival Script (v6+)
DOMAIN="www.ivan.agliardi.pro"
ADMIN_API_URL="https://$DOMAIN/ghost/api/admin"
ADMIN_API_KEY="<ID>:<SECRET>"
SITEMAP_MAIN="https://$DOMAIN/sitemap.xml"
SITEMAP_POSTS="https://$DOMAIN/sitemap-posts.xml"
INDEXNOW_API_KEY=""

b64url() { openssl base64 -A | tr '+/' '-_' | tr -d '='; }

iat=$(date +%s)
exp=$((iat + 300))
id="${ADMIN_API_KEY%%:*}"
secret="${ADMIN_API_KEY#*:}"

header_json=$(printf '{"alg":"HS256","typ":"JWT","kid":"%s"}' "$id")
payload_json=$(printf '{"iat":%d,"exp":%d,"aud":"/admin/"}' "$iat" "$exp")

header=$(printf '%s' "$header_json" | b64url)
payload=$(printf '%s' "$payload_json" | b64url)
signature=$(printf '%s' "$header.$payload" | openssl dgst -binary -sha256 -mac HMAC -macopt hexkey:"$secret" | b64url)

JWT="${header}.${payload}.${signature}"

TODAY=$(date +"%Y-%m-%d %H:%M:%S")
HTML="<p>Fresh ping automatico del $TODAY.</p>"
HTML_ESCAPED=$(printf '%s' "$HTML" | jq -R .)

echo "🧱  Creazione pagina 'Fresh Ping'..."
RESP=$(curl -s -i -X POST "$ADMIN_API_URL/pages/?source=html" \
  -H "Authorization: Ghost $JWT" \
  -H "Content-Type: application/json" \
  -d "{
    \"pages\": [{
      \"title\": \"Fresh Ping – $TODAY\",
      \"html\": ${HTML_ESCAPED},
      \"status\": \"published\",
      \"visibility\": \"public\",
      \"tags\": [{\"name\": \"#fresh\"}]
    }]
  }")

if echo "$RESP" | grep -q '"pages"'; then
  echo "✅  Pagina creata correttamente."
else
  echo "⚠️  Errore durante la creazione della pagina!"
  echo "---- Risposta Ghost API ----"
  echo "$RESP"
  exit 1
fi

echo
echo "📡  Pingo Google..."
curl -s "https://www.google.com/ping?sitemap=$SITEMAP_MAIN" > /dev/null && echo "➡️  Sitemap principale OK"
curl -s "https://www.google.com/ping?sitemap=$SITEMAP_POSTS" > /dev/null && echo "➡️  Sitemap posts OK"

echo
echo "🌐  Pingo Bing e IndexNow..."
curl -s -G "https://www.bing.com/ping" --data-urlencode "sitemap=$SITEMAP_MAIN" > /dev/null && echo "➡️  Bing sitemap OK"
curl -s -G "https://www.bing.com/ping" --data-urlencode "sitemap=$SITEMAP_POSTS" > /dev/null && echo "➡️  Bing posts OK"

if [ -n "$INDEXNOW_API_KEY" ]; then
  curl -s -X POST "https://api.indexnow.org/indexnow" \
    -H "Content-Type: application/json; charset=utf-8" \
    -d "{
      \"host\": \"$DOMAIN\",
      \"key\": \"$INDEXNOW_API_KEY\",
      \"urlList\": [\"https://$DOMAIN/\", \"$SITEMAP_POSTS\"]
    }" > /dev/null && echo "➡️  IndexNow ping inviato"
else
  echo "ℹ️  Nessuna chiave IndexNow configurata (opzionale)"
fi

echo
echo "🚀  Operazione completata."
echo "Controlla tra 48 ore nei log Nginx se Googlebot è tornato:"
echo "grep 'Googlebot' /var/log/nginx/access.log | tail -n 20"

La lezione che ho imparato

... perché non si finisce mai e poi mai di imparare ...

Questa esperienza mi ha insegnato molte cose, ma soprattutto mi ha chiarito una verità che spesso si dimentica: i problemi di indicizzazione non dipendono quasi mai dalla frequenza di pubblicazione, soprattutto quando — come nel mio caso — il sito produce regolarmente nuovi contenuti ogni settimana.

Le cause tecniche vere, quelle che possono portare Google a sospendere completamente il crawl, sono altre — e molto più subdole.

🟥 1. Incoerenze temporanee nei redirect (anche se ora sono perfetti)

Il passaggio da www.ivan.agliardi.pro a ivan.agliardi.pro e poi il ritorno al www ha sicuramente generato una fase transitoria in cui Google ha visto canonical inconsistente o URL con segnali contrastanti.

Bastano pochi giorni di:

  • duplicati percepiti
  • sitemap puntate a un dominio mentre i contenuti rispondono su un altro
  • redirect multipli o invertiti
  • cache DNS sfalsate

perché Google decida di mettere in pausa l’intero dominio, anche una volta risolto tutto.

🟧 2. Change of address “non dichiarato” (ma rilevato dai crawler)

Google vede i passaggi di dominio, sottodominio e modifica host come cambi strutturali, simili a una migrazione.

Anche se non hai cambiato realmente dominio, un passaggio www → naked domain → www produce:

  • nuova canonical
  • nuova sitemap
  • nuova base URL in Ghost
  • nuovo modello di link interni
  • nuove richieste HSTS

Dal punto di vista dei crawler, questo è sufficiente per “resettare” le priorità.

🟨 3. Crawl budget ridefinito

Quando Google rileva modifiche strutturali, può cestinare lo storico e ridefinire la priorità del sito da zero.

Durante questo periodo, il crawler:

  • rallenta
  • poi si ferma
  • poi riprende solo quando riceve segnali freschi affidabili

Questo meccanismo spiega perché anche con 1–2 articoli nuovi la settimana il sito è rimasto invisibile.

🟩 4. Ghost e la sitemap “troppo statica”

Ghost genera ottime sitemap, ma:

  • non cambiano se non modifichi pagine o post,
  • non includono cambiamenti strutturali (es. modifiche al template),
  • non segnalano “eventi” tecnici al crawler.

In un contesto di redirect appena risolti, questo può contribuire all’apparenza di “sito fermo”, anche quando non lo è.

🟦 5. Crawl sospeso per segnali contraddittori

Google odia gli stati “ambigui”.

Nel tuo caso specifico, la combinazione era perfetta per un blocco temporaneo:

  • variazione del dominio canonico
  • ritorno al dominio precedente
  • sitemap aggiornate a intermittenza
  • redirect corretti ma visti “in ritardo”
  • DNS propagati in due fasi (Ghost + Apache su server diversi)
  • contenuti nuovi, ma struttura percepita come instabile

Il risultato?

Google mette il sito in una sorta di “quarantena” tecnica finché non riceve un segnale chiaro e affidabile.

La vera soluzione: dare un segnale tecnico, non editoriale

Il mio script fresh ping non serve a “pubblicare più spesso”, serve a dare ai crawler un evento strutturale affidabile, un punto fermo e regolare:

  • una nuova pagina creata via API
  • sitemap pingate
  • IndexNow aggiornato
  • endpoint stabili
  • segnale settimanale ricorrente
  • nessuna ambiguità nei redirect

È questo che ha sbloccato la situazione, non certo la frequenza dei contenuti.

Il problema non era editoriale, era architetturale.

Ora, stiamo a vedere quanto ci mette Google a farmi risalire la china... 🤔

Condividi questo post