Advanced “New” Labels

Improving the way your site handles “new” labels using the popular Apache modules mod_perl.
Using Apache::Session

Once our handler has retrieved the user's ID from a cookie and established a connection with the database, we can store and retrieve session information at our convenience.

We can store information about this user in %session, the hash to which we tied Apache::Session. Each time our handler is invoked, we can retrieve information about this user based on his or her ID. For example, we can store a value with:

$session{"foo"} = "bar";

We can then retrieve that value in a later session with:

my $stuff = $session{"foo"};
While our program appears to be storing and retrieving values in %session, it is actually retrieving them from the database using DBI—which means that, so long as we ensure each user has a unique ID, we can keep everyone's values separate.

Since we have what amounts to a hash that extends across sessions, how can we store information on which URLs we have visited and when? The easiest way is to use the URL as a key into %session, then store the last time the user visited the site. For example, we can store the URL with the following code:

my $document_uri = $r->uri;
$session{$document_uri} = time;

We want to retrieve this information when determining whether a user has recently visited a particular link. In order to do that, we will modify label_url so that it expects a fourth argument, a reference to %session. This way, label_url will be able to retrieve session information about the URL in question. We create the reference by preceding %session with a backslash (\%session) before passing it to label_url. We then dereference the copy of %session as follows, at the beginning of label_url:

my $session = shift;
my %session = %{$session};
The full code of a working version of Apache::TagNew, including the label_url subroutine, is in Listing 3.

Listing 3.

The rest of label_url is largely the same, except for a portion in the middle where we test to see if the URL begins with a slash (/). We must be sure to store and retrieve the same key from %session; otherwise, we will get false readings regarding when we last visited the URL. Since we store the URL based on $ruri, which always begins with a slash and is relative to our server's root URL directory, we should retrieve the URLs in the same way.

We do this by getting the current URL and removing everything following the final slash:

$current_directory =~ s|^(\S+/)[\w.]+$|$1|;

What is left is indeed the current directory, to which we can prepend the URL:

$url = $current_directory . $url;
Now we can retrieve the session information about that URL, confident we are using the same set of keys for retrieval as we did earlier for storage. We retrieve session information about when we last viewed the file in question, turning it into a number of days relative to right now:
my $last_time = (time - $session{$url}) / 86400;
Then we retrieve the modification timestamp of this file, by prepending $rdocument_root (the full path name leading to each file on the web site, normally invisible to users) to the file. We can easily determine its modification date:
my $full_filename = $r->document_root . $url;
my $ctime = -M $full_filename;
Finally, we compare $ctime (the number of days since the file was modified) with $last_time (the number of days since the user last saw the file). If the former is smaller than the latter, we add the label:
if ($ctime < $last_time)
$label = "<font color=\"red\">New!</font>"";
This module seems to do a good job of labeling new documents on a user-by-user basis. As long as users enable cookies, they should be able to get an accurate reading of which files they have not seen in a long time.


For a medium that is supposed to adapt itself to our own needs, the Web is surprisingly primitive—for instance, in the way “new” documents are labeled on web sites. This month, we have seen how mod_perl allows us to personalize our site a bit more, showing people what is actually new from their perspective, rather than from the webmaster's perspective. I hope you also noticed how advanced some of these tools have become; with a little more than 100 lines of Perl code, we were able to make a substantial change to our web server that had little impact on performance, but provided great benefit to our users.


Reuven M. Lerner is an Internet and Web consultant living in Haifa, Israel, who has been using the Web since early 1993. His book Core Perl will be published by Prentice-Hall later this year. Reuven can be reached at The ATF home page, including archives and discussion forums, is at