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
  • WordPress
  • Blog
  • Migrare da Blogger a WordPress senza perdere articoli, immagini e indirizzi

Migrare da Blogger a WordPress senza perdere articoli, immagini e indirizzi

Alessandro Aili - WordPress Developer
Alessandro Aili WordPress Developer

Data di pubblicazione

2 Ottobre 2026

Tempo di lettura

24 minuti

Categoria

WordPress

Commenti

0

Un blog che si trasferisce in un sito nuovo: articoli, immagini e indirizzi che finiscono in .html passano intatti da una finestra all'altra

Migrare da Blogger a WordPress sembra un lavoro da pochi minuti, perché fra gli strumenti di WordPress c’è un importatore per Blogger. Oggi quel percorso si ferma al primo passo.

Blogger fa scaricare il backup da Google Takeout in un formato che l’importatore non riconosce, e l’importazione finisce con il messaggio di sempre e nessun articolo. Anche quando i testi arrivano, restano da sistemare a parte le immagini, che stanno sui server di Google, gli indirizzi, che su Blogger hanno una forma tutta loro, e il dominio blogspot.com, che appartiene a Google e non segue il blog.

Questa guida segue l’ordine in cui le cose vanno decise. Prima da dove parte il blog, poi cosa contiene il backup e come importarlo con uno script che tiene gli indirizzi di Blogger, infine cosa fare con quelli che non tornano. Il metodo che vale per qualsiasi piattaforma è nella guida per migrare a WordPress da un’altra piattaforma; qui c’è quello che vale solo per Blogger.

Una nota sulle fonti. Quello che dico di Blogger viene dalle guide ufficiali di Blogger e di Google, lette il 1° e il 2 ottobre 2026. Le prove le ho eseguite su WordPress 7.1.2 (PHP 8.3, WP-CLI 2.12.0) con un’esportazione vera, l’archivio Google Takeout del 22 agosto 2026 che il proprietario di quattordici blog ha pubblicato su GitHub. Ne ho importati cinque, 1.583 articoli in tutto. Dove un comportamento dipende da un plugin, accanto trovi la versione e la data.

Prima di tutto: blogspot.com o un dominio tuo

La prima domanda non riguarda WordPress.

Riguarda l’indirizzo a cui risponde oggi il blog, perché da questo dipende chi potrà gestire gli indirizzi vecchi dopo il passaggio.

Un blog su nomeblog.blogspot.com vive su un dominio di Google. Il giorno in cui passa a WordPress, gli indirizzi blogspot continuano a essere serviti da Blogger, e nessuna regola scritta su WordPress li può raggiungere. Un blog con un dominio tuo, come www.miodominio.it, punta invece a Blogger con un record DNS. Lo stesso dominio può puntare domani al nuovo hosting, e da quel momento agli indirizzi vecchi risponde WordPress.

Blog su blogspot.comBlog su un dominio tuo
Chi risponde agli indirizzi vecchi dopo il passaggioBloggerWordPress
Come si tengono gli indirizziPassando prima, dentro Blogger, a un dominio tuoCon la struttura dei permalink, più un redirect per quello che non torna
Cosa resta a GoogleIl dominio blogspot e il blog che ci rispondeSolo le immagini caricate su Blogger

Il dominio personalizzato si collega con un CNAME verso ghs.google.com e un secondo CNAME di verifica; la versione senza www rimanda al www con quattro record A verso gli indirizzi di Google e un’opzione delle impostazioni, come spiega la guida di Blogger sui domini personalizzati. Quando il dominio è attivo, Blogger manda l’indirizzo blogspot sul dominio, e la guida avverte che possono servire fino a 24 ore. Sui blog di Google che usano Blogger con un dominio proprio l’ho osservato così: un 301 che conserva percorso e parametri. Il passaggio da blogspot ha una sezione sua, più avanti.

Per sapere in quale caso sei basta guardare, nelle impostazioni del blog, la sezione sulla pubblicazione, dove c’è il dominio personalizzato. Lo dice anche il backup: nei blog senza dominio proprio che ho visto, il file settings.csv riporta BLOGSPOT nel campo blog_publishing_mode.

Con un dominio tuo, il resto del lavoro si fa su WordPress. Senza, c’è un passo in più da fare su Blogger prima del trasloco.

Cosa c’è nel backup di Blogger, e cosa no

La guida di Blogger al backup e all’importazione del blog oggi rimanda a Google Takeout. Il collegamento della guida apre Takeout già filtrato su Blogger, e quello che si scarica è un archivio compresso. Nella stessa guida i file .xml sono quelli che Blogger forniva in passato, mentre la pagina sulle impostazioni del blog dice ancora che il backup è un file .xml di articoli e commenti. Fa fede la prima, ed è quello che si trova nell’archivio.

Nell’esportazione che ho usato ogni blog ha una cartella con cinque file:

  • feed.atom, con articoli, pagine e commenti, bozze comprese, e anche i commenti che Blogger aveva segnato come spam;
  • settings.csv, con le impostazioni, fra cui il sottodominio blogspot e il fuso orario del blog, che servono più avanti;
  • theme-layouts.xml e theme-classic.html, il tema, che funziona solo su Blogger;
  • followers.csv, chi segue il blog con il proprio account.

Accanto alle cartelle dei blog ci sono Albums, con le immagini caricate su Blogger e un file .json per ciascuna, e Comments, che contiene solo i commenti scritti dal tuo account, già presenti nel feed.atom del blog. Le statistiche non ci sono, e per i video caricati direttamente su Blogger le impostazioni hanno una voce a parte, da cui si scaricano.

Il feed.atom è un file XML in formato Atom. Ogni voce dichiara cos’è con due campi propri di Blogger, il tipo (POST, PAGE, COMMENT) e lo stato (LIVE, DRAFT, SPAM_COMMENT). L’indirizzo vecchio sta in un campo chiamato filename, nella forma /2017/07/titolo.html, e il campo del link, che negli altri feed porta l’indirizzo della pagina, qui è vuoto. Sono questi dettagli a decidere quale strumento riesce a leggere il file.

Per avere un’idea delle proporzioni: nell’archivio che ho usato quindici file feed.atom contenevano 2.015 voci: 1.968 articoli, 121 dei quali in bozza, e 47 commenti, 18 dei quali di spam. Gli articoli pubblicati avevano tutti il loro indirizzo, mentre 80 bozze su 121 non ne avevano uno. C’è anche un campo per la descrizione di ricerca di ogni articolo, vuoto in tutto l’archivio: se tu l’avevi compilata, va ricopiata nel plugin SEO, perché lo script non la usa.

Perché Strumenti → Importa → Blogger non basta

In Strumenti → Importa WordPress propone un importatore per Blogger, con la descrizione “Importa articoli, commenti e utenti da un blog Blogger”. È il plugin Blogger Importer, alla versione 0.9.3: l’ultimo aggiornamento è del 21 ottobre 2024 e la scheda avverte che non è stato provato con le ultime tre versioni maggiori di WordPress.

Il codice spiega perché con il backup di oggi non funziona. L’importatore riconosce un articolo da una categoria tecnica, kind#post, che il formato storico di Blogger metteva in ogni articolo. Nel feed.atom di Takeout quella categoria non c’è: nell’archivio che ho usato, su 2.015 voci, zero. Ho caricato tre file veri, 284 voci in tutto, e il risultato è stato lo stesso tre volte.

Nessun articolo, nessun commento, nessuna categoria, e il solito messaggio di importazione conclusa.

La schermata non se ne accorge. WordPress accetta qualunque file caricato in Strumenti → Importa, perché non ne controlla il tipo prima di passarlo all’importatore, e il Blogger Importer, non trovando articoli, chiude come se fosse andato tutto bene. Le istruzioni del suo readme, poi, mandano a cercare l’esportazione in un menu di Blogger che non c’è più.

Chi ha conservato un vecchio backup .xml può ancora usarlo, con limiti che la prova su un’esportazione del 2019 ha mostrato uno per uno:

  • le pagine non vengono importate, solo articoli e commenti;
  • le immagini vengono scaricate soltanto per i 20 articoli più recenti, e rilanciare l’importazione non serve, perché il giro riparte sempre da quelli;
  • le bozze prendono la data del giorno dell’importazione;
  • lo slug viene ricavato dal titolo invece che da Blogger, e l’indirizzo cambia;
  • se il fuso orario di WordPress è diverso da quello del blog, un articolo pubblicato vicino alla mezzanotte di fine mese passa al mese accanto, e il suo indirizzo vecchio risponde 404.

Il WordPress Importer, quello dei file di esportazione di WordPress, non legge né l’uno né l’altro formato: con entrambi risponde che il file non è un WXR. Lo segnalo perché la pagina sull’importazione di WordPress.com, aggiornata il 30 settembre 2026, per Blogger suggerisce proprio l’importatore di WordPress quando il file ha l’estensione XML.

Importare il feed.atom: un plugin o uno script

Cosa chiedere a un importatore, e due plugin provati

Nella directory dei plugin ce ne sono alcuni scritti apposta per il formato di Takeout.

Prima di sceglierne uno conviene sapere cosa deve fare, perché i difetti che contano si vedono solo dopo, sul sito pubblicato. Un importatore adatto legge il feed.atom e distingue articoli, pagine, bozze, commenti e spam. Scarica nella Libreria media anche le immagini senza estensione, e per ogni articolo tiene lo slug di Blogger, o almeno l’indirizzo vecchio. E i redirect che crea non devono sparire il giorno in cui il plugin viene disattivato.

Ne ho provati due gratuiti sullo stesso archivio, il 2 ottobre 2026, con le opzioni preimpostate delle loro schermate. Feed Importer for Blogger 1.0.0, uscito il 3 febbraio 2026, ha pubblicato le bozze e ha trasformato i commenti in articoli intitolati “(No Title)”. Rilanciato sullo stesso file ha creato una seconda copia di tutto, perché cerca i doppioni proprio nel campo del link che Takeout lascia vuoto.

BtW Importer 4.2.1, aggiornato il 27 giugno 2026, ha tenuto le bozze come bozze ma non ha importato i commenti, e prende lo slug dal titolo. Nel blog di prova con 47 articoli solo 16 conservavano l’indirizzo di Blogger, e agli altri 31 risponde con un 301 del plugin. Con la struttura dei permalink che ricopia Blogger, però, quei 16 sono finiti in un ciclo di redirect, rimandati ciascuno su sé stesso; con la struttura Nome articolo il problema non c’è.

Disattivando il plugin i suoi redirect spariscono, e 15 indirizzi su 47 rispondevano 404.

C’è poi Blogger Importer Extended, che non legge il backup: si collega al blog con le API di Google attraverso il servizio di chi lo sviluppa. La versione gratuita importa fino a 20 articoli o pagine, oltre serve una licenza, e le bozze restano fuori. Non l’ho provato, perché richiede di collegare un account Google.

Lo script WP-CLI: stessi indirizzi, nessun redirect per gli articoli

Lo script qui sotto legge il feed.atom e fa le cose che chiedevo agli importatori. Crea articoli e pagine con lo slug e la data di Blogger, porta le bozze come bozze, le etichette come tag e i commenti con le loro risposte, scartando quelli segnati come spam. Scarica le immagini caricate su Blogger nella dimensione originale, anche quelle senza estensione, e riscrive i link fra un articolo e l’altro.

Si può rilanciare senza creare doppioni, e un giro interrotto si completa rilanciandolo.

Prima di lanciarlo servono due impostazioni. In Impostazioni → Generali il Fuso orario va messo uguale a quello del blog, che sta nel campo blog_time_zone di settings.csv. In Impostazioni → Permalink va scelta la Struttura personalizzata /%year%/%monthnum%/%postname%.html, di cui parlo nella sezione sugli indirizzi. Poi in cima allo script si scrive l’indirizzo del blog, e lo si lancia con wp eval-file dalla cartella del sito:

wp eval-file importa-blogger.php feed.atom --user=admin

Con --user si indica l’utente a cui vanno gli articoli, perché degli autori il feed riporta solo il nome.

<?php
/**
 * Importa in WordPress il backup di Blogger scaricato da Google Takeout (feed.atom).
 * Uso: wp eval-file importa-blogger.php feed.atom --user=admin
 *
 * Articoli e pagine con lo slug e la data di Blogger, bozze comprese; etichette come tag;
 * commenti con le risposte, senza quelli segnati come spam. Scarica nella Libreria media le
 * immagini caricate su Blogger, nella dimensione originale, e riscrive gli indirizzi delle
 * immagini e dei link fra un articolo e l'altro. Si può rilanciare: le voci già importate
 * vengono saltate. Alla fine scrive in redirect-blogger.csv gli indirizzi che non tornano.
 */

// Gli indirizzi del blog su Blogger: il sottodominio blogspot ed eventualmente il tuo dominio.
$vecchi_domini = array( 'nomeblog.blogspot.com' );
$tassonomia    = 'post_tag'; // 'category' se vuoi le etichette come categorie

require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/image.php';

if ( empty( $args[0] ) || ! is_readable( $args[0] ) ) {
	WP_CLI::error( 'Indica il file feed.atom da importare.' );
}
$feed = simplexml_load_file( $args[0] );
if ( ! $feed ) {
	WP_CLI::error( 'Il file non è un XML leggibile.' );
}
$b     = 'http://schemas.google.com/blogger/2018'; // lo spazio dei nomi dei campi propri di Blogger
$campo = fn( $voce, $nome ) => trim( (string) $voce->children( $b )->$nome );
$gmt   = fn( $voce ) => gmdate( 'Y-m-d H:i:s', strtotime( (string) $voce->published ) );

// Le voci già importate in un giro precedente, per non creare doppioni.
global $wpdb;
$articoli = array_map( 'intval', $wpdb->get_col( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_blogger_id'" ) );
$articoli = array_combine( array_map( fn( $id ) => get_post_meta( $id, '_blogger_id', true ), $articoli ), $articoli );
$commenti = array_map( 'intval', $wpdb->get_col( "SELECT comment_id FROM $wpdb->commentmeta WHERE meta_key = '_blogger_id'" ) );
$commenti = array_combine( array_map( fn( $id ) => get_comment_meta( $id, '_blogger_id', true ), $commenti ), $commenti );

// Un'immagine di Blogger si scarica una volta sola, nella dimensione originale (s0).
// Gli indirizzi recenti non hanno il nome del file: il tipo si legge dal file scaricato.
$scarica = function ( $url, $post_id ) use ( $wpdb ) {
	$chiave = preg_replace( array( '#/[swh]\d[^/]*/([^/]+)$#', '#=[^/=]*$#' ), array( '/$1', '' ), $url );
	$gia    = $wpdb->get_var( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_blogger_img' AND meta_value = %s", $chiave ) );
	if ( $gia ) {
		return (int) $gia;
	}
	$con_nome  = (bool) preg_match( '#/[^/]+\.\w{2,5}$#', $chiave );
	$originale = $con_nome ? preg_replace( '#/([^/]+)$#', '/s0/$1', $chiave ) : $chiave . '=s0';
	$tmp       = download_url( $originale );
	if ( is_wp_error( $tmp ) ) {
		return $tmp;
	}
	$tipi = array( 'image/jpeg' => 'jpg', 'image/png' => 'png', 'image/gif' => 'gif', 'image/webp' => 'webp', 'image/avif' => 'avif' );
	$est  = $tipi[ wp_get_image_mime( $tmp ) ] ?? '';
	if ( ! $est ) {
		wp_delete_file( $tmp );
		return new WP_Error( 'formato', 'Non è un formato immagine che WordPress accetta.' );
	}
	$nome = $con_nome ? pathinfo( urldecode( wp_parse_url( $chiave, PHP_URL_PATH ) ), PATHINFO_FILENAME ) : 'blogger-' . substr( md5( $chiave ), 0, 10 );
	$id   = media_handle_sideload( array( 'name' => sanitize_file_name( "$nome.$est" ), 'tmp_name' => $tmp ), $post_id );
	if ( is_wp_error( $id ) ) {
		wp_delete_file( $tmp );
		return $id;
	}
	update_post_meta( $id, '_blogger_img', $chiave );
	return $id;
};

// 1. Articoli e pagine.
$creati = $saltati = $immagini = $link = 0;
$etichette_viste = array();
foreach ( $feed->entry as $voce ) {
	$tipo  = $campo( $voce, 'type' );
	$stato = $campo( $voce, 'status' );
	$id_b  = (string) $voce->id;
	if ( ! in_array( $tipo, array( 'POST', 'PAGE' ), true ) || '' !== $campo( $voce, 'trashed' ) ) {
		continue;
	}
	$etichette = array_filter( array_map( fn( $c ) => (string) $c['term'], iterator_to_array( $voce->category, false ) ) );
	if ( 'POST' === $tipo && 'LIVE' === $stato ) {
		$etichette_viste += array_fill_keys( $etichette, true );
	}
	if ( isset( $articoli[ $id_b ] ) ) {
		$saltati++;
		continue;
	}
	if ( ! in_array( $stato, array( 'LIVE', 'DRAFT' ), true ) ) {
		WP_CLI::warning( 'Stato ' . $stato . ' per "' . $voce->title . '": lo importo come bozza.' );
	}
	$file = $campo( $voce, 'filename' ); // /2017/07/titolo.html, /p/titolo.html, vuoto se mai pubblicato
	$id   = wp_insert_post( wp_slash( array(
		'post_type'     => 'PAGE' === $tipo ? 'page' : 'post',
		'post_status'   => 'LIVE' === $stato ? 'publish' : 'draft',
		'post_title'    => (string) $voce->title,
		'post_name'     => $file ? basename( $file, '.html' ) : '',
		'post_content'  => (string) $voce->content,
		'post_date_gmt' => $gmt( $voce ),
		'meta_input'    => array( '_blogger_id' => $id_b, '_blogger_url' => $file ),
	) ), true );
	if ( is_wp_error( $id ) ) {
		WP_CLI::warning( $id_b . ': ' . $id->get_error_message() );
		continue;
	}
	if ( 'POST' === $tipo && $etichette ) {
		wp_set_object_terms( $id, $etichette, $tassonomia );
	}
	$articoli[ $id_b ] = $id;
	$creati++;
}

// 2. Immagini e link interni, quando tutti gli articoli esistono già. Un giro interrotto
// si completa rilanciando: si rilavora solo il testo che punta ancora a Blogger.
$per_url = array();
foreach ( $articoli as $id ) {
	$per_url[ get_post_meta( $id, '_blogger_url', true ) ] = $id;
}
$domini = implode( '|', array_map( fn( $d ) => str_replace( '\.blogspot\.com', '\.blogspot\.[a-z.]+', preg_quote( $d, '#' ) ), $vecchi_domini ) );
foreach ( $articoli as $id ) {
	$testo = get_post_field( 'post_content', $id );
	if ( ! preg_match( "#googleusercontent\.com/img/|bp\.blogspot\.com/|$domini#i", $testo ) ) {
		continue;
	}
	$html = new WP_HTML_Tag_Processor( $testo );
	while ( $html->next_tag() ) {
		$attr = array( 'IMG' => 'src', 'A' => 'href' )[ $html->get_tag() ] ?? '';
		$url  = $attr ? (string) $html->get_attribute( $attr ) : '';
		if ( preg_match( '#^https?://(blogger\.googleusercontent\.com/img/|[0-9]\.bp\.blogspot\.com/)#', $url ) ) {
			$allegato = $scarica( $url, $id );
			if ( is_wp_error( $allegato ) ) {
				WP_CLI::warning( "Articolo $id: " . $allegato->get_error_message() . ' ' . $url );
				continue;
			}
			$html->set_attribute( $attr, wp_get_attachment_url( $allegato ) );
			if ( 'src' === $attr ) {
				$html->remove_attribute( 'srcset' );
				$html->add_class( 'wp-image-' . $allegato );
				$immagini++;
			}
		} elseif ( 'href' === $attr && preg_match( "#^https?://(?:www\.)?(?:$domini)(/[^?\#]*)#i", $url, $m ) ) {
			$html->set_attribute( 'href', isset( $per_url[ $m[1] ] ) ? get_permalink( $per_url[ $m[1] ] ) : home_url( $m[1] ) );
			$link++;
		}
	}
	wp_update_post( wp_slash( array( 'ID' => $id, 'post_content' => $html->get_updated_html() ) ) );
}

// 3. Commenti, dal più vecchio, così le risposte trovano il commento a cui rispondono.
$voci = array_filter( iterator_to_array( $feed->entry, false ), fn( $v ) => 'COMMENT' === $campo( $v, 'type' ) );
usort( $voci, fn( $x, $y ) => strcmp( $gmt( $x ), $gmt( $y ) ) );
$importati = $spam = 0;
foreach ( $voci as $voce ) {
	$id_b    = (string) $voce->id;
	$post_id = $articoli[ $campo( $voce, 'parent' ) ] ?? 0;
	if ( 'LIVE' !== $campo( $voce, 'status' ) ) {
		$spam++;
		continue;
	}
	if ( isset( $commenti[ $id_b ] ) || ! $post_id ) {
		continue;
	}
	$commenti[ $id_b ] = wp_insert_comment( wp_slash( array(
		'comment_post_ID'    => $post_id,
		'comment_parent'     => $commenti[ $campo( $voce, 'inReplyTo' ) ] ?? 0,
		'comment_author'     => (string) $voce->author->name,
		'comment_author_url' => (string) $voce->author->uri,
		'comment_content'    => wp_kses_data( preg_replace( '#<br\s*/?>#i', "\n", (string) $voce->content ) ),
		'comment_date_gmt'   => $gmt( $voce ),
		'comment_date'       => get_date_from_gmt( $gmt( $voce ) ),
		'comment_approved'   => 1,
		'comment_meta'       => array( '_blogger_id' => $id_b ),
	) ) );
	$importati++;
}

// 4. Gli indirizzi che non tornano diventano una riga ciascuno di redirect-blogger.csv;
// in vecchi-url.txt tutti quelli pubblicati, da provare dopo il passaggio.
$csv  = fopen( 'redirect-blogger.csv', 'w' );
$mese = 0;
$da_provare = array();
foreach ( $per_url as $vecchio => $id ) {
	$nuovo = wp_parse_url( get_permalink( $id ), PHP_URL_PATH );
	if ( $vecchio && 'publish' === get_post_status( $id ) ) {
		$da_provare[] = home_url( $vecchio );
	}
	if ( $vecchio && 'publish' === get_post_status( $id ) && strtolower( $vecchio ) !== $nuovo ) { // le maiuscole le risolve WordPress
		fputcsv( $csv, array( $vecchio, $nuovo ), ',', '"', '' );
		$mese += (int) ( preg_match( '#^/\d{4}/\d{2}/#', $nuovo ) && substr( $vecchio, 0, 9 ) !== substr( $nuovo, 0, 9 ) );
	}
}
foreach ( array_keys( $etichette_viste ) as $nome ) {
	$termine = get_term_by( 'name', $nome, $tassonomia );
	if ( ! $termine ) {
		continue;
	}
	fputcsv( $csv, array( '/search/label/' . rawurlencode( $nome ), wp_parse_url( get_term_link( $termine ), PHP_URL_PATH ) ), ',', '"', '' );
}
fputcsv( $csv, array( '/feeds/posts/default', wp_parse_url( get_feed_link(), PHP_URL_PATH ) ), ',', '"', '' );
fclose( $csv );
file_put_contents( 'vecchi-url.txt', implode( "\n", $da_provare ) . "\n" );

if ( $mese ) {
	WP_CLI::warning( "$mese articoli hanno anno o mese diversi dall'indirizzo di Blogger (fuso diverso da blog_time_zone in settings.csv, o data cambiata dopo la pubblicazione): sono nel file dei redirect." );
}
WP_CLI::success( "Articoli e pagine creati $creati, saltati $saltati; immagini $immagini, link interni $link; commenti $importati, spam scartati $spam." );

Alla fine lo script scrive due file nella cartella da cui l’hai lanciato: redirect-blogger.csv, con gli indirizzi che non tornano, uno per riga, e vecchi-url.txt, con tutti gli indirizzi vecchi pubblicati, da provare dopo il passaggio. Su tre blog dell’archivio, 1.256 articoli in tutto, gli indirizzi vecchi pubblicati erano 1.174. Ne hanno risposto 200 senza redirect 1.171, e i 3 rimasti sono arrivati a destinazione con una regola del file. Il blog più grande, 983 articoli e 152 immagini, ha richiesto tre minuti.

Gli indirizzi: anno, mese e .html

La struttura che ricopia Blogger

Su Blogger gli articoli hanno l’anno e il mese nell’indirizzo e finiscono con .html, come /2017/07/titolo.html. Le pagine stanno sotto /p/ e le etichette sotto /search/label/. La parte dopo il mese la sceglie Blogger, e chi scrive può cambiarla articolo per articolo con il permalink personalizzato descritto nella guida di Blogger sui motori di ricerca. In WordPress la stessa forma si ottiene con la struttura personalizzata /%year%/%monthnum%/%postname%.html. L’ho provata con un blog vero di 47 articoli importato con lo script: gli indirizzi vecchi hanno risposto 200 tutti e 47, senza nessun redirect. Una conseguenza da conoscere prima è che una struttura che non finisce con la barra toglie la barra finale da tutto il sito, pagine e archivi compresi.

Tenere anno e mese nell’indirizzo è una scelta che su un sito nuovo sconsiglio, e spiego perché parlando della data negli URL. Qui conviene lo stesso. Google raccomanda di cambiare una cosa alla volta, e cambiare piattaforma è già la prima; toglierla dopo, a traffico stabile, è una decisione a parte.

Quello che non torna da solo

Lo slug di Blogger coincide di rado con quello che WordPress ricaverebbe dal titolo. Blogger toglie le parole brevi e accorcia i titoli lunghi, e sui blog di Google che usano Blogger gli slug diversi da quello del titolo erano 68 su 74 in uno e 97 su 107 in un altro. Gli strumenti che rigenerano lo slug, quindi, cambiano quasi tutti gli indirizzi. Lo script usa quello del file.

Restano alcuni casi, che lo script scrive nel file dei redirect:

  • gli articoli con la data cambiata dopo la pubblicazione, perché Blogger tiene l’indirizzo della prima: nell’archivio c’era un articolo con l’indirizzo di novembre 2019 e la data di luglio 2021;
  • gli slug già usati da un altro articolo in un altro mese, che Blogger ammette e WordPress no, aggiungendo -2 (2 casi su 901 nel blog più grande);
  • le pagine, perché /p/chi-sono.html diventa /chi-sono;
  • le etichette, perché /search/label/ diventa l’archivio del tag: Blogger esclude quelle pagine dalla scansione nel suo robots.txt, ma su WordPress lo stesso indirizzo risponde 200 come pagina di ricerca;
  • il feed, perché /feeds/posts/default diventa /feed.

Gli slug con le maiuscole, che Blogger conserva nei permalink scelti a mano, non servono: WordPress trova l’articolo da solo e risponde 200, con il canonical verso la versione minuscola. Una regola che cambiasse solo maiuscole e minuscole rischierebbe anzi di rimandare la pagina a sé stessa.

Il file si importa con il plugin gratuito Redirection (5.10.1), dalla sua schermata di importazione oppure con WP-CLI:

wp redirection import redirect-blogger.csv --format=csv

Rank Math nella versione gratuita non importa i CSV, e lì le righe si inseriscono una per una. Come si scrive una regola, e con quale codice, lo spiego nella guida sui quattro posti in cui si fa un redirect.

Il ?m=1, che manda in 404 gli indirizzi giusti

Blogger serve la versione per smartphone aggiungendo ?m=1 all’indirizzo, e chi condivide un articolo dal telefono spesso condivide quella. Su WordPress lo stesso indirizzo con ?m=1 risponde 404. Il motivo è che m è anche un parametro di WordPress, quello degli archivi per data, e m=1 chiede gli articoli dell’anno 1.

Nella prova, i 47 indirizzi che rispondevano 200 sono diventati 47 pagine 404.

Il parametro arriva anche per altre strade. Il 301 con cui Blogger manda l’indirizzo blogspot sul dominio personalizzato lo conserva. Rank Math, quando reindirizza, accoda la query string alla destinazione, e nella prova /p/chi-sono.html?m=1 ha ricevuto un 301 corretto verso /chi-sono?m=1, che rispondeva 404. Redirection, con l’impostazione predefinita, non applica proprio la regola se l’indirizzo ha un parametro che la regola non prevede.

Il rimedio è un plugin di poche righe da mettere nella cartella wp-content/mu-plugins, che fa ignorare a WordPress il solo m=1:

<?php
/**
 * Plugin Name: Indirizzi mobili di Blogger
 * Description: Toglie il ?m=1 dei vecchi indirizzi di Blogger, che WordPress leggerebbe come una data.
 */
add_filter( 'request', function ( $variabili ) {
	if ( isset( $variabili['m'] ) && '1' === $variabili['m'] ) {
		unset( $variabili['m'] );
	}
	return $variabili;
} );

Con il plugin attivo i 47 indirizzi con ?m=1 rispondono 200, con il canonical verso l’indirizzo senza parametro, come fa Blogger. Gli archivi per data veri, come ?m=2017, funzionano come prima. In Redirection, poi, sotto Opzioni conviene impostare Corrispondenza della query predefinita su Ignora tutti i parametri: le regole scattano anche con ?m=1 e il parametro sparisce dalla destinazione.

Da blogspot.com a un dominio tuo

Se il blog sta su blogspot.com, gli indirizzi vecchi restano su un dominio di Google. Fra le impostazioni descritte nella guida di Blogger, l’unica che manda l’indirizzo blogspot su un altro dominio è il dominio personalizzato: i reindirizzamenti personalizzati servono per le pagine del blog stesso, e il reindirizzamento del feed vale solo per il feed.

La strada più pulita è in due tempi, come chiede Google quando raccomanda di cambiare una cosa alla volta.

  1. Prima il dominio, dentro Blogger. Si collega come dominio personalizzato del blog il dominio che userà il sito WordPress. Blogger comincia a mandare gli indirizzi blogspot sul dominio con un 301, e per Google questo è un trasferimento di dominio. Lo strumento Cambio di indirizzo di Search Console si può usare, perché richiede un 301 dal server, e in questo caso lo trova.
  2. Poi la piattaforma, con lo stesso dominio. Quando il dominio nuovo è indicizzato e stabile, lo si sposta sull’hosting di WordPress tenendo gli stessi indirizzi. Per Google questo secondo passo è un trasferimento senza modifiche agli URL.

Per lo strumento Google chiede di essere proprietario di tutte e due le proprietà in Search Console, e di tenere i redirect per almeno 180 giorni; nella guida ai trasferimenti con cambio di URL consiglia di tenerli almeno un anno. Saltare il primo passo vuol dire che fra gli indirizzi vecchi e quelli nuovi non c’è nessun redirect, quindi niente che li colleghi, e il sito su WordPress comincia da capo mentre il blog vecchio resta online con gli stessi testi.

C’è un punto che la documentazione lascia aperto.

La guida di Blogger non dice se il reindirizzamento da blogspot resta attivo quando il dominio smette di puntare ai server di Google. Dopo il secondo passo va controllato con curl su qualche indirizzo blogspot, e ricontrollato nelle settimane successive.

L’alternativa che circola è reindirizzare dal tema di Blogger con un meta refresh. Google tratta un meta refresh a zero secondi come un redirect permanente, ma lo mette dopo quello del server, e il JavaScript ancora dopo. Il plugin più citato per farlo, Blogger To WordPress di rtCamp (2.3.2), genera un tema di Blogger che rimanda ogni articolo al sito nuovo. Il suo codice però, sul lato WordPress, risponde con un 302, che è un redirect temporaneo, e manda sulla home con un 301 tutto quello che non trova. In più legge solo gli articoli importati con il Blogger Importer, come dice la sua FAQ, e con il backup di oggi quindi non ne trova nessuno. Google sconsiglia i redirect in massa verso la home, che possono essere trattati come pagine inesistenti.

Le immagini e i video

Le immagini caricate su Blogger stanno su blogger.googleusercontent.com. La guida di Blogger sull’archiviazione delle immagini assicura che quegli indirizzi non scadono, ma restano indirizzi di Google. Non si possono reindirizzare, e quando le immagini passano nella Libreria media Google le deve trovare da capo. Conviene portarle lo stesso, perché altrimenti il sito nuovo dipende da un archivio che non controlli.

Una parte degli indirizzi non ha l’estensione nel nome, e finisce con l’indicazione della dimensione, come =w640-h397. Nell’archivio erano 6 su 194; sul blog degli sviluppatori Android, che usa Blogger, 331 su 1.072. La funzione media_sideload_image(), che molti script usano per scaricare un’immagine da un indirizzo, li rifiuta con l’errore “Invalid image URL.”, perché cerca l’estensione nell’indirizzo. Lo script li scarica nella dimensione originale, legge il tipo dal file e lo usa per il nome.

Nel blog più grande sono entrate tutte e 152, e un download andato in timeout si è completato rilanciando lo script.

Spesso l’immagine nel testo sta dentro un link che apre la versione grande, ancora su Blogger. Lo script porta nella Libreria media anche quella, e i due indirizzi finiscono sullo stesso file. Le immagini ospitate altrove, come l’unica dell’archivio che veniva da Wikimedia, restano dove sono.

La cartella Albums dell’archivio contiene le stesse immagini con il nome originale, ma senza l’indirizzo che le collega agli articoli. È una copia da conservare, non il modo più comodo per rimetterle al loro posto. Dopo l’importazione, una ricerca nel database dice se qualche immagine è rimasta su Blogger:

wp post list --post_type=any --post_status=any --s=googleusercontent.com --fields=ID,post_status,post_title

I video caricati direttamente su Blogger non sono nel backup: secondo la guida di Blogger su immagini e video si scaricano uno per uno dalle impostazioni, e vanno caricati di nuovo su WordPress. Quelli di YouTube sono iframe e arrivano con il testo, e nella prova i due del blog che li conteneva sono rimasti al loro posto.

Commenti, autori, etichette e pagine

I commenti arrivano con le risposte al loro posto, perché ogni commento dichiara a quale articolo e a quale altro commento risponde. Nell’archivio, accanto a 29 commenti pubblicati, ce n’erano 18 segnati come spam, e lo script li scarta. Degli autori dei commenti il file riporta il nome e il profilo, non l’email, e senza email WordPress non può mostrare gli avatar. Sul sito nuovo i commenti vanno protetti da capo, con un filtro contro lo spam scelto con criterio. Chi seguiva il blog con il proprio account Blogger, invece, non passa. Nel backup c’è followers.csv, con il nome e l’immagine del profilo di ciascuno ma senza un indirizzo email, e per avvisarli resta un ultimo articolo sul blog vecchio.

Degli autori degli articoli il feed riporta solo il nome. Lo script li assegna tutti all’utente indicato con --user, e se il blog aveva più autori conviene creare gli utenti in WordPress e cambiare l’autore dopo l’importazione. Le etichette diventano tag, che sono la cosa più simile: niente gerarchia e più d’una per articolo. Chi le vuole come categorie cambia una parola in cima allo script, e fra gli importatori di Strumenti → Importa c’è anche un convertitore che sposta i termini dalle categorie ai tag e viceversa.

Le pagine arrivano come pagine, con lo slug di Blogger e un indirizzo nuovo che finisce nel file dei redirect. Il tema invece non si importa, perché il file del backup serve solo a Blogger: quello del sito nuovo va scelto per WordPress, e qualche criterio per il tema di un sito professionale l’ho messo in fila a parte.

Il giorno del passaggio e i controlli dopo

WordPress va installato prima, seguendo i passi per installare WordPress sul nuovo hosting, e tenuto fuori dai motori di ricerca mentre lo si prepara. Meglio con una password chiesta dal server che con un noindex da ricordarsi di togliere, perché il noindex dimenticato è uno dei controlli da rifare il giorno del passaggio.

Con un dominio tuo il passaggio è un cambio di DNS. Blogger usa un CNAME per il www verso ghs.google.com e quattro record A per il dominio nudo, e sono quelli da far puntare al nuovo hosting, dopo aver abbassato il TTL qualche giorno prima, come in un passaggio senza interruzioni fra due server. Cambiare i nameserver sposta invece tutta la zona DNS, posta compresa.

La verifica della proprietà in Search Console deve funzionare anche dopo, quindi un file o un meta tag di verifica vanno rimessi sul sito nuovo. Se il blog resta su blogspot, il reindirizzamento del feed previsto dalle impostazioni di Blogger può mandare chi lo segue sul feed di WordPress.

Il giorno dopo si provano tutti gli indirizzi vecchi, non un campione. Lo script ha già scritto l’elenco in vecchi-url.txt, che è il file letto dal ciclo che prova ogni indirizzo vecchio della guida generale: ogni riga deve finire con 200 e al massimo un redirect. Nella prova, con i redirect importati, sono arrivati a 200 tutti e 50, anche con ?m=1 in coda.

Il blog su Blogger, intanto, non va cancellato. Un blog cancellato si recupera entro 90 giorni, come scrive la pagina sulle impostazioni, ma uno cancellato definitivamente non torna, e il suo indirizzo non si può più usare, come dice la guida di Blogger sulla cancellazione e il ripristino. Se il blog stava su blogspot, poi, i redirect verso il sito nuovo vivono proprio lì.

Domande frequenti

Il vecchio backup .xml di Blogger si può ancora importare?

Il Blogger Importer legge ancora quel formato, ed è l’unico caso in cui funziona. Porta però solo articoli e commenti, scarica le immagini dei soli 20 articoli più recenti e ricava gli slug dai titoli, quindi gli indirizzi cambiano e vanno reindirizzati. Blogger stesso accetta ancora i file .xml nella sua funzione di importazione, se vuoi ricaricarli su un blog Blogger.

Posso tenere l’indirizzo blogspot.com su WordPress?

Blogspot.com è un dominio di Google, e agli indirizzi blogspot risponde sempre Blogger. Puoi però far reindirizzare il blog verso un dominio tuo, collegandolo come dominio personalizzato prima di passare a WordPress. Blogger manda gli indirizzi vecchi sul dominio con un 301, e quando il dominio passa all’hosting nuovo gli stessi indirizzi li serve WordPress.

Passare da Blogger a WordPress fa perdere posizioni su Google?

Gli indirizzi che restano identici non hanno niente da recuperare, e Google scrive che i redirect permanenti non fanno perdere PageRank. Durante un trasferimento le posizioni oscillano, e per un sito di medie dimensioni Google parla di qualche settimana. A fare danni sono gli indirizzi che finiscono su un 404, come quelli con ?m=1 se nessuno li gestisce, e le immagini, che sul sito nuovo hanno indirizzi diversi.

Devo cancellare il blog su Blogger dopo il passaggio?

Una cancellazione definitiva non si annulla, e l’indirizzo del blog non si può più usare. Se il blog era su blogspot, è Blogger a mandare i visitatori sul dominio nuovo, e può farlo solo finché il blog esiste. Conviene tenerlo, almeno per tutto il tempo in cui i redirect servono.

Le immagini restano su Google anche dopo il trasloco?

Le copie su blogger.googleusercontent.com restano online, e Blogger dichiara che quegli indirizzi non scadono. Restano però indirizzi di Google, che non si possono reindirizzare: conviene portare le immagini nella Libreria media e non far dipendere il sito da quelle copie. Nel backup c’è una copia anche nella cartella Albums.

Si può portare su WordPress il tema di Blogger?

Il tema è nel backup, ma nel formato di Blogger, e funziona solo lì. Su WordPress il tema si sceglie o si costruisce da capo, e conviene farlo prima di importare, per vedere subito come appaiono i contenuti con la struttura nuova.

Da qui in avanti

Il passaggio da Blogger è riuscito quando nessuno se ne accorge: gli indirizzi vecchi rispondono, i link condivisi dal telefono funzionano, le immagini stanno nella Libreria media. Ci si arriva decidendo prima da dove parte il blog, poi la struttura dei permalink, poi l’importazione, e solo alla fine i redirect per quello che resta. Per tutto quello che non è specifico di Blogger, dal dominio registrato presso la piattaforma ai controlli della settimana dopo, vale la guida generale alla migrazione verso WordPress.

Se preferisci che lo faccia io

Portare un blog da Blogger a WordPress con gli stessi indirizzi, le immagini nella Libreria media e i redirect provati uno per uno è il lavoro del servizio di migrazione e trasferimento del sito. Se vuoi che me ne occupi io, scrivimi l’indirizzo del blog e quanti articoli ha.

Indice dei contenuti

  • Prima di tutto: blogspot.com o un dominio tuo
  • Cosa c’è nel backup di Blogger, e cosa no
  • Perché Strumenti → Importa → Blogger non basta
  • Importare il feed.atom: un plugin o uno script
  • Gli indirizzi: anno, mese e .html
  • Da blogspot.com a un dominio tuo
  • Le immagini e i video
  • Commenti, autori, etichette e pagine
  • Il giorno del passaggio e i controlli dopo
  • Domande frequenti
  • Da qui in avanti
  • Se preferisci che lo faccia io

Tag in Evidenza

MigrazioneRedirectSEO 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