# Plugin de WordPress para redireccionar URLs antiguas con redirecciones 301

- Link: https://binariocero.com/php/plugin-de-wordpress-para-redireccionar-urls-antiguas-con-redirecciones-301
- Published: 2026-09-05T09:32:12+02:00
- Author: Juan José Fernández Durán

![Loading](https://binariocero.com/wp-content/plugins/page-views-count/ajax-loader-
2x.gif)

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:

    ```wp-block-code
    https://site.com/nombre-del-articulo/
    ```

a una estructura que incluya la categoría:

    ```wp-block-code
    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:

    ```wp-block-code
    https://site.com/configurar-apache/
    ```

y el servidor responde indicando:

    ```wp-block-code
    301 Moved Permanently
    ```

junto con la nueva ubicación:

    ```wp-block-code
    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:

    ```wp-block-code
    /%postname%/
    ```

Una entrada llamada:

    ```wp-block-code
    Cómo instalar Apache en Debian
    ```

podría tener esta dirección:

    ```wp-block-code
    https://site.com/como-instalar-apache-en-debian/
    ```

Posteriormente cambiamos los enlaces permanentes a:

    ```wp-block-code
    /%category%/%postname%/
    ```

La misma entrada puede pasar a tener esta dirección:

    ```wp-block-code
    https://site.com/linux/como-instalar-apache-en-debian/
    ```

La URL antigua:

    ```wp-block-code
    https://site.com/como-instalar-apache-en-debian/
    ```

ya no existe y WordPress devuelve:

    ```wp-block-code
    404 Not Found
    ```

Esto 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:

    ```wp-block-code
    <?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:

    ```wp-block-code
    URL antigua
          ↓
    WordPress devuelve 404
          ↓
    se extrae el slug
          ↓
    se busca una entrada con ese slug
          ↓
    se obtiene su permalink actual
          ↓
    redirección 301
    ```

De esta manera no necesitamos conocer previamente la categoría de cada artículo.

## Cómo funciona el plugin

El plugin utiliza el hook:

    ```wp-block-code
    template_redirect
    ```

mediante:

    ```wp-block-code
    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:

    ```wp-block-code
    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:

    ```wp-block-code
    $path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
    ```

La variable:

    ```wp-block-code
    $_SERVER['REQUEST_URI']
    ```

contiene la URL solicitada.

Por ejemplo:

    ```wp-block-code
    /como-instalar-apache-en-debian/?utm_source=google
    ```

La función:

    ```wp-block-code
    parse_url()
    ```

permite obtener solamente la ruta:

    ```wp-block-code
    /como-instalar-apache-en-debian/
    ```

utilizando:

    ```wp-block-code
    PHP_URL_PATH
    ```

Finalmente:

    ```wp-block-code
    trim(..., '/')
    ```

elimina las barras iniciales y finales.

El resultado será:

    ```wp-block-code
    como-instalar-apache-en-debian
    ```

Este valor corresponde normalmente al **slug** de la entrada.

## Evitar procesar URLs con varias rutas

El plugin contiene la siguiente comprobación:

    ```wp-block-code
    if (strpos($path, '/') !== false || empty($path)) {
        return;
    }
    ```

Su objetivo es procesar exclusivamente las URLs antiguas que tengan esta estructura:

    ```wp-block-code
    /nombre-del-post/
    ```

Por ejemplo:

    ```wp-block-code
    /instalar-nginx-en-debian/
    ```

sí será procesada.

Sin embargo:

    ```wp-block-code
    /linux/instalar-nginx-en-debian/
    ```

no será procesada.

Tampoco se procesarán URLs como:

    ```wp-block-code
    /category/linux/
    ```

    ```wp-block-code
    /tag/debian/
    ```

    ```wp-block-code
    /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:

    ```wp-block-code
    $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:

    ```wp-block-code
    'post'
    ```

por lo que WordPress busca una entrada cuyo slug coincida con la ruta recibida.

Por ejemplo, para:

    ```wp-block-code
    /como-instalar-docker/
    ```

se buscaría una entrada cuyo slug sea:

    ```wp-block-code
    como-instalar-docker
    ```

Si WordPress encuentra la entrada, devuelve su objeto.

## Comprobar que la entrada está publicada

Posteriormente comprobamos:

    ```wp-block-code
    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:

    ```wp-block-code
    publish
    ```

## Obtener automáticamente la nueva URL

Esta línea es la que permite que el plugin funcione independientemente de la categoría:

    ```wp-block-code
    $new_url = get_permalink($post->ID);
    ```

WordPress genera automáticamente el permalink actual de la entrada.

Supongamos que tenemos:

    ```wp-block-code
    Slug:

    wake-on-lan-windows
    ```

y la entrada pertenece a la categoría:

    ```wp-block-code
    Windows
    ```

Si WordPress utiliza:

    ```wp-block-code
    /%category%/%postname%/
    ```

`get_permalink()` puede devolver:

    ```wp-block-code
    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-block-code
    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:

    ```wp-block-code
    301
    ```

indica el código HTTP utilizado.

Por tanto, WordPress responderá:

    ```wp-block-code
    HTTP/1.1 301 Moved Permanently
    ```

y enviará al navegador hacia la nueva URL.

El:

    ```wp-block-code
    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:

    ```wp-block-code
    https://site.com/configurar-wake-on-lan-windows/
    ```

Después de cambiar los permalinks, la entrada se encuentra en:

    ```wp-block-code
    https://site.com/windows/configurar-wake-on-lan-windows/
    ```

Cuando Google accede a:

    ```wp-block-code
    /configurar-wake-on-lan-windows/
    ```

WordPress no encuentra esa URL y genera un 404.

El plugin recibe:

    ```wp-block-code
    configurar-wake-on-lan-windows
    ```

y ejecuta:

    ```wp-block-code
    get_page_by_path(
        'configurar-wake-on-lan-windows',
        OBJECT,
        'post'
    );
    ```

WordPress encuentra la entrada.

A continuación:

    ```wp-block-code
    get_permalink($post->ID);
    ```

devuelve:

    ```wp-block-code
    https://site.com/windows/configurar-wake-on-lan-windows/
    ```

Finalmente se realiza:

    ```wp-block-code
    301
    ```

desde:

    ```wp-block-code
    /configurar-wake-on-lan-windows/
    ```

hacia:

    ```wp-block-code
    /windows/configurar-wake-on-lan-windows/
    ```

## Cómo instalar el plugin en WordPress

Para instalarlo manualmente podemos crear una carpeta dentro de:

    ```wp-block-code
    wp-content/plugins/
    ```

Por ejemplo:

    ```wp-block-code
    wp-content/plugins/redirect-301-url/
    ```

Dentro creamos el archivo:

    ```wp-block-code
    redirect-301-url.php
    ```

La estructura quedaría:

    ```wp-block-code
    wp-content/
    └── plugins/
        └── redirect-301-url/
            └── redirect-301-url.php
    ```

Introducimos dentro del archivo el código del plugin.

Posteriormente entramos en:

    ```wp-block-code
    WordPress
    → Plugins
    → Plugins instalados
    ```

Buscamos:

    ```wp-block-code
    Redirect 301 URL
    ```

y pulsamos:

    ```wp-block-code
    Activar
    ```

Desde 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:

    ```wp-block-code
    redirect-301-url/
    └── redirect-301-url.php
    ```

y comprimir la carpeta:

    ```wp-block-code
    redirect-301-url.zip
    ```

Posteriormente podemos instalarla desde:

    ```wp-block-code
    Plugins
    → Añadir plugin
    → Subir plugin
    ```

Seleccionamos:

    ```wp-block-code
    redirect-301-url.zip
    ```

e 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:

    ```wp-block-code
    functions.php
    ```

del 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:

    ```wp-block-code
    functions.php
    ```

la 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:

    ```wp-block-code
    https://site.com/nombre-antiguo-del-articulo/
    ```

El navegador debería enviarnos automáticamente hacia:

    ```wp-block-code
    https://site.com/categoria/nombre-antiguo-del-articulo/
    ```

Sin embargo, conviene comprobar también el código HTTP.

Podemos hacerlo desde Linux con:

    ```wp-block-code
    curl -I https://site.com/nombre-antiguo-del-articulo/
    ```

Deberíamos obtener una respuesta similar a:

    ```wp-block-code
    HTTP/2 301
    location: https://site.com/linux/nombre-antiguo-del-articulo/
    ```

Y al consultar la nueva URL:

    ```wp-block-code
    curl -I https://site.com/linux/nombre-antiguo-del-articulo/
    ```

deberíamos obtener:

    ```wp-block-code
    HTTP/2 200
    ```

El resultado deseado es por tanto:

    ```wp-block-code
    URL antigua
    301
    ↓
    URL nueva
    200
    ```

## Evitar cadenas de redirecciones

Es importante evitar situaciones como:

    ```wp-block-code
    URL antigua
    ↓
    301
    URL intermedia
    ↓
    301
    URL nueva
    ```

Lo recomendable es que la antigua URL apunte directamente al destino final:

    ```wp-block-code
    URL antigua
    ↓
    301
    URL definitiva
    ```

El uso de:

    ```wp-block-code
    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:

    ```wp-block-code
    Linux
    Docker
    Tutoriales
    ```

Sin embargo, cuando la estructura utiliza:

    ```wp-block-code
    /%category%/%postname%/
    ```

WordPress debe elegir una categoría para construir el permalink.

El plugin no decide qué categoría utilizar.

Simplemente utiliza:

    ```wp-block-code
    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:

    ```wp-block-code
    /post/
    ```

y las nuevas:

    ```wp-block-code
    /categoria/post/
    ```

No intenta solucionar cualquier tipo de 404.

Esto es intencionado.

El código:

    ```wp-block-code
    if (strpos($path, '/') !== false || empty($path)) {
        return;
    }
    ```

impide procesar rutas más complejas.

Por ejemplo:

    ```wp-block-code
    /2025/post/
    ```

    ```wp-block-code
    /blog/post/
    ```

    ```wp-block-code
    /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:

    ```wp-block-code
    'post'
    ```

mediante:

    ```wp-block-code
    get_page_by_path($path, OBJECT, 'post');
    ```

Por tanto, no intenta redireccionar páginas:

    ```wp-block-code
    page
    ```

ni otros tipos de contenido personalizados.

Si tenemos una página:

    ```wp-block-code
    /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:

    ```wp-block-code
    404
    ```

Las páginas normales, categorías y artículos no realizan la búsqueda adicional.

Por tanto:

    ```wp-block-code
    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:

    ```wp-block-code
    /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:

    ```wp-block-code
    slug
    ↓
    ID del post
    ↓
    permalink actual
    ```

No 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:

    ```wp-block-code
    /post/
    →
    /categoria/post/
    ```

los enlaces internos deberían apuntar directamente hacia la URL nueva.

Es decir, debemos evitar:

    ```wp-block-code
    Página A
    ↓
    URL antigua
    ↓
    301
    ↓
    URL nueva
    ```

y utilizar directamente:

    ```wp-block-code
    Página A
    ↓
    URL nueva
    ```

Tambié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:

    ```wp-block-code
    /post-antiguo/
    ```

La respuesta correcta debe ser:

    ```wp-block-code
    301
    ```

hacia:

    ```wp-block-code
    /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:

    ```wp-block-code
    is_404()
    ```

para detectar una URL inexistente,

    ```wp-block-code
    get_page_by_path()
    ```

para localizar la entrada utilizando su slug,

y:

    ```wp-block-code
    get_permalink()
    ```

para obtener automáticamente su nueva dirección.

Finalmente:

    ```wp-block-code
    wp_safe_redirect($new_url, 301);
    ```

realiza la redirección permanente.

El resultado es un sistema sencillo:

    ```wp-block-code
    /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.
