1

I simply want to show green circle after username if user is online and nothing if user is offline.

I've found this 5 years old question but both of the ideas seems bad because I've been told than setting transients often is rather expensive and also constant database update seems like a bad idea.

Has there been any changes? Is there a better way to check if (not current) user is online?

How come there's a simple function is_user_logged_in() for current user but there's still no way to check for others? Isn't there some kind of flag or something?

2 Answers 2

5

WordPress doesn't track if a user is online. It can only know if the current is online, which is always yes ( else there would be no request ). If you want to know if a different user that isn't the current user is online, that information doesn't exist, and you'll need to implement it yourself.

is_user_logged_in checks if the current user is authenticated aka logged in, it's not a test if a user is online

In order to do this you're also going to have to make compromises, and realtime online or not status tracking is not something you can do solely within WordPress.

Your options include:

  • Updating a timestamp every time you access a page in user meta, then using that timestamp as a test ( aka if a users timestamp is within the last 5 minutes consider them online ), have an AJAX call ping your site to refresh the timer. Note that if the user closes their browser just after loading a page, they'll still show online for 5 minutes, and there's a performance cost to doing this, it will not scale with traffic
  • Having a flag that indicates a user is online, and setting it to true when a user hits any page. Have a cron job that sets all flags to false at regular intervals. This will be cheaper to query on, but it's more expensive to run. You can make it less expensive by increasing the time delay of cron jobs, thus reducing accuracy. This still makes logged in users more expensive as every page load includes a database write. It will not scale with traffic.
  • Use an external service and set up a Heroku/Simperium/Node server that's independent of WordPress and tracks online state. How you would do this is beyond the scope of this site as you're moving into other areas of expertise outside of WordPress. This is the most complex and expensive option, but it does mean your WordPress install is not adversely impacted. It does mean that the online presence data is unavailable in WordPress itself, you will not be able to query unless you build mechanisms to do so which will be expensive. The code that makes the icon green will need to be in javascript on the browser. The worst case scenario here however is that your presence logic fails as your external server buckles under load, but your WordPress site no longer has DB writes on every page load, and your site scales better with traffic than the other options

Overall, what you're asking for is non-trivial, and while sounding simple, will either be very performance heavy, inaccurate, or require an additional server and development time. There is a trade off.

Also, any solution you devise that runs in PHP will necessarily mean that you can no longer do full page caches unless the online offline functionality is powered by javascript. Otherwise, if you show someone as online and your pages are cached for 24 hours, they'll still be online for the following 24 hours. If you use either of the first 2 options I presented, you'll also be unable to use caching for logged in users, and tools such as batcache or Varnish will break your system if applied to those users unless an uncached AJAX based system is used to indicate that someone is online

Will this change in the future? No, WordPress doesn't handle this kind of functionality or store this kind of data. WordPress does track sessions in user meta, but this is not the kind of data you are looking for. This may indicate how many devices a user has logged in on, but it's by no means reliable, and it can't be used to give an online or offline indicator

0

I know this is an old question, but here is what I've developed using WordPress token sessions.

First of all, I've developed a function that update timestamp of current session. If I access to a web page where I'm connected, login timestamp and expiration timestamp are updated (login to current timestamp)

add_action('init', function() {

    $sessions = get_user_meta(get_current_user_id(), 'session_tokens', true);

    $session = $sessions[hash('sha256', wp_get_session_token())];

    $duration = $session['expiration'] - $session['login'];

    $sessions[hash('sha256', wp_get_session_token())]['login'] = current_time('U');

    $sessions[hash('sha256', wp_get_session_token())]['expiration'] = current_time('U') + $duration;

    update_user_meta(get_current_user_id(), 'session_tokens', $sessions);

});

After this, I calculate time passed after user login in actives sessions.

If this time between current and login is less than 5 minutes, I think user is "online". If this time is between 5 and 20 minutes, I think user is "away".

function is_user_online($user = null) {

    if (is_null($user)) {
        $user = get_current_user_id();
    }

    $session_time = false;

    $sessions = get_user_meta($user, 'session_tokens', true);

    foreach ($sessions as $session) {

        $time = current_time('U') - $session['login'];

        if ($time == false || $time < $session_time) {
            $session_time = $time;
        }

    }

    if (is_numeric($session_time) && $session_time <= 1200 && $session_time > 300) {
        $session_time = 'away';
    } else if (is_numeric($session_time) && $session_time <= 300) {
        $session_time = 'online';
    } else {
        $session_time = false;
    }

    return $session_time;

}

I've also modified session life. 1 hour for normal and 7 days for "remember me".

add_filter('auth_cookie_expiration', function($seconds, $user_id, $remember){

    if ($remember) {
        $expiration = 7*24*60*60;
    } else {
        $expiration = 60*60;
    }

    if (PHP_INT_MAX - time() < $expiration) {
        $expiration = PHP_INT_MAX - time() - 5;
    }

    return $expiration;

}, 99, 3);

With this solution you can't know if user is online at real time but I think is a great solution :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.