Training, Open Source computer languages
PerlPHPPythonMySQLApache / TomcatTclRubyJavaC and C++LinuxCSS 
Search for:
Home Accessibility Courses Diary The Mouth Forum Resources Site Map About Us Contact
 
For 2023 (and 2024 ...) - we are now fully retired from IT training.
We have made many, many friends over 25 years of teaching about Python, Tcl, Perl, PHP, Lua, Java, C and C++ - and MySQL, Linux and Solaris/SunOS too. Our training notes are now very much out of date, but due to upward compatability most of our examples remain operational and even relevant ad you are welcome to make us if them "as seen" and at your own risk.

Lisa and I (Graham) now live in what was our training centre in Melksham - happy to meet with former delegates here - but do check ahead before coming round. We are far from inactive - rather, enjoying the times that we are retired but still healthy enough in mind and body to be active!

I am also active in many other area and still look after a lot of web sites - you can find an index ((here))
php counter for web pages

Posted by jill (jill), 13 February 2003
We need a php script to count hits on web pages.  There are loads of free ones, can anyone recommend one?  Also are there likely to be any security issues in using it/them?

TIA

Posted by admin (Graham Ellis), 13 February 2003
Do you simply want to count your visitors, or count and log them? Do you want to tell your visitors their number, or be secretive about what your doing?  Do you want to be able to count in an ordinary HTML page, or can the page counted by PHP?  Do I ask far too many questions??

I've put together a little demo (there are lots of free counters because it's very easy to do) that does the whole thing on your site, under your control.  I know you know some PHP, and having it under your control means that you can look after your own security issues.

Firstly, here's a page of plain old HTML, but it calls up an image that looks - well - a bit odd:
Code:
<head><title>Demonstration of a PHP Counter</title></head>
<body bgcolor=white>
<center>
<h1>Graphic Counter demonstration from a PHP page</h1>
<table><tr><td><img src=click.php4></td>
<td>This is a demonstration of a page that's written in
pure HTML, but it calls up a counter (running on the same
site) written in PHP.   We use an image link as that's the
common or garden way to include one file in another in almost
any version of HTML.<br><br>
By the way - I think that counters that tell you how many
visitors you've had suck - you're not told how many people
are ahead of you at Tesco, so why do you want to know here.
Mind you, from a training point of view it's a nifty little
demo!</td></tr></table>
</center>
</body>


The  Image is actually a piece of PHP which returns an image to the browser when it's loaded.   Here's the file click.php4:
Code:
<?php
// Set header type to image and get image - NOT optional
header("content-type: image/jpg");
$im = ImageCreateFromJPEG("trl.jpg");

// Following section OPTIONAL - provides a log file
$fh = fopen("counter.demo","a");
fputs ($fh,"$_SERVER[HTTP_REFERER] ".
       date("r").
       " $_SERVER[REMOTE_ADDR]\n");
fclose ($fh);

// Following section OPTIONAL - adds a counter
$fh = fopen("counter.num","r+");
$num = fgets($fh,32);
$num = $num + 1;
rewind ($fh);
fputs ($fh,"$num\n");
fclose ($fh);

// Following section OPTIONAL - adds count to image
$fg = ImageColorAllocate($im,255,255,255);
$n = sprintf("No.%04d",$num);
imagettftext($im,30,0,10,290,$fg,
         "/home/wellho/public_html/wellimg/acadian.ttf",$n);

// Send out the image - NOT optional
ImageJPEG($im);
?>


And the result is an image with a changing number written over it, and records written to a log file too so that you know something about your visitors.

I have put the live code at
http://www.wellho.net/wellimg/demopic.html
and you can see the log file if you want at
http://www.wellho.net/wellimg/counter.demo
and the counter record file at
http://www.wellho.net/wellimg/counter.num

You ask about security.   The counter files should really be in a different directory that can't be see from the web - I've just got them where they are for you to see how they work ...

P.S.  Counters are notoriously unreliable at telling you how many visitors you really have to an HTML page ... some visitors won't be notified to you at all as they're getting their stuff from a cache, and other will be counted more than once as they refresh ...


Posted by jill (jill), 14 February 2003
Thanks for your very prompt reply - but it has prompted more questions!  First, to answer yours:

We do want to count and log the visitors, and we do not require them to see the result.
The pages we are counting do not get cached, we have <meta http-equiv="pragma" content="no-cache"> etc in our template, so every hit will be counted.  We do not need to count in an html page, we just need to be able to get the log and the results.  And no, you do not ask too many questions, unless I do.

Unfortunately, although the code appears relatively short I don't completely understand it.  Sorry.  I can understand the bit where it adds one to the counter, and the bit where it puts the 'referer' into the log, but not the image bit really.  If you did not want an image in the demopic page, how would you get the script to run?.  Also presumably if you were counting hits on lots of pages you would need a mechanism - I suppose you could just do the log file, then get that into excel and do totals or something, or else have lots of separate counter.num files, perhaps called by the name of the 'referer'.

When I tested it on your site, I found that in I.E. every time I hit refresh the counter was incremented, but in Netscape 4 this did not happen - do you know why?  Also I looked up HTTP_REFERER in php.net and found this:

'The address of the page (if any) which referred the user agent to the current page. This is set by the user agent. Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. In short, it cannot really be trusted.'

Is this why it does not work in Netscape 4?

Finally I loaded demopic.html, click.php onto our server and created two empty files counter.num and counter.demo with permissions 666, in a folder with write permissions as well, and I could not get it to work, or even show the image in the page at all.  (I have put the permissions back after testing because our server admins do not want folders with write permissions on the server - not sure how to get round this either - you answered an earlier question on this topic advising that the webserver should have write permissions, but this has not been resolved yet.)

Any further help will be very much appreciated

Posted by admin (Graham Ellis), 14 February 2003
Ah - I had so much fun with the clever graphics and adding the number on top of the page and it turns out you don't need all that clever stuff     .... I'll answer the things that have mysified you but turn out to not be relevant in your situation here, then go on to give you a more tuned answer in a further follow up.

The whole business of using the image at all is to find something that can be included in a plain ole HTML web page that will cause some PHP to be run - you can't just say "please include this PHP in my HTML page" if the server isn't parsing it so you have to use something the browser will trigger - either an image or a piece of code in a browser-understood language.  An image is a neat solution, as it also gives the ability to provide back something that changes to reflect the count if you had wanted that. As you don't need to do this (as it turns out) there are much easier ways.

The Explorer / Netscape differerence relates to different caching habits - on Netscape you often have to "shift-reload" or even load separately to get images to come up again after they've been cached;  note the warning on the end of my initial post about counter reliability!

It's possible that the version of PHP on your server doesn't have all the Imagexxxxxx functions loaded; that may cause the problem that you describe there.  If you don't want to modify the image, then you can use much easier functions to read and output the jpeg file, passing through binary data.

What else?   The log file ... I just chose some data that's provided by PHP to write to the log file - I had a look through $_SERVER and chose what I thought looked useful.  You're right - many of the things can be falsified, but it really depends what you're looking for what you put to that file.

I have a "PHP day" scheduled for tomorrow - I'm updating training notes, and I've added a note to that to have a look at counter code too.  I'll post further ....

Posted by admin (Graham Ellis), 16 February 2003
OK ... back to you on counting users.   The metrics of your requirement
       * You want to log ALL accesses to a PHP page
       * You have to keep log AWAY from document directory
       * You want to gather RELIABLE information
And you don't want to tell people the count, nor attempt to count
accesses to .html pages.

Firstly the matter of "all" to a PHP page shouldn't be a problem, as
such pages should not be cached; any web server worth its salt will
tell clients not to cache, and cache servers and proxies should obey
such instructions - after all, the ",php" or ".php4" extension is like
waving a red flag that says "I will be changing".  Depending on browsers,
settings, etc, it MIGHT be that some browsers will cache a page on
occasions - but here's a question for you: "do you regard a pressing of
the Back button on a browser to be a fresh hit?".   In any case, the
page will probably be reloaded if it's a form that's been submitted via
a POST.

Keeping data AWAY from the document directory.  Fine; I would go for a
plain text file to contain log records in a private directory. The log
file itself will need write permissions for the web server which (it
depends on how your admin is set up) is probably group write permissions.

How many log records will you be generating?  If you've got tens of
visitors per minute sometimes (e.g. if you're running a class and you tell
everyone to go the page at the same instant, or if you have a site that's
very popular), you may wish to consider either:
       a) File Locking or
       b) Keeping log records in an SQL table

Your original question was about scripts to log; personally, I would tend
to "roll my own".  A particular note - there are some logging scripts that
use offsite "counter farms" where the counting is done at someone else's
system.  Sure means there's no writes on your system, but it puts up network
traffic, and adds in another cog - another potential machine that could
be unavailable when you're visited, and a system who's owner could be interested
in your statistics for his marketing or sales purposes.

Looking at the third issue - what can you log that's reliable?  Not as much
as you might like!  You're right that the User Agent (browser) can falsify
anything in the header it send.   The IP address referring may not be the true
one for the browser, but a caching or proxy server, or the IP address may be
rewritten by some form of bridge.   You should certainly record the timestamp,
any cookies you get back, hidden fields if you use them.  I would record the IP
address and the user agent string - not as 100% reliable but because they'll
help you tell one user apart from another if you're logging a page that folks
keep coming back to.  I don't think there's any way of telling visitors who are
using the same browser version through the same IP rewrite bridge apart unless
you do have cookies or hidden fields.

You've caught me in expansive mood this morning; I'll put together an example
that logs information that's as reliable as possible to a hidden text file, and
I'll use file locking to be double-plus sure that my PHP script won't damage
its own file by multithreading. Beware - file locking is a COOPERATIVE locking
system so processes can ignore the lock - it's up to YOU to lock in each script
that uses the file!


Posted by admin (Graham Ellis), 16 February 2003
Here we go ... the code.  Firstly, the page with the counter

Code:
<body bgcolor=white><?php include_once("../../private/logem.inc") ?>
This is a test PHP page that will be logged.  You won't see anything
change in this page when you call it up.   It's a demo, and you should
have been given another URL to visit to actually look at your results.
<br><br>Graham Ellis
</body>


The included file (also in the private directory):

Code:
<?php // Counter script - add a record to a log file
$status = 0;
$fh = fopen("../../private/records.log","a");

// Get exclusive lock for writing. Wait if need be.

if ($fh) {
$status = 1;
$lstat = flock($fh,2);
if ($lstat) {
       // Although we opened for append, someone else may
       // have written while we were awaiting our lock.
       // Make double-plus sure we are at end now that we
       // have our lock!!
       $status = 2;
       $nowat = ftell($fh);
       $nowsz = filesize("../../private/records.log");
       if ($nowat != $nowsz) {
               fseek($fh,$nowsz-$nowat);
               }

// Write to the log file
$line = array (
       $_SERVER[REMOTE_ADDR],          # Remote IP
       $_SERVER[SCRIPT_NAME],          # Script that's logging
       "_".$_COOKIE[PHPSESSID],        # Useful if we're using PHP sessions
       time(),
       $_SERVER[HTTP_USER_AGENT],      # Script that's logging
       "_".$_SERVER[HTTP_REFERER]      # Where they came from
       );

fputs ($fh,implode("\t",$line)."\n");
rewind($fh);            // force a flush
flock($fh,3);           // release the lock
}

fclose ($fh);

}

?>



I've gone really "over the top" with my file locking there!   The $status variable does nothing, except provide a return from the included file that you can check to see whether your logging worked (2), failed at file lock time (1) or couldn't see the log file at all (0).

A quick script to look at the log file:

Code:
<body bgcolor=white>
This is a PHP test page that will show you what's in the demo log
file.<HR>
<?php $hits = file("../../private/records.log");
print (implode("<br>",$hits));
?>
</body>


If you want to run the logging script, see
http://www.wellho.net/demo/mustcount.php4
and if you want to see the log file
http://www.wellho.net/demo/showcount.php4

P.S.  Note use of tabs as separators in the log file - makes it very easy to export the data to excel (if you must) or MySQL (much better ), and also to interpret the log file in PHP using explode or fgetcsv.   Note also the pre-pending of "_" to fields that may be null - just ensures that something is visible in the fields if you need to see it on a browser

Posted by jill (jill), 17 February 2003
Thanks for all this, and I have not completely got to grips with the code, but I did not manage to communicate the requirements quite right: We do wish to log and count all accesses to HTML pages, not php pages, we  just do not need to show the resulting count in the page itself.

If you do have time to explain further, I will be very grateful, but as you have spent so much time already, I will understand if you don't!



Posted by admin (Graham Ellis), 18 February 2003
Ah - some of the answers are a useful reminder to me of file locking and graphics manipulation issues, and I've been taking the opportunity to update training notes  

Within an HTML page, you cannot usually add any of your own code which will count accesses on the server directly; web servers pass the HTML through without parsing it.  The options you have are
a) Looking at server logs (do you have access to these?) as they may well provide you with enough information
b) Getting the server to parse the page even though it's HTML;  you could simply rename the file (and links to it) as .php4 and use the code posted in my second answer.  It's probable that the web server is set up to recognise index.php4 if you haven't got index.html anyway for the home page.  You might also have access to the .htaccess file for the directory of interest, and you may be able to add
       AddType application/x-httpd-php .html
into it (check with your sys admin to see if they're OK with you doing this!) so that HTML files are parsed
c) Have the client do something to log the access back with the server.   My first example did this via an image; the other alternative (rather out of my field) is javascript.   These methods rely on the browser, and not all accesses will be logged - it's very unlikely that a search engine would run your javascript for example.

No easy answer on this one / counts / logging.   If it was easy to log exactly who visited you with authourity, then it would be easy to add them to spam lists .... we would then all have to be very careful what web pages we visited.

Posted by jill (jill), 18 February 2003
Many thanks for the advice and help - I shall now try and digest it.

Posted by admin (Graham Ellis), 20 July 2003
Footnote on this thread - in PHP 4.3, there's a problem writing with a true type text font directly onto a full colour image, as was done in an earlier example in this thread.  As an alternative, you can write to a new image with a transparent background and merge the two.   A bit off topic; do post separately if you would like further details / example



This page is a thread posted to the opentalk forum at www.opentalk.org.uk and archived here for reference. To jump to the archive index please follow this link.

Comment: "Thank you for your sharing! It is nice code for PHP Counter ..."
Visitor Ranking 2.0 (5=excellent, 1=poor)

Comment by anny (published 2011-02-25) Suggested link.
Thank you for your sharing! It is nice code for PHP Counter [#3894]

You can Add a comment or ranking or edit your own comments

Average page ranking - 2.0

© WELL HOUSE CONSULTANTS LTD., 2024: Well House Manor • 48 Spa Road • Melksham, Wiltshire • United Kingdom • SN12 7NY
PH: 01144 1225 708225 • FAX: 01144 1225 793803 • EMAIL: info@wellho.net • WEB: http://www.wellho.net • SKYPE: wellho