File Under: Blog Publishing

How Many Users Are on Your Site Right Now

Hello, readers. You seem to be sending me a lot of e-mail lately. Fortunately, my spam sorter takes care of most of it, but a substantial stream of questions and comments keeps pouring in, inscrutable character sets and all. I wish they were all as eloquent as this one:

Paul Loved your articel! I have a few question. 1 How to setup? thanks.. derek meatburp

…but lately there have been more than a couple asking how to implement what’s apparently a very desirable feature — a little display of how many users are currently accessing a site. Of course there are dozens of pre-packaged scripts to do this, but, just because I love you all, let’s take a walk through a couple of ways to build this sort of feature from scratch. We’ll use PHP, the popular and friendly scripting language, for our examples.

Contents

  1. Tracking “Uniques”
  2. Using Session Data
  3. Keeping a Tally by Hand

Tracking “Uniques”

The basic principle behind this sort of feature requires keeping a tally of unique site visitors. Because there’s no real way to tell when a user has left the site, our shortcut is to assume that anyone who loaded a page within a particular time window — say, the last 60 seconds — is ostensibly still on the site, and hence is one of our Users Online. So all we have to do is grab the total tally for the last minute and display it, and we have our much-requested feature.

The question is, how do we get this tally? There are a few possibilities.

Using Session Data

If you’re smart and lucky enough to be working on a site that already uses nicely configured PHP sessions, our work is easy. Sessions, by their very nature, keep track of who’s using the site, in order to maintain state data about what they’re doing.

PHP creates a temporary file for each session it created. In the simplest case, if your site is set up to initiate a session for each user, and if no other process is using the directory PHP is using for its session files, counting users is as simple as counting the files in the session directory. However, chances are, your setup isn’t quite that simple. If multiple sites are hosted on the same web server, and PHP is configured to put all its session files into the same temp directory, you’ll be counting everyone’s users, not just your own. So a little configuration is necessary.

The function session_save_path() controls the session save path. Hard to guess, I know. If this function isn’t called, the path is assigned by the session.save_path directive in the master php.ini file (to which you may or may not have access), and defaults to /tmp. Either change the relevant php.ini line to point to a nice dedicated (and secure) directory:

  session.save_path = /my/special/session/directory

or specify it in the PHP code before the session_start() directive:

 session_save_path("/my/special/session/directory");

Then, when we want to count users, it’s as simple as:

 $sessionfiles = session_save_path() . "/sess_*"; // match files in the

 path that begin with "sess_"

 $sessionarray = glob($sessionfiles); // put those files in an array $sessioncount = count($sessionarray);

 // count the array size

Note that the very handy function glob() was introduced in PHP 4.3. It finds files on the server according to a matching pattern. If your PHP server is running an older edition, you can accomplish the same thing in a couple more steps with opendir() and foreach().

The above code can be made into a simple function so you can stick the number anywhere on your site:

 function usersonline() {

 	$sessionfiles = session_save_path() . "/sess_*";

 	$usersonline = count(glob($sessionfiles));

 	return $usersonline;

 	}

If your site doesn’t use sessions, you might want to start for this reason alone, simply by adding a session_start() command to the top of each page. Soon you will discover the myriad benefits of PHP sessions and wonder how you ever lived without them.

Or, if sessions aren’t your thing (perhaps you’re still running PHP3 – how cute!), you might want to just keep a straight tally.


Keeping a Tally by Hand

Instead of using files that another process creates for us, as above, in this method we have to take the initiative and write to a file or database every time a user hits the site. Then we can look at that database and see who’s online. For the purposes of this example, I’ll use a MySQL database. First, create the database. Create a file called usersonlinedb.txt containing the following text:

 CREATE TABLE usersonline (

 who varchar(16) not null,

 whenn int(16) not null);

Use this text file to create a MySQL database instance from the command line:

 mysql -u root usersonline < usersonlinedb.txt



Then feel free to delete the text file. If you don’t have shell access, or don’t like typing, or prefer another way of interacting with MySQL, go right ahead and use your favorite interface.

Then we use a little PHP function, similar to those used around the web, to insert the user’s IP address into the database every time a page is loaded, as well as a time stamp.

 <?php

 function usersonline() {



 // First, we set some configuration variables.

 $timeout = time() - 60; // number of seconds to keep users in database $dbhost = "localhost"; $dbuser = "root";

 // fill in your MySQL username $dbpass = ""; // fill in your MySQL password $dbname  = "usersonline";



 // We make a connection to the database mysql_connect($dbhost,$dbuser,$dbpass);

 mysql_select_db($dbname);



 // Insert some data

 $time = time();

 $query = mysql_query("INSERT INTO usersonline

 VALUES('$REMOTE_ADDR','$time')");

 if (!$query) { die('Invalid query: ' . mysql_error()); }



 // Delete older data

 mysql_query("DELETE FROM usersonline WHERE whenn < $timeout"); if (!$query) { die('Invalid query: ' . mysql_error()); }



 // Count up the entries

 $uniqueusers = mysql_query("SELECT DISTINCT who FROM usersonline");

 if (!$uniqueusers) { die('Invalid query: ' . mysql_error()); } $usersonline = mysql_num_rows($uniqueusers);



 // And close the database connection.

 mysql_close();

 return $usersonline;

 }

 ?>

This function is longer than the sessions one, but what it does is pretty basic. Whenever the function is called (e.g., whenever a user hits the site), it makes a connection to the database we created in step one. Then the function does three things. It inserts the user’s IP address into the database table, along with the current time (measured, as Unix likes to do, in one long human-unfriendly number representing the number of seconds elapsed since January 1, 1970; I am writing this at 1102604961). Next, it removes any rows from the database table whose timestamps are older than the $timeout variable, which is equal to the current time minus 60 seconds (aka, a minute ago). This timeout is adjustable; make it 6,000 seconds and your “users online” number will skyrocket. Thirdly, the function does a SELECT DISTINCT, retrieving all the unique entries that remain in the table, each of which represents a separate IP address and presumably a user. It then tallies up the number and returns it in the variable $usersonline.

This variable can then be stuck into a web page wherever you like.

Readers who don’t use MySQL, or don’t want the server overhead of pummeling their database like this, may prefer to use a flat text file instead of a database. (Which method is easier on the server depends on the details of individual setup.) The principle is the same, but instead of using mysql_query and all that, you’ll want to use fopen() and file() to read the flat file line-by-line into an array. Implementing this is left as an exercise for the reader. Since Apache logs hits in a flat file much like this one, readers who need additional exercise might want to just read and parse Apache’s log file instead of creating their own.

And that’s all there is to it! I look forward to every last drop of your feedback.