Plugin de WordPress para redireccionar URLs antiguas con redirecciones 301
![]()
Cuando se modifica la estructura de enlaces permanentes de WordPress, es habitual que las URLs antiguas de las entradas comiencen a devolver errores 404 Not Found.
Por ejemplo, podemos pasar de una estructura sencilla:
https://site.com/nombre-del-articulo/a una estructura que incluya la categoría:
https://site.com/linux/nombre-del-articulo/Este cambio puede mejorar la organización de las URLs, pero tiene una consecuencia importante: todas las URLs antiguas que ya estén indexadas por Google, enlazadas desde otros sitios web o guardadas por los usuarios dejarán de funcionar.
Para evitarlo podemos crear un pequeño plugin de WordPress que detecte las URLs antiguas y realice automáticamente una redirección HTTP 301 hacia la nueva dirección del artículo.
¿Qué es una redirección 301?
Una redirección 301 indica a navegadores y motores de búsqueda que un recurso ha sido trasladado de forma permanente a otra URL.
El navegador solicita:
https://site.com/configurar-apache/y el servidor responde indicando:
301 Moved Permanentlyjunto con la nueva ubicación:
https://site.com/linux/configurar-apache/El navegador accederá automáticamente a la nueva dirección.
Desde el punto de vista SEO, utilizar una redirección 301 es especialmente importante cuando se modifica la estructura de URLs de una web, ya que permite indicar a los buscadores que el contenido no ha desaparecido, sino que simplemente se encuentra en otra dirección.
El problema al cambiar los enlaces permanentes
Supongamos que originalmente WordPress utiliza esta configuración:
/%postname%/Una entrada llamada:
Cómo instalar Apache en Debianpodría tener esta dirección:
https://site.com/como-instalar-apache-en-debian/Posteriormente cambiamos los enlaces permanentes a:
/%category%/%postname%/La misma entrada puede pasar a tener esta dirección:
https://site.com/linux/como-instalar-apache-en-debian/La URL antigua:
https://site.com/como-instalar-apache-en-debian/ya no existe y WordPress devuelve:
404 Not FoundEsto puede generar numerosos errores 404 si el sitio tiene cientos o miles de artículos.
Crear una redirección manual para cada entrada no resulta práctico.
La solución consiste en utilizar WordPress para localizar automáticamente el artículo correspondiente al slug de la URL antigua y obtener posteriormente su nueva dirección.
Crear el plugin Redirect 301 URL
Podemos crear un pequeño plugin personalizado.
El código es el siguiente:
<?php
/**
* Plugin Name: Redirect 301 URL
* Description: Redirect 301 URL antiguas
* Version: 1.0
* Author: Juan Jose Fernadnez Duran
*/
add_action('template_redirect', function () {
if (!is_404()) {
return;
}
$path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
// Solo URLs antiguas del tipo /nombre-del-post/
if (strpos($path, '/') !== false || empty($path)) {
return;
}
$post = get_page_by_path($path, OBJECT, 'post');
if (!$post || $post->post_status !== 'publish') {
return;
}
$new_url = get_permalink($post->ID);
if ($new_url) {
wp_safe_redirect($new_url, 301);
exit;
}
});El plugin tiene una función muy concreta:
URL antigua
↓
WordPress devuelve 404
↓
se extrae el slug
↓
se busca una entrada con ese slug
↓
se obtiene su permalink actual
↓
redirección 301De esta manera no necesitamos conocer previamente la categoría de cada artículo.
Cómo funciona el plugin
El plugin utiliza el hook:
template_redirectmediante:
add_action('template_redirect', function () {template_redirect se ejecuta cuando WordPress ya ha procesado la petición y conoce qué tipo de contenido debe mostrar.
Esto permite comprobar si la petición actual corresponde a un error 404.
Comprobar que WordPress devuelve un 404
La primera comprobación es:
if (!is_404()) {
return;
}Con ello el plugin solamente trabaja sobre URLs que WordPress no ha podido resolver.
Si estamos visitando una entrada, página, categoría, etiqueta o cualquier URL válida, el plugin no realiza ninguna operación.
Esto es importante porque evita interferir con las URLs normales del sitio.
Obtener la URL solicitada
A continuación obtenemos la ruta solicitada por el usuario:
$path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');La variable:
$_SERVER['REQUEST_URI']contiene la URL solicitada.
Por ejemplo:
/como-instalar-apache-en-debian/?utm_source=googleLa función:
parse_url()permite obtener solamente la ruta:
/como-instalar-apache-en-debian/utilizando:
PHP_URL_PATHFinalmente:
trim(..., '/')elimina las barras iniciales y finales.
El resultado será:
como-instalar-apache-en-debianEste valor corresponde normalmente al slug de la entrada.
Evitar procesar URLs con varias rutas
El plugin contiene la siguiente comprobación:
if (strpos($path, '/') !== false || empty($path)) {
return;
}Su objetivo es procesar exclusivamente las URLs antiguas que tengan esta estructura:
/nombre-del-post/Por ejemplo:
/instalar-nginx-en-debian/sí será procesada.
Sin embargo:
/linux/instalar-nginx-en-debian/no será procesada.
Tampoco se procesarán URLs como:
/category/linux//tag/debian//wp-json/Esto ayuda a evitar redirecciones inesperadas.
Buscar el artículo por su slug
Una de las partes más importantes del plugin es:
$post = get_page_by_path($path, OBJECT, 'post');A pesar de su nombre, get_page_by_path() no se limita exclusivamente a páginas.
En este caso se especifica:
'post'por lo que WordPress busca una entrada cuyo slug coincida con la ruta recibida.
Por ejemplo, para:
/como-instalar-docker/se buscaría una entrada cuyo slug sea:
como-instalar-dockerSi WordPress encuentra la entrada, devuelve su objeto.
Comprobar que la entrada está publicada
Posteriormente comprobamos:
if (!$post || $post->post_status !== 'publish') {
return;
}Esto evita realizar redirecciones hacia:
- entradas inexistentes;
- borradores;
- entradas privadas;
- entradas pendientes de publicación;
- contenidos no publicados.
Solamente se redireccionará hacia entradas cuyo estado sea:
publishObtener automáticamente la nueva URL
Esta línea es la que permite que el plugin funcione independientemente de la categoría:
$new_url = get_permalink($post->ID);WordPress genera automáticamente el permalink actual de la entrada.
Supongamos que tenemos:
Slug:
wake-on-lan-windowsy la entrada pertenece a la categoría:
WindowsSi WordPress utiliza:
/%category%/%postname%/get_permalink() puede devolver:
https://site.com/windows/wake-on-lan-windows/El plugin no necesita conocer la categoría.
Es WordPress quien genera la dirección correcta basándose en la configuración actual de enlaces permanentes.
Ejecutar la redirección 301
Finalmente se ejecuta:
wp_safe_redirect($new_url, 301);
exit;wp_safe_redirect() es una función de WordPress diseñada para realizar redirecciones de forma segura.
El segundo parámetro:
301indica el código HTTP utilizado.
Por tanto, WordPress responderá:
HTTP/1.1 301 Moved Permanentlyy enviará al navegador hacia la nueva URL.
El:
exit;es importante porque detiene inmediatamente la ejecución de PHP después de enviar la redirección.
Ejemplo completo de funcionamiento
Imaginemos que Google tiene indexada esta URL antigua:
https://site.com/configurar-wake-on-lan-windows/Después de cambiar los permalinks, la entrada se encuentra en:
https://site.com/windows/configurar-wake-on-lan-windows/Cuando Google accede a:
/configurar-wake-on-lan-windows/WordPress no encuentra esa URL y genera un 404.
El plugin recibe:
configurar-wake-on-lan-windowsy ejecuta:
get_page_by_path(
'configurar-wake-on-lan-windows',
OBJECT,
'post'
);WordPress encuentra la entrada.
A continuación:
get_permalink($post->ID);devuelve:
https://site.com/windows/configurar-wake-on-lan-windows/Finalmente se realiza:
301desde:
/configurar-wake-on-lan-windows/hacia:
/windows/configurar-wake-on-lan-windows/Cómo instalar el plugin en WordPress
Para instalarlo manualmente podemos crear una carpeta dentro de:
wp-content/plugins/Por ejemplo:
wp-content/plugins/redirect-301-url/Dentro creamos el archivo:
redirect-301-url.phpLa estructura quedaría:
wp-content/
└── plugins/
└── redirect-301-url/
└── redirect-301-url.phpIntroducimos dentro del archivo el código del plugin.
Posteriormente entramos en:
WordPress
→ Plugins
→ Plugins instaladosBuscamos:
Redirect 301 URLy pulsamos:
ActivarDesde ese momento el plugin comenzará a procesar los errores 404 correspondientes a URLs antiguas.
Instalarlo mediante un archivo ZIP
Otra posibilidad es crear esta estructura:
redirect-301-url/
└── redirect-301-url.phpy comprimir la carpeta:
redirect-301-url.zipPosteriormente podemos instalarla desde:
Plugins
→ Añadir plugin
→ Subir pluginSeleccionamos:
redirect-301-url.zipe instalamos el plugin.
Después solamente tendremos que activarlo.
Por qué utilizar un plugin y no functions.php
También sería posible introducir el código dentro del archivo:
functions.phpdel tema.
Sin embargo, no es recomendable.
Las redirecciones forman parte del funcionamiento del sitio web y no de su diseño.
Si introducimos el código dentro de:
functions.phpla funcionalidad dependerá del tema activo.
Si posteriormente cambiamos de tema, las redirecciones dejarían de funcionar.
Mantener esta función como plugin independiente permite:
- cambiar de tema sin perder las redirecciones;
- activar o desactivar fácilmente el sistema;
- mantener separado el código del tema;
- localizar fácilmente la funcionalidad;
- actualizar el código independientemente del diseño.
Cómo comprobar que funciona
Antes de considerar terminada la migración es recomendable probar varias URLs antiguas.
Podemos abrir:
https://site.com/nombre-antiguo-del-articulo/El navegador debería enviarnos automáticamente hacia:
https://site.com/categoria/nombre-antiguo-del-articulo/Sin embargo, conviene comprobar también el código HTTP.
Podemos hacerlo desde Linux con:
curl -I https://site.com/nombre-antiguo-del-articulo/Deberíamos obtener una respuesta similar a:
HTTP/2 301
location: https://site.com/linux/nombre-antiguo-del-articulo/Y al consultar la nueva URL:
curl -I https://site.com/linux/nombre-antiguo-del-articulo/deberíamos obtener:
HTTP/2 200El resultado deseado es por tanto:
URL antigua
301
↓
URL nueva
200Evitar cadenas de redirecciones
Es importante evitar situaciones como:
URL antigua
↓
301
URL intermedia
↓
301
URL nuevaLo recomendable es que la antigua URL apunte directamente al destino final:
URL antigua
↓
301
URL definitivaEl uso de:
get_permalink($post->ID)ayuda precisamente a conseguirlo, ya que WordPress devuelve el permalink actualmente configurado para ese post.
Artículos con varias categorías
Hay que tener en cuenta un aspecto importante de WordPress.
Una misma entrada puede pertenecer a varias categorías:
Linux
Docker
TutorialesSin embargo, cuando la estructura utiliza:
/%category%/%postname%/WordPress debe elegir una categoría para construir el permalink.
El plugin no decide qué categoría utilizar.
Simplemente utiliza:
get_permalink()y, por tanto, respeta la URL que WordPress genere para esa entrada.
Esto evita duplicar la lógica interna de generación de permalinks.
Limitaciones del plugin
El plugin está específicamente diseñado para una migración donde las URLs antiguas tienen una estructura de un único nivel:
/post/y las nuevas:
/categoria/post/No intenta solucionar cualquier tipo de 404.
Esto es intencionado.
El código:
if (strpos($path, '/') !== false || empty($path)) {
return;
}impide procesar rutas más complejas.
Por ejemplo:
/2025/post//blog/post//category/linux/no serán procesadas.
Esto reduce considerablemente el riesgo de crear redirecciones incorrectas.
Qué ocurre con páginas de WordPress
El código busca exclusivamente:
'post'mediante:
get_page_by_path($path, OBJECT, 'post');Por tanto, no intenta redireccionar páginas:
pageni otros tipos de contenido personalizados.
Si tenemos una página:
/contacto/el plugin no la utilizará como destino de una redirección.
Esto es especialmente conveniente porque el objetivo del plugin es resolver exclusivamente URLs antiguas correspondientes a entradas.
Impacto sobre el rendimiento
El plugin únicamente ejecuta la búsqueda cuando WordPress ya ha determinado que la petición corresponde a un:
404Las páginas normales, categorías y artículos no realizan la búsqueda adicional.
Por tanto:
if (!is_404()) {
return;
}es también importante desde el punto de vista del rendimiento.
La consulta adicional solamente se produce sobre las URLs que ya habrían terminado mostrando una página de error.
Ventajas frente a crear cientos de redirecciones manuales
Un sitio con 2.000 entradas podría necesitar aproximadamente 2.000 reglas individuales:
/post-1/ → /linux/post-1/
/post-2/ → /windows/post-2/
/post-3/ → /mysql/post-3/
...Nuestro plugin convierte este problema en una sola lógica dinámica.
WordPress actúa como base de datos de las redirecciones:
slug
↓
ID del post
↓
permalink actualNo necesitamos mantener una tabla independiente con miles de URLs.
Consideraciones SEO después de cambiar los permalinks
Una migración de URLs no termina al crear las redirecciones.
También conviene revisar los enlaces internos del sitio.
Aunque una redirección 301 solucione:
/post/
→
/categoria/post/los enlaces internos deberían apuntar directamente hacia la URL nueva.
Es decir, debemos evitar:
Página A
↓
URL antigua
↓
301
↓
URL nuevay utilizar directamente:
Página A
↓
URL nuevaTambién es recomendable actualizar el sitemap XML y verificar que contiene exclusivamente las nuevas URLs.
Google Search Console
Después de modificar la estructura de enlaces permanentes podemos encontrar temporalmente URLs antiguas dentro de Google Search Console.
Es normal que Google continúe rastreando durante un tiempo:
/post-antiguo/La respuesta correcta debe ser:
301hacia:
/categoria/post-antiguo/Con el tiempo Google irá sustituyendo la dirección antigua por la nueva.
También podemos utilizar Search Console para detectar antiguas URLs que no hayan encontrado correctamente su destino.
Conclusión
Cambiar la estructura de enlaces permanentes de WordPress puede generar cientos o miles de errores 404 si las antiguas URLs ya habían sido indexadas o enlazadas.
En lugar de crear manualmente una redirección para cada artículo, podemos aprovechar las propias funciones de WordPress.
Nuestro plugin utiliza:
is_404()para detectar una URL inexistente,
get_page_by_path()para localizar la entrada utilizando su slug,
y:
get_permalink()para obtener automáticamente su nueva dirección.
Finalmente:
wp_safe_redirect($new_url, 301);realiza la redirección permanente.
El resultado es un sistema sencillo:
/post-antiguo/
↓
301
↓
/categoria/post-antiguo/que permite realizar una migración de enlaces permanentes de WordPress sin tener que mantener manualmente cientos de reglas de redirección.
