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:
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:
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!
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..
It’s hard to say without seeing your code and understanding more about your set-up. Sorry!
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
Great.. Can you please explain where your merging digits with number icons? Can you please explain in details how the code does this? Thanks
I would suggest that you start by reading the PHP documentation for fread and imagecopymerge.
If you have a specific question after that, just let me know.
Is fread/fwrite better that fgets/fputs?
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.
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 )
Awesome blog sir! simple and clear! Looking forward for your more php tuts
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!!
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.
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.
how it works?
I placed it on my site and not showing any counter.
Just show blank image. Where to add those images?
Hi there,
See my answer to the above comment.
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
Hi there,
I would guess that counter.txt (or whatever you have called it) is empty.
Can you check if this is the case.
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
Hi,
Just enter the desired value into the text file (counter.txt in my example).
Thanks for your prompt response.I can not find
the text file.
No probs!
The script will create it if it doesn’t exist.
So you can just create it yourself of run the script.
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
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?
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?
Nevermind, I found a solution myself, but thanks for an AWESOME counter
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.
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.
When we refresh the page counter automatic increase.
Please help me.
Sounds like you aren’t setting the session properly.
Did you include all of the relevant code?
I cannot seem to get the counter to increment. PNGs display correctly if I manually tweak the .txt
Permissions on the .txt are 777
Is the script writing anything at all to the file?
i kept getting
the image “http://localhost/counter/” cannot be displayed because it contains errors
what could be the problem
thanks
Hard to say.
Could you provide the code you are using to create the image?
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
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.
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
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.
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
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
I also added the first code on the top of my code page index.php right after second and closed script with a ?>
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!
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.
Hi,
It’s hard to say what is going on without seeing any code.
If you need help, please read this comment.
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
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.
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
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.
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.
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.
Hey,very innovative and unique but helpful tutorial with many new concepts..thanks for tutoring…looking for more in future..!
Thanks Ankur and Thanos. I appreciate your comments.
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.
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.
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.
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.
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.
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.
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
Hi,
Glad you found it useful.
Just remove all of the session related stuff and it’l count every time the page is loaded.
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.
Hi,
I would probably have the link fire off an AJAX request to the PHP script when it is clicked.
e.g. (assumes jQuery):
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!”
Could you register an account at community.sitepoint.com and post your problem in the JavaScript forum.
Let me know when you have done that (e.g. via Twitter) and I’ll answer you there.
Hi thanks – I registered and posted my question and code there. The topic is PHP Counter (Read/Write) Increments on Page Refresh and its in the JavaScript category. Thanks again.
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
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.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?
It sounds like you need to give your png file a transparent background.
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
Hi,
Your idea sounds fine to me.
Regarding the cookies, maybe one of these posts will help: http://hibbard.eu/tag/cookies/
Hello Again, thx for ur time, have same problem like Don, any way to create image final transparent? all images are transparent, but printed in white, thx and regards
Ninjaedit: well. with…
fix white padding and corner
http://puu.sh/gfhsP/18edf3f96f.png
the white box is my custom png transparent called “j”
atm the only solution i found is change transparent image (“j”) to same bg color. work.. but haver a better choise? ty
Glad you got it working. Thanks for taking the time to share your solution.
I cant get my counter to work help please?
Lol. Sure, but please provide some details. I’m not psychic.
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.
“Headers already sent” means that your PHP script already sent the HTTP headers, and as such it can’t make modifications to them now.
See here: http://stackoverflow.com/questions/8812754/cannot-send-session-cache-limiter-headers-already-sent
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…
Hi,
What do you mean with “count a visit for two links”?
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.
Not sure. Try inserting the extra zero manually:
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
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…
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
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.
Question from Gaurav posted here: http://community.sitepoint.com/t/hit-counter-is-not-working/198320