CodeLair website tutorials, articles & scripts

PHP Hit Counter

Published: 3 April 2005   •   Updated: 17 July 2007   •   Tags: php

This script will allow you to track the number of (non-unique) visitors to your site, or to each page.

The first part shows how to put a very simple hit counter on your pages. When a visitor loads the page, the count (stored in a file) is incremented. You can also choose whether or not to display the hit count on your pages. The second script below is similar to the first, however this one keeps track of the number of hits to each page separately and displays the hit counts in order of popularity.

The basic script #

In a text editor, create a blank text file called hitcount.txt. This will be used to store the number of hits on a page, or across all pages. Upload this, and CHMOD it to ‘666’ (there should be an option in your FTP program to do this - consult the Help files if you are not sure). 666 means the file is writable by PHP.

Next, create a file named counter.php. Copy the following code into it:

<?php

$filename = 'hitcount.txt';
$handle = fopen($filename, 'r');
$hits = trim(fgets($handle)) + 1;
fclose($handle);

$handle = fopen($filename, 'w');
fwrite($handle, $hits);
fclose($handle);

// Uncomment the next line to display the number of hits on your page.
//echo $hits;
?>

The first section opens the file in reading mode. It reads the number of hits in the file, which is then incremented and written back to the file. Every time counter.php is opened the number of hits goes up. So on every page you want to record the number of visitors, you need to include counter.php by means of a PHP include:

<?php include('counter.php'); ?>

As per usual, change counter.php to your path to the file. If you include it on every page of your site, you will count the total number of hits for all your pages (note that this is not unique visitors), and if you just put it on one page (say, the home page), you will count the number of hits for that page only.

You can also use the counter on SHTML pages (with .shtml extension), provided that your server supports PHP (and SSI of course). Just use this include:

<!-- #include file="counter.php" -->

Do you want to display the number of hits on your page somewhere? Simply uncomment the last line by removing the double slash so it reads:

echo $hits;

Then include the script wherever you want the count to be displayed. Since the script just displays a number, you can wrap the include in any HTML you want, for example:

<p>This web site has had <b><?php include('counter.php'); ?></b> hits since January 1st, 2007.</p>

A more advanced script #

What if you want to track the number of hits to each page individually? With the previous script you’d have to make separate counter.php and hitcount.txt files for every page you wanted to track. With the following script, this is not necessary: we have one PHP file which recognizes the current page being viewed and tallies a hit for that page. The text file now stores the page URL and the number of hits for that page. A new page, viewhits.php, displays all the pages and their respective hit counts.

First create a new blank hitcount.txt file (perhaps in another folder), and then copy the following code into a new counter.php file (we’ll walk through it below).

<?php

$filename = 'hitcount.txt';
$handle = fopen($filename, 'r');
$outbuffer = '';
$found = false;
$hits = 1;
$currentPage = $_SERVER['PHP_SELF'];

// reading data from file
while (!feof($handle))
{
$buffer = trim(fgets($handle));
if (strlen($buffer) > 0)
{
// extract the page url and count
list($page, $count) = explode('|', $buffer);
if (!$found && $page == $currentPage)
{
$hits = $count + 1;
$outbuffer .= $currentPage . '|' . $hits . "\n";
$found = true;
}
else
{
$outbuffer .= $buffer . "\n";
}
}
}
fclose($handle);

if (!$found)
{
$outbuffer .= $currentPage . "|1\n";
}

// writing updated data to file
$handle = fopen($filename, 'w');
fwrite($handle, $outbuffer);
fclose($handle);

// Uncomment the next line (remove //) to display the number of hits on your page.
//echo $hits;
?>

As before, we start by reading the hitcount.txt file. This file uses a different format to the previous one - rather than just one number, we store a URL and hit count on every line, separated by the pipe character (|). The URL comes from $_SERVER['PHP_SELF'].
If the page on a line matches what the visitor is viewing, we increase the count. As we go along we save all the existing pages in a variable $outbuffer so we can write that back out to the file at the end.

As before, include this file on any page you want to count hits for. With the last line of code uncommented, the number of hits for the visited page will be displayed.

Viewing stats for all your pages #

Finally, make another new PHP file, called viewhits.php and copy in the code below. This first bit reads the list of pages and hit counts from the text file, and exits if we don’t have anything yet. If we do habve hits, it uses array_multisort to sort the list based on the number of hits (descending). The total number of hits for all pages is also counted.

<?php

$filename = "hitcount.txt";
$i = 0;
$total = 0;

echo '<h1>CodeLair Hit Counter</h1>';

// check that there is something in the file
if (!filesize($filename) > 0)
{
echo '<p class="info">No statistics recorded yet!</p>';
exit;
}

// get list of pages from file
$handle = fopen($filename, 'r');
while (!feof($handle))
{
$buffer = trim(fgets($handle));
if (strlen($buffer) > 0)
{
list($pages[$i], $count[$i]) = explode('|', $buffer);
$total += $count[$i];
$i++;
}
}
fclose($handle);

// sort list
array_multisort($count, SORT_DESC, $pages);

This second part displays the results in a nice table. The numbers are formatted, using the PHP function number_format. This makes large numbers easier to read by adding commas in the standard way, e.g. ‘1,234’ or ‘9,876,543’. We also encode all output content using htmlspecialchars for security.

// display results
echo '<p class="info">TOTAL HITS<br><b>' . htmlspecialchars(number_format($total)) . '</b></p>';
echo '<table>';
echo '<tr><th>Filename</th><th>Hits</th></tr>';

for ($j = 0; $j < $i; $j++)
{
echo '<tr>';
echo '<td class="text">' . htmlspecialchars($pages[$j]) . '</td>';
echo '<td class="number">' . htmlspecialchars(number_format($count[$j])) . '</td>';
echo '</tr>';
}
echo '</table>';
?>

To format the table nicely, try this CSS:

body {
margin: 20px;
background: #f9f9f9;
font-family: "Trebuchet MS";
text-align: center;
}
body, td, th {
font-size: 13px;
}

table {
border-collapse: collapse;
margin: 20px auto;
padding: 0;
}
tr {
background-color: #f4ecf4;
}
tr:hover {
background-color: #f8f8e8;
}
th {
padding: 8px 10px;
border: 1px solid #c5a3c2;
background-color: #e9d9e8;
text-align: center;
}

td {
padding: 8px 10px;
border: 1px solid #c5a3c2;
}
td.text {
text-align: left;
}
td.number {
text-align: right;
}

Now you have your own simple hit counter for your site!