Alessandro Aili - WordPress Developer
Alessandro Aili - WordPress DeveloperPlay Alessandro Aili - WordPress DeveloperDrag Alessandro Aili - WordPress DeveloperView
Alessandro Aili - WordPress Developer
  • Homepage
  • Chi sono
  • Portfolio
  • Aree di Attività
    • Sviluppo di Siti Web Personalizzati
    • Ottimizzazione delle Prestazioni
    • Sicurezza del Sito Web
    • Aggiornamenti e Manutenzione
    • Sviluppo di Temi e Plugin Personalizzati
    • Migrazione e Trasferimento del Sito
  • Blog
  • Contatti
Alessandro Aili - WordPress Developer
Alessandro Aili - WordPress Developer Alessandro Aili - WordPress Developer
  • Homepage
  • Chi sono
  • Portfolio
  • Aree di Attività
    • Sviluppo di Siti Web Personalizzati
    • Ottimizzazione delle Prestazioni
    • Sicurezza del Sito Web
    • Aggiornamenti e Manutenzione
    • Sviluppo di Temi e Plugin Personalizzati
    • Migrazione e Trasferimento del Sito
  • Blog
  • Contatti
MENU Alessandro Aili - WordPress Developer
  • Home
  • SEO
  • Blog
  • Come fare un redirect in WordPress: quale codice, con quale strumento e i quattro che fa già da solo

Come fare un redirect in WordPress: quale codice, con quale strumento e i quattro che fa già da solo

Alessandro Aili - WordPress Developer
Alessandro Aili WordPress Developer

Data di pubblicazione

15 Settembre 2026

Tempo di lettura

24 minuti

Categoria

SEO

Commenti

0

Schema di un redirect 301: un vecchio indirizzo che manda a uno nuovo in un salto solo, con accanto i quattro redirect automatici di WordPress

Un redirect è una risposta del server che dice «non qui: là». Chi legge non se ne accorge; per Google è un segnale su quale indirizzo tenere nei risultati. Su WordPress si può fare in tre posti diversi — con il plugin SEO, sul server, in PHP — e la scelta del codice conta più dello strumento. Ma la cosa che quasi nessuna guida dice è un’altra: WordPress ne fa già quattro da solo, senza che tu abbia configurato niente, e due di questi ti conviene conoscerli prima di scrivere qualunque regola — perché spiegano un vecchio indirizzo che «funziona ancora» e una regola nuova che manda in loop.

Questa guida va in quest’ordine: quando un redirect serve e quando no, quale codice usare, i quattro redirect automatici del core; poi i tre modi per farne uno tuo, l’ordine delle operazioni che rompe i siti quando è sbagliato, e come verificare il risultato senza fidarsi del browser.

Una nota sulle fonti. Tutto quello che segue l’ho verificato il 15 settembre 2026 sul codice sorgente di WordPress 7.1 e di Rank Math 1.0.278, sulla documentazione di Google Search e di Search Console, sulla RFC 9110 e sulle documentazioni di Apache e nginx. Il codice è stato eseguito, non solo riletto: i comportamenti del core e i blocchi PHP in un’installazione WordPress 7.1 vera (WordPress Playground), il file .htaccess su un Apache 2.4.67 reale, e i redirect di questo sito con curl. Dove compare una versione o un numero, accanto c’è la data.

Cos’è un redirect e quando serve davvero

Tecnicamente è una risposta HTTP con un codice della famiglia 3xx e un’intestazione Location con il nuovo indirizzo: il browser rifà la richiesta lì, e lo stesso fa Googlebot, che secondo la documentazione sui codici di stato segue fino a dieci salti — «By default, Google’s crawlers follow up to 10 redirect hops» — ignorando qualunque contenuto restituito dall’indirizzo di partenza. Il redirect è anche uno dei due segnali «forti» con cui Google sceglie l’indirizzo canonico: nella pagina sulla canonicalizzazione è il primo dell’elenco, «a strong signal that the target of the redirect should become canonical», accanto a rel="canonical" e sopra la sitemap, che è un segnale debole.

Serve in tre casi. Un indirizzo è cambiato: lo slug di un articolo, la categoria che sta nel permalink, il dominio. Due pagine sono diventate una: la vecchia manda alla nuova, che ne assorbe il contenuto. Una pagina è stata rimossa e ne esiste un’altra che risponde alla stessa domanda. Quando ha senso cambiare l’indirizzo — e quando invece è solo voglia di riordinare — l’ho scritto nella guida alla struttura del sito, dove spiego quando lo slug si cambia e quando si lascia com’è; come si decide fra accorpare e cancellare sta nella guida su come ripulire un sito senza romperlo. Qui do per prese quelle decisioni e mi occupo di eseguirle.

Non serve in due casi che sembrano uguali ai primi. Una pagina rimossa senza una sostituta vera deve rispondere 404 (o 410): per Google un 4xx significa che il contenuto non c’è più e l’indirizzo esce dall’indice — non è un fallimento, è la risposta giusta, purché sia un 404 vero e non un soft 404. E non si manda mai tutto in home page: la guida di Google ai trasferimenti lo dice testualmente, «Don’t redirect many old URLs to one irrelevant single URL destination, such as the home page of the new site. This can confuse users and might be treated as a soft 404 error». Il redirect ha senso quando la destinazione risponde alla domanda di chi arriva; se non risponde, è un vicolo cieco con un codice 301 davanti.

Il codice è la parte che conta: 301, 302, 307, 308 e 410

Il numero che accompagna il redirect dice due cose: se lo spostamento è permanente o temporaneo, e cosa deve fare il client con il metodo della richiesta. La prima distinzione è quella che decide cosa mostra Google: nella documentazione sui redirect (aggiornata il 14 aprile 2026) è scritta in una riga — «Permanent redirects: Show the new redirect target in search results. Temporary redirects: Show the source page in search results». La seconda distinzione è quella per cui esistono il 307 e il 308: la RFC 9110, che definisce HTTP, ammette che con 301 e 302 un client possa trasformare una richiesta POST in GET, e dice di aver aggiunto 307 e 308 «to unambiguously indicate method-preserving redirects».

CodiceCosa dichiara (RFC 9110)Cosa ne fa GoogleQuando usarlo su WordPress
301 Moved PermanentlyNuovo indirizzo permanente; il client può cambiare POST in GET; la risposta è cacheable per defaultSegnale forte che la destinazione diventi canonicaTutto ciò che si sposta per sempre: slug, categoria, pagina accorpata, dominio
302 FoundLa risorsa è temporaneamente altrove; il client continua a usare l’indirizzo originaleSegnale debole; l’indirizzo di partenza resta nei risultatiSolo se davvero tornerà: una promozione, una pagina in manutenzione
307 Temporary RedirectCome 302, ma il metodo della richiesta non cambia«Equivalent to 302»Un 302 che deve preservare un POST; raro su un sito di contenuti
308 Permanent RedirectCome 301, ma il metodo non cambia; la RFC avverte che, essendo più giovane, «might not be recognized everywhere»«Equivalent to 301»Un 301 che deve preservare un POST; per le pagine normali il 301 basta
410 GoneRisorsa rimossa di proposito, condizione probabilmente permanenteCome ogni 4xx: contenuto ignorato, indirizzo rimosso dall’indicePagina eliminata senza sostituta, quando vuoi dirlo in modo esplicito

Due precisazioni che valgono più della tabella. Google tratta 307 e 308 come 302 e 301 ma aggiunge: «keep in mind that they’re semantically different. Use the status code that’s appropriate for the redirect so other clients (for example, e-readers, other search engines) may benefit from it». E sul 410: la stessa documentazione mette 404 e 410 nello stesso gruppo — «All 4xx errors, except 429, are treated the same» — quindi la differenza è per le persone e per gli strumenti, non per l’indicizzazione. La RFC lo dice con la sua precisione: il 410 «is primarily intended to assist the task of web maintenance», e se non sai se la rimozione è definitiva, il 404 «ought to be used instead».

La regola pratica per un sito WordPress è corta. 301 per tutto ciò che si sposta e non torna; 302 solo se sai già quando lo toglierai, perché finché c’è Google continua a mostrare l’indirizzo vecchio; 307 e 308 quando c’è un modulo o un’API dietro; 410 quando cancelli e vuoi dirlo. Il rischio vero non è scegliere male fra questi: è ottenere un 302 senza volerlo, perché — come vedrai — è il valore predefinito di più strumenti di quanti immagini.

I quattro redirect che WordPress fa da solo

Prima di aggiungere una regola conviene sapere cosa succede già. Nel core ci sono quattro meccanismi che rispondono con un redirect senza che nessuno li abbia configurati; li ho letti nel sorgente della 7.1 e provati uno per uno, su un’installazione pulita e su questo sito. Tre rispondono 301, uno 302, e tutti mandano l’intestazione X-Redirect-By: WordPress — che è il modo più rapido per riconoscerli.

1. Il redirect canonico: www, barra finale, ?p=

La funzione redirect_canonical(), nel core dalla versione 2.3, riporta ogni richiesta alla forma «giusta» dell’indirizzo: aggiunge o toglie www in base all’indirizzo impostato in Impostazioni → Generali, mette o toglie la barra finale secondo la struttura dei permalink, trasforma ?p=123 nel permalink leggibile, elimina /index.php/ dal percorso, e — dettaglio che riguarda la sicurezza più della SEO — trasforma ?author=1 nell’archivio dell’autore, rivelandone lo username: è il motivo per cui nella checklist di sicurezza consiglio di chiudere l’enumerazione degli utenti. Risponde sempre 301. Non fa invece una cosa che molti gli attribuiscono: non porta da HTTP a HTTPS. Lo schema della richiesta viene conservato tale e quale; quel redirect lo fa il server, o la CDN.

2. Il vecchio slug: vale per gli articoli, non per le pagine

Quando cambi lo slug di un articolo pubblicato, WordPress salva quello vecchio in un metadato, _wp_old_slug, e da quel momento wp_old_slug_redirect() (dalla 2.1) risponde 301 dal vecchio indirizzo al nuovo. È per questo che un articolo rinominato «funziona ancora» anche senza plugin. Ma la funzione che salva il metadato, wp_check_for_changed_slugs(), ha un limite scritto nel codice: «We’re only concerned with published, non-hierarchical objects». Le pagine sono gerarchiche, quindi restano fuori. L’ho provato: rinominato lo slug di un articolo e di una pagina nella stessa installazione, il vecchio indirizzo dell’articolo risponde 301, quello della pagina 404. Se cambi lo slug di una pagina — la pagina servizi, la pagina contatti — il redirect lo devi fare tu. (Dalla 4.9.3 lo stesso meccanismo copre anche la data, per chi ha l’anno o il mese nel permalink.)

3. Il redirect «indovinato» sui 404, che nessuno ha chiesto

Questo è quello da conoscere. Quando una richiesta finisce in 404 e contiene un nome di articolo, redirect_guess_404_permalink() (dalla 2.3) cerca nel database un articolo il cui slug inizia con quel nome — la query è post_name LIKE 'nome%' — e se lo trova risponde 301 verso di lui. Non guarda la categoria nell’indirizzo, solo il nome. Su questo sito, il 15 settembre 2026: /blog/seo/s/ risponde 301 verso la guida su schema.org, /blog/seo/wordpress/ verso l’articolo su WordPress 7.1, che sta in un’altra categoria, e /blog/seo/child/ verso la guida al child theme, che sta in un’altra ancora.

Le conseguenze pratiche sono due. La prima: un test fatto con un indirizzo «parziale» mente — vedi un 301 e pensi che esista una regola, mentre è WordPress che tira a indovinare. La seconda, più seria, la vedrai nella sezione sull’ordine delle operazioni: se il nuovo slug di un articolo è il prefisso del vecchio (tema-wordpress-professionale-2025 → tema-wordpress-professionale, un cambio che ho fatto davvero), questo meccanismo può rimandare il nuovo indirizzo al vecchio e chiudere un anello. Dalla 5.5 esiste un filtro per renderlo esatto invece che «per prefisso», e uno per spegnerlo del tutto:

<?php
// In un mu-plugin o nel functions.php del child theme.
// Solo corrispondenze esatte dello slug sui 404 (WordPress 5.5+).
add_filter( 'strict_redirect_guess_404_permalink', '__return_true' );

// Oppure: nessun tentativo di indovinare, un 404 resta un 404.
// add_filter( 'do_redirect_guess_404_permalink', '__return_false' );

Con il primo filtro attivo, nella mia installazione di prova /guide/articolo/ è tornato a rispondere 404 mentre l’indirizzo completo continuava a rispondere 200. Non è un’impostazione da mettere ovunque: su un blog con slug lunghi il «tentativo» salva davvero qualche link scritto male. È un’impostazione da conoscere quando verifichi.

4. Le scorciatoie per l’amministrazione

Dalla 3.4, wp_redirect_admin_locations() manda /admin e /dashboard alla bacheca e /login alla pagina di accesso, con un 302 — l’unico dei quattro che non è permanente. È anche il primo che sparisce: le funzioni che nascondono la pagina di accesso — Hide Backend, nel plugin di sicurezza che uso qui — la rimuovono, perché il loro scopo è proprio che /login non porti da nessuna parte. Su questo sito i tre indirizzi rispondono 404 per quel motivo.

Chi li spegne, e perché conviene saperlo

Nessuno dei quattro è garantito su un sito reale, perché i plugin li sostituiscono. Rank Math, quando l’opzione Reindirizzamento automatico è attiva, rimuove il redirect del vecchio slug del core e lo rimpiazza con una regola propria, salvata nella sua tabella. Un plugin che gestisce i permalink può prendere in carico anche il redirect canonico: su questo sito lo fa Permalink Manager, e si vede dall’intestazione X-Redirect-By: Permalink Manager su ?p=1296, dove il core avrebbe scritto WordPress. Il plugin di sicurezza toglie le scorciatoie. La conseguenza è che l’unico modo di sapere cosa fa il tuo sito è chiederglielo: nella sezione sulla verifica c’è il comando, e l’intestazione X-Redirect-By ti dice ogni volta chi ha risposto.

Dove si fa un redirect: quattro livelli

Una richiesta attraversa, nell’ordine, la CDN se c’è, il web server, e poi WordPress — dove il plugin SEO e il tuo codice PHP intervengono dopo che il core ha caricato tutto. Ogni livello può rispondere con un redirect, e più è vicino a chi chiede meno costa. La scelta non è di gusto:

LivelloStrumentoQuando è la scelta giustaCosa serve
CDNLe regole di redirect della CDN (su Cloudflare, Redirects)Dominio intero, HTTP → HTTPS, www; elenchi lunghi che devono rispondere senza toccare il serverAccesso al pannello della CDN
Web server.htaccess su Apache, blocco server su nginxCartelle intere, cambio di struttura, tutto ciò che deve valere anche se WordPress è spentoAccesso ai file o alla configurazione; su nginx non esiste .htaccess
PluginRank Math, RedirectionSingoli indirizzi, slug cambiati, pagine accorpate: il caso quotidianoSolo la bacheca; conta gli accessi e, con il registro dei 404, mostra gli indirizzi mancanti
PHP tuowp_safe_redirect() su template_redirectRedirect condizionali: dipende da chi chiede, da un parametro, da una dataUn mu-plugin o il child theme

Un principio che vale per gli ultimi due livelli, e che spiega buona parte dei «non funziona»: un redirect fatto in PHP vale solo se PHP viene eseguito. Se l’indirizzo di partenza ha una copia in una cache di pagina, quella copia viene servita prima — il file advanced-cache.php dei plugin di cache è incluso dal core prima ancora di aprire la connessione al database — e la regola non scatta finché la cache di quell’indirizzo non viene svuotata. Vale per la cache del plugin, del server e della CDN. Ci torno nella verifica.

Metodo 1 — Con Rank Math: la regola, l’automatismo e l’opzione da non attivare

È il metodo che uso su questo sito, e i numeri sono suoi: al 15 settembre 2026 la schermata dei reindirizzamenti contiene 22 regole. Ne ho verificate sedici dall’esterno — le nove vecchie pagine sulle versioni di WordPress che ho fatto confluire nella pagina unica sulle versioni, cinque cambi di slug, un accorpamento, una ricategorizzazione — e rispondono tutte in un salto solo, con l’intestazione X-Redirect-By: Rank Math. Il modulo è gratuito, ma compare solo in Modalità avanzata: Rank Math SEO → Bacheca → Moduli → Reindirizzamenti, come dice la documentazione del plugin.

La regola

In Rank Math SEO → Reindirizzamenti → Aggiungi nuovo i campi sono tre più uno. URL di origine: il percorso senza dominio, blog/vecchia-pagina/, con accanto il tipo di confronto — Esatto, Contiene, Inizia con, Termina con, Regex. Per un singolo indirizzo usa sempre Esatto: nel sorgente il confronto esatto toglie la barra finale da entrambi i lati, quindi copre sia /vecchia-pagina/ sia /vecchia-pagina; gli altri tre confronti per sottostringa catturano più di quello che pensi (un Inizia con blog/guida prende anche blog/guida-completa-al-backup). URL di destinazione: l’indirizzo completo, con https://. Tipo di reindirizzamento: 301 reindirizzamento permanente è il predefinito, e le alternative sono 302, 307, 410 e 451. Poi lo Stato, Attivo. La query string della richiesta viene accodata alla destinazione: /vecchia-pagina/?utm_source=x arriva a /nuova-pagina/?utm_source=x.

Modulo di un reindirizzamento in Rank Math: URL di origine con confronto Esatto, URL di destinazione, tipo 301, stato Attivo

Per una cartella intera — la categoria rinominata con %category% nel permalink — serve Regex: origine ^guide/(.*)$, destinazione https://www.tuosito.it/manuali/$1/. Un dettaglio che ho scoperto eseguendola: Rank Math confronta l’indirizzo senza barre iniziali e finali, quindi $1 arriva senza la barra in fondo — nella mia prova /guide/qualcosa/ finiva su /manuali/qualcosa, che, se la pagina esiste, WordPress corregge con un secondo salto. La barra va scritta nella destinazione. Esiste anche la strada breve per un singolo articolo: nel meta box di Rank Math sotto l’editor, scheda Avanzate, l’interruttore Reindirizza crea la stessa regola con l’URL di quel post come origine.

L’automatismo sui cambi di slug

In Rank Math SEO → Impostazioni generali → Reindirizzamenti c’è Reindirizzamento automatico, spento per impostazione predefinita. Acceso, ogni volta che cambi lo slug di un articolo, di una pagina, di una categoria o di un tipo di contenuto personalizzato pubblicato, il plugin crea da solo una regola 301 dal vecchio permalink al nuovo e te lo dice con un avviso in bacheca. L’ho verificato con una pagina — che il core, come hai visto, non copre — e con una categoria: la regola per l’archivio è comparsa, e gli articoli sotto la vecchia categoria sono stati riportati al nuovo indirizzo dal redirect canonico del core. Su questo sito è acceso.

Due cose da sapere prima di accenderlo. La prima: da quel momento Rank Math rimuove il redirect del vecchio slug del core, quindi gli slug che avevi cambiato prima non hanno una regola e il loro vecchio indirizzo torna a rispondere 404 — nella mia installazione di prova è successo esattamente questo all’articolo rinominato prima dell’attivazione. Se accendi l’opzione su un sito che ha già una storia, la lista dei vecchi slug va ricostruita a mano. La seconda: l’automatismo vale per i post che restano pubblicati; se un articolo pubblicato finisce nel cestino, il plugin non crea niente — mostra un avviso che ti propone di reindirizzarlo, e la decisione resta tua.

L’opzione da lasciare com’è

Nella stessa schermata c’è Comportamento di riserva: cosa fare quando un 404 non corrisponde a nessuna regola. Il predefinito è 404 standard, e va lasciato. Le alternative, Reindirizza alla homepage e Reindirizzamento personalizzato, trasformano ogni indirizzo inesistente in un 301 verso una pagina sola: l’ho provato, un indirizzo inventato risponde 301 verso la home. È il soft 404 descritto sopra, fabbricato in serie. C’è poi Debug dei reindirizzamenti, che mostra agli amministratori una schermata con la regola applicata invece di eseguirla: utile per dieci minuti, da spegnere subito dopo. Un’ultima cosa che il plugin fa e che vale la pena conoscere: quando salvi una regola con origine e destinazione uguali te lo segnala e la disattiva. Non controlla, però, i loop fra due regole, né quelli che nascono dall’incontro con i redirect del core.

Impostazioni dei reindirizzamenti in Rank Math: comportamento di riserva su 404 standard e reindirizzamento automatico attivo

Se non usi Rank Math, Redirection di John Godley fa lo stesso lavoro da solo — versione 5.10.0 al 15 settembre 2026, oltre due milioni di installazioni attive, con i confronti per espressione regolare e un registro dei 404 che aiuta a trovare gli indirizzi dimenticati. Le regole che seguono valgono per tutti e due.

Metodo 2 — Dal server: .htaccess su Apache, return su nginx

Il server risponde prima che WordPress esista, quindi non c’è cache di pagina che possa nascondere la regola e non c’è plugin che possa disattivarla. È il livello giusto per una cartella intera o per un cambio di struttura, e per i siti in cui il plugin di redirect non c’è. Su Apache le direttive vanno nel file .htaccess nella radice del sito — fuori dal blocco compreso fra # BEGIN WordPress e # END WordPress, che WordPress rigenera e, come avverte il commento che scrive lui stesso, «Any changes to the directives between these markers will be overwritten». Questo file l’ho eseguito su un Apache 2.4.67:

# .htaccess — prima del blocco "# BEGIN WordPress"

# Un singolo indirizzo. Attenzione: Redirect fa match per PREFISSO,
# quindi cattura anche /blog/vecchia-pagina/altro/ e lo manda a /blog/nuova-pagina/altro/
Redirect 301 "/blog/vecchia-pagina/" "https://www.tuosito.it/blog/nuova-pagina/"

# Lo stesso indirizzo, e SOLO quello (con o senza barra finale)
RedirectMatch 301 "^/blog/vecchia-pagina/?$" "https://www.tuosito.it/blog/nuova-pagina/"

# Una cartella intera, conservando il resto del percorso
RedirectMatch 301 "^/guide/(.*)$" "https://www.tuosito.it/manuali/$1"

# Una pagina rimossa senza sostituta
Redirect gone "/blog/pagina-rimossa/"

Tre cose che la documentazione di mod_alias dice e che le guide dimenticano. Redirect senza codice risponde 302 («If no status argument is given, the redirect will be “temporary” (HTTP status 302)»): nella mia prova, una riga senza il numero ha risposto 302. Redirect lavora per prefisso — «any request beginning with URL-path will return a redirect» — e la parte di percorso in più viene accodata alla destinazione: è comodo per una cartella, è un errore per un indirizzo singolo, dove serve RedirectMatch con l’espressione regolare ancorata. E non serve RewriteRule: Apache stesso, nella pagina su quando non usare mod_rewrite, scrive che il redirect semplice «should be accomplished using these directives rather than RewriteRule».

Su nginx il file .htaccess non esiste e non viene letto: le regole stanno nel blocco server della configurazione, che sull’hosting gestito di solito non tocchi tu — lì il pannello espone i redirect, oppure resta il plugin. Se la configurazione è tua, la documentazione del modulo rewrite dà due direttive: return con il codice, e rewrite con il flag permanent per il 301 (redirect darebbe 302). Questo blocco l’ho scritto sulla documentazione e riletto, non eseguito — sulla macchina con cui ho fatto le altre prove nginx non c’era:

# Dentro il blocco server { ... } del sito

# Un singolo indirizzo: "=" è il match esatto
location = /blog/vecchia-pagina/ {
    return 301 https://www.tuosito.it/blog/nuova-pagina/;
}

# Una cartella intera, conservando il resto del percorso
location ^~ /guide/ {
    rewrite ^/guide/(.*)$ https://www.tuosito.it/manuali/$1 permanent;
}

# Una pagina rimossa senza sostituta
location = /blog/pagina-rimossa/ {
    return 410;
}

Il redirect di un dominio intero è un caso a sé, con una mappa uno-a-uno degli indirizzi, il vecchio dominio da tenere vivo e lo strumento di cambio di indirizzo in Search Console: l’ho descritto nella guida alla migrazione di un sito WordPress senza downtime, e qui non lo ripeto.

Metodo 3 — In PHP: wp_safe_redirect, template_redirect e il 302 che non volevi

Il codice serve quando la regola dipende da qualcosa: da chi sta chiedendo, da un parametro, da una data, da uno stato del contenuto. Per un elenco di indirizzi fissi resta peggiore del plugin, che si legge in bacheca e conta gli accessi. La forma corretta è un’azione su template_redirect — che scatta quando WordPress ha già capito cosa è stato chiesto, quindi con i tag condizionali disponibili — e una chiamata a wp_safe_redirect() seguita da exit. Questo blocco l’ho eseguito nell’installazione di prova, come mu-plugin:

<?php
/**
 * Plugin Name: Redirect vecchia pagina
 * Description: Manda /vecchia-pagina/ a /nuova-pagina/ con un 301. File in wp-content/mu-plugins/.
 */
add_action( 'template_redirect', function () {
	if ( ! is_404() ) {
		return; // l'indirizzo esiste ancora: non si tocca
	}

	$richiesto = untrailingslashit( wp_parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH ) );

	if ( '/vecchia-pagina' === $richiesto ) {
		wp_safe_redirect( home_url( '/nuova-pagina/' ), 301 );
		exit;
	}
} );

Quattro cose, tutte verificate eseguendo. Il codice va scritto. La firma è wp_safe_redirect( $location, $status = 302 ): senza il secondo argomento la risposta è 302, temporanea — nella prova, una chiamata senza codice ha risposto 302. È l’errore più comune di tutto l’articolo, perché il redirect funziona lo stesso e nessuno guarda il numero. exit è obbligatorio: la funzione manda l’intestazione e restituisce il controllo, come dice la documentazione, «does not exit automatically, and should almost always be followed by a call to exit;»; senza, WordPress continua a costruire la pagina. wp_safe_redirect accetta solo host consentiti: il tuo e quelli aggiunti con il filtro allowed_redirect_hosts; se la destinazione è altrove, manda alla bacheca — nella prova, un redirect verso un dominio esterno è finito su /wp-admin/. Per un dominio esterno usa wp_redirect(), sapendo che non controlla niente. E ogni risposta porta X-Redirect-By: WordPress, che puoi cambiare con il terzo argomento per riconoscere i tuoi redirect nei log.

Il controllo su is_404() non è un vezzo: senza, una regola scritta sull’indirizzo di un post ancora pubblicato lo rende irraggiungibile, e un errore nel confronto può reindirizzare pagine che non c’entrano. Per un redirect che dipende dal contenuto — un articolo che rimanda a un altro finché resta in bozza, per esempio — al posto di is_404() usi is_singular() con l’ID, e il resto non cambia.

L’ordine delle operazioni: cambio di slug e accorpamento sono opposti

Le due operazioni più frequenti hanno un ordine giusto ciascuna, e sono l’uno il contrario dell’altro. L’ho imparato facendole su questo blog — nove pagine accorpate in una, cinque slug cambiati — e il modo più rapido per spiegarlo è mostrare cosa succede quando si sbaglia.

Accorpamento: prima la regola, poi la bozza. Due articoli diventano uno: la vecchia pagina va reindirizzata verso quella che resta. Si crea la regola mentre il vecchio post è ancora pubblicato, e solo dopo lo si mette in bozza. Con la regola attiva il vecchio indirizzo risponde 301 già da subito — l’ho verificato: una regola di Rank Math sull’indirizzo di un articolo pubblicato scatta comunque, perché il plugin controlla le regole prima di servire la pagina — e mettendo in bozza per primo, invece, esiste un intervallo in cui l’indirizzo risponde 404 a chiunque passi, Googlebot compreso. Mai il cestino al posto della bozza: il cestino rinomina lo slug aggiungendo __trashed e dopo trenta giorni cancella, mentre la bozza conserva il post com’è, nel caso servisse tornare indietro.

Cambio di slug: prima il nuovo slug, poi la regola. Qui il post è uno solo e cambia indirizzo. Se hai l’automatismo di Rank Math acceso, salvi lo slug nuovo e la regola nasce da sola. Se lo fai a mano, l’ordine è lo stesso: prima salvi lo slug, poi crei la regola dal vecchio al nuovo. Farlo al contrario — regola prima, slug dopo — sembra innocuo e invece può chiudere un anello, per colpa del redirect «indovinato» visto sopra. Il caso l’ho riprodotto nell’installazione di prova: articolo con slug articolo-redirect-nuovo, regola creata in anticipo verso /guide/articolo-redirect/, che ancora non esiste. Il vecchio indirizzo risponde 301 verso il nuovo (la regola); il nuovo è un 404, e WordPress cerca un articolo il cui slug inizia con articolo-redirect — lo trova, è quello vecchio — e risponde 301 all’indietro. curl rimbalza fra i due finché non lo fermi; il browser si arrende con ERR_TOO_MANY_REDIRECTS. Succede ogni volta che il nuovo slug è un prefisso del vecchio, e togliere un anno dallo slug — -2025 — è esattamente quel caso: due dei cinque slug che ho cambiato su questo blog lo erano.

Un terzo caso che rientra nel primo: rinominare una categoria quando %category% è nel permalink. Cambiano l’archivio e tutti gli articoli che ci stanno dentro. L’archivio ha bisogno della sua regola (l’automatismo di Rank Math la crea); gli articoli, se il redirect canonico del core è attivo, vengono riportati da soli al nuovo indirizzo — nella prova, /risorse/risorsa-uno/ è passato a /risorse-nuove/risorsa-uno/ con un 301 firmato WordPress. Ma i link interni non li corregge nessuno: quelli si riscrivono, ed è la parte descritta nella guida alla struttura, nella sezione su cosa fare quando la struttura del sito cambia.

Come si verifica un redirect, senza fidarsi del browser

Il browser è lo strumento peggiore per questo lavoro, per una ragione scritta nella RFC 9110: una risposta 301 «is heuristically cacheable», quindi il browser può memorizzarla e continuare a eseguirla anche dopo che hai corretto o cancellato la regola. Il terminale non ha memoria. Il comando che uso, sempre dall’indirizzo canonico — con https:// e con o senza www come lo usa il sito, altrimenti conti come «salto» la normalizzazione del server:

# Una richiesta, senza seguire il redirect: codice, destinazione e chi ha risposto
curl -sI https://www.tuosito.it/blog/vecchia-pagina/ | grep -i -E "^HTTP/|^location:|^x-redirect-by:"

# Seguendo la catena: quanti salti, dove finisce, con che codice
curl -sIL -o /dev/null -w "salti=%{num_redirects} finale=%{url_effective} codice=%{http_code}\n" https://www.tuosito.it/blog/vecchia-pagina/

# Con un parametro qualsiasi: se la risposta cambia, c'era una cache di mezzo
curl -sI "https://www.tuosito.it/blog/vecchia-pagina/?nc=$(date +%s)" | head -1

Il risultato buono è uno solo: 301, un salto, destinazione che risponde 200 e che ha il canonical su sé stessa. Su questo sito, per esempio, /blog/trend-novita/wordpress-6-8/ risponde HTTP/2 301, location: …/versioni-di-wordpress/, x-redirect-by: Rank Math, e il secondo comando dice salti=1. Se i salti sono due, di solito uno è HTTP → HTTPS o www, e la regola va scritta direttamente sulla forma finale; se il primo comando mostra 200 dove ti aspetti 301, prova il terzo: se con il parametro compare il redirect, la copia in cache dell’indirizzo vecchio è ancora servita e va svuotata; se non compare, la regola non è stata salvata o non corrisponde. L’intestazione X-Redirect-By chiude il cerchio: Rank Math, WordPress, un altro plugin, oppure niente — e in quel caso ha risposto il server o la CDN.

Poi Search Console, che però dice cose diverse da quelle che ti aspetti. Nel rapporto Indicizzazione delle pagine, il vecchio indirizzo finisce fra le pagine non indicizzate con il motivo Pagina con reindirizzamento: è lo stato corretto, non un errore — la guida del rapporto lo definisce «un URL non canonico che reindirizza a un’altra pagina», e aggiunge che la destinazione «potrebbe essere indicizzata o meno». Il motivo da guardare è un altro, Errore di reindirizzamento: «una catena di reindirizzamento troppo lunga», «un loop di reindirizzamento», un URL troppo lungo o vuoto nella catena. E lo strumento Controllo URL non serve a vedere il redirect: il test dell’URL pubblicato, dice la sua guida, «segue prima tutti i reindirizzamenti implementati dalla pagina, poi la testa. Tuttavia, il test non indica che questa ha seguito un reindirizzamento». Per il redirect, il terminale.

Gli errori che vedo più spesso

  • Il 302 involontario. Redirect di Apache senza codice, wp_redirect() senza secondo argomento, il flag redirect di nginx al posto di permanent: tre modi di dire a Google che l’indirizzo vecchio è ancora quello buono. Il redirect funziona, il numero è sbagliato, e nessuno lo guarda.
  • La catena dopo il secondo spostamento. Se un indirizzo era già stato reindirizzato una volta, la regola vecchia punta a un indirizzo che ora reindirizza a sua volta. Google avverte: «we advise redirecting to the final destination directly». La regola più vecchia si aggiorna alla destinazione finale, non si lascia in catena.
  • Tutto in home page. L’opzione di riserva del plugin, una RedirectMatch troppo larga, un «tanto vale mandarli in home»: soft 404 in serie, e chi arriva non trova quello che cercava.
  • I link interni lasciati al vecchio indirizzo. Il 301 serve a chi arriva da fuori; dentro il sito, ogni link che passa da un redirect è un salto inutile a ogni clic e a ogni scansione. Si cercano e si riscrivono, e nella checklist SEO on-page è il controllo 11.
  • Il prefisso che prende troppo. Redirect di Apache e i confronti Inizia con e Contiene del plugin catturano tutto ciò che comincia con la stringa. Per un singolo indirizzo: confronto esatto o espressione regolare ancorata.
  • Il test fatto nel browser. Un 301 sbagliato provato nel browser resta nel browser. Una finestra privata basta per la sessione; curl per la verità.
  • La regola tolta troppo presto. Google chiede di tenere i redirect «for as long as possible, generally at least 1 year», e dal punto di vista di chi legge «consider keeping redirects indefinitely». Una regola costa niente; un link esterno che torna a dare 404 costa un lettore.

Domande frequenti

Un redirect 301 fa perdere posizioni?

Non per il redirect in sé. Per Google un 301 è un segnale forte che la destinazione debba diventare l’indirizzo canonico, e la sua guida ai trasferimenti descrive un periodo in cui i segnali passano al nuovo indirizzo, non un periodo in cui si perdono. Quello che fa perdere posizioni è ciò che spesso accompagna il redirect: una destinazione che non risponde alla stessa domanda, una catena di più salti, i link interni lasciati sul vecchio indirizzo, o una regola tolta dopo poche settimane. Se il redirect è uno, diretto e verso una pagina equivalente, una flessione di qualche settimana è normale.

Per quanto tempo va tenuto un redirect?

Il più a lungo possibile. Google indica almeno un anno come tempo minimo perché tutti i segnali passino al nuovo indirizzo, compresi i link di altri siti che puntano ancora a quello vecchio, e suggerisce di tenerli a tempo indeterminato dal punto di vista di chi legge. Una regola in un plugin o in un file di configurazione non costa niente; un link esterno che torna a rispondere 404 costa un lettore ogni volta. Si toglie solo quando l’indirizzo di partenza non riceve più visite, e il contatore degli accessi del plugin serve a saperlo.

Se cambio lo slug di un articolo, WordPress fa il redirect da solo?

Sì per gli articoli pubblicati, no per le pagine. Il core salva il vecchio slug in un metadato e risponde 301 dal vecchio indirizzo al nuovo, ma la funzione che lo fa esclude per scelta i contenuti gerarchici, cioè le pagine: rinominata una pagina, il vecchio indirizzo risponde 404. E anche per gli articoli l’automatismo può essere stato sostituito dal plugin SEO o da un plugin per i permalink, che lo spengono per gestirlo in proprio. Il modo sicuro è verificare il vecchio indirizzo dal terminale dopo ogni cambio di slug, qualunque cosa ti aspetti che succeda.

Posso reindirizzare una pagina cancellata alla home?

Puoi, ma è la scelta peggiore fra quelle disponibili. Google la considera un possibile soft 404, cioè una pagina che dichiara di esistere e non consegna niente, e chi arriva da un link o da un risultato di ricerca si ritrova in home senza sapere perché. Se esiste una pagina che risponde alla stessa domanda, il redirect va lì; se non esiste, la risposta corretta è un 404 vero o un 410, che dicono a Google di togliere l’indirizzo dall’indice e a chi legge che il contenuto non c’è più. La home page va bene come destinazione solo quando è davvero la pagina più pertinente, e capita di rado.

Meglio fare i redirect con un plugin o sul server?

Dipende da cosa devi reindirizzare e da chi lo manterrà. Il plugin è la scelta giusta per i casi di ogni giorno — uno slug cambiato, due pagine accorpate — perché si gestisce dalla bacheca, conta gli accessi e non richiede di toccare file. Il server è la scelta giusta per le cartelle intere, per i cambi di struttura e per tutto ciò che deve rispondere anche quando WordPress non gira, perché non passa dalla cache di pagina e nessun plugin può disattivarlo. Su un hosting gestito con nginx, dove il file .htaccess non esiste, la scelta è di fatto fra il plugin e il pannello dell’hosting. La verifica è la stessa a ogni livello: un salto, codice 301, destinazione che risponde 200.

Perché un indirizzo che non ho mai reindirizzato risponde 301?

Quasi sempre è WordPress che tira a indovinare. Quando una richiesta finisce in 404 e contiene un nome, il core cerca un articolo il cui slug inizia con quel nome e, se lo trova, risponde 301 verso di lui, senza guardare la categoria nell’indirizzo. Per questo un indirizzo abbreviato «funziona» anche senza regole, e un test fatto con un indirizzo parziale non dice niente sulle regole che hai creato. L’intestazione X-Redirect-By della risposta dice chi ha risposto: se c’è scritto WordPress e non esiste una regola, è questo meccanismo. Dalla versione 5.5 si può limitare alle corrispondenze esatte o spegnere con un filtro.

Da qui in avanti

Se devi ricordare una cosa sola: prima di scrivere una regola, chiedi al sito cosa risponde già. Un comando dal terminale sull’indirizzo che vuoi spostare ti dice se è un 200, un 404 o un redirect che non hai mai creato — e l’intestazione X-Redirect-By ti dice di chi è. Poi il codice giusto, un salto solo, i link interni riscritti, e la stessa verifica ripetuta dopo aver salvato. Tutto il resto — il plugin, il file, la funzione — è il mezzo.

Il redirect è una delle poche cose che, fatte male, non si vedono per mesi. Per questo sta nel piano di manutenzione del sito come controllo periodico, e per questo, quando si tocca la struttura degli indirizzi, conviene farlo una volta e bene: nella guida su come installare e configurare WordPress i permalink stanno fra le cose da decidere il primo giorno proprio per non dover reindirizzare tutto il sito un anno dopo.

Se preferisci che lo faccia io

Ricostruire la mappa degli indirizzi di un sito, trovare i 404 con traffico, le catene e i redirect fatti con il codice sbagliato, e sistemarli nell’ordine giusto è una parte dell’audit SEO tecnico che faccio sui siti WordPress. Se vuoi che me ne occupi io, guarda come lavoro nelle aree di attività oppure scrivimi: partiamo dagli indirizzi del tuo sito, non da una checklist.

Indice dei contenuti

  • Cos’è un redirect e quando serve davvero
  • Il codice è la parte che conta: 301, 302, 307, 308 e 410
  • I quattro redirect che WordPress fa da solo
  • Dove si fa un redirect: quattro livelli
  • Metodo 1 — Con Rank Math: la regola, l’automatismo e l’opzione da non attivare
  • Metodo 2 — Dal server: .htaccess su Apache, return su nginx
  • Metodo 3 — In PHP: wp_safe_redirect, template_redirect e il 302 che non volevi
  • L’ordine delle operazioni: cambio di slug e accorpamento sono opposti
  • Come si verifica un redirect, senza fidarsi del browser
  • Gli errori che vedo più spesso
  • Domande frequenti
  • Da qui in avanti
  • Se preferisci che lo faccia io

Tag in Evidenza

RedirectSEO tecnicaWordPress

Condividi


Lascia un commento Annulla risposta

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Alessandro Aili - WordPress Developer Alessandro Aili - WordPress Developer
Sono un WordPress developer che affronta tutte le tue sfide online.
Skills
  • Sviluppo di Siti Web Personalizzati
  • Ottimizzazione delle Prestazioni
  • Sicurezza del Sito Web
  • Aggiornamenti e Manutenzione
  • Sviluppo di Temi e Plugin Personalizzati
  • Migrazione e Trasferimento del Sito
© Copyright 2026 Alessandro Aili
  • Mappa del sito
  • Privacy Policy
  • Cookie Policy
  • Preferenze cookie
Alessandro Aili - WordPress Developer