How to Make a Simple Visitor Counter Using PHP

Imagine you want a visitor counter on your homepage. Sure, there are plenty of free ones out there, but I’m never happy about embedding random third-party code in my website, and besides wouldn’t it be more fun to make your own?

Of course it would!


Here’s what we’ll be making

Number of visitors to this page so far:

Visitor counter


Count all the visitors!

In order to do this, the first thing we’ll need is a method of keeping track of the number of visitors to the site. You could store this number in a database, but that’ll make things a bit more complicated. Therefore, for the purposes of this demonstration, I’ll use a plain and simple text file.

In addition to this, we’ll also need a method of identifying unique visitors, as the counter should only increment once per visitor, not once per page view. For this we’ll use a session variable.

<?php
session_start();
$counter_name = "counter.txt";

// Check if a text file exists.
// If not create one and initialize it to zero.
if (!file_exists($counter_name)) {
  $f = fopen($counter_name, "w");
  fwrite($f,"0");
  fclose($f);
}

// Read the current value of our counter file
$f = fopen($counter_name,"r");
$counterVal = fread($f, filesize($counter_name));
fclose($f);

// Has visitor been counted in this session?
// If not, increase counter value by one
if(!isset($_SESSION['hasVisited'])){
  $_SESSION['hasVisited']="yes";
  $counterVal++;
  $f = fopen($counter_name, "w");
  fwrite($f, $counterVal);
  fclose($f);
}

echo "You are visitor number $counterVal to this site";

As you can see I’m using four of PHP’s filesystem functions to create, read from, write to and close the text file. I’m also checking if our session variable is set before incrementing the counter. So far, so good…

Display the Number as an Image

Now all we need to do is read the number stored in the text file and display it on our web page as an image. Here are the steps I’ll take to accomplish this:

  • Pad the counter value with zeros, so that it has a length of five digits in total. For example a value of one will display as 00001.
  • Split the counter value into an array of individual digits. This means that “00001” would become ["0", "0", "0", "0", "1"]
  • Using PHP’s imagecreatefrompng function, create a reference to six png files (one to act as the canvas and five individual digits).
  • Using- PHP’s imagecopymerge function, combine these six png files into one.
  • Output the finished image an free it from memory.

The code for this is a little more complicated, so let’s step through it bit by bit. Steps one and two are achieved thus:

$counterVal = str_pad($counterVal, 5, "0", STR_PAD_LEFT);
$chars = preg_split('//', $counterVal);

Now, before we can start manipulating images with PHP we need an image set to work with. I’ve chosen to go with the Danielle Young’s free Otto number set (since taken offline), which I’m using with her kind permission. If this isn’t your kind of thing, a quick Google search should uncover a few more, for example: http://www.bittbox.com/freebies/free-glass-number-icons.

Whatever you decide to use, please make sure that you abide by the author’s terms and conditions.

In preparation for dynamically creating the final image, I have made one transparent png file (canvas.png) which will act as a canvas. This measures 296px by 75px. I have also resized the individual images to a dimension of 56px by 75px and saved them with the same file name as the digit they represent. These will be placed onto the canvas as shown in the diagram:

The positioning of the digits upon the canvas

I can now use imagecreatefrompng to get a reference to canvas.png, as well as to the individual digits, stored in the elements of the $char array.

$im = imagecreatefrompng("canvas.png");
$src1 = imagecreatefrompng("$chars[1].png");
$src2 = imagecreatefrompng("$chars[2].png");
$src3 = imagecreatefrompng("$chars[3].png");
$src4 = imagecreatefrompng("$chars[4].png");
$src5 = imagecreatefrompng("$chars[5].png");

Then we need to fit the individual digits onto the canvas and send the result to the browser to display.

We can use imagecopymerge to accomplish the first part. The parameters it takes are as follows:

  • destination image link resource
  • source image link resource
  • x-coordinate of destination point
  • y-coordinate of destination point
  • x-coordinate of source point
  • y-coordinate of source point
  • source width
  • source height
  • pct (we can just leave this at 100).
imagecopymerge($im, $src1, 0, 0, 0, 0, 56, 75, 100);
imagecopymerge($im, $src2, 60, 0, 0, 0, 56, 75, 100);
imagecopymerge($im, $src3, 120, 0, 0, 0, 56, 75, 100);
imagecopymerge($im, $src4, 180, 0, 0, 0, 56, 75, 100);
imagecopymerge($im, $src5, 240, 0, 0, 0, 56, 75, 100);

With that done we need to send the image to the browser and free it from memory:

header('Content-Type: image/png');
echo imagepng($im);
imagedestroy($im);

Here’s the complete listing:

<?php
  session_start();
  $counter_name = "counter.txt";

  // Check if a text file exists.
  //If not create one and initialize it to zero.
  if (!file_exists($counter_name)) {
    $f = fopen($counter_name, "w");
    fwrite($f,"0");
    fclose($f);
  }
  // Read the current value of our counter file
  $f = fopen($counter_name,"r");
  $counterVal = fread($f, filesize($counter_name));
  fclose($f);

  // Has visitor been counted in this session?
  // If not, increase counter value by one
  if(!isset($_SESSION['hasVisited'])){
    $_SESSION['hasVisited']="yes";
    $counterVal++;
    $f = fopen($counter_name, "w");
    fwrite($f, $counterVal);
    fclose($f);
  }

  $counterVal = str_pad($counterVal, 5, "0", STR_PAD_LEFT);
  $chars = preg_split('//', $counterVal);
  $im = imagecreatefrompng("canvas.png");

  $src1 = imagecreatefrompng("$chars[1].png");
  $src2 = imagecreatefrompng("$chars[2].png");
  $src3 = imagecreatefrompng("$chars[3].png");
  $src4 = imagecreatefrompng("$chars[4].png");
  $src5 = imagecreatefrompng("$chars[5].png");

  imagecopymerge($im, $src1, 0, 0, 0, 0, 56, 75, 100);
  imagecopymerge($im, $src2, 60, 0, 0, 0, 56, 75, 100);
  imagecopymerge($im, $src3, 120, 0, 0, 0, 56, 75, 100);
  imagecopymerge($im, $src4, 180, 0, 0, 0, 56, 75, 100);
  imagecopymerge($im, $src5, 240, 0, 0, 0, 56, 75, 100);

  // Output and free from memory
  header('Content-Type: image/png');
  echo imagepng($im);
  imagedestroy($im);
?>

Now you can write the following in your HTML code and have it display your very own visitor counter:

<p>Number of visitors to this page so far:</p>
<img alt="Visitor counter" src="counter.php" />

You can see the finished script in action at the top of the page. I hope you have found this useful!


This post currently has 86 responses

  1. Pulkit says:

    i make cms i use your tutorial but when user login then counter some time count 2 and some time 1 why this occured..??how fix it..

    • hibbard.eu says:

      It’s hard to say without seeing your code and understanding more about your set-up. Sorry!

    • aleg says:

      i used Switch-Case on index,
      that make its count 2.

      so when i remove my switch-case script its count 1.

      *so you have idea how to fix it? cause i need my switch-case script

  2. Egemen Turan says:

    Great.. Can you please explain where your merging digits with number icons? Can you please explain in details how the code does this? Thanks

  3. Graham says:

    Is fread/fwrite better that fgets/fputs?

    • hibbard.eu says:

      fread() and fgets() have slightly different uses:

      fread() reads raw data and will stop after a specified (or default) number of bytes.

      fgets() reads one line from a file.

      As for fputs() and fwrite() – one is simply an alias of the other.

  4. TheDeerDude says:

    Very useful and easy to understand tutorial! Well explained! Thank you :3
    Here’s mine: http://thedeerdude.cba.pl/ (At the bottom of the page of course 😉 )

  5. wendell says:

    Awesome blog sir! simple and clear! Looking forward for your more php tuts 🙂

  6. Michael says:

    I love this! Finally, someone who will talk about how it is done! Can’t wait to fold it into my website!! Only change I think I’ll make will be to use MySQL and opt for a simpler display. Great tutorial!!

  7. valentine says:

    hello

    Thanks for the good and informative tutorial, i have some issues with the implementing of this php counter to my own site. It looks like everything is working, but the counter it self are not able to find the images of numbers. Where do i have to place the number images, in a folder together with the PHP script? I have now everything in root of my site.

    • hibbard.eu says:

      Hi there, thanks for your comments.

      It doesn’t really matter where you place the images in relation to the PHP script (I ended up having mine in a folder called digits in the same directory as the PHP script).

      What is important is that you pass the correct path to the imagecreatefrompng() function.

      $src1 = imagecreatefrompng("digits/$chars[1].png");
  8. SAM says:

    how it works?
    I placed it on my site and not showing any counter.

    Just show blank image. Where to add those images?

  9. larry oriola says:

    Thanks for ur great tutorial bt it given me this error warning; fread parameter must be greater than 0.
    I dnt understand this error. Plz help me

    • hibbard.eu says:

      Hi there,

      I would guess that counter.txt (or whatever you have called it) is empty.
      Can you check if this is the case.

  10. Raghavendra says:

    Thanks a lot for this nice tutorial.I am using hit counter which popups an advertisement.I want to use your code please advise me how and where I have to insert the current no of visitors already visited this webpage.
    thanks

  11. wowsers says:

    How would I go about deleating the way it checks sessions(I’m going to make two counters on my website, one counting visitors and one counting total page-views)

    Please help

    • hibbard.eu says:

      Hi,

      If you want one counter to be persistent and one counter to be session based, then simply use a session to store the number of page views associated with a user.

      Or did I misunderstand your question?

      • wowsers says:

        Yes almost, but I can’t find how to make the script read the total numberof visitors(regardless of user amount), could you give an example?
        would making an else{ after and copy the write text do anything?

      • wowsers says:

        Nevermind, I found a solution myself, but thanks for an AWESOME counter 😉

  12. adidas4death says:

    Hy!

    I try to make this counter but I cannot see any image, just a little “broken” image (like something cannot load the image)

    what went wrong?

    Thanks in advance.

    • hibbard.eu says:

      Hi,

      It’s hard to say what went wrong without seeing some code.
      The first thing I would check is if the paths to your images within the PHP script are correct.

  13. Jagrut says:

    When we refresh the page counter automatic increase.

    Please help me.

    • hibbard.eu says:

      Sounds like you aren’t setting the session properly.

      Did you include all of the relevant code?

      session_start();
      
      if(!isset($_SESSION['hasVisited'])){
        $_SESSION['hasVisited']="yes";
        ...
      }
      
  14. Brink says:

    I cannot seem to get the counter to increment. PNGs display correctly if I manually tweak the .txt

  15. kenneth says:

    i kept getting

    the image “http://localhost/counter/” cannot be displayed because it contains errors

    what could be the problem
    thanks

    • hibbard.eu says:

      Hard to say.
      Could you provide the code you are using to create the image?

      • kenneth says:

        i was able to solve the problem , i jus had to read the instructions more carefully

        but another problem i have encountered is that whenever i change the digit in the counter.txt file, it gives me the same error i encountered before

        “http://localhost/counter/” cannot be displayed because it contains errors

        is there any way i cant manipulate the counter.txt file so that the counter displays i have a lot of visitors

        • hibbard.eu says:

          You should be able to manually alter the text file and have the counter script display whatever number is in there.

          Double check your code, then if you still can’t get it to work, let me know.

          • kenneth says:

            Thanks was able to correct it by removing echo “You are visitor number $counterVal to this site”;

            code works fine but can you give me pointers on how to put this code on a page , i keep getting the same error wen i try adding anything new

  16. hibbard.eu says:

    It’s a bit hard to say what’s wrong without seeing any code, therefore I would suggest the following:

    Go to SitePoint forums and register an account. Post your question in the PHP forum and let me know you have done this.

    I will answer you there.

  17. Gichelli says:

    Thank you for this great tutorial, it looks so good and works great.

    I wanted to help others to understand this tut with the parts that was confusing to me as I am a completely new to this..
    the pictures of my site i made them smaller, so made canvas.png and 1.png, 2png… etc, the same height of canvas and smaller width.. basically it was a fourth of the orginal size.

    in part of the script I just changed it instead every 60 I increased it every 15

    imagecopymerge($im, $src1, 0, 0, 0, 0, 56, 75, 100);
    imagecopymerge($im, $src2, 15, 0, 0, 0, 56, 75, 100);
    imagecopymerge($im, $src3, 30, 0, 0, 0, 56, 75, 100);
    

    this is how i got the pics to show in my website.

    I also added the first code on the top of my code page index.php right after second and closed script with a ?>. I added this Usted es el visitante numero:
    in the part where I wanted the visitor counter to go. mine was at the end of the page.

    I also uploaded the counter.php to my server which contained all the code.

    I had to write this to help out I am sorry if is too basic for some of you.. I was just really lost as I didnt really get it at first.. thanks to the author.. great

  18. Gichelli says:

    I also added the first code on the top of my code page index.php right after second and closed script with a ?>

    • hibbard.eu says:

      Hi Gichelli,

      Thank you for taking the time to share this.
      Hopefully it will be useful for others.

      That’s also a pretty groovy looking visitor counter on your website!

  19. Yogesh Sharma says:

    when i use your code, nothing happened on index page, in this term only in counter.text file, the value is incresing but, nothig show on index page, Reply me plsssssssss.

  20. Gichelli says:

    Thanks to you Hibbard,

    I was wondering if this counter will count a visitor only once and never count the ip of the computer, cellphone? or every day I hit the site counts as a new counter. I made a site for someone else and he got lots of hit and I could not really give him an answer as I was not sure..

    Thank you

    • hibbard.eu says:

      Hi there,

      The counter is session based, so it will not count the same visitor twice in the same session.

      If you don’t want to count the same visitor twice at all, you’ll need to use a cookie.

      • zeeshan says:

        can u give me a whole code of cookies that count the visitor within 24 hour count the same visitor once. after 24 hour the visitor who visit the site that also count..
        please upload the code

  21. Don says:

    Anxious to get this working, but have a dumb question(showing my ignorance of PHP).
    When placing the file names for the numbers, do I have to include $chars and [1] or is my file name inside the brackets or what? For example if my files would be named one.png,two.png, etc.. how would that string look?
    Thanks for your help.

    • hibbard.eu says:

      Hi,

      The way the script works, is that it splits the string in the text file into single digits and then looks for image files corresponding to those digits, e.g. 1.png, 2.png

      The easiest thing for you to do is to name your image files accordingly.

  22. Thanos says:

    Very awesome tutorial, clean and simple yet just to the point.
    I was looking to create my own visitor counter but you sir just did it just fine.

    Thanks again and keep it like that.

  23. Ankur says:

    Hey,very innovative and unique but helpful tutorial with many new concepts..thanks for tutoring…looking for more in future..!

  24. admin says:

    Thanks Ankur and Thanos. I appreciate your comments.

  25. pratik bhattacharya says:

    Great Tutorial !! but i could not make it work.the counter.txt is incrementing by 1.but the image is not displaying.

    i have downloaded the zip file and rename dy-otto-0.png file to canvas.png and placed it in my localhost folder.
    but the image not appearing.and it appears to be like a broken image symbol under title Hit Counter.how can i fix it?
    thanks in adv.

    • admin says:

      Hi Patrik,

      Use your browser tools to see what the image src has been set to. This should give you a clue as to why it isn’t working.

  26. simon says:

    Hi I get this error… can’t find out what conflict there is with the session:
    Warning: session_start() [function.session-start]: Cannot send session cache limiter – headers already sent (output started at …

    The site is http://www.ossi-bau.com

    Any idea? tried several things but doesn’t work.

    • admin says:

      Hi there,

      “Headers already sent” means that your PHP script already sent the HTTP headers, and as such it can’t make modifications to them now.

      Check that you don’t send ANY content before calling session_start.

  27. Vivek says:

    i have created a counter.php file then i’m using it in html page

    like this :

    Number of visitors to this page so far:

    Bt no image is coming please help.

    • admin says:

      Try using your browser’s tools to see if a broken image is being inserted into the page.

      If not, you’ll have to provide some more information.

  28. Jim says:

    Hello and thank you for posting this script, it’s awesome! What do I need to change or add so every visit (hit) is counted (if the same visitor visits 3 times the same day, or I guess it would be 3 times during the same session)? – Thanks, Jim

    • admin says:

      Hi,

      Glad you found it useful.
      Just remove all of the session related stuff and it’l count every time the page is loaded.

  29. Tony Malibu says:

    Hi – I really like this script. However, I am trying to modify so that the text file updates when a certain link is clicked. Here’s what I have, but it isn’t working. Any help would be greatly appreciated.

    <php
      session_start();
      $counter_name = 'counter.txt';
    
      if (!file_exists($counter_name)) {
        $f = fopen($counter_name, "w");
        fwrite($f,"0");
        fclose($f);
      }
    
      $f = fopen($counter_name,"r");
      $counterVal = fread($f, filesize($counter_name));
      fclose($f);
    
      if(isset($_GET['link'])){
        $counterVal++;
        $f = fopen($counter_name, "w");
        fwrite($f, $counterVal);
        fclose($f);
      }
    
      echo '' . $counterVal .'';
    ?>
    
    • admin says:

      Hi,

      I would probably have the link fire off an AJAX request to the PHP script when it is clicked.

      e.g. (assumes jQuery):

      $("a.myClass").on("click", function(e){
        e.preventDefault();
        $.ajax({
          url: '/path/to/file',
          type: 'POST',
          data: {param1: 'value1'},
          success: function(response){ ... })
        })
      });
      
      • Tony Malibu says:

        Hi – Still struggling with this one as I’ve never used ajax. I was able to get it to work without jquery/ajax. The problem is that the value increments when I click the link, as well as when I refresh the page. Hope you’re able to help or offer a suggestion. Here’s what I have:

        a href=”?link=1″ title=”Share with Your Friends via Email!”

  30. myndot says:

    hello, thanks for awesome script.
    can I use it without image??
    I want to use this script but no image, just text/number counter.
    how to do that??
    Thanks

    • admin says:

      Hi,
      All you need to do in this case is skip the image generation – you have the value you require in $counterVal, so you can just echo that to the page.

  31. Don says:

    I have my counter at the bottom of my page. I made my canvas file transparent, but filled it with zeros. I created my own numbers with transparent backgrounds, but when they display on my page I see white, verticle stripes. What causes this do you think?

  32. Akras says:

    Hello, nice work, im a bit noob, let me know if i’m mistaken, dont like so much zeros, so, change $counterVal, 5, “x”, STR_PAD_RIGHT); in “x”.png im create and transparent image and result 9 visit + 1 = 10 without extra zeros, work fine but is good this option? and other question, is there any way to set cookie to reset in x hours? thx for script, sry for my bad english

  33. charles says:

    I cant get my counter to work 🙁 help please?

  34. Mads says:

    I am trying to add the visitor counter to one of the webservers built by someone else. The php script (counter.php) runs fine when it is written as a separate script with the beginning as: session_start() but when I add this script in the folder containing other php scripts for the web server, it gives an error: “Cannot send session cache limiter – headers already sent ..” and neither does the counter.txt gets incremented. Please help with a suggestion.

  35. Duska says:

    I want to my page to have to counters which need to count a visit for two links. I don’t have an idea how to do that…

  36. Adam says:

    Hi there,
    How can I use 2 types of numbers?
    first 4 with blue background and the last one with purple background, I can’t load it… the blue one will have names (00,01,02,03,04….) and the purple numbers (0,1,2,3,4,5….) but how can I use the blue one for the first 4 letters and the purple one for the last letter? help please.

    • admin says:

      Not sure. Try inserting the extra zero manually:

      $src5 = imagecreatefrompng("0$chars[5].png");
      
  37. Gaurav says:

    Hello, I want counter in my webpage.its working when not use IMAGE but when I use IMAGE counter is not working..I’m change the image name counter.png to dy-otto-0.png. when open the page only dy-otto-0.png,after refreshing the page without any increment same image show….please help thank you

  38. Dev says:

    I have a problem to Implementing image in counter path is fine but no increment in image and counter.txt file Please help…I’m waiting your response…

  39. abhay says:

    http://localhost/count/cookie.php: cannot to display it contain errors..

    this error will give on my site ..
    how can i recover plz help …. reply as soon as

  40. admin says:

    Gaurav, Dev and abhay,

    Thanks for your comments.

    Unfortunately, it is a bit difficult to diagnose coding problems in the comments section of a blog.

    If you would like help with any of these issues, please head over to SitePoint forums (http://community.sitepoint.com), register an account and post your questions in the PHP forum.

    If you let me know when you’ve done that, I’ll answer you there.

Comments are closed!