Metadati Next.js nel body: nove condizioni verificate
Neaptide · 12 ottobre 2026 · 8 min di lettura
Abbiamo testato Next.js 15.5.22 in nove condizioni: HTML ricevuto, DOM del browser e posizione del canonical. Risultati e limiti per la SEO.
In questo articolo

Trovare metadati dopo la chiusura di head può dipendere dallo streaming di Next.js. Nella nostra applicazione locale compilata per la produzione, i metadati asincroni comparivano nel body per due profili di richiesta e in head per il terzo. I valori erano presenti in tutte le risposte complete, ma questo non dimostra che un motore di ricerca accetti ogni tag in quella posizione.
Identifica prima il tag, il profilo della richiesta e la rappresentazione del documento che stai esaminando. Il test spiega la consegna dei metadati. Per canonical considera anche il requisito di Google relativo a head: trovare l'URL corretto in un punto qualsiasi del documento non basta a validare l'implementazione.
Che cosa abbiamo testato
Il 12 ottobre 2026 abbiamo testato Next.js 15.5.22 con React e React DOM 19.2.6 e Node v25.2.1. Tre modalità e tre profili HTTP User-Agent hanno prodotto nove condizioni, eseguite due volte ciascuna. Abbiamo conservato 18 risposte HTTP 200 complete, intestazioni e HTML. I due passaggi concordavano su numero, valori e posizione dei tag.
Il confronto comprendeva un oggetto metadata statico, una funzione generateMetadata asincrona con configurazione predefinita e la stessa funzione con htmlLimitedBots: /.*/. Entrambe le route usavano force-dynamic: statico indica l'export dei metadati, non una pagina prerenderizzata. La funzione asincrona attendeva deliberatamente 250 ms, senza richieste esterne. Il ritardo rende osservabile la sequenza, ma non rappresenta un carico reale né un punteggio di prestazioni.
La risposta HTML dipendeva dal profilo

| Modalità metadati | UA browser | UA Googlebot | UA Twitterbot |
|---|---|---|---|
| Oggetto · predefinita | head | head | head |
| Async · predefinita | body | body | head |
| Async · bloccante | head | head | head |
Il collettore inviava una stringa simile a Chrome 134, Googlebot/2.1 oppure Twitterbot/1.0. Sono valori di intestazione, non visite di quei servizi. Tutte le richieste usavano Accept: text/html e Accept-Encoding: identity, senza cookie o intestazioni di navigazione client. Le stringhe esatte sono nei risultati scaricabili.
Il browser ha mantenuto i tag async nel body
Abbiamo caricato le tre modalità anche nel browser collegato, il cui User-Agent ricevuto indicava Chrome 154. Nel DOM, title, description e canonical erano in head nelle modalità statica e bloccante. Restavano nel body nella modalità async predefinita: non abbiamo osservato uno spostamento in head. Questi tre caricamenti sono distinti dalle 18 richieste HTTP e non simulano il rendering di Googlebot.
| Modalità | DOM: tutti e tre i tag |
|---|---|
| Oggetto · predefinita | head |
| Async · predefinita | body |
| Async · bloccante | head |
Il canonical richiede una verifica specifica
Next.js documenta lo streaming dei metadati nel body e la consegna bloccante per i bot con capacità HTML limitate. Questo spiega il comportamento riprodotto. Google precisa però che il link HTML canonical viene accettato in head; anche il suo esempio JavaScript lo inserisce in document.head. Le indicazioni generali del framework non risolvono questo requisito specifico.
Nella nostra modalità async predefinita, canonical rimane nel body sia nella risposta sia nel DOM. Non possiamo dire che Google l'abbia accettato o rifiutato: l'applicazione era locale, conteneva noindex e non è stata inviata all'indicizzazione. Verifica quindi la route pubblicata. Se canonical rimane fuori da head, adotta un'implementazione conforme alla posizione documentata da Google e ripeti i controlli. La configurazione bloccante riportata sotto ha ottenuto head nel test; non dimostra un miglioramento del posizionamento.
Come controllare la propria route
- Salva la risposta completa dell'URL in produzione, le intestazioni della richiesta e la versione distribuita. Controlla i veri elementi title, description e canonical: una stringa in uno script React non è un ulteriore tag HTML.
- Esamina separatamente il DOM renderizzato: valori, duplicati e appartenenza a head o body. Un titolo corretto nella scheda del browser non verifica canonical.
- Confronta i profili pertinenti al servizio che presenta il problema. Distingui browser, stringa del bot e richiesta effettiva del servizio esterno: sostituire User-Agent verifica solo la selezione della risposta sul server.
- Applica i requisiti del singolo tag. Per canonical controlla la pagina pubblicata con gli strumenti Google disponibili e le informazioni sulla canonicalizzazione, assicurandoti che il link HTML sia in head. Il DOM locale non rivela quale canonical abbia scelto Google.
- Modifica la parte necessaria, ricompila e ripeti gli stessi controlli. Se cambi lo streaming, valuta anche il caricamento con il carico reale: il nostro ritardo artificiale non stima le prestazioni in produzione.
La configurazione effettivamente testata
Per la terza modalità abbiamo ricompilato la stessa applicazione con questa opzione. Tutti e tre i tag erano in head per ogni profilo verificato. L'opzione sostituisce la regola predefinita di riconoscimento dei bot; /.*/ corrisponde a qualsiasi User-Agent. Conserva le altre impostazioni e valuta la portata della modifica prima di adottarla.
// next.config.mjs
export default {
htmlLimitedBots: /.*/,
};L'opzione cambia la consegna dei metadati nell'intera applicazione. Non abbiamo testato espressioni limitate a bot specifici, cache di produzione o navigazione tra route. L'esperimento non giustifica il passaggio di tutti i siti alla modalità bloccante.
Ripetere l'esperimento
Scarica l'applicazione di test e il lockfile delle dipendenze. Il README contiene i comandi di compilazione e avvio delle due configurazioni, poi del collettore Python. Avvia i server in due terminali separati ed esegui il collettore dalla radice dell'archivio estratto. Mantieni il test locale: include un ritardo artificiale, noindex e canonical example.test. L'archivio delle prove contiene l'HTML originale e le acquisizioni DOM; results.json raccoglie i profili completi e le osservazioni analizzate.
Esaminare le prove
- Protocollo, risultati e fonti · JSON
- Metodo e limiti · TXT
- Applicazione riproducibile · ZIP
- Risposte HTTP e DOM originali · ZIP
Abbiamo verificato una versione, due compilazioni locali e tre caricamenti nel browser. Non abbiamo testato CDN, crawler remoti reali, navigazione client, errori nei metadati o Cache Components. Non abbiamo misurato indicizzazione, posizioni, citazioni IA, traffico, conversioni o Core Web Vitals. Raccolta e verifica sono state svolte dalla stessa persona. Ricontrolla la tua versione e il tuo ambiente.