Skip to content

Instantly share code, notes, and snippets.

@mattattui
Last active November 17, 2023 13:55
Show Gist options
  • Star 11 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save mattattui/3006531 to your computer and use it in GitHub Desktop.
Save mattattui/3006531 to your computer and use it in GitHub Desktop.
Count online users
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
<title>Pinger test</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<h1>Online user counter</h1>
<p id="counter">Users online: <span id="userCount">loading…</span></p>
<script type="text/javascript" charset="utf-8">
$().ready(function (){
var token = '';
var pinger = setInterval(function (){
$.ajax({
cache: false,
data: {
token: token,
},
timeout: 2500,
type: 'GET',
url: 'pinger.php',
dataType: 'json',
success: function (data, status, jqXHR){
$('#userCount').text(data.userCount);
token = data.token;
}
});
}, 5000);
});
</script>
</body>
</html>
<?php
// Look for token
$token = (isset($_GET['token']) && preg_match('/^[0-9a-f]{8}$/', $_GET['token'])) ? $_GET['token'] : false;
if (!$token) {
$token = sprintf('%08x', crc32(microtime()));
}
// get current minute, build APC key
$quadrant = ceil(date_create()->format('s') / 15); // between 1-4
$previousQuadrant = $quadrant - 1 < 1 ? 4 : $quadrant - 1;
$key = 'pinger_'.$quadrant;
$previousKey = 'pinger_'.$previousQuadrant;
// get tokens for the last 30 seconds
$current = apcu_fetch($key);
$previous = apcu_fetch($previousKey);
if (!is_array($current)) {
$current = array();
}
if (!is_array($previous)) {
$previous = array();
}
// Add current token if not found
if (count($current) < 250 && !in_array($token, $current)) {
$current[] = $token;
apcu_store($key, $current, 31);
}
// Build return object: userCount, token
$output = array(
'userCount' => count($current) > 250 ? '250+' : count(array_unique(array_merge($current, $previous))),
'token' => $token,
);
header('Content-Type: application/json');
print json_encode($output);
exit;
@mattattui
Copy link
Author

Shows how many people are on the site "now". Accurate to about 30 seconds. Not for any page expecting more than about 250 concurrent visitors.

If you have multiple servers, this script (and maybe even this whole method) is not for you. You could switch to memcached, but if you have enough users to need more than one server, you probably don't want the extra traffic that this would create.

@dejurin
Copy link

dejurin commented Nov 11, 2015

Good solution, but I recommend use this with Crawler Detect that remove bots.

@andreadd
Copy link

Hello, can you help me?
My page doesn't work. It always shows "Users online: loading…"
https://www.andreadd.it/appunti/post-laurea/index.html

Thank you very much.

@ArtsyMedia
Copy link

Hello, can you help me?
My page doesn't work. It always shows "Users online: loading…"
https://www.andreadd.it/appunti/post-laurea/index.html

Thank you very much.

Same is happening for me.

@mattattui
Copy link
Author

@ArtsyMedia Sorry, this script is nearly 10 years old and… some things have changed! First, it relies on the APC PHP extension which has been replaced with APCU - you'll need to make sure that extension is installed, and then change the function calls apc_fetch and apc_store to the corresponding APCU equivalents apcu_fetch and apcu_store.
Secondly, the jquery dependency is very old. I haven't tried it, but a quick glance at the docs suggests that you can just replace the <script src="…"> tag with <script src="https://code.jquery.com/jquery-3.6.0.min.js" type="text/javascript"></script>.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment