# Tutorial: Il tuo sito è visibile alle Intelligenze Artificiali?
23 febbraio 2026 — Alessandro Caprai
---
## Guida pratica per verificare e ottimizzare l'accessibilità del tuo sito da parte dei Large Languege Model
***Metodo***\*: Basato su test reali condotti su siti in produzione con Claude, ChatGPT, Gemini e Perplexity\*
I Large Language Models (LLM) come Claude, ChatGPT, Gemini e Perplexity stanno diventando un canale di scoperta e traffico sempre più rilevante per i siti web. Tuttavia, il modo in cui questi sistemi accedono ai contenuti è profondamente diverso sia dai browser tradizionali sia dai motori di ricerca classici.
Un sito perfettamente indicizzato su Google può risultare **completamente invisibile** agli LLM. I motivi sono molteplici: firewall dell'hosting, configurazione errata del robots.txt, contenuto reso solo via JavaScript, sitemap illeggibili, cache avvelenate dei crawler.
Questa guida fornisce un percorso strutturato in 9 livelli per diagnosticare e risolvere ogni possibile punto di blocco. Ogni test è stato verificato sul campo.
### SEO vs GEO: perché serve una nuova prospettiva
La SEO tradizionale (Search Engine Optimization) si concentra sulla visibilità nei risultati dei motori di ricerca. La **GEO** (Generative Engine Optimization) estende questo concetto all'ecosistema dell'intelligenza artificiale generativa: come fare in modo che gli LLM trovino, leggano e citino correttamente i tuoi contenuti.
La GEO non sostituisce la SEO, la integra. Un sito ottimizzato per la GEO è anche un sito con una SEO più solida, perché molti dei requisiti sono condivisi: contenuto accessibile, struttura chiara, metadati coerenti. Ma la GEO aggiunge requisiti specifici — come la leggibilità da parte di crawler che non eseguono JavaScript, la compatibilità dei Content-Type con i tool degli LLM, l'esposizione esplicita delle relazioni tra contenuti multilingua, e l'adozione di protocolli emergenti come **llms.txt** per comunicare direttamente con i modelli di linguaggio.
---
## Livello 1 — Firewall e Bot Protection dell'hosting
### Cosa verificare
Il primo e più insidioso livello di blocco. Molti hosting moderni offrono sistemi di protezione bot che bloccano il traffico non-browser **prima ancora che raggiunga il tuo server**. Il blocco avviene in modo silenzioso: non vedrai nulla nei tuoi log applicativi.
Questo è particolarmente critico perché il blocco può generare una **cache avvelenata** nel crawler dell'LLM: se il crawler viene bloccato una volta, potrebbe memorizzare il blocco e non riprovare per giorni o settimane, anche dopo che hai corretto la configurazione.
### Piattaforme coinvolte
Piattaforma Dove controllare Vercel Dashboard → Progetto → Firewall → Rules → Bot Management Cloudflare Dashboard → Security → Bots Netlify Site settings → Security (se presente) AWS CloudFront WAF → Web ACLs → Bot Control Hosting tradizionale Pannello del firewall applicativo (ModSecurity, ecc.)
### Test da eseguire
**1.1 — Verifica Bot Protection generica**
Accedi al pannello del tuo hosting e controlla se esistono protezioni bot attive. Cerca due tipi di protezione, spesso configurabili separatamente:
- **Bot Protection generica** — blocca tutto il traffico non-browser (headless requests, curl, script automatici)
- **AI Bots Managed Ruleset** — blocca specificamente i crawler degli LLM (ClaudeBot, GPTBot, ecc.)
Se vuoi che gli LLM accedano al tuo sito, imposta entrambi su **"Log"** (monitoraggio senza blocco) anziché "Block" o "Challenge".
**1.2 — Verifica nei log live**
Questo è il test diagnostico chiave. Chiedi a un LLM (es. Claude, ChatGPT) di accedere a una pagina specifica del tuo sito, poi controlla immediatamente i log live del firewall:
- Se **vedi la richiesta nei log** → il blocco è a livello applicativo (robots.txt, middleware, risposta del server)
- Se **non vedi alcuna richiesta** → il blocco avviene a livello di firewall/infrastruttura, oppure l'LLM sta usando una risposta cachata e la richiesta non parte nemmeno
**1.3 — Verifica WAF e regole custom**
Controlla se hai regole WAF personalizzate che bloccano user-agent specifici. I principali user-agent degli LLM sono:
LLM / Servizio User-Agent Claude (Anthropic) `ClaudeBot` ChatGPT (OpenAI) `GPTBot`, `ChatGPT-User` Gemini (Google) `Google-Extended` Perplexity `PerplexityBot` Apple AI `Applebot-Extended` Microsoft Copilot `Bingbot` (condiviso con Bing Search) Meta AI `FacebookBot` Common Crawl (usato da molti LLM) `CCBot`
**1.4 — Test con User-Agent specifici**
Verifica dal tuo terminale che il server risponda correttamente ai diversi user-agent:
```bash
# Test con User-Agent di Claude
curl -I -H "User-Agent: ClaudeBot" https://tuosito.com/
# Test con User-Agent di ChatGPT
curl -I -H "User-Agent: GPTBot" https://tuosito.com/
# Confronto con User-Agent browser standard
curl -I -H "User-Agent: Mozilla/5.0" https://tuosito.com/
```
Se gli user-agent LLM ricevono risposte diverse (403, 503, redirect a challenge), il firewall li sta bloccando.
### Segnali di problema
- L'LLM restituisce "non riesco ad accedere" ma il sito funziona nel browser
- Nessuna traccia nei log del server quando l'LLM tenta l'accesso
- Errori generici tipo "robots.txt disallowed" anche se il robots.txt è configurato correttamente
- Risposte HTTP diverse in base allo User-Agent
---
## Livello 2 — robots.txt
### Cosa verificare
Il file robots.txt è il primo file che i crawler (inclusi quelli degli LLM) leggono prima di accedere a qualsiasi pagina. Una configurazione errata può bloccare tutto il sito. Inoltre, se il robots.txt stesso non è raggiungibile, molti crawler interpretano questo come "accesso negato a tutto".
### Test da eseguire
**2.1 — Verifica l'accessibilità del robots.txt**
```bash
curl -I https://tuosito.com/robots.txt
```
Controlla che il codice di risposta sia `200 OK` e non `403`, `404` o `500`. Un robots.txt inaccessibile è spesso il sintomo di un blocco a livello di firewall (vedi Livello 1).
**2.2 — Verifica il contenuto effettivamente servito**
```bash
curl -s https://tuosito.com/robots.txt
```
Confronta il contenuto restituito con quello che ti aspetti. Attenzione ai conflitti tra generazione statica e dinamica:
Framework File statico File dinamico Prevalenza Next.js `public/robots.txt` `app/robots.ts` Dinamico sovrascrive statico Nuxt.js `public/robots.txt` Modulo `@nuxtjs/robots` Dipende dalla configurazione Gatsby `static/robots.txt` Plugin `gatsby-plugin-robots-txt` Plugin sovrascrive WordPress File fisico Plugin SEO (Yoast, Rank Math) Plugin sovrascrive Siti statici File nella root — —
Se entrambe le fonti esistono, quella dinamica potrebbe sovrascrivere quella statica con regole diverse da quelle previste.
**2.3 — Aggiungi Allow esplicito per i bot LLM**
Per massimizzare la compatibilità, aggiungi regole esplicite per ogni bot LLM. Molti crawler verificano prima se esiste una regola specifica per il proprio user-agent; un Allow esplicito rimuove ogni ambiguità:
```
User-Agent: ClaudeBot
User-Agent: GPTBot
User-Agent: ChatGPT-User
User-Agent: Google-Extended
User-Agent: PerplexityBot
User-Agent: Applebot-Extended
Allow: /
Disallow: /admin/
Disallow: /api/
User-Agent: *
Allow: /
Disallow: /admin/
Disallow: /api/
Sitemap: https://tuosito.com/sitemap.xml
```
**2.4 — Verifica il Content-Type del robots.txt**
```bash
curl -I https://tuosito.com/robots.txt | grep -i content-type
```
Deve essere `text/plain`. Se il server restituisce `text/html` o altro MIME type, alcuni crawler potrebbero non interpretarlo correttamente come file robots.
**2.5 — Verifica la coerenza tra robots.txt e firewall**
Un errore comune è avere un robots.txt che dice "Allow" ma un firewall che blocca. Il robots.txt è solo una direttiva: se il firewall nega l'accesso a monte, il robots.txt non viene nemmeno letto. I due livelli devono essere coerenti.
### Segnali di problema
- Il robots.txt restituisce un errore HTTP (403, 404, 500)
- Esistono sia il file statico che quello dinamico con regole diverse
- Le regole `Disallow` sono troppo ampie (es. `Disallow: /` senza `Allow`)
- Il Content-Type non è `text/plain`
- Il firewall blocca a monte rendendo il robots.txt irraggiungibile
---
## Livello 3 — Meta tag e header HTTP
### Cosa verificare
Anche con un robots.txt perfetto, meta tag HTML o header HTTP possono bloccare l'indicizzazione a livello di singola pagina. Questi controlli sono granulari e possono essere applicati selettivamente a specifiche pagine o sezioni del sito.
### Test da eseguire
**3.1 — Controlla i meta tag robots nel** `<head>`
```bash
curl -s https://tuosito.com/pagina | grep -i "robots"
```
Cerca tag come:
```html
<!-- BLOCCANTI — impediscono indicizzazione -->
<meta name="robots" content="noindex">
<meta name="robots" content="nofollow">
<meta name="robots" content="none">
<meta name="robots" content="noindex, nofollow">
<!-- PERMISSIVI — consentono indicizzazione -->
<meta name="robots" content="index, follow">
<!-- Oppure semplicemente l'assenza del tag (default = index, follow) -->
```
Attenzione: alcuni framework iniettano automaticamente meta tag `noindex` in determinate condizioni (es. pagine di errore, pagine di preview, ambienti di staging).
**3.2 — Controlla l'header X-Robots-Tag**
```bash
curl -I https://tuosito.com/pagina | grep -i "x-robots"
```
L'header `X-Robots-Tag: noindex` nella risposta HTTP blocca l'indicizzazione anche senza meta tag nel HTML. È spesso usato da CDN, middleware o configurazioni server-side.
**3.3 — Controlla header specifici per bot AI**
Alcuni framework, CDN o middleware aggiungono header o comportamenti diversi per i bot AI:
```bash
# Confronta le risposte con diversi User-Agent
curl -I -H "User-Agent: ClaudeBot" https://tuosito.com/pagina
curl -I -H "User-Agent: Mozilla/5.0" https://tuosito.com/pagina
```
Confronta: codice di stato, header `X-Robots-Tag`, eventuali redirect, Content-Type. Devono essere identici.
### Segnali di problema
- `noindex` presente nel `<head>` di pagine che dovrebbero essere visibili
- `X-Robots-Tag` restrittivo negli header HTTP
- Risposte diverse in base allo User-Agent (redirect, 403, challenge page)
- Meta tag `noindex` iniettati automaticamente dal framework in produzione
---
## Livello 4 — Middleware e rewrite
### Cosa verificare
I framework moderni (Next.js, Nuxt, SvelteKit, Remix, ecc.) usano middleware che intercettano le richieste e possono modificare il comportamento prima che raggiungano la pagina. Questo è particolarmente critico per siti multilingua (redirect sulla lingua) e siti con autenticazione.
### Test da eseguire
**4.1 — Controlla che il middleware non intercetti risorse SEO**
Il middleware non dovrebbe intercettare robots.txt, sitemap.xml, favicon.ico e altri file statici. Risorse da escludere dal middleware:
- robots.txt
- sitemap.xml (e sitemap index)
- favicon.ico
- File statici (assets, immagini, CSS, JS)
- API routes (se non richiedono auth)
**4.2 — Verifica i redirect del middleware per i bot**
Se il middleware gestisce la localizzazione (es. redirect da `/` a `/it/`), verifica che non crei loop di redirect o pagine di errore per i bot. I bot tipicamente non inviano cookie di preferenza lingua:
```bash
# Testa come un bot senza cookie
curl -v -H "User-Agent: ClaudeBot" https://tuosito.com/ 2>&1 | grep -i "location\|301\|302\|307"
```
Se vedi redirect multipli o loop, il middleware sta creando problemi per i crawler.
**4.3 — Verifica l'assenza di blocco basato su User-Agent nel middleware**
Controlla che il codice del middleware non contenga logica di blocco per i bot. Pattern problematici da cercare nel codice middleware:
- Blocco di User-Agent che contengono "Bot" o "Crawler"
- Redirect a pagine di challenge/captcha per User-Agent non-browser
- Risposta 403/401 per richieste senza cookie di sessione
**4.4 — Verifica i rewrite URL**
Se il sito usa URL rewriting (es. da slug semplificati a percorsi interni), verifica che i rewrite funzionino anche per i bot:
```bash
curl -s -o /dev/null -w "%{http_code}" -H "User-Agent: ClaudeBot" https://tuosito.com/articolo-esempio
```
Deve restituire `200`, non `404` o `500`.
### Segnali di problema
- Il middleware intercetta richieste a `robots.txt` o `sitemap.xml`
- Redirect infiniti per bot che non gestiscono cookie di lingua
- Risposte 403 o 401 per User-Agent non-browser
- Pagine che funzionano nel browser ma restituiscono 404 via curl
---
## Livello 5 — Rendering e contenuto accessibile
### Cosa verificare
Gli LLM e i loro crawler generalmente **non eseguono JavaScript**. Se il contenuto del tuo sito viene caricato solo via client-side rendering (CSR), i bot vedranno una pagina vuota o parziale. Questo è uno dei problemi più comuni e sottovalutati.
### Impatto per strategia di rendering
Strategia di rendering Visibilità ai bot LLM Static Site Generation (SSG) ✅ Ottima — HTML completo alla prima richiesta Server-Side Rendering (SSR) ✅ Buona — HTML generato ad ogni richiesta Incremental Static Regeneration (ISR) ✅ Buona — simile a SSG con aggiornamento Client-Side Rendering (CSR) ❌ Problematica — contenuto assente per i bot Hydration parziale ⚠️ Variabile — dipende da cosa è server-rendered
### Test da eseguire
**5.1 — Verifica il rendering senza JavaScript**
```bash
curl -s https://tuosito.com/pagina | grep -c "<article\|<p\|<h1\|<h2"
```
Se il contenuto HTML principale (titoli, paragrafi, articoli) non è presente nella risposta iniziale, significa che viene caricato via JavaScript e i bot non lo vedranno.
**5.2 — Confronta il contenuto SSR vs browser**
Conta gli elementi visibili nei due contesti:
1. Apri la pagina nel browser → conta gli articoli/sezioni/elementi visibili
2. Fai un `curl` della stessa pagina → conta gli stessi elementi nell'HTML grezzo
3. Se il browser mostra più contenuto, la differenza è caricata via JavaScript e **invisibile ai bot**
Esempio pratico: se la homepage mostra 8 articoli nel browser ma il `curl` ne restituisce solo 6, i 2 mancanti sono caricati dinamicamente.
**5.3 — Verifica il lazy loading e l'infinite scroll**
Se usi infinite scroll, pulsanti "carica altri" o lazy loading per gli articoli, i contenuti caricati dinamicamente non saranno visibili ai crawler. Assicurati che almeno tutti i contenuti principali siano nel HTML iniziale (SSR/SSG).
Per le liste di articoli, considera di includere tutti gli articoli recenti nel HTML iniziale, oppure usa la paginazione con URL distinti (`/blog/page/2`) anziché il caricamento dinamico.
**5.4 — Testa la versione LLM-friendly (se presente)**
Alcuni siti offrono una versione in Markdown o testo semplice per gli LLM. Se presente, verifica che sia accessibile:
```bash
curl -s https://tuosito.com/pagina/markdown
```
Offrire un endpoint dedicato per LLM è una best practice emergente nella GEO. Il protocollo llms.txt (vedi Livello 9) standardizza questo approccio proponendo che ogni pagina abbia una versione Markdown accessibile aggiungendo `.md` all'URL.
**5.5 — Verifica il contenuto strutturato (Schema.org)**
I dati strutturati in formato JSON-LD aiutano gli LLM a comprendere il tipo e la struttura del contenuto:
```bash
curl -s https://tuosito.com/pagina | grep -i "application/ld+json"
```
Schema.org markup per `Article`, `BlogPosting`, `FAQPage`, `HowTo` sono particolarmente utili per la GEO.
### Segnali di problema
- Il `curl` restituisce HTML con poco o nessun contenuto testuale
- Articoli mancanti rispetto a quelli visibili nel browser
- Contenuti importanti caricati solo dopo interazione utente (scroll, click)
- Assenza di dati strutturati JSON-LD
---
## Livello 6 — Sitemap
### Cosa verificare
La sitemap è fondamentale per comunicare ai crawler la struttura completa del sito. Se non è leggibile o è mal configurata, i bot potrebbero non scoprire tutte le tue pagine o non comprendere le relazioni tra le versioni linguistiche dei contenuti.
### Test da eseguire
**6.1 — Verifica l'accessibilità della sitemap**
```bash
curl -s -o /dev/null -w "%{http_code}" https://tuosito.com/sitemap.xml
```
Deve restituire `200`.
**6.2 — Verifica il Content-Type**
```bash
curl -I https://tuosito.com/sitemap.xml | grep -i content-type
```
Questo è un problema critico verificato sul campo: alcuni tool LLM trattano `application/xml` come **dati binari** e non riescono a leggerne il contenuto. Per massimizzare la compatibilità, servi la sitemap con:
```
Content-Type: text/xml; charset=utf-8
```
Nota: molti framework forzano `application/xml` e non permettono di sovrascrivere il Content-Type tramite configurazione. In questi casi, la soluzione è generare la sitemap manualmente tramite un route handler o un endpoint API custom, dove puoi controllare il Content-Type direttamente nella risposta HTTP.
**6.3 — Verifica la struttura sitemap index (siti multilingua)**
Se il sito è multilingua e usi una sitemap index che punta a sitemap figlie per lingua, verifica la catena completa:
```bash
# Sitemap index principale
curl -s https://tuosito.com/sitemap.xml
# Sitemap figlie per lingua
curl -s https://tuosito.com/it/sitemap.xml
curl -s https://tuosito.com/en/sitemap.xml
```
La sitemap index dovrebbe avere questa struttura:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://tuosito.com/it/sitemap.xml</loc>
<lastmod>2026-02-23T10:00:00.000Z</lastmod>
</sitemap>
<sitemap>
<loc>https://tuosito.com/en/sitemap.xml</loc>
<lastmod>2026-02-23T10:00:00.000Z</lastmod>
</sitemap>
</sitemapindex>
```
**6.4 — Verifica che il robots.txt punti alla sitemap index**
Nel robots.txt, referenzia un solo punto di ingresso — la sitemap index principale — anziché elencare tutte le sitemap figlie:
```
# ✅ CORRETTO — un solo punto di ingresso
Sitemap: https://tuosito.com/sitemap.xml
# ❌ RIDONDANTE — le figlie sono già referenziate nell'index
Sitemap: https://tuosito.com/it/sitemap.xml
Sitemap: https://tuosito.com/en/sitemap.xml
Sitemap: https://tuosito.com/es/sitemap.xml
```
Per siti monolingua senza sitemap index, punta direttamente alla sitemap:
```
Sitemap: https://tuosito.com/sitemap.xml
```
**6.5 — Verifica la presenza dei tag** `hreflang` **(siti multilingua)**
Questo è il test più importante per siti multilingua. Senza `hreflang`, i crawler non possono collegare le versioni linguistiche dello stesso contenuto. Ogni URL deve dichiarare tutte le sue varianti linguistiche, **incluso sé stessa**.
Aggiungi il namespace `xhtml` nell'elemento `<urlset>` e i link alternati in ogni `<url>`:
```xml
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
<url>
<loc>https://tuosito.com/it/blog/articolo-esempio</loc>
<lastmod>2026-02-12</lastmod>
<changefreq>monthly</changefreq>
<priority>0.7</priority>
<xhtml:link rel="alternate" hreflang="it" href="https://tuosito.com/it/blog/articolo-esempio" />
<xhtml:link rel="alternate" hreflang="en" href="https://tuosito.com/en/blog/example-article" />
<xhtml:link rel="alternate" hreflang="es" href="https://tuosito.com/es/blog/articulo-ejemplo" />
</url>
</urlset>
```
Per verificare se i tag sono presenti:
```bash
curl -s https://tuosito.com/it/sitemap.xml | grep -c "hreflang"
```
Se il risultato è `0`, i tag mancano e le relazioni multilingua non sono dichiarate.
**6.6 — Verifica la coerenza delle** `priority`
Le priority devono riflettere la reale importanza delle pagine. Una distribuzione uniforme delle priority equivale a non avere priority:
Tipo di pagina Priority consigliata Homepage 1.0 Pagine categoria / Sezioni principali 0.8 Articoli / Post / Pagine di contenuto 0.7 Chi sono / Contatti / About 0.5 Legal / Privacy / Cookie / Registrazione 0.3 (o escluse dalla sitemap)
**6.7 — Verifica che pagine funzionali non siano nella sitemap**
Pagine come registrazione, login, legal, privacy policy, cookie policy, termini di servizio sono pagine funzionali e generalmente non dovrebbero essere nella sitemap. Includerle diluisce il crawl budget e segnala ai motori che hanno la stessa importanza dei contenuti originali.
```bash
curl -s https://tuosito.com/sitemap.xml | grep -iE "registr|legal|login|admin|privacy|cookie|terms|signup|signin"
```
**6.8 — Verifica la coerenza di** `lastmod` **e** `changefreq`
Incoerenze in questi campi riducono la fiducia del crawler in tutta la sitemap:
- `lastmod` deve riflettere la data reale dell'ultima modifica del contenuto, non la data di generazione della sitemap
- `lastmod` **delle pagine categoria** deve corrispondere alla data dell'ultimo articolo pubblicato al loro interno
- `changefreq` deve essere realistico: dichiarare `weekly` per pagine statiche che non cambiano mai è un segnale di inaffidabilità
- **Tutte le URL dovrebbero avere** `lastmod`: pagine senza `lastmod` vengono trattate come a bassa priorità di aggiornamento
```bash
# Controlla le date nella sitemap
curl -s https://tuosito.com/sitemap.xml | grep -B1 "lastmod"
# Conta le URL senza lastmod
curl -s https://tuosito.com/sitemap.xml | grep "<loc>" | wc -l # totale URL
curl -s https://tuosito.com/sitemap.xml | grep "lastmod" | wc -l # URL con lastmod
```
**6.9 — Verifica la completezza della sitemap**
Confronta il numero di URL nella sitemap con il numero di pagine effettive del sito:
```bash
curl -s https://tuosito.com/sitemap.xml | grep -c "<loc>"
```
Ogni pagina pubblica con contenuto originale dovrebbe essere presente. Pagine orfane (presenti nel sito ma assenti dalla sitemap) potrebbero non essere mai scoperte dai crawler.
### Segnali di problema
- Sitemap restituisce errori (404, 500)
- Content-Type `application/xml` interpretato come binario da alcuni crawler LLM
- Mancano i tag `xhtml:link` con `hreflang` su siti multilingua
- robots.txt elenca le sitemap figlie anziché puntare all'index
- Pagine funzionali (legal, registrazione, login) nella sitemap con priority alta
- `lastmod` incoerente, assente o uguale per tutte le pagine
- `changefreq: weekly` su pagine che non cambiano mai
- Priority uniformi che non differenziano tra contenuti e pagine di servizio
- `lastmod` delle categorie non aggiornato all'ultimo articolo pubblicato
- Pagine del sito assenti dalla sitemap
---
## Livello 7 — Cache dei crawler LLM
### Cosa verificare
I crawler degli LLM memorizzano le risposte. Se il tuo sito ha bloccato un crawler in passato (anche involontariamente, ad esempio tramite un firewall configurato di default), quel blocco può persistere nella cache del crawler per un periodo indefinito, anche dopo aver corretto la configurazione.
Questo è un problema particolarmente insidioso perché tutto sembra corretto dal tuo lato, ma l'LLM continua a non accedere al sito.
### Come funziona la cache avvelenata
1. Il crawler dell'LLM prova ad accedere al tuo `robots.txt`
2. Il firewall dell'hosting blocca la richiesta (403 o pagina di challenge)
3. Il crawler interpreta il blocco come "robots.txt dice disallow all"
4. Questa interpretazione viene cachata
5. Da quel momento, il crawler non tenta nemmeno di accedere al sito — blocca tutto internamente sulla base della cache
6. Tu correggi il firewall e il robots.txt, ma il crawler continua a usare la cache avvelenata
### Test da eseguire
**7.1 — Diagnostica di cache avvelenata**
Se un LLM dice di non poter accedere al tuo sito ma i log del server non mostrano alcuna richiesta:
1. Correggi la configurazione (firewall, robots.txt, ecc.)
2. Chiedi all'LLM di accedere a una pagina specifica
3. Controlla i log del server in tempo reale:
- **Richiesta presente nei log** → il problema è nella risposta del server, non nella cache
- **Richiesta assente nei log** → cache avvelenata: la richiesta non parte nemmeno
**7.2 — Forza l'invalidazione della cache**
Dopo aver corretto la configurazione:
- **Attendi**: la cache si invalida tipicamente in ore o giorni, non minuti
- **Ritesta periodicamente**: prova ogni poche ore per verificare se la cache è stata aggiornata
- **Verifica il robots.txt per primo**: spesso il robots.txt è il file la cui cache viene aggiornata prima di tutto il resto. Se l'LLM riesce a leggere il robots.txt aggiornato, il resto seguirà
**7.3 — Forza il re-crawling (se possibile)**
Alcuni provider LLM offrono meccanismi per richiedere un re-crawling:
- **Google (Gemini)**: Google Search Console → Richiedi indicizzazione
- **Microsoft (Copilot)**: Bing Webmaster Tools → Submit URL
- **Anthropic (Claude)**: Al momento non esiste un tool pubblico equivalente; l'invalidazione avviene automaticamente
- **OpenAI (ChatGPT)**: Al momento non esiste un tool pubblico di re-crawling
### Segnali di problema
- L'LLM riporta errori di accesso ma nei log del server non c'è traccia della richiesta
- Il problema persiste anche dopo aver corretto tutte le configurazioni
- Il sito funziona con `curl` manuale ma non con il tool dell'LLM
- Il robots.txt viene letto correttamente ma le pagine restano bloccate (cache parziale)
---
## Livello 8 — Indicizzazione nei motori di ricerca degli LLM
### Cosa verificare
Alcuni LLM usano motori di ricerca propri (non Google) per trovare contenuti. Il tuo sito potrebbe essere ben indicizzato su Google ma completamente assente dal motore di ricerca usato dall'LLM. Inoltre, il motore di ricerca usato da ciascun LLM può cambiare e non è sempre documentato.
### Test da eseguire
**8.1 — Testa la ricerca dall'LLM**
Chiedi direttamente all'LLM di cercare un tuo articolo con una query molto specifica (es. titolo esatto + nome del sito). Ripeti il test con diversi LLM:
- Chiedi a **Claude** di cercare il tuo articolo
- Chiedi a **ChatGPT** di cercare lo stesso articolo
- Chiedi a **Perplexity** di cercare lo stesso articolo
- Chiedi a **Gemini** di cercare lo stesso articolo
Se il sito appare nei risultati di alcuni LLM ma non di altri, il problema è nell'indicizzazione del motore di ricerca specifico, non nel tuo sito.
**8.2 — Verifica su Google Search Console**
Controlla che il sito sia indicizzato su Google:
- Numero di pagine indicizzate vs pagine totali del sito
- Errori di crawling segnalati
- Copertura dell'indice
- Richieste di indicizzazione pendenti
**8.3 — Verifica su Bing Webmaster Tools**
Molti LLM (incluso ChatGPT/Copilot) usano Bing come fonte di ricerca. Registra il sito su Bing Webmaster Tools e verifica:
- Stato dell'indicizzazione
- Errori di crawling
- Sitemap submitted e processate
**8.4 — Verifica su altri webmaster tools**
- **Yandex Webmaster** — usato da alcuni LLM per mercati specifici
- **IndexNow** — protocollo supportato da Bing, Yandex e altri per notificare nuovi contenuti in tempo reale
### Segnali di problema
- Il sito appare su Google ma non nei risultati di ricerca dell'LLM
- Basso numero di pagine indicizzate rispetto al totale
- Errori di crawling nei webmaster tools
- Sitemap non processata o con errori nei webmaster tools
---
## Livello 9 — Il protocollo llms.txt e i contenuti LLM-friendly
### Cosa verificare
Oltre all'accessibilità tecnica (Livelli 1-8), esistono protocolli e formati specifici progettati per rendere i contenuti direttamente comprensibili dagli LLM. Il più importante è **llms.txt**, una proposta di standard aperto creata da Jeremy Howard (co-fondatore di fast.ai e Answer.AI) a settembre 2024.
Il concetto è semplice: così come `robots.txt` dice ai crawler "cosa puoi vedere" e `sitemap.xml` dice "dove si trovano le pagine", `llms.txt` **dice agli LLM "ecco come capire il mio sito"**.
### Il protocollo llms.txt
Il file `/llms.txt` è un file Markdown posizionato nella root del sito che fornisce una mappa curata e leggibile di tutto il sito in un formato ottimizzato per le context window degli LLM. A differenza della sitemap (che elenca tutte le URL), il llms.txt offre una selezione ragionata dei contenuti più importanti con descrizioni e contesto.
Specifiche del formato (da llmstxt.org):
- Un **H1** con il nome del progetto o sito (obbligatorio)
- Un **blockquote** con una descrizione breve e chiave del progetto
- Zero o più **paragrafi** con informazioni di contesto
- Zero o più **sezioni H2** contenenti liste di link con descrizioni
- Una sezione opzionale **"Optional"** con risorse secondarie che l'LLM può saltare se ha una context window limitata
### Test da eseguire
**9.1 — Verifica la presenza del file llms.txt**
```bash
curl -s -o /dev/null -w "%{http_code}" https://tuosito.com/llms.txt
```
Se restituisce `404`, il file non esiste e il sito non sta comunicando la propria struttura agli LLM.
**9.2 — Verifica il contenuto e il formato del llms.txt**
```bash
curl -s https://tuosito.com/llms.txt
```
Il file deve seguire il formato standard. Ecco un esempio per un sito aziendale:
```markdown
# Nome Azienda
> Breve descrizione dell'azienda e dei suoi servizi principali.
> Informazioni chiave che ogni LLM dovrebbe conoscere.
L'azienda opera nel settore X dal YYYY. I servizi principali sono A, B e C.
Il sito è disponibile in italiano, inglese e spagnolo.
## Servizi
- [Servizio principale](https://tuosito.com/servizi/principale.html.md): Descrizione concisa del servizio
- [Consulenza](https://tuosito.com/servizi/consulenza.html.md): Descrizione della consulenza offerta
## Blog e approfondimenti
- [Articolo importante](https://tuosito.com/blog/articolo.html.md): Perché questo articolo è rilevante
- [Guida tecnica](https://tuosito.com/blog/guida.html.md): Cosa copre questa guida
## Chi siamo
- [About](https://tuosito.com/chi-siamo.html.md): Storia e mission dell'azienda
- [Team](https://tuosito.com/team.html.md): Il team e le competenze
## Optional
- [Case study dettagliato](https://tuosito.com/case-study.html.md): Approfondimento opzionale
- [Documentazione tecnica](https://tuosito.com/docs.html.md): Riferimento tecnico completo
```
Nota: i link nel llms.txt dovrebbero puntare alle versioni Markdown delle pagine (vedi test 9.3), non alle pagine HTML complete.
**9.3 — Implementa le versioni Markdown delle pagine**
La proposta llms.txt include una convenzione fondamentale: ogni pagina del sito dovrebbe avere una versione Markdown accessibile aggiungendo `.md` all'URL originale. Questa versione contiene solo il contenuto testuale strutturato, senza navigazione, sidebar, footer, popup o elementi UI.
```bash
# Pagina HTML originale
curl -s https://tuosito.com/blog/articolo.html
# Versione Markdown per LLM
curl -s https://tuosito.com/blog/articolo.html.md
```
Se il sito usa URL senza estensione (es. `/blog/articolo`), la convenzione è aggiungere `index.html.md`:
```bash
curl -s https://tuosito.com/blog/articolo/index.html.md
```
In alternativa, puoi adottare un percorso custom purché sia coerente:
```bash
curl -s https://tuosito.com/blog/articolo/markdown
```
La versione Markdown deve contenere:
- Il titolo dell'articolo (H1)
- L'autore e la data di pubblicazione
- Il contenuto completo strutturato con heading, paragrafi, liste
- I link alle fonti citate
- Nessun elemento di navigazione, UI o marketing
**9.4 — Implementa il file llms.html per chatbot e sistemi RAG**
Oltre al llms.txt (pensato per i crawler) e alle versioni Markdown (pensate per le singole pagine), un terzo file completa l'ecosistema: **llms.html**.
Il llms.html è una pagina HTML strutturata che funziona come **fonte di conoscenza per chatbot aziendali e sistemi RAG** (Retrieval Augmented Generation). Contiene tutti i contenuti del sito in formato strutturato, aggiornato dinamicamente, e può essere usata come knowledge base per:
- Chatbot custom sul proprio sito
- GPT personalizzati (Custom GPTs di OpenAI)
- Agenti AI aziendali
- Qualsiasi sistema che necessiti di una fonte di conoscenza aggiornata
```bash
curl -s -o /dev/null -w "%{http_code}" https://tuosito.com/llms.html
```
A differenza del llms.txt (che è una mappa con link), il llms.html contiene il testo completo dei contenuti, organizzato in sezioni, pronto per essere ingerito da un sistema RAG senza ulteriori passaggi.
**9.5 — Referenzia il llms.txt nel robots.txt**
Così come il robots.txt referenzia la sitemap, è buona pratica aggiungere un riferimento al llms.txt. Anche se non esiste ancora uno standard formale per questo, alcuni crawler iniziano a cercarlo:
```
Sitemap: https://tuosito.com/sitemap.xml
# LLM-friendly content map
# llms.txt: https://tuosito.com/llms.txt
```
**9.6 — Usa dati strutturati (Schema.org)**
I dati strutturati JSON-LD aiutano gli LLM a comprendere il tipo, l'autore, la data e la struttura del contenuto:
```html
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "BlogPosting",
"headline": "Titolo dell'articolo",
"author": {
"@type": "Person",
"name": "Nome Autore"
},
"datePublished": "2026-02-12",
"dateModified": "2026-02-15",
"description": "Descrizione dell'articolo",
"inLanguage": "it"
}
</script>
```
Schema.org markup per `Article`, `BlogPosting`, `Product`, `FAQPage`, `HowTo`, `Organization` e `LocalBusiness` sono particolarmente utili per la GEO.
**9.7 — Struttura il contenuto in modo chiaro**
Gli LLM interpretano meglio i contenuti quando:
- Ogni pagina ha un solo `<h1>` chiaro e descrittivo
- I sottotitoli (`<h2>`, `<h3>`) seguono una gerarchia logica
- I paragrafi trattano un concetto alla volta
- Le informazioni chiave sono all'inizio del testo (struttura a piramide invertita)
- Le liste e le tabelle sono usate per dati strutturati
**9.8 — Dichiara l'autorship e la data**
Gli LLM danno più peso ai contenuti con autore identificabile e data chiara:
- Includi nome dell'autore visibile nella pagina
- Includi la data di pubblicazione e di ultimo aggiornamento
- Usa i meta tag `article:author`, `article:published_time`, `article:modified_time`
**9.9 — Monitora le citazioni degli LLM**
Testa periodicamente se gli LLM citano il tuo sito quando rispondono a domande pertinenti ai tuoi contenuti. Chiedi agli LLM domande su argomenti che il tuo sito tratta in profondità e verifica se il tuo sito appare come fonte.
### Relazione tra sitemap.xml, llms.txt e llms.html
File Scopo Destinatari Contenuto `sitemap.xml` Elenco completo delle URL del sito Motori di ricerca (Google, Bing) e crawler LLM URL, lastmod, priority, hreflang `robots.txt` Direttive di accesso per i crawler Tutti i crawler Allow/Disallow per User-Agent `llms.txt` Mappa curata e contesto del sito LLM durante l'inference Markdown strutturato con link alle versioni .md `llms.html` Knowledge base completa Chatbot, GPT custom, sistemi RAG HTML strutturato con contenuto completo `*.html.md` Versione pulita di ogni pagina LLM che accedono a pagine specifiche Markdown del solo contenuto, senza UI
Tutti questi file coesistono e hanno scopi complementari. Nessuno sostituisce gli altri.
### Segnali di problema
- File `/llms.txt` assente (404)
- llms.txt presente ma con formato non standard o contenuto generico
- Nessuna versione Markdown disponibile per le pagine del sito
- I link nel llms.txt puntano a pagine HTML complete anziché a versioni .md
- Assenza di dati strutturati JSON-LD
- Contenuto senza autore o data identificabile
- L'LLM non cita il sito quando gli si fanno domande pertinenti ai contenuti pubblicati
---
## Checklist rapida
### Accessibilità e infrastruttura
\# Test Comando/Azione Esito atteso 1 Bot Protection hosting Pannello Firewall hosting Log o disattivato 2 AI Bots ruleset Pannello Firewall hosting Log o disattivato 3 Risposta a User-Agent LLM `curl -I -H "User-Agent: ClaudeBot" tuosito.com` 200 OK, identico a browser 4 robots.txt accessibile `curl -I tuosito.com/robots.txt` 200 OK, `text/plain` 5 robots.txt Allow per LLM `curl -s tuosito.com/robots.txt` Allow esplicito per bot LLM 6 robots.txt punta a sitemap index `curl -s tuosito.com/robots.txt | grep Sitemap` Un solo link alla sitemap index
### Meta tag e middleware
\# Test Comando/Azione Esito atteso 7 Meta robots `curl -s tuosito.com/pagina | grep robots` Nessun noindex 8 X-Robots-Tag `curl -I tuosito.com/pagina` Nessun noindex 9 Middleware non blocca bot `curl -I -H "User-Agent: ClaudeBot" tuosito.com/pagina` 200 OK, no redirect loop
### Rendering e contenuto
\# Test Comando/Azione Esito atteso 10 Contenuto nel HTML iniziale `curl -s tuosito.com | grep "<h1|<article|<p"` Contenuto principale presente 11 Conteggio elementi SSR vs browser Conta articoli in curl vs browser Numeri identici 12 Dati strutturati JSON-LD `curl -s tuosito.com/pagina | grep "ld+json"` Schema.org presente
### Sitemap
\# Test Comando/Azione Esito atteso 13 Sitemap accessibile `curl -I tuosito.com/sitemap.xml` 200 OK 14 Sitemap Content-Type `curl -I tuosito.com/sitemap.xml | grep content-type` `text/xml; charset=utf-8` 15 hreflang presenti (multilingua) `curl -s tuosito.com/sitemap.xml | grep hreflang` Tag per ogni lingua 16 No pagine funzionali `curl -s tuosito.com/sitemap.xml | grep -iE "legal|login|registr"` Nessun risultato 17 Priority differenziate Revisione manuale della sitemap Coerenti con importanza pagine 18 lastmod coerente `curl -s tuosito.com/sitemap.xml | grep lastmod` Date reali, non uniformi
### Verifica end-to-end
\# Test Comando/Azione Esito atteso 19 llms.txt presente `curl -s -o /dev/null -w "%{http_code}" tuosito.com/llms.txt` 200 OK 20 llms.txt formato corretto `curl -s tuosito.com/llms.txt` Markdown strutturato con H1, blockquote, sezioni H2 21 Versioni Markdown delle pagine `curl -s tuosito.com/blog/articolo.html.md` Contenuto Markdown pulito 22 llms.html per RAG `curl -s -o /dev/null -w "%{http_code}" tuosito.com/llms.html` 200 OK (se implementato) 23 Test accesso da LLM Chiedi a Claude/GPT di leggere una pagina Contenuto restituito 24 Log server durante test LLM Controlla log live durante il test Richiesta visibile 25 Ricerca del sito tramite LLM Chiedi all'LLM di cercare un tuo articolo Sito nei risultati 26 Citazione da parte dell'LLM Chiedi all'LLM un topic che tratti Sito citato come fonte
---
## Quando ripetere i test
L'ecosistema dei crawler LLM è in rapida evoluzione. Ripeti i test periodicamente, in particolare dopo:
- Aggiornamenti del framework (Next.js, Nuxt, WordPress, ecc.)
- Modifiche all'hosting, al piano o alla CDN
- Aggiornamenti del firewall, del WAF o delle regole bot
- Deploy di nuove funzionalità che coinvolgono middleware o rendering
- Segnalazioni di utenti che non riescono a trovare il sito tramite LLM
- Rilascio di nuovi LLM o aggiornamenti significativi di quelli esistenti
---
## Glossario
Termine Definizione **GEO** Generative Engine Optimization: ottimizzazione per la visibilità negli LLM.
**SEO** Search Engine Optimization: ottimizzazione per i motori di ricerca.
**SSR** Server-Side Rendering: il contenuto HTML è generato dal server **CSR** Client-Side Rendering — il contenuto è generato dal JavaScript nel browser.
**SSG** Static Site Generation: le pagine HTML sono pre-generate al build.
**WAF** Web Application Firewall: firewall a livello applicativo.
**robots.txt** File che indica ai crawler quali pagine possono o non possono accedere.
**Sitemap** File XML che elenca tutte le pagine del sito per i crawler.
**hreflang** Attributo che indica la lingua e la regione di una pagina.
**Cache avvelenata** Quando un crawler memorizza un blocco e continua a usarlo anche dopo la correzione.
**Content-Type** Header HTTP che indica il formato del contenuto della risposta.
**User-Agent** Header HTTP che identifica il client che effettua la richiesta.
**Crawl budget** Numero di pagine che un crawler è disposto a scansionare su un sito.
**JSON-LD** Formato per dati strutturati embedded nell'HTML.
**Schema.org** Vocabolario standard per dati strutturati sul web **llms.txt** File Markdown nella root del sito che fornisce una mappa curata dei contenuti per gli LLM (standard proposto da Jeremy Howard, llmstxt.org).
**llms.html** Pagina HTML strutturata che funziona come knowledge base per chatbot e sistemi RAG.
**RAG** Retrieval Augmented Generation: tecnica che permette a un LLM di accedere a fonti di conoscenza esterne per generare risposte più accurate.
**Inference** Il momento in cui un LLM genera una risposta a una richiesta dell'utente, potenzialmente consultando fonti esterne.