Redirect Non-Administrators After Login in WordPress

For more technical users or to skip the the background explanation, skip directly to the code.

When it comes to building themes or plugins in WordPress, you rarely want administrators, editors, subscribers, and so on to anything other than the dashboard just after they’ve logged in.

After all, these authors are usually loggin in to write posts, edit their information, or generally manage their content.

But if you’re building a more advanced theme or an application, then allowing users to view the dashboard may be outside the scope of what you’re looking to allow.

As such, here’s an easy to redirect non-admin users to another page after logging into WordPress. Note that this post was updated on December 13, 2012 thanks to the recommendations in Simon’s comment.

Understanding The Functions

Before actually taking a look at the function for redirecting users, there are two key functions that you need to be understood:

1. Getting The Site URL

Straight form the Codex:

The site_url template tag retrieves the site url for the current site (where the WordPress core files reside) with the appropriate protocol, ‘https’ if is_ssl() and ‘http’ otherwise.

In order to redirect the user to the homepage after logging into the application, we need to be able to direct them to the proper location of the application.

Generally speaking, the process will work like this:

  • Direct administrators to the dashboard (or /wp-admin/) to be exact
  • Direct all other users to the homepage

To do this, we can use the site_url() function in the following way:

  • admin_url();
  • site_url();

Easy enough.

2. Roles and Capabilities

Next, in WordPress, users have roles and there are five distinct roles each of which grant a user certain capabilities within the application.

The roles are:

  1. Administrator
  2. Editor
  3. Author
  4. Contributor
  5. Subscriber

You can read more about the distinctions between each of these roles on the Roles and Capabilities Codex article.

Whenever a user logs into WordPress, there is a filter that we have available: login_redirect. This particular function is used to change the location to which the user is directed after logging into WordPress.

At this point, we’ve got everything we need to setup a function to redirect non-admin users after login.

How To Redirect Non Admin Users After Login

The algorithm for doing this is simple:

  • If the user is an administrator, continue to admin_url()
  • Otherwise, redirect to, say the site_url()

The login_redirect filter will pass three arguments to the function:

  1. $redirect_to
  2. $request
  3. $user

We’re primarily concerned with the third as we can take a look at its roles attribute to determine if it contains the administrator value.

With that said, here’s the first pass at creating the conditional:

if( is_array( $user->roles ) ) {
	if( in_array( 'administrator', $user->roles ) ) {
	} else {

We can easily consolidate this into a ternary operation and convert it into a function:

 * Redirect non-admins to the homepage after logging into the site.
 * @since 	1.0
function acme_login_redirect( $redirect_to, $request, $user  ) {
	return ( is_array( $user->roles ) && in_array( 'administrator', $user->roles ) ) ? admin_url() : site_url();
add_filter( 'login_redirect', 'acme_login_redirect', 10, 3 );

And with that, we are now redirecting non-admin users to the website’s homepage rather then the dashboard.

73 Replies to “Redirect Non-Administrators After Login in WordPress”

  1. Just for the sake of nagging: The location of the /wp-admin directory depends on site_url() rather than home_url() doesn’t it? site_url( '/wp-admin' ) or even admin_url() instead of home_url( '/wp-admin' ) therefore would seem an itsy bit more safe to me. ;)

    1. Sure, sure – this is a good point and is honestly an easy mistake to make especially if you’re used to having your home_url and site_url be the same (which, of course, many people do not!

      I’ll update the post – thanks for reminding me!

      1. You should always use admin_url() instead of site_url( '/wp-admin' ) as it respects the protocol (http or https) as defined by the FORCE_SSL_ADMIN constant in wp-config.php

  2. I used to do the in_array() check for roles, then switched to current_user_can( 'role' )/user_can( 'role' ) and have been using those for awhile without problems (even $user->has_cap( 'role' ) says it should work).

    However, I just checked the Codex and there’s a newish update that says not to use roles with current_user_can(), although user_can() hasn’t been updated with a similar message. The inline code comments say roles are accepted, though. Strange. The Codex comment was added by Scribu, so I’m inclined to lend it credence. Here’s a relevant ticket.

    I wish that would get ironed out or a new $user->has_role() method were added, but in the meantime, it appears the in_array() check might be best. This is gonna bug me now; thanks Tom.

    As for the redirect, an approach I’ve taken that prevents users without the right capability from accessing the dashboard even if they type the URL in directly is to just hook into an action early in the page life cycle, check is_admin(), make sure its not an AJAX request, then do the role checking and redirect if necessary.

    1. I *think* that advice is on there because a role names have no inherent meaning to WordPress – they’re just labels. So you can have an admin with the capabilities of a contributor and vice-versa. If I’m right, its just a security measure when distributing plug-ins when you don’t know a priori who has what capabilities. Of course, in this context it arguably makes sense to use ‘administrator’ rather than `manage_options`.

      1. Thanks Stephen, that make sense. I’ve always used capabilities for plugins that might be distributed just because checking roles in that context doesn’t make sense, but it’s nice to know current_user_can( 'role' ) should work when the roles are known. I suppose a custom ‘access_dashboard’ capability could be added for this scenario as well and role checking could be eliminated.

  3. Hi,

    I’m trying to use your code on a test project but I keep getting a weird message over the login form that reads:
    Notice: Undefined property: WP_Error::$roles in /Users/roberto/Sites/Wordpress-pt-BR-RELOADED/wp-content/themes/viewportindustries-starkers-4.0/functions.php on line 228

    Line 228 contains this code I copied from your tutorial:
    return ( is_array( $user->roles ) && in_array( ‘administrator’, $user->roles ) ) ? admin_url() : site_url();

    1. As best as I can tell, you’ve pasted the code into your theme’s functions.php and WordPress is returning a problem with the $user object.

      In fact, from what it looks like, it’s not actually getting an instance of a user – instead, it’s getting an instance of WP_Error which means something else is going wrong earlier in the code.

      Hope this helps!

      1. I really can’t figure out what’s wrong. I removed all other code from functions.php but still get the error. Has everyone used the code with this issue?

        1. Right now, the best thing to do is to debug the arguments coming into the function and make sure nothing is null.

          The easiest way to do this is to add this line as the first line of the function:

          print_r( func_get_args() );

      2. I picked up this code, have been using it, and also appreciate it.

        But I also ran into the “Undefined property: WP_Error::$roles” issue reported above. Did some digging on that, and finally realized that the error was getting generated when the user logs out from the site. I changed my function to look like this, and the errors went away:

        function mysite_login_redirect($redirect_to, $request, $user)


        if (!isset($_GET[‘loggedout’]))


        return (is_array($user->roles) && in_array(‘administrator’, $user->roles)) ? admin_url() : site_url();



        add_filter(‘login_redirect’, ‘mysite_login_redirect’, 10, 3);

        1. i know this is pretty stale, but i fixed this issue by changing the operation slightly:

          return (isset($user->roles) && is_array($user->roles) && in_array(‘administrator’, $user->roles)) ? admin_url() : site_url();

          the isset check is also in the WP codex for the login_redirect

  4. Well written Tom!

    I created a custom form outside the WordPress theme template, added “redirect_to” hidden field, and pointed to /wp-login.php. I found lots of flaw after implementation and I found the solution in your code.

    Thank you for sharing.

    1. Yeah – there are a lot of problems where hidden fields can cause some dangerous side effects especially if the user is comfortable enough with the browser console and JavaScript :).

      They have their place, for sure, but I’m glad to know this helped you out – thanks for the comment!

  5. THANK you for this! I have been having trouble getting to my dashboard after logging in ever since I updated to WP 3.5.1 – it kept sending me to the homepage (which is silly because as the admin, I login to do work, not to read my site)…….putting your code in my functions.php file did the trick!

    NOW how do I also redirect to the dashboard for editors? Something as simple as:

    ~return ( is_array( $user->roles ) && in_array( ‘administrator”editor’, $user->roles ) ) ? admin_url() : site_url();~

    Should there be a common in between the two roles?

      1. Well that worked but gave me a warning message (didn’t stop it from working but just displayed this at the top):

        Warning: in_array() []: Wrong datatype for second argument in ….[my path to/functions.php line..]

        SO I did this instead:

        in_array( ‘administrator’ || ‘editor’, $user->roles )

        And that also worked without generating the warning message.

        Thanks again for this post – I found it VERY helpful!!

  6. Thanks Tom… just what I was looking for. I’m using wordpress to handle a site that is only partly a blog and so I need to handle login specially. You gave me some useful info and explained it well… Thanks! jas…

  7. Hello,

    if we have several roles to redirect might be better to use something like

    if ( count( array_diff( $user->roles, array( 'administrator', 'editor', 'author', 'contributor' ) ) ) !== count( $user->roles ) )

    for comparing two arrays, so we don’t have to use multiple OR ||.

    Thanks for the post!

  8. I did it a little differently…I wanted ONLY subscribers to be redirected to the home page after logging in, so I changed line 7 to:
    return ( is_array( $user->roles ) && in_array( 'subscriber', $user->roles ) ) ? site_url() : admin_url();
    It works, but does that seem correct? I’m hoping this won’t break anything. :)

  9. Good stuff … could you modify this code to send people to a specific page, instead of the homepage. I’m working on a membership site, and after a member (non-admin) logs in, I’d like to send them to a “member dashboard” page I have setup. …
    p.s. I’m not a php programmer … :-)

  10. While in development, I wanted visitors to log in to view the site. This worked easily, redirecting subscribers from the default Profile page and giving editors access the tools they need to work on content.

  11. The error everyone is finding is due to the $user variable not being defined and taking on the WP_Error class.

    Instead of checking is_array( $user->roles ) you should check if it’s set and in an array.


    isset( $user->roles ) && is_array( $user->roles ) […]

    I’ve also just released a simple plugin to manage Login Redirects inside WordPress on

  12. That’s great BUT what happens when the logged in user wants to change their password? They are also redirected…

    The purposes of the redirection should be login -> When logging in, I want to go to the place that I’m actually logging in to see… I also want flexibility to update my password and user details as well…

    1. That’s still possible – rather than directing to one of the URLs defined in the code, you should be able to look at the referral URLs (or some of the query string values depending on the WordPress page) and just update the code accordingly.

  13. Hey Tom,

    This is pretty solid! I do have a question – I know to use a custom url for the non-admin re-direct it has to be an absolute url reference. for example: home_url(‘products’) – However, I have built user dashboards into my site that conveys private information. Each users’ dashboard url has been set up as SO – what I want to do with this function is to have the non-admin redirect function redirect the user a dynamic url that appends their username to the home_url.

    ideally I’d want to set up a variable for the username of the current and call it $username (which i’ve done for other functions) and then plug it into your function with home_url($username);, but of course, that has to be a direct link and won’t work with the dynamic plug that i’ve set up.

    Hopefully i’ve explained what I’m trying to do somewhat clearly – do you have any advice as to how to accomplish this?

      1. okay cool! That’s the first thing I tried and didn’t have any luck with it, but I’ll dig back in to it and see if I can get it to work.

        If I understand correctly, writing that function into the functions.php file will override any redirect functions that exist elsewhere, right?

        Thanks for your help!

        1. If I understand correctly, writing that function into the functions.php file will override any redirect functions that exist elsewhere, right?

          Not necessarily – if there is a plugin or another hook that’s ordered itself with a higher priority, then it could technically fire before yours such that yours is never actually hit.

  14. okay cool! That’s the first thing I tried and didn’t have any luck with it, but I’ll dig back in to it and see if I can get it to work.

    If I understand correctly, writing that function into the functions.php file will override any redirect functions that exist elsewhere, right?

    Thanks for your help!

    1. You should be able to get that information out of the $_REQUEST variables. By doing some proper sniffing and conditionals, you should be able to load the page just fine without any type of redirect loop.

    1. You’re need to look to see what the user role is; however, I’m more of a fan of using the function for current_user_can and then passing in one of the available capabilities.

      For example, if you could do something like this (in pseudo code):

      `if ( current_user_can( ‘edit_posts’ ) ) {

      // redirect here


  15. Wanted to send a quick note of appreciation for the code (and the ability to jump down right to it from the top). Thanks Tom.

    p.s. First time here… came from Google. You’re top result for “wordpress redirect subscriber after login”

  16. very good one …

    in case of increasing security I think it`s better to change the main URL of dashboards ( specially the admin panel) and use it as a argument in function .

    this article of yours was very helpful thanks for it…

Leave a Reply