WP Function to show current online users

Howdy!

I am creating a plugin that, in between other features, will show the number of current online users. However, there doesn't seem to be a build in WP function that can retrieve that info for me.

I have searched the web on this topic. However, there is a lot of references to plugins but no actually simple code example.

So, can anyone tell me, with the best coding practices implemented, how I will be able to create a function that displays the number of current online/logged in users?

Thanks a lot!
Sincerely,
Mika

  • Mika

    Hey Michelle.

    Thanks. You too! Maybe I will be able to join the WPMU team one day, so I can be in good (online) company everyday :wink:

    I ran through WP-UserOnline (https://wordpress.org/plugins/wp-useronline/installation/) and Quick Count's (https://wordpress.org/plugins/quick-count/) source code, however, since it is object oriented programming, I am a bit lost, as my main focus, at the moment, is procedural coding.

    So, I would love, if some brainy developer could help me out here (Hint to @Jose my favorite PHP developer!!) :smiley:

    I hope you've enjoyed your weekend Michelle!

    Cheers,
    Mika

  • Vinod Dalvi

    Hi Mika,

    To display current online users try adding the following code in the functions.php file of your child theme or add it in your site using any of the following plugins.

    http://wordpress.org/plugins/code-snippets/
    http://wordpress.org/plugins/add-actions-and-filters/

    function  user_online_update(){
    
    	if ( is_user_logged_in()) {
    
    		// get the user activity the list
    		$logged_in_users = get_transient('online_status');
    
    		// get current user ID
    		$user = wp_get_current_user();
    
    		// check if the current user needs to update his online status;
    		// he does if he doesn't exist in the list
    		$no_need_to_update = isset($logged_in_users[$user->ID])
    
    		    // and if his "last activity" was less than let's say ...1 minutes ago
    		    && $logged_in_users[$user->ID] >  (time() - (1 * 60));
    
    		// update the list if needed
    		if(!$no_need_to_update){
    		  $logged_in_users[$user->ID] = time();
    		  set_transient('online_status', $logged_in_users, (2*60)); // 2 mins
    		}
    	}
    }
    add_action( 'wp', 'user_online_update' );
    
    function display_logged_in_users(){
    	// get the user activity the list
    	$logged_in_users = get_transient('online_status');
    
    	if ( !empty( $logged_in_users ) ) {
    		echo "<br/><strong>Logged in users are as following :</strong>";
    			foreach ( $logged_in_users as $key => $value) {
    					$user = get_user_by( 'id', $key );
    					echo '<br/> Looged in user name is ' . $user->display_name;
    			}
    	} else{
    		echo "<br/><strong>No user is logged in.</strong>";
    	}
    
    }

    Then display current online users by calling the function display_logged_in_users as following wherever you want to.

    <?php display_logged_in_users(); ?>

    You have to wait at least two minutes to update the current user online status.

    Best Regards,
    Vinod Dalvi

  • Mika

    Hey Vinod,

    I have two questions:

    1. I have implemented your code and made a few modifications, so the number of current users is shown instead of their name. However, when I do a print_r to see the set_transient, I can at times see that two transient is set for one person, how come?

    2. Would it be smart to hook into the wp_logout function and delete the users transient when they logout? It would look something like this:

    function clear_transient_on_logout() {
    
    	$users_transient_id = get_transient('online_status');
    
    	if(is_array($users_transient_id)){
    		foreach($users_transient_id as $id){
    			delete_transient($id);
    		}
    	}else{
    		delete_transient($users_transient_id);
    	}
    }
    add_action('wp_logout', 'clear_transient_on_logout');

    (note that I added det is_array function to deal with the multiple transtits per person.

    Finally, sorry about all the questions, help me out here:

    When a user logs in to his website, a transient is set. 60 sec later, it expires and what happens then? Is a new transient created for that user automatically or?

    Thanks a lot!
    I really appreciate.
    Sincerely,
    Mika

  • Vinod Dalvi

    Hi Mika,

    Glad the code provided is also working for you :slight_smile:

    1. I have implemented your code and made a few modifications, so the number of current users is shown instead of their name. However, when I do a print_r to see the set_transient, I can at times see that two transient is set for one person, how come?

    I could also reproduce this on my test site and i found it's happening because i had used the hook "init" and didn't check the condition is_user_logged_in so i changed it to "wp" in my previous code adding the condition and it's working fine now.

    Please use this updated code and let me know how it's working for you.

    2. Would it be smart to hook into the wp_logout function and delete the users transient when they logout? It would look something like this:

    The wp_logout hook will not work here as we need to retrieve user ID who is looged out and delete his record from transient but we can achieve this using clear_auth_cookie hook as following.

    function clear_transient_on_logout() {
    
    	$user_id = get_current_user_id();
    
    	$users_transient_id = get_transient('online_status');
    
    	if(is_array($users_transient_id)){
    		foreach($users_transient_id as $id => $value ){
    			if ( $id == $user_id ) {
    				unset($users_transient_id[$user_id]);
    				set_transient('online_status', $users_transient_id, (2*60)); // 2 mins
    				break;
    			}
    		}
    	}else{
    		delete_transient('online_status');
    	}
    }
    add_action('clear_auth_cookie', 'clear_transient_on_logout');

    When a user logs in to his website, a transient is set. 60 sec later, it expires and what happens then? Is a new transient created for that user automatically or?

    When any user logs in then the transient is created which gets expired after 2 minutes but in the meanwhile if any user does any activity on your site which causes page refresh then the transient is updated extending its expiration time again for 2 minutes and it happens continuously.

    If any user doesn't do any activity with in two minutes then for non logged in users it will display the message "No user is logged in." until any user does any activity.

    You can change the timing in the code by using the appropriate value which suits your site need.

    Cheers,
    Vinod Dalvi

    • Mika

      Hey Vinod!

      Thanks a lot for your reply. It makes all very much sense!

      The only thing I need some clarification on is when you write:

      I could also reproduce this on my test site and i found it's happening because i had used the hook "init" and didn't check the condition is_user_logged_in so i changed it to "wp" in my previous code adding the condition and it's working fine now.

      What code did you exactly change with the "wp"? :slight_smile:

      I really appreciate your time!
      Sincerely,
      Mika

  • Vinod Dalvi

    Hi Mika,

    What code did you exactly change with the "wp"? :slight_smile:

    I have changed my previous code as following

    Before Editing :
    add_action( 'init', 'user_online_update' );

    After Editing:
    add_action( 'wp', 'user_online_update' );

    And you can see i have added the following condition in the function user_online_update as we don't need to do anything with the users who are not logged in.

    if ( is_user_logged_in()) {

    Cheers,
    Vinod Dalvi

  • Mika

    Hey Vinod,

    Thanks for the clarification.

    1. Let me try to clarify something to get a better understanding of the clear_auth_cookie () function:

    Whenever a user login, a session session is set for that user. Is that correct?
    If yes, is the session then destroyed when the user logout?
    If yes, is the clear_auth_cookie() function "activated" when the session is destroyed?
    And, if yes, do we then basically say: "When clear_auth_cookie is activated, then destroy the transiet"?

    2. When we use this function "function clear_transient_on_logout()" you add "set_transient('online_status', $users_transient_id, (2*60)); // 2 mins" right after you unset the transiet. By why? Isn't our purpose to remove the transiet? Can't seem to get my head around it.

    3. Finally (thank you so much for your patience with me), here is my current code:

    // Creates the new widget section to the administration dashboard, if the user has the administrator user role.
    add_action('wp_dashboard_setup', 'm1ka_online_users_widget');
    function m1ka_online_users_widget() {
    	if(current_user_can('manage_options')){
    		wp_add_dashboard_widget('m1ka_online_users', 'Users Stats', 'm1ka_online_users');
    	}
    }
    
    /****************************************
    	 Add Online User Count Function
    *****************************************/
    
    function  user_online_update(){
    
    	if ( is_user_logged_in()) {
    
    		// get the user activity the list
    		$logged_in_users = get_transient('online_status');
    
    		// get current user ID
    		$user = wp_get_current_user();
    
    		// check if the current user needs to update his online status;
    		// he does if he doesn't exist in the list
    		$no_need_to_update = isset($logged_in_users[$user->ID])
    
    		    // and if his "last activity" was less than let's say: 1 minutes ago
    		    && $logged_in_users[$user->ID] >  (time() - (1 * 60));
    
    		// update the list if needed
    		if(!$no_need_to_update){
    		  $logged_in_users[$user->ID] = time();
    		  set_transient('online_status', $logged_in_users, $expire_in = (2*60)); // 2 mins
    		}
    	}
    }
    add_action( 'wp', 'user_online_update' );
    
    function clear_transient_on_logout() {
    
    	$user_id = get_current_user_id();
    
    	$users_transient_id = get_transient('online_status');
    
    	if(is_array($users_transient_id)){
    		foreach($users_transient_id as $id => $value ){
    			if ( $id == $user_id ) {
    				unset($users_transient_id[$user_id]);
    				set_transient('online_status', $users_transient_id, (2*60)); // 2 mins
    				break;
    			}
    		}
    	}else{
    		delete_transient('online_status');
    	}
    }
    add_action('clear_auth_cookie', 'clear_transient_on_logout');
    
    // Adds the content to the widget section
    function m1ka_online_users() {
    
    	$logged_in_users = count(get_transient('online_status')); // gets number of logged-in users
    	$total_users = count_users(); // gets user info
    
       	echo '<div style="width: 48%; float: left; text-align: center;"><h1>';
       			_e('Total Users: ', 'm1ka_ouw');
       				echo $total_users['total_users'];
       	echo '</h1></div>';
    
       	echo '<div style="width: 48%; float: left; text-align: center;"><h1>';
       			_e('Online Users: ', 'm1ka_ouw');
       				echo $logged_in_users;
       	echo '</h1></div><div style="clear: both;"></div>';
    }

    I have added this code on a local WordPress installation with three users. I have logged in with two of the users in two different browsers. The only output I get is:

    Total Users: 3 Online Users: 1

    I can't seem to get my head around what the issue is (why both users isn't registered as online users)?

    Vinod, once again, thanks for all your patience and help!!! :slight_smile:

    Sincerely,
    Mika

  • aristath

    Hello again @Mika, I hope you're well today!

    Whenever a user login, a session session is set for that user. Is that correct?

    Correct.

    If yes, is the session then destroyed when the user logout?

    Correct again. :slight_smile:

    And, if yes, do we then basically say: "When clear_auth_cookie is activated, then destroy the transiet"?

    Not exactly... we say that when the user logs out, their ID should be removed from the array of logged-in users in the transient.

    2. When we use this function "function clear_transient_on_logout()" you add "set_transient('online_status', $users_transient_id, (2*60)); // 2 mins" right after you unset the transiet. By why? Isn't our purpose to remove the transiet? Can't seem to get my head around it.

    We don't want to remove the transient.
    The 'online_status' transient contains an array of logged-in user IDs.
    That transient should always be present. all we do is add and remove user IDs to the array of IDs in that transient.

    I just updated your code a bit, try using this:

    <?php
    
    /**
     * Creates the new widget section to the administration dashboard if the user has the administrator user role.
     */
    add_action('wp_dashboard_setup', 'm1ka_online_users_widget');
    function m1ka_online_users_widget() {
    	if ( current_user_can( 'manage_options' ) ) {
    		wp_add_dashboard_widget( 'm1ka_online_users', 'Users Stats', 'm1ka_online_users' );
    	}
    }
    
    /**
     * Runs on each page load.
     * If the user does not exist in the array in the 'online_status' transient, then add them.
     */
    function  user_online_update(){
    
    	if ( is_user_logged_in() ) {
    
    		// get the user activity the list
    		$logged_in_users = get_transient( 'online_status' );
    
    		// get current user ID
    		$user = wp_get_current_user();
    
    		// check if the current user needs to update his online status;
    		// he does if he doesn't exist in the list
    		// and if his "last activity" was less than let's say: 1 minutes ago
    		$no_need_to_update = isset( $logged_in_users[$user->ID] ) && $logged_in_users[$user->ID] >  ( time() - ( 1 * 60 ) );
    
    		// update the list if needed
    		if ( ! $no_need_to_update ) {
    			$logged_in_users[$user->ID] = time();
    			set_transient( 'online_status', $logged_in_users, $expire_in = (  2 * 60 ) ); // 2 mins
    		}
    	}
    }
    add_action( 'wp', 'user_online_update' );
    
    /**
     * Runs when a user logs out.
     * If the user exists in the 'online_status' array, remove them from there and update the transient.
     */
    function clear_transient_on_logout() {
    
    	$user_id = get_current_user_id();
    
    	$users_transient_id = get_transient( 'online_status' );
    
    	if ( is_array( $users_transient_id ) ) {
    		if ( $users_transient_id[$user_id] ) {
    			unset( $users_transient_id[$user_id] );
    			set_transient( 'online_status', $users_transient_id, ( 2 * 60 ) ); // 2 mins
    		}
    	}
    }
    add_action( 'clear_auth_cookie', 'clear_transient_on_logout' );
    
    /**
     * The contents of the widget
     */
    function m1ka_online_users() {
    
    	$logged_in_users = count( get_transient( 'online_status' ) ); // gets number of logged-in users
    	$total_users = count_users(); // gets user info
    
       	echo '<div style="width: 48%; float: left; text-align: center;">'
    	echo '<h1>' . __( 'Total Users: ', 'm1ka_ouw' ) . $total_users['total_users'] . '</h1>';
    	echo '</div>';
    
       	echo '<div style="width: 48%; float: left; text-align: center;">';
    	echo '<h1>' . __( 'Online Users: ', 'm1ka_ouw' ) . $logged_in_users . '</hi>';
    	echo '</div><div style="clear: both;"></div>';
    }

    I hope that helps!

    Cheers,
    Ari.

  • Mika

    Hey Air.

    Thanks for the clarification :slight_smile:

    I tried to updated the code. Here was my process:

    1. I logged in with one user and it said: Total Users: 3 Online Users 1
    2. I logged in with a second user and it said: Total Users: 3 Online Users 2
    3. I logged in out with the second user and it said: Total Users: 3 Online Users 1
    4. I logged in with the second user and it said: Total Users: 3 Online Users 1
    5. I logged in with third user and it said: Total Users: 3 Online Users 1

    No quite sure why I hit this wall?

    Sincerely,
    Mika

  • aristath

    Hello again!

    Could you please grant us access to your backend so that we may see exactly what is happening?
    To do so, from your dashboard go to WPMUDEV => Support => Support Access and click on the "Grant access" button.

    Please note that you must have the WPMU DEV Dashboard plugin installed on your site to complete the above process.
    Also I may need to install this plugin in order to experiment with the code and try to fix it: https://wordpress.org/plugins/wpide/

    Where exactly have you added that code? (which file)?

    Please advise,
    Ari.

  • aristath

    Hello again @Mika,

    I just logged-in on your site and took a look at your code and what happens on the dashboard.
    Unfortunately I was unable to figure this one out for you, and so was Vinod.

    I'm afraid this requires a lot more custom coding that what we can provide through these forums.

    If you need further assistance with this, then you can always post a new job on our Jobs Board on https://premium.wpmudev.org/wordpress-development/ so that a skilled developer can do that for you.

    Cheers,
    Ari.

  • Jose

    Hey there Mika,

    Hope you are doing fantastic :slight_smile:

    Ari is right about this being beyond our scope unfortunatelly. Nevertheless, I would love to see this sorted.

    I'm following the thread from the beggining, and my first thought was our Chat plugin.
    It implements the neccesary logic to know if other users are online or not, so I guess it would be useful for you to take a look into the code and maybe grab some ideas from there. :wink:

    Hope this helps!

    Cheers,
    Jose

Thank NAME, for their help.

Let NAME know exactly why they deserved these points.

Gift a custom amount of points.