SEO con Next.js: come faccio a farmi citare da ChatGPT?
Rendi ogni pagina leggibile senza JavaScript, descrivila e lascia entrare il crawler di ricerca di ChatGPT. In Next.js questo significa Server Components con il testo nell'HTML, la Metadata API per titolo, canonical e lingue, app/robots.ts che consente OAI-SearchBot, app/sitemap.ts, e JSON-LD nella pagina. Niente di tutto questo garantisce una citazione; elimina però i motivi per cui ChatGPT non può usare la tua pagina.
Dati
- OpenAI dice che i siti che escludono OAI-SearchBot non vengono mostrati nelle risposte della ricerca di ChatGPT, e una modifica a robots.txt può richiedere circa 24 ore per avere effetto. (OpenAI: Overview of OpenAI crawlers)
- OpenAI dice che bloccare GPTBot segnala solo che i contenuti non devono servire ad addestrare i suoi modelli; le visite di ChatGPT-User sono avviate dagli utenti e non servono a decidere cosa compare nella ricerca. (OpenAI: Overview of OpenAI crawlers)
- Next.js dice che l'esportazione metadata e generateMetadata, disponibili dalla versione 13.2.0, funzionano solo nei Server Components, così i metadati possono stare nell'HTML iniziale. (Documentazione di Next.js: generateMetadata)
- Next.js genera robots.txt da app/robots.ts dalla versione 13.3.0, con regole per ogni user agent. (Documentazione di Next.js: robots.txt)
- app/sitemap.ts supporta gli URL alternativi per lingua dalla versione 14.2.0 di Next.js, e il limite di Google è di 50.000 URL per sitemap. (Documentazione di Next.js: sitemap.xml)
Quale crawler di OpenAI devo consentire?
OAI-SearchBot è quello che decide se la ricerca di ChatGPT può mostrare il tuo sito. I tre hanno compiti diversi, quindi bloccali o consentili separatamente.
// app/robots.ts
import type { MetadataRoute } from "next";
export default function robots(): MetadataRoute.Robots {
return {
rules: [
{ userAgent: "*", allow: "/" },
// ChatGPT search: must be allowed to be shown in answers
{ userAgent: "OAI-SearchBot", allow: "/" },
// Model training: your choice, it does not decide search
{ userAgent: "GPTBot", allow: "/" },
],
sitemap: "https://www.example.com/sitemap.xml",
};
}| User agent | Cosa fa | Effetto del blocco |
|---|---|---|
| OAI-SearchBot | Scansiona i siti per le funzioni di ricerca di ChatGPT | Le tue pagine non vengono mostrate nelle risposte della ricerca di ChatGPT |
| GPTBot | Scansiona contenuti che possono servire ad addestrare i modelli di OpenAI | I contenuti non servono all'addestramento; la ricerca non cambia |
| ChatGPT-User | Visita una pagina quando la domanda di un utente ne ha bisogno | robots.txt potrebbe non applicarsi; non decide la ricerca |
Perché il testo deve essere generato sul server?
Perché i crawler di ChatGPT leggono l'HTML che il tuo server invia e non eseguono JavaScript. Nell'App Router le pagine sono Server Components per impostazione predefinita; il testo recuperato in un Client Component dopo il caricamento manca in quell'HTML. Mantieni la pagina come Server Component e sposta nei file "use client" solo le parti interattive.
Cosa devono includere i metadati di ogni pagina?
Un titolo e una descrizione unici, un URL canonical e, nei siti multilingua, le alternative per lingua. generateMetadata le costruisce per ogni pagina; Next.js trasforma le alternative in link rel="canonical" e hreflang. Il JSON-LD va nella pagina come semplice tag script, con "<" sostituito come mostra la documentazione di Next.js, e deve dire le stesse cose del testo visibile.
// app/guides/[slug]/page.tsx (a Server Component: no "use client")
import type { Metadata } from "next";
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
const { slug } = await params;
const page = await getPage(slug);
return {
title: page.title,
description: page.description,
alternates: {
canonical: `/guides/${slug}`,
languages: { "pt-BR": `/pt/guides/${slug}`, es: `/es/guides/${slug}` },
},
};
}
export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const page = await getPage(slug);
const jsonLd = { "@context": "https://schema.org", "@type": "Article", headline: page.title };
return (
<article>
<script type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd).replace(/</g, "\\u003c") }} />
<h1>{page.title}</h1>
<p>{page.answer}</p>
</article>
);
}Come lo testo come farebbe un crawler?
Scarica la pagina online senza browser e cerca il testo della risposta, il titolo, il canonical e il JSON-LD. Se il testo non è nell'HTML grezzo, ChatGPT non può citarlo.
# 1. The text is in the raw HTML (no JavaScript run) curl -s -A "OAI-SearchBot" https://www.example.com/guides/my-page | grep -i "a sentence from the answer" # 2. Title, canonical and JSON-LD are there too curl -s https://www.example.com/guides/my-page | grep -iE "<title>|rel=\"canonical\"|ld\+json" # 3. robots.txt and sitemap answer curl -s https://www.example.com/robots.txt curl -s https://www.example.com/sitemap.xml | grep -c "<loc>"
Con una configurazione perfetta vengo citato?
No. La configurazione rende le pagine leggibili e idonee; ChatGPT sceglie le fonti in base a quanto bene una pagina risponde alla domanda. Il contenuto deve comunque essere la risposta più chiara a ciò che chiedono i tuoi acquirenti.
Passo dopo passo
- Controlla robots. Aggiungi app/robots.ts che consente OAI-SearchBot e punta alla sitemap; decidi separatamente su GPTBot.
- Tieni le pagine sul server. Verifica che ogni pagina pubblica sia un Server Component con il testo principale nell'HTML.
- Aggiungi i metadati. Usa generateMetadata per un titolo, una descrizione, un canonical e le alternative di lingua unici su ogni pagina.
- Aggiungi JSON-LD e la sitemap. Genera il JSON-LD nella pagina ed elenca ogni URL pubblico in app/sitemap.ts.
- Testa il sito online. Esegui i controlli con curl dopo il deploy, non in localhost.
Errori comuni
- Bloccare GPTBot e OAI-SearchBot con un'unica regola quando si voleva bloccare solo l'addestramento.
- Caricare il testo dell'articolo in useEffect, così l'HTML che riceve il crawler è vuoto.
- Copiare lo stesso titolo, la stessa descrizione o lo stesso canonical su ogni pagina dal layout radice.
- JSON-LD che afferma cose che la pagina visibile non dice.
Come lo risolve easyIndex
easyIndex si adatta bene a un sito Next.js perché il lavoro resta nel tuo repository: il tuo agente di codifica scrive le pagine e easyIndex fornisce i passi via MCP, controlla ogni pagina quando viene inviata e la verifica sul sito online, così un passo si completa con le prove che verifica, non con il report dell'agente.
Poi la dashboard mostra i visitatori degli assistenti AI per pagina e quali pagine leggono i crawler AI. Un solo piano con tutte le funzioni: US$ 30 al mese per sito, prova gratuita di 7 giorni con un sito.
Domande frequenti
Devo bloccare GPTBot?
È una tua scelta. OpenAI dice che GPTBot serve per l'addestramento e OAI-SearchBot per la ricerca, quindi bloccare solo GPTBot non ti esclude dalla ricerca di ChatGPT.
Mi serve il Pages Router o l'App Router?
Entrambi possono inviare HTML generato sul server. Questa guida usa l'App Router, dove le pagine sono Server Components per impostazione predefinita e vive la Metadata API.
Serve llms.txt?
No. La ricerca di ChatGPT legge le tue pagine; un file llms.txt non sostituisce il testo nell'HTML.
Quanto tempo passa prima che una modifica a robots.txt conti?
OpenAI dice circa 24 ore perché i suoi sistemi di ricerca si adeguino dopo un aggiornamento di robots.txt.
Continua a leggere
- ChatGPT e Claude vedono il mio sito fatto in JavaScript?
- Quali crawler AI esistono e come li consento in robots.txt?
- I dati strutturati (schema) aiutano l'AI a citare il mio sito?
- Come faccio a far consigliare la mia azienda da ChatGPT?
- Come faccio il GEO con Claude Code o Codex?
- Come funziona easyIndex, cosa mi serve e quanto tempo ci vuole per vedere i risultati?
Verificato il .