Redirect WordPress users after login by role
Authentication and navigation are separate jobs. WordPress can confirm who signed in, yet still send that person to the same screen even when an editor, warehouse operator or WooCommerce customer needs a more relevant destination. Role-aware routing keeps those journeys separate without duplicating the login process.
The safest implementation is a server-side filter that receives the authenticated WordPress user, checks an allowlist of roles and returns a trusted internal URL. It suits core logins, custom staff portals and customer accounts while remaining compatible with normal password-reset flows. The WordPress Q&A guides also provide examples useful when a plugin changes the usual redirect behaviour.
Compare redirect mechanisms
Several WordPress mechanisms can influence where a browser goes next, but they are not interchangeable. A redirect filter runs at the authentication boundary and can inspect the user’s role. Front-end routing rules run on ordinary page requests, while client-side scripts act only after HTML and JavaScript have reached the browser.
| Mechanism | When it runs | User details available | Best fit |
|---|---|---|---|
login_redirect filter |
After successful authentication | Receives the WP_User object |
Role-specific login destinations |
wp_login action |
Immediately after sign-in | Receives user details | Logging or session tasks, not choosing a URL |
template_redirect |
During front-end requests | Access through the current user | Restricting login or account pages |
| JavaScript redirect | After the browser loads a page | Limited to exposed client-side data | Visual fallback, not protected routing |
For most sites, login_redirect provides the cleanest foundation because it receives the authenticated WP_User object and its return value becomes the login destination. The wp_login action is useful for audit events but cannot choose a URL by itself. Browser scripts and generic page routing should remain secondary because they can expose the wrong page and make protected destinations harder to enforce.
Define role destinations
Roles provide a useful starting point because they describe a person’s main function: administrator, editor, author, contributor, subscriber or a WooCommerce customer. They are not the same as permissions. A custom membership role may have no matching entry, while a plugin can add capabilities that should influence the destination. A robust map therefore defines known roles explicitly and leaves unknown roles alone.
Australian sites often have mixed audiences. A Sydney office may give administrators and editors a staff dashboard, while a Melbourne membership business sends subscribers to a profile page. A Brisbane warehouse using WooCommerce may need shop managers on order reports and customers on their own account history. These examples show why one fixed post-login URL can be inconvenient across the Australian market.
Decide which destination is the fallback before coding it. For instance, administrators can begin in /wp-admin/, content roles can begin at the Posts screen, and customers can begin at /my-account/. If the My Account page does not exist, use a genuine landing page rather than sending every customer to a 404 response.
Build a reliable redirect hook
Place the code in a child theme’s functions.php, a small must-use plugin, or a code snippets extension used by your team. A filter in a child theme keeps the behaviour with the design, while a must-use plugin survives theme changes. Test it in staging before deployment and avoid editing a parent theme that will be overwritten.
add_filter( 'login_redirect', 'qa_role_login_redirect', 10, 3 );
function qa_role_login_redirect( $redirect_to, $requested_redirect_to, $user ) {
if ( ! ( $user instanceof WP_User ) ) {
return $redirect_to;
}
$role_destinations = array(
'administrator' => admin_url(),
'shop_manager' => admin_url( 'admin.php?page=wc-reports' ),
'editor' => admin_url( 'edit.php' ),
'author' => admin_url( 'edit.php?post_type=post' ),
'contributor' => admin_url( 'edit.php?post_type=post' ),
'customer' => home_url( '/my-account/' ),
'subscriber' => home_url( '/my-account/' ),
);
foreach ( $user->roles as $role ) {
if ( isset( $role_destinations[ $role ] ) ) {
return $role_destinations[ $role ];
}
}
return $redirect_to;
}
The callback accepts three arguments because the filter provides both the current destination and the URL originally requested. The loop gives each known role a trusted internal destination and falls back to WordPress behaviour for unmapped roles. In the standard login flow, WordPress passes the returned value to wp_safe_redirect(), but the function should still return only URLs built with admin_url() or home_url(); never pass an unvalidated redirect_to value straight through.
Using capabilities for sensitive checks also prevents a role label from becoming a false security boundary. For example, manage_options is a better test for the main admin area than checking whether a string equals administrator.
Handle role and user exceptions
The simple map overrides a requested destination. Most installations need a default role map and a small set of trusted exceptions that can be applied in code.
Common role destinations
- Administrators begin in the Dashboard, where site configuration remains available.
- Editors and authors begin on the Posts list, reducing the number of clicks to their work.
- WooCommerce shop managers begin with Orders or Reports.
- Customers and subscribers begin on a working My Account page.
Useful routing exceptions
- Keep a requested redirect only after validating it with
wp_validate_redirect( $requested_redirect_to, $fallback ). - Send a customer to a specific order or subscription page when a trusted flow generated that URL.
- Give a custom staff role its own landing page while leaving unknown roles unchanged.
Users can occasionally hold more than one role, so the order of checks matters. The example follows the role order stored by WordPress, which is normally sufficient for a single-role account. If a membership plugin grants overlapping roles, define an explicit priority or use current_user_can() for the sensitive branch. Never let a query string choose the user’s destination, since that would let someone request a staff screen.
Protect redirects and Australian user data
Redirect targets are part of the site’s access controls. A customer should not be placed in an administrative URL, and an editor should not gain capabilities merely because the browser reached a convenient screen. Keep role mapping in code, keep authorisation in capability checks, and make sure the final destination is internal to the WordPress installation.
For organisations covered by the Privacy Act 1988, the Australian Privacy Principles still apply when a site handles covered personal information, even when the redirect itself only chooses a page. Avoid placing email addresses, order identifiers or other personal details in redirect parameters, and do not log full URLs containing such data. A role name may be recorded as a routing event, but it should not be treated as a substitute for access control.
For an Australian WooCommerce merchant, the customer landing page should still expose order history, invoices and required support information. That supports normal servicing obligations under the Australian Consumer Law, including keeping the records needed to discuss a product issue or consumer guarantee. Role routing should improve navigation without hiding the information a customer needs when contacting the business.
Australian customers commonly check an account from a phone while travelling between work, shops or appointments, so the redirected page should load cleanly on a small screen. Do not infer a role from an Australian city, IP address or local time zone; those values describe location, not authority. Assign access from the authenticated WordPress account instead.
Test every login path
Build a test matrix using real staging accounts for an administrator, editor, customer and any custom role. Sign in through the normal form and record the final URL, page title and visible menu. Repeat with a mobile viewport because a desktop dashboard can conceal a broken customer page or an oversized plugin screen.
Also test a login that includes a legitimate redirect_to value, such as a request to open an order. A role-based default should not erase a safe, intentional destination, while an unsafe external URL must never be honoured. Failed sign-ins, expired sessions and password resets should follow their normal paths and must not trigger the success filter.
Check WooCommerce and membership integrations separately. Create an order as a test customer, confirm that the account page shows it, and check that a shop manager can reach reports without encountering a role loop. Test one user holding several roles as well, because this exposes ordering errors that single-role accounts cannot reveal.
Troubleshoot plugin and theme conflicts
If the redirect is ignored, inspect active login, membership and security plugins before changing the hook. Many offer their own post-login settings, and two callbacks can compete for the same filter. Remove or reconfigure the duplicate behaviour, then confirm that the theme or snippets extension containing your function is active.
A redirect loop usually means the target page sends the browser back to login, the selected account lacks the required capability, or the My Account page itself triggers another redirect. Clear WordPress and browser caches on staging, disable object caching for the test session, and inspect the browser’s redirect chain. A cache can preserve an old Location response even when the PHP callback is correct.
Use wp_debug_log() sparingly to record the role, mapped destination and result without logging credentials or personal details. Increasing WP_DEBUG_LOG can expose PHP notices from an incompatible plugin, while the debug log is useful for separating a theme conflict from a server configuration problem. Remove temporary logging before launch.
Deploy the same way you tested: keep the child theme or must-use plugin, confirm that HTTPS and PHP versions meet the hosting provider’s requirements, and retest each role after updates. Membership plugins can rename or add roles, so revisit the mapping when the site’s user model changes. The finished flow then has one predictable server-side rule, a safe fallback and a destination suited to each authenticated account.