WordPress Hosting

¿Sabías que WordPress hace redirecciones automáticamente si modificas una URL?

¿A que pensabas que si cambiabas la URL de una entrada provocabas un error 404 sí o sí? Pues no, así que otro plugin que igual te vas a poder ahorrar desde ya.

¡De nada!

Y es que resulta que cuando cambias el slug de una entrada en WordPress, la URL antigua sigue funcionando con una redirección a la nueva, eso lo hace una función nativa, del core, que se llama wp_old_slug_redirect().

Ni plugin ni nada, esta joyita viene de serie, pero casi nadie sabe que está ahí, ni que se puede incluso tocar para que haga lo que tú quieras.

Te cuento cómo funciona por dentro, dónde están sus límites (las páginas, sobre todo) y cómo personalizarla para que haga lo que necesites.

Cómo funciona la redirección automática de slugs antiguos

Cuando editas el slug de una entrada ya publicada, por ejemplo cambias /mi-articulo/ por /articulo-definitivo/, WordPress no se limita a cambiar la URL.

Lo que hace es guardar el slug antiguo en la tabla wp_postmeta con la clave _wp_old_slug asociada a esa entrada. De eso se encarga la función wp_check_for_changed_slugs(), que compara el slug nuevo con el anterior cada vez que actualizas algo.

A partir de esoe moment entra en juego wp_old_slug_redirect(), enganchada al hook template_redirect.

Cuando alguien llega por la URL antigua, en vez de entregar un feo error 404, esta función busca si ese slug está guardado en algún _wp_old_slug y, si lo encuentra, hace un 301 permanente a la URL actual con wp_redirect( $link, 301 ).

Así la URL vieja sigue viva, no rompes los enlaces que apuntan desde fuera y el SEO no se resiente, porque el 301 traspasa la autoridad de enlaces.

Un par de detalles más que conviene que sepas.

  • Guarda todos los slugs antiguos, no solo el último. Si le cambias el slug tres veces a una entrada, las tres URLs viejas siguen redirigiendo bien a la actual.
  • También cubre los cambios en enlaces permanentes con estructura de fecha. Si tu URL lleva año y mes y cambias la fecha de publicación, el core guarda un _wp_old_date y la redirección lo tiene en cuenta igual.

Cómo personalizar el comportamiento

WordPress ofrece dos filtros para tocar estas redirecciones sin reescribir nada, y para lo que no cubren puedes montarte tu propia versión.

Cambiar la URL de destino

El filtro old_slug_redirect_url (disponible desde WordPress 4.4) te deja modificar la URL de destino a la que se redirige, justo antes de que se ejecute el 301.

Es perfecto si quieres añadir parámetros de seguimiento, o mandar el tráfico de las URLs viejas a otro sitio. Aquí tienes un ejemplo:

/**
 * Modifica la URL de destino usada para redirecciones de slugs antiguos
 *
 * @param string $link La URL a la que va a redirigir WordPress
 * @return string La (posiblemente modificada) URL de destino
 */
add_filter( 'old_slug_redirect_url', 'ayudawp_old_slug_redirect_url' );
function ayudawp_old_slug_redirect_url( $link ) {

	// Ejemplo: etiqueta las URLs viejas para poderles rastrearlas en Google Analytics
	return add_query_arg( 'utm_source', 'old-slug', $link );
}

Si devuelves una cadena vacía o false cancelas la redirección para esa petición y dejas que WordPress siga su curso, que normalmente acaba en el 404.

Decidir a qué entrada apunta

El otro filtro, old_slug_redirect_post_id (desde WordPress 4.9.3), actúa un paso antes y cambia el ID de la entrada que WordPress ha localizado a partir del slug antiguo.

Lo normal es usarlo para casos puntuales, como redirigir el slug antiguo de una entrada que has borrado hacia otra que la sustituye. Si devuelves 0 desactivas la redirección para esa petición.

/**
 * Cambia qué entrada resuelve un slug antiguo antes de que salte la redirección
 *
 * @param int $id El ID de la entrada asignado al antiguo slug
 * @return int E ID de la entrada a la que redirigir (devuelve 0 para cancelar la redirección)
 */
add_filter( 'old_slug_redirect_post_id', 'ayudawp_old_slug_redirect_post_id' ); 
function ayudawp_old_slug_redirect_post_id( $id ) {

	// Devuelve 0 para cancelar la redirección o a un ID distitno para apuntar a otro sitio.
	return $id;
}

Desactivar completamente la redirección

Si prefieres que WordPress no haga ninguna de estas redirecciones automáticas, porque las gestionas con un plugin o porque te han dado guerra, basta con quitar la función del hook.

// Desactivar las redirecciones automáticas de WordPress de antiguos slugs en todo el sitio 
remove_action( 'template_redirect', 'wp_old_slug_redirect' );

Ponlo en un mu-plugin para que no dependas del tema o de un plugin de códigos. A partir de este momento los _wp_old_slug que ya tengas guardados dejan de redirigir, aunque siguen ocupando sitio en la base de datos hasta que los borres.

Eso con las entradas ¿funciona también con páginas?

Esto es un poco putada. Todo lo anterior funciona con entradas y con tipos de contenido personalizados sin jerarquía, pero no con las páginas.

Si cambias el slug de una página WordPress ni siquiera guarda el _wp_old_slug, así que la URL vieja te devuelve un 404 a pelo.

No es un despiste de WordPress, está hecho aposta.

La función wp_check_for_changed_slugs() descarta los tipos de contenido jerárquicos, y wp_old_slug_redirect() hace lo mismo con un if ( is_post_type_hierarchical( $post_type ) ) return;.

El motivo es por rendimiento, porque en las páginas la URL se crea con la jerarquía de las superiores (si las hay), así que cambiar el slug de una página madre o superior afectaría a las URLs de todas sus hijas, y resolver eso bien obligaría a una búsqueda por árbol que el core prefiere ahorrarse.

Pero…

… puedes hacer que funcione también con páginas

Como el core pasa de las páginas, si las necesitas cubiertas con redirecciones automáticas te toca hacer dos cosas por tu cuenta, guardar el slug antiguo cuando cambie y montar después la redirección.

Lo primero es guardar el slug antiguo de la página al actualizarla, que es justo lo que el core no hace.

/**
 * Almacena el slug antiguo de las páginas que WordPress evitaba hacer al ser
 * las páginas un tipo de contenido jerárquico
 *
 * @param int     $post_id     El ID de la página
 * @param WP_Post $post_after  La página después de actualizar
 * @param WP_Post $post_before La página antes de actualizar
 */
add_action( 'post_updated', 'ayudawp_save_old_page_slug', 10, 3 ); 
function ayudawp_save_old_page_slug( $post_id, $post_after, $post_before ) {

	// Solo páginas publicadas cuyo slug haya cambiado
	if ( 'page' !== $post_after->post_type || 'publish' !== $post_after->post_status ) {
		return;
	}

	if ( '' === $post_before->post_name || $post_after->post_name === $post_before->post_name ) {
		return;
	}

	// Almacena el slug anterior, evitando duplicados
	$old_slugs = (array) get_post_meta( $post_id, '_wp_old_slug' );

	if ( ! in_array( $post_before->post_name, $old_slugs, true ) ) {
		add_post_meta( $post_id, '_wp_old_slug', $post_before->post_name );
	}
}

Y lo segundo es la redirección en sí, que solo salta en los 404 para no cargar el resto de páginas.

/**
 * Redirect an old page slug to its current permalink.
 * WordPress core only does this for non-hierarchical post types.
 */
add_action( 'template_redirect', 'ayudawp_old_page_slug_redirect' ); 
function ayudawp_old_page_slug_redirect() {

	// Actúa solo en los 404 en los que se solicitó una ruta de página
	if ( ! is_404() || '' === get_query_var( 'pagename' ) ) {
		return;
	}

	// Usa el último segmento de ruta como el slug donde buscar
	$parts = explode( '/', untrailingslashit( get_query_var( 'pagename' ) ) );
	$slug  = end( $parts );

	$pages = get_posts(
		array(
			'post_type'   => 'page',
			'post_status' => 'publish',
			'numberposts' => 1,
			'meta_key'    => '_wp_old_slug',
			'meta_value'  => $slug,
		)
	);

	if ( ! empty( $pages ) ) {
		wp_safe_redirect( get_permalink( $pages[0]->ID ), 301 );
		exit;
	}
}

Con esto cubres el caso normal, que es cambiar el slug de una página concreta.

Lo que no resuelve es cuando cambias el slug de una página superior y quieres que redirijan también las URLs antiguas de sus hijas, porque ahí entra el lío del árbol de jerarquías del que se libra el core.

Y como aquí el código de estado lo controlas tú, si quieres un 302 temporal en vez del 301, solo tienes que cambiar el número en el código.

Cuidado con los plugins de redirecciones

Si tienes instalado un plugin de redirecciones del tipo Redirection o las herramientas para redirecciones de los plugins de SEO como Rank Math, porque pueden pisar el sistema nativo.

A más de uno le ha pasado que tras instalarlo los _wp_old_slug que WordPress había guardado dejan de redirigir y las URLs antiguas acaban en un 404.

No pasa siempre ni con todos los plugins pero si cambias un slug y la redirección automática no salta como esperabas, revisa si algún plugin está interceptando antes el template_redirect.

Cómo limpiar los _wp_old_slug que se acumulan

Cada cambio de slug deja un registro nuevo en wp_postmeta, y eso en una web con muchos años y muchos cambios se va acumulando, y aunque no es nada grave, si quieres hacer limpieza o te encuentras con una redirección rara que apunta donde no debe, puedes borrarlos.

La forma más directa es por SQL, y como siempre, antes haz una copia de seguridad, porque esto elimina de golpe todas las redirecciones de slug que tengas en marcha. Cambia wp_ por el prefijo real de tu instalación.

DELETE FROM wp_postmeta WHERE meta_key = '_wp_old_slug';

Si usas WP-CLI lo lanzas con wp db query, y si solo quieres limpiar una página o entrada concreta puedes usar wp post meta delete con el ID de esa entrada y la clave _wp_old_slug, sin tocar el resto.

¿Redirección nativa o plugin?

Para que lo tengas como resumen, esto es lo que cubre el sistema nativo y cuándo igual es mejor usar otra cosa.

Situación Redirección nativa Qué hacer
Cambias el slug de una entrada o CPT no jerárquico Sí, automática Nada, lo gestiona WordPress
Cambias el slug de una página No La redirección a mano o el código de este artículo
Cambias toda la estructura de permalinks No Plugin de redirecciones o reglas en el servidor
Mueves contenido de un dominio a otro No Redirecciones 301 en el servidor o un plugin
Quieres estadísticas de 404 y redirecciones No Un plugin tipo Redirection
Rediriges una URL vieja a otra cualquiera Solo con el filtro El filtro old_slug_redirect_url o un plugin

Mi consejo es que no instales un plugin de redirecciones solo porque has cambiado un par de slugs de entradas, que para eso WordPress ya se apaña solo.

Guárdate el plugin para cuando de verdad lo necesites, como cambios masivos de estructura o migraciones, y para las páginas tira del código de aquí arriba, te lo deja resuelto sin cargar el sitio con otro plugin más.

Compártelo en tus redes
Resúmelo con tu IA

¿De cuánta utilidad te ha parecido este contenido?

¡Haz clic en las estrellas para valorarlo!

Promedio de puntuación 5 / 5. Total de votos: 3

¡Todavía no hay votos! Sé el primero en valorar este contenido.

Ya que has encontrado útil este contenido...

¡Sígueme en las redes sociales!

¿Te gustó este artículo? ¡Ni te imaginas lo que te estás perdiendo en YouTube!



Sobre el autor

Deja un comentario

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

Scroll al inicio