Display online Users on WordPress

Earlier today I ran into a problem where I needed a simple way to display which registered users are online right now on the site.

I've done a Video explaining what was my solution and how to apply it to a theme, but I myself hate when I see a video without any code that I can easily take a look at, so below the video you will find a explanation of the code step by step, and in the end the plugin I created for this purpose.

Please note that I will comment further the code on the video, but there are some comments on each one of the snippets here


Variables used

We will use only two variables on this plugin:

  • static protected $_instance = null; -- Holds the static instance of our class after the plugin is initialized
  • static protected $prefix = 'OnlineNow'; -- Prefix we will use on the Database Options

Class Instance handling

When dealing with plugins in WordPress a good practice is to save a static variable of the main class on a private/protected variable and create a static method to instantiate the class whenever you call this method the first time:

static public function instance(){
    null === self::$_instance and self::$_instance = new self;
    return self::$_instance;
}

Plugin Initialization

Here is where our plugin will hook into WordPress and do the required actions to allot this plugin to work as we expect.

static public function init(){
    // Lock this class to be initialized only once
    if ( null !== self::$_instance ){
        return false;
    }
    add_action( 'wp_login', array( self::instance(), 'login' ), 10, 2 );
    add_action( 'clear_auth_cookie', array( self::instance(), 'logout' ), 10 );

    // Register Shortcodes
    add_shortcode( 'online:list', array( self::instance(), 'shortcode_list' ) );
    add_shortcode( 'online:qty', array( self::instance(), 'shortcode_qty' ) );

    add_filter('widget_text', 'do_shortcode');

    return true;
}

Register when a User logs in

We need to register when a user do the login so that we can save it in the database to grab this value and display for the users.

public function login( $user_login, $user ) {
    $users = get_option( self::$prefix . '-users', array() );

    if ( in_array( $user->ID, $users ) ){
        return;
    }

    $users[] = $user->ID;

    update_option( self::$prefix . '-users', $users );
}

Register when a User logs out

Just like when we register the action of login and add the user ID to the database option, now we will remove that ID when the user logs out.

public function logout() {
    $users = get_option( self::$prefix . '-users', array() );

    $user_id = get_current_user_id();

    if ( ! in_array( $user_id, $users ) ){
        return;
    }

    update_option( self::$prefix . '-users', array_diff( $users , array( $user_id ) ) );
}

Grab the users logged in

We need a method that will allow us to get the users from the database option, I've also allowed the developer to exclude or include a user to the list.

public function get_users( $include = array(), $exclude = array() ){
    // Retrieve the users from Database
    $users = get_option( self::$prefix . '-users', array() );

    // Parse Shortcode atts to exclude
    if ( is_string( $exclude ) ){
        $exclude = array_map( 'trim', explode( ',', $exclude ) );
    }

    // Exclude users based on shortcode attribute
    $users = array_diff( (array) $users, (array) $exclude );

    // Parse Shortcode atts to include
    if ( is_string( $include ) ){
        $include = array_map( 'trim', explode( ',', $include ) );
    }

    // Include users based on shortcode attribute
    $users = array_merge( (array) $users, (array) $include );

    // Garantee that the array is safe for usage
    $users = array_unique( array_filter( (array) $users ) );

    // Remove all non existent users
    $users = array_map( array( $this, 'user_exists' ), $users );

    // Garantee that the array is safe for usage
    $users = array_filter( (array) $users );

    return $users;
}

Then I used a method inside of the get_users to check if the user exists before return the list of WP_User objects - on video.

public function user_exists( $user_id ){
    $user = new WP_User( $user_id );

    // Check if the users exists
    if ( ! $user->exists() ){
        return false;
    }

    return $user;
}

List Online Users Shortcode

After we did all the hard work of storing the data about user on the database, now we will use that information to print an HTML with the list of users that are currently online.

public function shortcode_list( $atts ) {
    $atts = (object) shortcode_atts( array(
        'avatar' => false,

        'exclude' => '',
        'include' => '',
    ), $atts );

    $users = $this->get_users( $atts->include, $atts->exclude );

    $html = '<ul class="users-online">';
    foreach ( (array) $users as $user ) {
        $html .= '<li>';
        // Allow the user to control the avatar size and if he wants to show
        if ( is_numeric( $atts->avatar ) ){
            $html .= get_avatar( $user , $atts->avatar );
        }
        $html .= '<span>' . $user->display_name . '</span>';
        $html .= '</li>';
    }
    $html .= '</ul>';
    return $html;
}

Display the quantity of Users Online

The user might also want to display the quantity of users that are online with a shortcode, so we will deal with that too.

public function shortcode_qty( $atts ) {
    $atts = (object) shortcode_atts( array(
        'plural' => __( '%s users online', 'online-now' ),
        'singular' => __( 'One user online', 'online-now' ),
        'zero' => __( 'Zero users online', 'online-now' ),

        'numeric' => false,

        'exclude' => '',
        'include' => '',
    ), $atts );

    $users = $this->get_users( $atts->include, $atts->exclude );

    if ( $atts->numeric ){
        return count( $users );
    }

    if ( count( $users ) === 0 ) {
        $text = $atts->zero;
    } elseif ( count( $users ) === 1 ) {
        $text = $atts->singular;
    } else {
        $text = $atts->plural;
    }

    return sprintf( $text, count( $users ) );
}

Repository and Download

You can always checkout the oficial repository for this plugin and/or download the latest version of the code to install it in your WordPress.

Discussions — 36 Responses

  • Achoron January 11, 2015 on 3:17 pm

    I have installed the plugin onto my site as is and added the shortcode [online:list avatar='16'] but it displays nothing. What exactly do I have to edit within the plugin for it to show the users? I am using wordpress 4.1

    Reply
    • Gustavo Bordoni Achoron January 11, 2015 on 7:54 pm

      Hi Achoron, It will depend on which place you've added the shortcode. You've installed the plugin and activated it correct?

      Reply
  • Rez January 15, 2015 on 10:08 pm

    Thank you, add this to wordpress plugins, youd think somebody would have soomething working by now like this geez

    Reply
  • hypermediaz March 3, 2015 on 6:14 pm

    Hi Gustavo, I installed and activated the plugin as you described. I want to display the online users in the sidebar of the main page. I added a text box with the shortcode [online:list avatar='16'] but it does not display anything. Can you please clarify the process to make this work. I am using WordPress 4.1. Thanks for the help.

    Reply
    • Gustavo Bordoni hypermediaz March 7, 2015 on 4:28 pm

      Hi Hypermediaz, It will only track the users that logged in and out while the plugin is active.

      To see yourself on the list you would have to log-out then login again.

      And I updated the code to allow a message when there is no users online available.

      Reply
      • hypermediaz Gustavo Bordoni March 10, 2015 on 11:41 am

        Hi, thank you very much for the help. Have a nice day.

        Reply
  • beda69 June 13, 2015 on 2:24 pm

    Hey :) I understand this does not list ONLINE (ACTIVE) users but LOGGED IN users. Correct? It's somehow a difference to really ONLINE status (a user might never logout but also not be online)

    Reply
    • Gustavo Bordoni beda69 June 14, 2015 on 11:33 pm

      Hi Beda69, you are 100% correct, I might improve the plugin with something cool from your suggestion.

      Create some sort of "timeout" after the login an the user is no longer active on the Website.

      Thanks for the answer.

      Reply
  • Joel James August 5, 2015 on 9:10 am

    What if they did not logout and left the site? It will show wrong count right?

    Reply
    • Gustavo Bordoni Joel James August 6, 2015 on 8:46 am

      As I replied for beda69 above that's 100% correct, I will implement a filterable timeout to allow that number to be accurate.

      Reply
  • Nick034 August 25, 2015 on 12:57 pm

    Hello..this look great if can work with latest wp..when I activate this plugin what code I need to add to my author.php theme file to get user online/offline status next to name?

    Reply
    • Gustavo Bordoni Nick034 September 19, 2015 on 11:09 am

      After you activate the plugin you will only need the to call for the Shortcode on a Page, on in your case on the author.php file, you can call the method directly, like the following:

      $online_users = OnlineNow::instance()->get_users();
      
      // This will hold if the Author is online
      $status = in_array( the_author_meta( 'ID' ), $online_users ); 
      Reply
  • Nick034 August 25, 2015 on 1:06 pm

    In official wp plugins directory there is plugin wp-recall,he has good online/offline status for register members but I don't need that whole plugin for my site just that code for online status..can you make something like this?

    Reply
    • Gustavo Bordoni Nick034 September 19, 2015 on 11:10 am

      Sorry if I didn't understand your question, can you explain a little bit further?

      Reply
  • Rob October 16, 2015 on 11:30 am

    Thanks for a good tutorial and the user friendly coding! Im trying to use this plugin to display when a certain user type is online, say "subscribers". Is there a fairly simple way to do that?

    Reply
    • Gustavo Bordoni Rob October 16, 2015 on 1:17 pm

      Hi Rob,

      To do that you would need to change the code after the line#191:

      foreach( $users as $key => $user ) {
          // Check if the user is not something then unset it
          if ( ! in_array( 'subscriber', $user->roles ) ) {
              unset( $users[ $key ] );
          }
      }
      
      // This will reset the keys after removing non-wanted users
      $users = array_values( $users );

      Hope this helps.

      Reply
  • tzeby1Sebastian October 29, 2015 on 2:48 am

    Helo, thank you for this great plugin, how I can check if the user is online in a normal get users loop? or a normal wpdb get_results loop? I supose it needs to be smth like this, is_user_online($user_id); ? I`m getting undefined function is_user_online(); Thank you

    Reply
    • Gustavo Bordoni tzeby1Sebastian October 29, 2015 on 9:15 am

      Hey Tzeby1,

      First if you can check the version of the plugin you are using, it should be 0.2.1 for the following code to work.

      You can use the function called is_user_onlinenow:

      if ( is_user_onlinenow( $user_id ) ) {
          // User is Online
      } else {
          // User is not Online
      }
      Reply
      • Joan Gustavo Bordoni December 20, 2015 on 3:23 pm

        Hello Gustavo, Thank you for this pluggin. I activated it (version(0.2.1)) but i can't use the function is_user_onlinenow(). It did'nt recognize other connection I use it in localhost with different browser for each connection. Thank you for reply

        Reply
      • Gustavo Bordoni Gustavo Bordoni December 20, 2015 on 6:16 pm

        It will only recognize if you are logged in on a user, if you were logged with other users on other browsers and it still didn't show, then you found a bug that I will try to reproduce and fix. Let me know.

        Reply
  • Joan December 22, 2015 on 7:59 am

    Hi, I change the code for my case. it's not really proper, but for me it works. In my case, $user->iD was not recognize in $users

    public function is_user_online( $user = 0 ) {
            $user = $this->user_exists( $user );
    
            if ( ! $user ){
                return false;
            }
            $users = $this->get_users();
            /*echo "";
            print_r( $users);
            echo "";echo $user->data->ID;*/
            $liste_u=array();
            foreach($users as $u)
            {
                $liste_u[]=$u->data->ID;
            }
            /*print_r($liste_u);
            if( in_array( $user->data->ID, $liste_u )) echo "in array";die();
            return in_array( $user->ID, $users );*/
            return in_array( $user->data->ID, $liste_u );
        }

    Thanks for the quick answer and the good job ;)

    Reply
  • Gustavo Bordoni December 22, 2015 on 8:21 pm

    Ahh Now I know what happened, I will fix the code on the plugin, thanks for the report man.

    Reply
  • Phillip April 9, 2016 on 7:57 pm

    Hi Gustavo, first of all great plugin. one issue I noticed though was that custom local avatars are not supported. I'm using Advanced Custom Fields to set up custom local avatars using this code: https://gist.github.com/ControlledChaos/cd6558219cfbc0a75d6f however the plugin only displays the default avatar of a user. Is there a section of code I can alter to display the local avatars? Thanks in advance.

    Reply
    • Gustavo Bordoni Phillip April 19, 2016 on 9:58 am

      Hi Phillip,

      Sorry for the delay on my answer, the code should be able to get custom avatars if the method is using the required.

      I will be sure to make tests with the Code you provided me on your comment. I should release a new version of the plugin next month.

      So we will see how it goes.

      My Best Regards,

      Reply
  • paulmellish April 18, 2016 on 2:33 am

    How easy would be be to turn this upside down and show users of a certain role that are not online?

    I have created 4 dummy accounts using a custom 'role' for customers to use as a demo, if an demo account is is use then the link would disappear.

    Reply
    • Gustavo Bordoni paulmellish April 19, 2016 on 10:02 am

      Uhnn I like the Use-case. I will send you an email about this and we will make this happen.

      I want to turn this into a new Article for the blog ahaha.

      Reply
  • Jonas April 19, 2016 on 5:30 am

    This is so confusing :(

    I activated the plugin, now what? what is the shortcode?

    Reply
    • Gustavo Bordoni Jonas April 19, 2016 on 9:55 am

      Im so Sorry Jonas, the plugin was supposed to be coupled with the Video as a "teaching" tutorial.

      Basically after installing you will have access to a few Shortcodes:

      • [online:list] - That should give you a list of users online
      • [online:qty] - That should give you a number, which is the quantity of users online

      Let me know if I can help you in any way.

      Reply
      • Jonas Gustavo Bordoni April 19, 2016 on 1:20 pm

        Oh thanx for your quickly response. Well i have another question.

        I tried something like this....

        But shows an error....

        Warning: strpos() expects parameter 1 to be string, array given in C:\wamp\www\crazyviral\wp-includes\shortcodes.php on line 205

        I found a possible solution, change this -- if ( false === strpos( $content, '[' ) ) { -- for this -- if ( false === strpos( (string) $content, '[' ) ) { --

        The error message disappeared, but only shows a text "array".

        Any hint?

        Reply
        • Gustavo Bordoni Jonas April 23, 2016 on 4:32 am

          Hi Jonas,

          After taking a good look at could possibly be doing this, Im almost sure this is a conflict been raised by another plugin you have active, because this is Core Behavior.

          If you can, try deactivating your all the other plugins and switching to one of the WordPress default themes for testing purposes.

          When deactivating do it one by one so you can know the source of the problem.

          This will allow you to have a clean environment. After that let me know how thing go.

          My Best Regards,

          Reply
          • Jonas Gustavo Bordoni April 26, 2016 on 4:58 am

            Hi Gustavo, its me again.........LOL.

            Well i finally made the plugin works and its great!!! just exactly what i was looking for.

            So, i have other questions if you could help me.

            1.- In my blog, there are 5 authors/contributors, and each one of them publishes just one post. So, how can i show a link to his post using 'online:list' shortcode?

            2.-Theres a div which is auto refresh by javascript any certain time, inside the div theres an include 'online.php in that file i inserted the shortcode. But show an error message ...Fatal error: Call to undefined function do_shortcode() in.....

            3.-How can i create another shortcode to show only the authors name when someone enters to his post?

            Sorry for bother so much.

          • Gustavo Bordoni Gustavo Bordoni May 3, 2016 on 6:17 pm

            Hi Jonas,

            So, basically to auto-refresh after some time you will need to use an AJAX request that should be created using WordPress methods (check the article), it's not a simple process but after checking that article you can do a little bit more research on google to get more info on AJAX requests on WordPress.

            This Call to undefined Function is due to not including WordPress before trying to execute your PHP file, which using WP ajax will solve.

            To be able to display a link you would have to craft a custom shortcode that that would be a "duplicate" of what I did on the method shortcode_list but with a WP_Query to check for the latest Post that this author has published. (You can also check on google how to do that)

            To create a new Shortcode you just need to duplicate the method and change it's name, and duplicate the shortcode initialization on the beginning of the code:

            add_shortcode( 'online:list', array( self::instance(), 'shortcode_new_list' ) );

            Be careful to name everything correctly otherwise it won't work.

            Sorry for the late response, and my best regards,

  • Dave September 1, 2016 on 9:59 pm

    Great script! I'm trying to get it to show the most recent users online, in order of their activity. Is this possible at all with some variable you've set, or something I would need to create? If the latter, any tips on where to start?

    Cheers.

    Reply
    • Gustavo Bordoni Dave September 2, 2016 on 11:27 pm

      Hi Dave, I'm going to update this video and Article with a few new tricks to the Code.

      I like your idea, of improving the Ordering, but basically I would say that you would have to store more data to be able to do that.

      Sorry for not been able to help you now.

      Reply
      • Dave Gustavo Bordoni September 8, 2016 on 1:59 pm

        Gustavo, if you'd like to get in touch with me I'd be willing to pay for certain customizations. Cheers.

        Reply
  • Jagdeep singh November 22, 2016 on 8:20 am

    Hello thanks for this great plugin it solve my all problams . how can i get the all users list and then indigate the online and offline users with green or red sign,

    Thanks

    Reply

Leave a Reply