Redirección por rol en WordPress después del login: snippet moderno y plugins

WordPress login screen with multiple user role icons (administrator crown, editor pencil, subscriber person) branching out...

Cuando un suscriptor inicia sesión en WordPress, aterriza por defecto en el escritorio de administración, una pantalla que no tiene ningún sentido para alguien que solo va a leer contenido premium o gestionar su cuenta. Redirigirlo automáticamente a la página correcta según su rol mejora la experiencia de usuario y evita que vea partes del backend que no le corresponden.

El hook correcto: login_redirect

El hook que hay que usar es login_redirect, no admin_init como se usaba en los snippets de 2012. El hook admin_init se ejecuta en cada carga del escritorio, no solo después del login, lo que causa redirecciones inesperadas. login_redirect se ejecuta exactamente en el momento del login y recibe la URL de redirección por defecto, el objeto del usuario y la URL solicitada.

Snippet moderno: redirección por rol en functions.php

Este snippet cubre los roles estándar de WordPress (administrator, editor, author, subscriber) y el rol customer de WooCommerce. Usa current_user_can() en lugar de comparar el nombre del rol directamente, lo que es más robusto si tienes roles personalizados que heredan capacidades.

/**
 * Redirige a los usuarios a una URL específica según su rol después del login.
 * Hook: login_redirect
 *
 * @param string  $redirect_to           URL de redirección por defecto.
 * @param string  $requested_redirect_to URL solicitada antes del login (si la hay).
 * @param WP_User $user                  Objeto del usuario logueado.
 * @return string URL de destino.
 */
function wpdirecto_redirect_after_login( $redirect_to, $requested_redirect_to, $user ) {
    // Si hay un error en el login, devolver la URL por defecto.
    if ( is_wp_error( $user ) ) {
        return $redirect_to;
    }

    // Si el usuario ya tenía una URL de destino explícita y es del mismo sitio,
    // respetarla (evita open redirect).
    if ( ! empty( $requested_redirect_to ) && wp_validate_redirect( $requested_redirect_to ) ) {
        return $requested_redirect_to;
    }

    // Administrador: al escritorio de WordPress.
    if ( $user->has_cap( 'manage_options' ) ) {
        return admin_url();
    }

    // Editor: al listado de entradas.
    if ( $user->has_cap( 'edit_others_posts' ) ) {
        return admin_url( 'edit.php' );
    }

    // Autor: a sus propias entradas.
    if ( $user->has_cap( 'publish_posts' ) ) {
        return admin_url( 'edit.php?author=' . $user->ID );
    }

    // Customer de WooCommerce: a la página Mi cuenta.
    if ( $user->has_cap( 'read' ) && class_exists( 'WooCommerce' ) ) {
        $myaccount_page = get_option( 'woocommerce_myaccount_page_id' );
        if ( $myaccount_page ) {
            return get_permalink( $myaccount_page );
        }
    }

    // Suscriptor y otros roles sin capacidades especiales: a la portada.
    return home_url( '/' );
}
add_filter( 'login_redirect', 'wpdirecto_redirect_after_login', 10, 3 );Lenguaje del código: PHP (php)

Puedes añadir este código al fichero functions.php de tu tema hijo, o mejor aún, en un plugin de un fichero propio para que no se pierda si cambias de tema. Si quieres aplicarlo con mayor seguridad sin depender del tema, usa un mu-plugin (must-use plugin) en la carpeta wp-content/mu-plugins/.

Versión como MU-plugin (recomendada)

Los mu-plugins se cargan antes que los plugins normales y no se pueden desactivar desde el panel. Crea el fichero wp-content/mu-plugins/redirect-by-role.php con este contenido:

<?php
/**
 * Plugin Name: Redirect by Role After Login
 * Description: Redirige usuarios al destino correcto según su rol de WordPress.
 */
if ( ! defined( 'ABSPATH' ) ) exit;

add_filter( 'login_redirect', function( $redirect_to, $requested_redirect_to, $user ) {
    if ( is_wp_error( $user ) ) return $redirect_to;
    if ( ! empty( $requested_redirect_to ) && wp_validate_redirect( $requested_redirect_to ) ) {
        return $requested_redirect_to;
    }
    if ( $user->has_cap( 'manage_options' ) ) return admin_url();
    if ( $user->has_cap( 'edit_others_posts' ) ) return admin_url( 'edit.php' );
    if ( $user->has_cap( 'publish_posts' ) ) return admin_url( 'edit.php?author=' . $user->ID );
    return home_url( '/' );
}, 10, 3 );Lenguaje del código: HTML, XML (xml)

Importante: seguridad contra open redirect

Un open redirect ocurre cuando tu sitio redirige a una URL externa sin validarla. Si alguien envía a tus usuarios un enlace del tipo tudominio.com/wp-login.php?redirect_to=https://sitiomalicioso.com y el código no valida que la URL de destino pertenece a tu dominio, el atacante puede usarlo para phishing.

El snippet anterior usa wp_validate_redirect() que, por defecto, solo permite redirecciones al mismo dominio. No construyas URLs de redirección con datos directos de $_GET o $_POST sin pasar por esta función.

Plugins alternativos

  • Peter’s Login Redirect: permite configurar redirecciones por rol, usuario individual y URL de destino desde el panel de WordPress, sin tocar código.
  • LoginWP (antes Peter’s Login Redirect): la versión comercial con más opciones, incluyendo redirecciones condicionales por fecha, dispositivo o primer login.

Si también trabajas con WooCommerce, puede interesarte ver la lista de plugins imprescindibles para WooCommerce, algunos de los cuales incluyen gestión avanzada de cuentas de cliente. Para la seguridad general del login, consulta nuestra guía de mejores prácticas de seguridad en WordPress. Y si necesitas gestionar otras personalizaciones de comportamiento del sitio, el artículo sobre trucos en functions.php puede serte útil.

Preguntas frecuentes

¿Por qué usar login_redirect en lugar de admin_init?

El hook admin_init se ejecuta en cada visita al escritorio de WordPress, no solo al hacer login. Usarlo para redirecciones provoca comportamientos inesperados: el usuario es redirigido cada vez que intenta acceder al admin, no solo al autenticarse. El hook login_redirect se ejecuta exclusivamente en el proceso de autenticación.

¿Puedo redirigir según el nombre del rol en lugar de por capacidades?

Sí, puedes usar in_array('administrator', $user->roles), pero no es lo recomendado. Si tienes roles personalizados que heredan capacidades de administrador, este método los ignoraría. Usar has_cap('manage_options') es más robusto porque comprueba la capacidad real, independientemente del nombre del rol.

¿Cómo redirigir solo en el primer login de un usuario?

Puedes usar user meta para marcar el primer login: en el hook login_redirect, comprueba si el meta _first_login_done existe para ese usuario. Si no existe, redirige a la página de bienvenida y guarda el meta con update_user_meta(). En visitas posteriores el meta ya estará y la redirección especial no se ejecutará.

¿Este snippet funciona con WooCommerce?

Sí. El snippet incluye una rama específica para el rol customer de WooCommerce que redirige a la página de Mi Cuenta configurada en WooCommerce. La condición class_exists('WooCommerce') evita errores si WooCommerce no está instalado.

¿El snippet protege contra open redirect?

Sí. Usa wp_validate_redirect() antes de respetar una URL de redirección externa, lo que garantiza que solo se permiten redirecciones al mismo dominio. Las URLs externas son ignoradas y el usuario va a la URL asignada por rol.

David Carrero Fernández-Baillo

Experimentando con un sitio web sobre WordPress, este popular gestor de contenidos, entre otros muchos proyectos.

Te puede interesar...

    Comments are closed

    WordPress Directo
    WPDirecto.com es una revista especializada en WordPress y WooCommerce que ofrece una amplia gama de recursos, incluyendo tutoriales, análisis de plugins y plantillas, consejos de optimización y estrategias de SEO, para ayudar a los usuarios a mejorar y personalizar sus sitios web, manteniéndolos informados sobre las últimas novedades y tendencias en el mundo de WordPress.

    © 1995-2025 Color Vivo Internet, SLU (Medios y Redes Online).. Otros contenidos se cita fuente. Infraestructura cloud servidores dedicados de Stackscale.