Member Sign In
Not a member?

A Wired.com user account lets you create, edit and comment on Webmonkey articles. You will also be able to contribute to the Wired How-To Wiki and comment on news stories at Wired.com.


It's fast and free.

Webmonkey is a property of Wired Digital.
processing...
Join Webmonkey

Please send me occasional e-mail updates about new features and special offers from Wired/Webmonkey.
Yes No

Please send occasional e-mail offers from Wired/Webmonkey affiliated web sites and publications, and carefully selected companies.
Yes No

I understand and agree that registration on or use of this site constitutes agreement to Webmonkey's User Agreement and Privacy Policy.
Webmonkey is a property of Wired Digital.
processing...

Retrieve Sign In

Please enter your e-mail address or username below. Your username and password will be sent to the e-mail address you provided us.

or
Webmonkey is a property of Wired Digital.
processing...

Welcome to Webmonkey

A private profile page has been created for you.
As a member of Webmonkey, you can now:
  • edit articles
  • add to the code library
  • design and write a tutorial
  • comment on any Webmonkey article
Close
Webmonkey is a property of Wired Digital.

Sign In Information Sent

An e-mail has been sent to the e-mail address registered in this account.
If you cannot find it in your in-box, please check your bulk or junk folders.
Sign In
Webmonkey is a property of Wired Digital.

How Many Users Are on Your Site Right Now

/skill level/
/viewed/
0 Times

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.

This tutorial, originally submitted by Webmonkey contributor Paul Adams, is a wiki. Portions of it may fall out of date. Please help Webmonkey keep it current by editing it. If you have extra advice, log in and add it.

Contents

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.

Introduction

What you'll need

Steps

Alternate methods

Suggested readings

  • This page was last modified 02:06, 14 May 2008.
Edit this article
Reddit Digg
 

/related_articles/

See more related articles

Subscribe now

Special Offer For Webmonkey Users

WIRED magazine:
The first word on how technology is changing our world.

Subscribe for just $10 a year