Como hacer redirecciones 301 con template_redirect en PHP en WordPress

Contents

Introducción

En WordPress, template_redirect es un hook muy útil que se ejecuta justo antes de que se cargue la plantilla que renderiza la página pública. Es el lugar adecuado para aplicar redirecciones en PHP usando las funciones nativas de WordPress (wp_redirect, wp_safe_redirect, etc.) sin interferir con la carga del panel de administración. En este artículo explico en detalle cuándo y cómo usar template_redirect para implementar redirecciones 301 (permanentes), con ejemplos prácticos, buenas prácticas y precauciones para evitar bucles y problemas de rendimiento.

¿Por qué usar template_redirect?

  • Se ejecuta justo antes de renderizar la plantilla: permite redirigir antes de enviar contenido al cliente.
  • Acceso a funciones de WordPress: puedes usar las funciones condicionales (is_singular, is_category, is_404, etc.) para redirecciones contextuales.
  • Flexible y programable: puedes aplicar lógica compleja que no es posible con reglas de servidor (.htaccess o nginx) o con plugins que gestionan redirecciones básicas.

¿Cuándo no usarlo?

  • Para un gran volumen de redirecciones simples y estáticas (por rendimiento es mejor hacerlo a nivel del servidor con .htaccess o reglas de nginx).
  • Para redirecciones que deben aplicarse en el admin o en AJAX template_redirect corre en la parte pública, así que verifica si necesitas add_action en hooks diferentes.

Conceptos clave antes de empezar

  • wp_redirect / wp_safe_redirect: funciones para redirigir. Usar wp_safe_redirect cuando se redirigen URLs que pueden ser externas y wp_redirect para redirecciones internas/seguras. Ambas aceptan código de estado HTTP (301, 302).
  • exit después de la redirección: imprescindible para detener la ejecución y evitar que WordPress continúe y potencialmente envíe salida adicional.
  • Evitar bucles: comprueba que la URL de destino no sea la misma que la actual antes de redirigir.
  • Prioridad y orden: puedes ajustar la prioridad del add_action(template_redirect, mi_funcion, priority) para que la redirección ocurra antes o después de otras funcionalidades.
  • No en admin ni en REST/AJAX: verifica is_admin(), DOING_AJAX o REST requests si es necesario.

Ejemplos prácticos

1) Redirección simple 301 por ruta

Redirige /antigua-pagina a /nueva-pagina con código 301.


2) Redirección preservando query string

Si quieres mantener los parámetros GET al redirigir, usa add_query_arg() o http_build_query con _GET.


3) Redirección por ID de post o slug antiguo

Redirigir un post eliminado a otro post existente (por ID). Útil si conoces los IDs de los elementos que cambiaste.


4) Redirección con expresiones regulares (por patrones)

Redirigir URLs que siguen un patrón (por ejemplo, blog/old-category/ a blog/new-category/).

 /blog/new-category/slug
    if ( preg_match(#^/blog/old-category/(. )#, path, matches) ) {
        slug = matches[1]
        dest = home_url( /blog/new-category/{slug}/ )
        wp_safe_redirect( dest, 301 )
        exit
    }
}
?>

5) Evitar bucles y verificar cabeceras

Comprobar que la URL actual no sea igual a la de destino y que no se hayan enviado cabeceras ya.


6) Redirigir HTTP -> HTTPS o non-www -> www (ejemplo en PHP, aunque se recomienda hacerlo a nivel de servidor)

Mejor implementar en servidor por rendimiento, pero si no puedes, aquí un ejemplo seguro chequeando host y esquema.


Buenas prácticas

  • Evitar realizar muchas redirecciones programadas: para grandes listas uso de .htaccess/nginx o plugins especializados es más eficiente.
  • Usar wp_safe_redirect cuando puedas: protege contra redirecciones a URLs externas maliciosas.
  • Escapar URLs: esc_url(), esc_url_raw() al generar destinos.
  • Comprobar is_admin y DOING_AJAX: para evitar redirigir peticiones de administración o AJAX accidentalmente.
  • Revisar headers_sent: template_redirect normalmente corre antes de enviar cabeceras, pero si hay plugins que envían salida, comprobar headers_sent() evita errores.
  • Usar prioridades apropiadas: si otras funcionalidades también usan template_redirect puede que necesites prioridad baja/alta para tu hook.
  • Registrar redirecciones en un solo punto: centraliza la lógica (archivo functions.php o un archivo include) para mantener control y evitar duplicados.

Consideraciones SEO

  • Usa 301 para redirecciones permanentes (traslado definitivo). Para pruebas temporales usa 302.
  • Evita cadenas largas de redirecciones (A -> B -> C), mejor apuntar A -> C directamente.
  • Comprueba que los encabezados HTTP devuelvan correctamente 301 (puedes usar curl, DevTools del navegador o herramientas SEO).
  • Si cambias estructura de permalinks masiva, actualiza sitemaps y comunica cambios a Google Search Console.

Depuración y comprobaciones

  1. Activa WP_DEBUG y revisa registros de error si algo falla.
  2. Usa curl -I https://tusitio/antigua-pagina para ver código de estado y cabeceras Location.
  3. Revisa que no existan plugins duplicando redirecciones (y generar bucles).
  4. Prueba con distintos navegadores y borra cache para evitar falsos positivos por cache de navegador o CDN.

Ejemplo avanzado: Mapa de redirecciones y función central

Implementa un array con pares {origen => destino} y un proceso centralizado que gestione preservación de query strings, saneamiento y prevención de bucles.

 /nueva-pagina/,
        /old-path/producto => /productos/nombre-producto/,
        /blog/2018/(.)    => /archivo-2018/1, // ejemplo con regex si lo deseas
    )

    request_path = untrailingslashit( parse_url( _SERVER[REQUEST_URI], PHP_URL_PATH ) )

    foreach ( redirect_map as source => target ) {
        if ( strpos(source, () !== false ) {
            // Tratamiento como regex
            pattern = #^ . source . #
            if ( preg_match( pattern, request_path, matches ) ) {
                // Sustituye variables 1, 2... en target si existen
                destination = preg_replace( pattern, target, request_path )
                // Añadir query args si existen
                destination = add_query_arg( _GET, home_url( destination ) )
                if ( untrailingslashit( home_url( request_path ) ) === untrailingslashit( destination ) ) {
                    return
                }
                wp_safe_redirect( esc_url_raw( destination ), 301 )
                exit
            }
        } else {
            // Igualación simple
            if ( request_path === rtrim( source, / ) ) {
                destination = add_query_arg( _GET, home_url( target ) )
                if ( untrailingslashit( home_url( request_path ) ) === untrailingslashit( destination ) ) {
                    return
                }
                wp_safe_redirect( esc_url_raw( destination ), 301 )
                exit
            }
        }
    }
}
?>

Notas finales

La ejecución de redirecciones desde template_redirect es poderosa y flexible, ideal cuando la lógica debe depender del entorno de WordPress (post types, taxonomías, condiciones dinámicas). Sin embargo, para un gran volumen de reglas estáticas o para mejorar performance, considera delegar al servidor web. Siempre valida con herramientas HTTP que las redirecciones devuelvan el código 301 correcto y evita bucles comprobando cuidadosamente la URL actual frente a la de destino.



Acepto donaciones de BAT's mediante el navegador Brave 🙂



Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *