Blog (my web musings)

Find out what's interesting me, get tips, advice, and code gems that don't fit elsewhere.


Search Blog


I was inspired by a recent forum thread, to write a click counter that can count clicks / hits to any HTML element (links, buttons, images, etc.). Multiple counts are saved to one text file (no database needed) using PHP, while AJAX displays the increasing numbers in real time. No page refresh required!

It's very light-weight because no dependencies or large JavaScript libraries are used - it's all plain JS. AJAX & PHP Click-Counter with Flat File Storage (text file):

Demo

Compatibility

PHP5 required. Works in all browsers, and IE8+

HTML markup

HTML markup for a clickable element looks like this;

<button class="click-trigger" data-click-id="click-001">Click Me</button>

I've used a button above, but it could also be an image;

<img src="/path/to/img.jpg" class="click-trigger" data-click-id="click-002" alt="Click!" />

Or a link;

<a href="/page.htm" class="click-trigger" data-click-id="click-003">I am a clickable link</a>

In fact, it doesn't really matter what the element is, so long as it carries the common class="click-trigger" class and a unique ID in an HTML5 "data-" attribute data-click-id="click-001". The unique ID will be used in a few places later, most notably in the text file that holds all the click counts.

JavaScript / AJAX

Now for some JavaScript / AJAX, which goes before the closing </body> tag of the page that has a clickable element;

<script>
var clicks = document.querySelectorAll('.click-trigger'); // IE8
for(var i = 0; i < clicks.length; i++){
    clicks[i].onclick = function(){
        var id = this.getAttribute('data-click-id');
        var post = 'id='+id; // post string
        var req = new XMLHttpRequest(); req.open('POST', 'counter.php', true);
        req.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.onreadystatechange = function(){
           if (req.readyState != 4 || req.status != 200) return;
           document.getElementById(id).innerHTML = req.responseText;
           };
       req.send(post);
       }
    }
</script>

You can see in the block of script above where the class="click-trigger" class is used, in the 1st line, to identify clickable elements. The 4th line then makes use of the unique "data-" attribute ID data-click-id="click-001" so AJAX can post this data to the "counter.php" file on line 7.

PHP

The "counter.php" file is where all the server-side magic happens;

<?php 

$file = 'counter.txt'; // path to text file that stores counts
$fh = fopen($file, 'r+');
$id = $_REQUEST['id']; // posted from page
$lines = '';
while(!feof($fh)){
    $line = explode('||', fgets($fh));
    $item = trim($line[0]);
    $num = trim($line[1]);
    if(!empty($item)){
        if($item == $id){
           $num++; // increment count by 1
           echo $num;
           }
        $lines .= "$item||$num\r\n";
        }
    }
file_put_contents($file, $lines);
fclose($fh);

?>

Having received the posted "data-" ID, PHP processes the lines stored inside the "counter.txt" text file, matches the clicked item ID and increments the count number alongside. Then it saves the changes back to "counter.txt", which is formatted like this;

click-001||36
click-002||123
click-003||513

One entry per line, with the "data-" ID and click count number separated by 2 pipes. To add a new click count item, just add the new line manually to the end of the "counter.txt" file, using 0 as the start count;

click-004||0

Back to the "counter.php" file for a second - you may have noticed that the incremented count number is echo'd back (echo $num;)? This is sent back to the web page and printed, in real time, inside another HTML element that has the same ID as the posted "data-" ID. So, for a clickable element that looks like this;

<button class="click-trigger" data-click-id="click-001">Click Me</button>

The HTML element holding the click count number should look like this;

<span id="click-001"></span>

In order to take the click counts from the "counter.txt" file and print them into the web page, we resort to PHP. The code below reads each line item into an array and assigns each unique ID as a key that can be easily referenced on the page;

<?php 

$clickcount = explode("\n", file_get_contents('counter.txt'));
foreach($clickcount as $line){
    $tmp = explode('||', $line);
    $count[trim($tmp[0])] = trim($tmp[1]);
    }

?>

This can go anywhere in the web page above the HTML element that holds the click count, which now looks like this;

<span id="click-001"><?php echo $count['click-001'];?></span>

Note, that the unique ID is used here again to grab the correct count number from the corresponding item in the storage file. Each item can be referenced by its unique ID key like this;

$count['click-001'];

That's about it! If you didn't get it, don't worry - you can download a sample demo pack from the demo page which will show you everything setup and working together.