Software, Development, and WordPress

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 ) ) {
		admin_url();
	} else {
		site_url();
	}
}

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 Comments

  1. Caspar Hübinger

    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. ;)

    • tommcfarlin

      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!

      • Simon Blackbourn

        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

        • tommcfarlin

          Good catch, Simon. Updating the post now and giving credit where it’s due!

  2. Edward Caissie

    Very nice bit of code … would make for a sweet little plugin.

  3. Brady Vercher

    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.

    • Stephen Harris

      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`.

      • Brady Vercher

        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.

  4. Ciprian

    Nice function, but after the user is redirected after logging in, if http://site.com/wp-admin is accessed, the dashboard is shown to the user.

    • tommcfarlin

      To handle this, you can just use is_admin() and current_user_can and then redirect based on the result of the conditional.

      • Roberto

        Tom,
        Could you please post here the code with this is_admin() and current_user_can option added?
        It would be perfect for what I want.
        Thanks.

      • HunterJones

        Interesting. How would you use these functions?

  5. Roberto

    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();

    • Tom McFarlin

      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!

      • Roberto

        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?

        • Tom McFarlin

          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() );

      • Barry Tuber

        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);

        • dan

          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

  6. Ron

    I agree, nice code, work fine. Thank you Tom.

  7. Yogi Liman

    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.

    • Tom McFarlin

      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!

  8. Trisha

    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?

    • Trisha

      Jeesh….obviously I meant “comma” (in between the user roles)….bad, bad keyboard. :-)

    • Tom McFarlin

      Close! You should be able to do something like this:

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

      And then you’ll be good to go.

      • Trisha

        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() [function.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!!

        • Tom McFarlin

          There you go – I was coding on the fly soI wasn’t sure what I provided would work as stated, but nice work :)

      • Andrea Reed

        Awesome! Just what I was looking for!! Thanks!

  9. Lisa

    THANK YOU. This saved me.

  10. Todd

    Thanks! This is useful. You saved me from making lots of mistakes.

  11. komal

    this one worked perfectly!

  12. jason

    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…

  13. Antonio

    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!

    • Tom McFarlin

      Sure thing, Antonio. Always welcoming alternative ways of doing these sort of things!

  14. Toure

    Interesting! Will probably use this, but to redirect user to own account page (user custom page) after login.

    • Tom McFarlin

      Awesome – yep, that’s one really useful way to take advantage of this.

  15. Thea

    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. :)

  16. Doug

    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 … :-)

  17. Pam

    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.

  18. The Frosty

    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.

    Example:

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

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

    • Tom

      Thanks for sharing this — big help, for sure :).

  19. Shannon

    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…

    • Tom

      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.

    • The Frosty

      Maybe you should create a front end profile page where users can manage their profile? I’ve got a plugin in the works for that on Extendd.com.

  20. Jon

    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 http://www.mysiteurl.com/username. 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?

    • Tom

      Assuming I understand your question correctly, wp_redirect should do exactly what you need.

      You may need to tweak the $location bit some with the proper URL and the given user’s username, but that should achieve it.

      • Jon

        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!

        • Tom

          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.

          • Jon

            I hadn’t really thought about the plugins – duh. Good call, thanks man!

  21. Jon

    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!

  22. Nadine Schmelter

    Many thanks for the detailed post . Great :-)

  23. sam

    What if I want to redirect users to the same page they came from when they logged in?

    • Tom

      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.

  24. Ryan

    Hi, this is exactly what I need, but I’m such a WordPress rookie. Within what file do you insert this code, do I just paste it into functions.php?

    • Tom

      functions.php is a fine place for it to go so long as you know what you’re doing (and what the code is doing :).

  25. Nick

    the theme I’m using has profiles with the users name at the end. How would I redirect to the appropriate profile?

    Thanks alot

    • Tom

      This is a bit outside the scope of this particular article, so I’m afraid there’s not much I can do to help with this right now.

  26. Justin

    I believe you have a syntax error:

    if( is_array( $user->roles ) {

    if you left out a ) closing parenthesis. so it should be

    if( is_array( $user->roles ) ){

  27. telemarker

    hey tom,

    nice function, works!

    what is the code for always redirecting no matter what user role?

    thanks thomas

    • Tom

      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

      }`

    • Tom

      Just do a wp_redirect to the site_url() once the login process has completed.

  28. Keith Lock

    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”

    • Tom

      Glad it was helpful, Keith – thanks!

  29. Evintel

    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

© 2020 Tom McFarlin

Theme by Anders NorenUp ↑