Migrar PrestaShop a otro servidor sin perder el SEO (ni un pedido)
Cambiar de hosting parece la migración fácil: mismo dominio, misma versión, mismas páginas. Y aun así es donde muchas tiendas pierden pedidos y posiciones, casi siempre por un detalle que nadie comprobó. Esta es la guía que seguimos, con los comandos que usamos y las trampas reales que nos encontramos al mover una tienda de 1.391 páginas entre su hosting, nuestro laboratorio y un servidor de ensayos.
Qué se pierde de verdad al cambiar de servidor
Google trata un cambio de hosting sin cambio de direcciones como algo normal. Lo único que advierte es que, justo después, su robot rastrea algo menos durante unos días y luego vuelve a subir (lo explica en su guía de traslados sin cambios de URL). Lo que de verdad se pierde es esto:
- Pedidos huérfanos. El cambio de DNS no llega a todo el mundo a la vez: durante un rato, unos clientes compran en el servidor nuevo y otros en el viejo. Si el viejo sigue abierto, esos pedidos se quedan en una base de datos que vas a tirar.
- Páginas que dejan de responder igual. Una ficha que da 200 en el servidor viejo y 404 o 500 en el nuevo es una ficha que Google acabará sacando de sus resultados.
- Páginas «vivas» pero vacías. Un 200 no significa que la página funcione: nos hemos encontrado páginas que respondían 200 con 0 bytes de contenido. Si solo miras el código de respuesta, no las ves.
- Velocidad. Si el servidor nuevo responde más lento, lo notan tus clientes antes que Google.
- Lo que vive fuera de PrestaShop: las tareas programadas (cron), el envío de correos, el certificado SSL y la verificación de Search Console. Nada de eso va en la copia de la tienda, y todo falla sin avisar.
Antes de tocar nada: la lista
- Una copia completa, restaurada al menos una vez. Ficheros y base de datos. Una copia que nunca se ha restaurado no es una copia, es una esperanza. Cómo hacerla bien.
- Un solo cambio cada vez. Mismo PHP y misma versión de PrestaShop que en el servidor viejo. Si quieres subir de PHP o pasar a PrestaShop 9, se hace antes o después, nunca el mismo día: si algo falla, tienes que saber qué lo ha roto. (Actualizar a la 9 es otra guía.)
- Que el servidor nuevo cumpla los requisitos. PrestaShop 8 y 9 piden las mismas extensiones de PHP: CURL, DOM, Fileinfo, GD, Iconv, Intl, JSON, Mbstring, OpenSSL, PDO, PDO_MySQL, SimpleXML y Zip. La 9 necesita PHP 8.1 o superior y recomienda un
memory_limitde 512M como mínimo; la 8, de 256M (requisitos oficiales). - Los límites de PHP, comparados uno a uno.
memory_limit,max_execution_time,max_input_vars,upload_max_filesizeypost_max_size, en los dos servidores. Los principales salen en el panel de PrestaShop, en Parámetros avanzados → Información. En nuestro caso, el laboratorio tenía 512M, sin límite de tiempo y 20.000 variables; la tienda real, 256M, 30 segundos y 1.000. Lo que funciona en uno puede caerse en el otro. - Baja el TTL del DNS una semana antes. El TTL es el tiempo que el resto de internet recuerda a qué servidor apunta tu dominio. Google recomienda bajarlo al menos una semana antes del traslado. Con 300 segundos, quien respete ese valor pasará al servidor nuevo en minutos, no en horas.
- El inventario de lo que no está en la copia: las tareas programadas (y sus direcciones con clave), cómo envía correos la tienda (SMTP o la función
mail()del servidor), las reglas propias del.htaccess, el certificado SSL y cómo verificaste Search Console (si fue con un fichero HTML o una etiqueta, tiene que viajar con la web).
Paso 1 · Copiar los ficheros
Con acceso SSH a los dos servidores, lo más limpio es copiar desde el nuevo con rsync. Se salta la caché (se regenera sola) y, si lo repites el día del cambio, solo copia lo que haya cambiado desde la última vez:
# Desde el servidor NUEVO (PrestaShop 1.7, 8 o 9)
rsync -az --stats \
--exclude 'var/cache/*' --exclude 'var/logs/*' \
usuario@servidor-viejo:/ruta/de/la/tienda/ /ruta/nueva/de/la/tienda/
Sin SSH, que es lo normal en un hosting compartido, solo queda el FTP, y aquí está la primera trampa: una tienda tiene muchos más ficheros de los que parece. La que migramos tenía 169.734 en su hosting. Bajarlos uno a uno por FTP son horas, y cualquier corte deja la copia a medias sin avisar. Lo que funciona es comprimir en el servidor, mover un solo fichero y descomprimir en el nuevo por tandas, porque muchos hostings cortan cualquier proceso a los 30 segundos. Con un descompresor troceado dejamos 79.589 ficheros en su sitio en 36 segundos, en un hosting con ese límite.
La trampa del .htaccess y la versión de PHP
En muchos hostings con cPanel, la versión de PHP de la web se guarda dentro del .htaccess, en un bloque que escribe el propio panel con una línea AddHandler application/x-httpd-…. Si copias el .htaccess de otro servidor, o restauras uno de una copia, ese bloque desaparece o apunta a una versión que allí no existe, y la web pasa a ejecutarse con el PHP por defecto del servidor. Nos pasó: el panel decía PHP 8.2 y el servidor estaba sirviendo 7.4. Después de copiar, revisa ese bloque y comprueba la versión real (no la que dice el panel del hosting) en Parámetros avanzados → Información.
Y si cambias de Apache a Nginx, ten en cuenta que Nginx no lee el .htaccess: las direcciones amigables y cualquier regla propia hay que reescribirlas en su configuración.
Paso 2 · Copiar la base de datos
Con SSH, mysqldump con --single-transaction saca una copia coherente sin bloquear la tienda mientras vende (las tablas de PrestaShop usan InnoDB):
# En el servidor VIEJO
mysqldump --single-transaction --quick --default-character-set=utf8mb4 \
-u USUARIO -p NOMBRE_BD | gzip > tienda.sql.gz
# En el servidor NUEVO, con la base ya creada y vacía
gunzip < tienda.sql.gz | mysql --default-character-set=utf8mb4 -u USUARIO -p NOMBRE_BD_NUEVA
Sin SSH, el exportador de phpMyAdmin suele morir con las bases grandes por el mismo límite de tiempo. La solución es la misma que con los ficheros: por tandas. Así pasamos una base de 2,9 millones de filas en 115 segundos.
Y antes de dar la copia por buena, cuenta. Esta consulta tiene que dar exactamente lo mismo en las dos bases (cambia ps_ por tu prefijo si usas otro):
SELECT 'pedidos' AS que, COUNT(*) AS total, MAX(id_order) AS ultimo FROM ps_orders
UNION ALL
SELECT 'clientes', COUNT(*), MAX(id_customer) FROM ps_customer
UNION ALL
SELECT 'productos', COUNT(*), MAX(id_product) FROM ps_product
UNION ALL
SELECT 'carritos', COUNT(*), MAX(id_cart) FROM ps_cart;
Paso 3 · Decirle a PrestaShop dónde está su base nueva
En PrestaShop 1.7, 8 y 9, los datos de conexión viven en app/config/parameters.php. Cambia solo lo que sea distinto en el servidor nuevo:
'database_host' => 'localhost',
'database_port' => '',
'database_name' => 'nombre_bd_nueva',
'database_user' => 'usuario_nuevo',
'database_password' => '••••••••',
'database_prefix' => 'ps_',
Después, vacía la caché. La parte moderna de PrestaShop (Symfony) guarda ahí su configuración ya compilada, y se regenera sola en la primera visita:
rm -rf var/cache/prod/* var/cache/dev/*
Si al abrir la tienda ves un error de conexión, el fallo está en esos datos o en los permisos del usuario de la base: cómo localizarlo.
Paso 4 · Probar el servidor nuevo con tu dominio real, sin tocar el DNS
Aquí está la trampa que más tiempo hace perder: PrestaShop solo responde con su propio dominio. Si abres el servidor nuevo por su IP o por una dirección provisional del hosting, la tienda te redirige a tu dominio de siempre… que todavía apunta al servidor viejo. Crees que estás probando la tienda nueva y estás mirando la de siempre.
La solución es engañar solo a tu ordenador. Añade esta línea al fichero hosts (en Mac y Linux, /etc/hosts; en Windows, C:\Windows\System32\drivers\etc\hosts) con la IP del servidor nuevo:
203.0.113.10 tutienda.com www.tutienda.com
Desde ese momento, tu navegador abre el servidor nuevo con tu dominio real, y el resto del mundo sigue comprando en el viejo. Si el servidor nuevo aún no tiene certificado, el navegador avisará: para probar, sirve. Haz el recorrido completo: portada, categoría, ficha, buscador, carrito, alta de cliente y el panel. Y cuando acabes, quita la línea, o seguirás viendo ese servidor pase lo que pase con el DNS.
Comparar todas las páginas, una a una
Probar diez páginas a mano no basta: una tienda tiene cientos o miles. Este script recoge todas las direcciones de tus sitemaps (los que declara tu robots.txt) y pide cada una a los dos servidores, sin tocar el DNS: la opción --resolve de curl hace lo mismo que el fichero hosts, pero solo para esa petición. Funciona en Mac y Linux:
#!/usr/bin/env bash
# comparar-servidores.sh — compara cada URL del sitemap en el servidor actual y en el nuevo
# Uso: ./comparar-servidores.sh tutienda.com 203.0.113.10
set -u
DOMINIO="$1" # el dominio de la tienda, sin https://
IP_NUEVA="$2" # la IP del servidor nuevo
locs() { grep -o '<loc>[^<]*</loc>' | sed -e 's#</*loc>##g' -e 's/&/\&/g'; }
recorrer() { # si es un índice de sitemaps, abre cada hijo; si no, saca sus URLs
local xml; xml=$(curl -s "$1")
if grep -q '<sitemapindex' <<<"$xml"; then
locs <<<"$xml" | while read -r hijo; do recorrer "$hijo"; done
else
locs <<<"$xml"
fi
}
# 1) Todas las URLs de los sitemaps que declara el robots.txt
curl -s "https://$DOMINIO/robots.txt" | tr -d '\r' \
| awk 'tolower($1)=="sitemap:"{print $2}' \
| while read -r sm; do recorrer "$sm"; done | sort -u > urls.txt
echo "URLs encontradas: $(wc -l < urls.txt | tr -d ' ')"
# 2) Cada URL, contra el servidor actual y contra el nuevo (sin tocar el DNS)
while read -r url; do
actual=$(curl -s -m 30 -o /dev/null -w '%{http_code} %{size_download} %{time_starttransfer}' "$url")
nuevo=$(curl -sk -m 30 -o /dev/null -w '%{http_code} %{size_download} %{time_starttransfer}' \
--resolve "$DOMINIO:443:$IP_NUEVA" --resolve "www.$DOMINIO:443:$IP_NUEVA" "$url")
echo "$url $actual $nuevo"
sleep 0.2 # sin prisa: el servidor actual sigue vendiendo
done < urls.txt > comparacion.txt
# 3) Lo que hay que revisar: código distinto, página vacía o menos de la mitad de contenido
awk '$2!=$5 || $6==0 || $6<$3*0.5 {print "REVISAR:", $1, "| actual", $2, $3"B | nuevo", $5, $6"B"}' comparacion.txt
awk '{a+=$4; n+=$7} END {if (NR) printf "Respuesta media: actual %.2f s · nuevo %.2f s (%d URLs)\n", a/NR, n/NR, NR}' comparacion.txt
Se ejecuta con tu dominio y la IP nueva: bash comparar-servidores.sh tutienda.com 203.0.113.10. Te devuelve tres cosas: las direcciones cuyo código de respuesta cambia (un 200 que pasa a 404 o a 500), las que en el servidor nuevo salen vacías o con menos de la mitad de contenido, y el tiempo medio de respuesta de cada servidor. Lo probamos en una tienda real cuyo sitemap genera un módulo de terceros, con un índice que enlaza a otros sitemaps: encontró sus 1.033 direcciones sin tocar nada.
Si la lista de «REVISAR» no está vacía, no se cambia el DNS.
Paso 5 · El día del cambio, sin perder ni un pedido
- Elige la hora en que menos vendes. No hace falta adivinarla: tus pedidos de los últimos 90 días te la dicen.
SELECT HOUR(date_add) AS hora, COUNT(*) AS pedidos FROM ps_orders WHERE date_add >= NOW() - INTERVAL 90 DAY GROUP BY hora ORDER BY pedidos; - Pon el servidor viejo en mantenimiento (Parámetros de la tienda → General → Mantenimiento) y añade tu IP en «IP de mantenimiento» para seguir viéndola tú. En mantenimiento, PrestaShop responde con un código 503 («vuelve en un rato»), que es la forma correcta de cerrar unos minutos sin que Google lo tome por un error. Cómo activarlo.
- Última copia: la base de datos entera otra vez (ya no entra ningún pedido) y los ficheros que hayan cambiado desde el ensayo. Con el
rsyncdel paso 1, solo viajan las imágenes y documentos nuevos. - Cuenta otra vez. La consulta del paso 2, en los dos servidores. El último
id_ordertiene que ser idéntico: si el nuevo tiene uno menos, se ha quedado un pedido por el camino. - Cambia el DNS, los dos registros. El dominio con
wwwy sin él son dos registros distintos, y cambiar solo uno deja la tienda partida entre dos servidores. En nuestra migración, el panel del hosting incluso los trataba como dos webs separadas. - Abre la tienda nueva. La base que copiaste viene en mantenimiento y con tu IP dentro. Haz una compra de prueba real, con pago y envío, comprueba que llega el correo de confirmación y, entonces, quita el mantenimiento.
- El servidor viejo se queda cerrado, no apagado. Durante unos días seguirá recibiendo visitas de quien aún tenga el DNS antiguo: que vean el mantenimiento, no una tienda que acepta pedidos. Google recomienda no apagarlo hasta que deje de recibir tráfico.
Después: las primeras 72 horas
- Que el mundo ya ve el servidor nuevo:
dig +short tutienda.comydig +short www.tutienda.comdeben devolver la IP nueva. - El script, otra vez, ahora contra el servidor nuevo ya público. Tiene que salir igual que en el ensayo.
- Correos. Si la tienda envía con la función
mail()del servidor, la IP de salida ha cambiado y puede que tu registro SPF no la incluya: los correos de pedido acaban en spam o no llegan. Qué revisar. - Tareas programadas. Las del servidor viejo no se mudan solas. Las que llaman a direcciones de módulos (feeds, sincronizaciones, copias) se vuelven a crear en el nuevo.
- Search Console. En Ajustes → Estadísticas de rastreo ves cómo responde tu servidor a Google, día a día y por código de respuesta. Que el rastreo baje unos días es normal; que suban los errores 5xx o 404, no.
- El certificado: comprueba que en el servidor nuevo se renueva solo, antes de que caduque.
¿Y si además cambias de dominio?
Entonces ya no es una mudanza, es un traslado, y las reglas cambian: cada dirección vieja necesita una redirección 301 a su equivalente nueva (no a la portada), hay que avisar a Google con la herramienta de Cambio de dirección de Search Console y decirle a PrestaShop su nuevo dominio, que vive en dos sitios de la base de datos (y en physical_uri, si además cambia de carpeta):
UPDATE ps_configuration SET value = 'nuevodominio.com'
WHERE name IN ('PS_SHOP_DOMAIN', 'PS_SHOP_DOMAIN_SSL');
UPDATE ps_shop_url SET domain = 'nuevodominio.com', domain_ssl = 'nuevodominio.com'
WHERE id_shop = 1;
Y un consejo que nos ahorró un disgusto: antes de aplicar un mapa de redirecciones, comprueba cuántos de sus orígenes ya funcionan. En una migración preparamos un mapa de 1.017 reglas «por si acaso» y, al medirlo, 832 (el 81,8 %) redirigían direcciones que respondían bien. Aplicarlo habría roto más páginas de las que arreglaba.
Señales de que no deberías hacerlo tú
- No tienes SSH y la tienda ocupa varios gigas.
- Tu tienda vende a diario y no puedes cerrar más de unos minutos.
- No sabes cómo envía los correos ni qué tareas programadas tiene.
- El servidor nuevo es de otro tipo que el viejo (de cPanel a Plesk, de Apache a Nginx).
- Nunca has restaurado tu copia de seguridad.
Si te reconoces en dos o más, cambiar de servidor no es un fin de semana con el FTP: es un proyecto con ensayo, plan de vuelta atrás y comprobación página a página.
Cuándo merece la pena que lo hagamos nosotros
- Migración de servidor: copia, ensayo en el servidor nuevo con tu dominio real, comparación de todas tus direcciones antes del DNS y compra de prueba después. Desde 250 € (IVA incluido).
- Migración a PrestaShop 8/9: si además toca cambiar de versión, por separado y ensayada en copia. Desde 390 € (IVA incluido).
- Mantenimiento mensual: copias semanales verificadas y vigilancia, para que la próxima mudanza empiece con una copia que ya sabemos restaurar.
¿Cambiamos tu tienda de servidor sin perder tu sitio en Google?
Lo ensayamos primero en el servidor nuevo con tu dominio real, comparamos todas tus páginas y solo entonces cambiamos el DNS, a la hora en que menos vendes. Desde 250 € (IVA incluido). Escríbenos y te decimos qué necesita tu tienda.