Software, your way.
How To Get Good Custom Software
(Download)
(PDF)
burger menu icon
WillMaster

WillMaster > LibraryStatistics and Tracking

FREE! Coding tips, tricks, and treasures.

Possibilities weekly ezine

Get the weekly email website developers read:

 

Your email address

name@example.com
YES! Send Possibilities every week!

Statistics for Syndicated Content

This article comes with a complete page view tracking system for JavaScript syndicated content. You can find out who is syndicating your content and how many times the content is being viewed.

This system will also work with regular web pages. Put the logging code into your web page content the same way you would for syndicated content.

This tracking system for JavaScript syndicated content comes in 3 sections: The tracking code to paste into content being syndicated and two scripts, a script for logging content location and page views and another for viewing the data in the log file.

The code and scripts for the system can be copied from the online version of this article, URL at end of this ezine version.

The Tracking Code

The tracking code is composed of JavaScript and a NOSCRIPT tag. It calls the logging script with an image tag.

The JavaScript sends the URL of the page where the content is at (the web page syndicating your content). JavaScript is used for this because more and more browsers are not providing page referrer information. The JavaScript also uses a random number to bypass browser image cache.

The image is a clear GIF, generated from within the logging script. Its size can be any you prefer

If the browser is not JavaScript enabled, the NOSCRIPT tag kicks in. The same image tag URL is used, but no URL is sent to the logging script. The logging script will, however, use the referrer information if the browser provides it. If the browser is not JavaScript enabled and does not provide referrer information, it is so marked (as blank) in the log.

The tracking code is the same for all content using the system. It can be put into content templates if you use them.

Here is the tracking code.

<script type="text/javascript" language="JavaScript"><!--
// Replace URL between quotes on next line, keep the ? at end of URL.
var statsurl = "http://example.com/cgi-bin/counter.cgi?";
statsurl += document.URL;
statsurl += '&1'+Math.random();
document.write('<img src="'+statsurl+'" height="1" width="2" border="0">');
//--></script>
<noscript>
<!-- Replace URL between quotes on next line -->
<img src="https://example.com/cgi-bin/stats/counter.cgi" height="1" width="2" border="0" alt="monitoring image">
</noscript>

Replace both instances of http://example.com/cgi-bin/counter.cgi in the above JavaScript with the URL to the logging script.

The Logging Script

This script creates and updates a tab-delimited file — suitable for importing into spreadsheet software, if you wish to manipulate the data that way.

Each record has 4 fields.

  1. A 10-digit number representing the date and time of the page view (according to the server's clock). It is for use by file scanning software.

  2. The server date in human-readable format.

  3. The server time in human-readable format.

  4. The URL of the web page where the content is being syndicated. If the browser being used is not JavaScript enabled and does not provide referrer information, this field will be blank.

There is one record for each recorded page view.

Here is the logging script.

#!/usr/bin/perl
######################################
#
# Personal Statistics Gathering Script
# Version 1.0
#
# Monday, September 25, 2006
#
# Created by Will Bontrager
# /contact.shtml
#
# Copyright 2006 Bontrager Connection, LLC
#
# Permission to use this software is granted only 
#   in conjunction with full agreement with the 
#   "BONTRAGER CONNECTION, LLC SOFTWARE LICENSE AGREEMENT". 
#   If agreement is not available online at 
#   /master/LicenseAgreement.html 
#   then it will be linked to from pages within the 
#   websites of willmaster.com or other domains 
#   owned/operated by Bontrager Connection, LLC.
#
# Usage: See the "Statistics for Syndicated Content" 
#    article at
#    willmaster.com -- article originally published 
#    in Possibilities ezine.
#
######################################
use strict; # this line may be commented out after testing

# Specify location of log file between quotes 
#    (directory, if specified, must exist with 
#    appropriate permissions). Location must be 
#    identical to location specified in log 
#    scanning script.

my $LogLocation = "logs/counterlog.txt";

#
# No other modifications required.
#

sub ClearGIF
{
    # Modified excerpt from module Base64.pm,v 2.16 2001/02/24 06:28:10 gisle
    local($^W) = 0;
    my $str = qq~R0lGODlhBQAFAJH/AP///wAAAMDAwAAAACH5BAEAAAIALAAAAAAFAAUAAAIElI+pWAA7\n~;
    $str =~ tr|A-Za-z0-9+=/||cd;
    $str =~ s/=+$//;
    $str =~ tr|A-Za-z0-9+/| -_|;
    return join '',map(unpack("u",chr(32 + length($_)*3/4) . $_),$str =~ /(.{1,60})/gs);
} # ClearGIF

sub MakeDateTime
{
    my ($second,$minute,$hour,$day,$month,$year,$weekday,$yearday,$dst) = localtime;
    $year += 1900;
    $month = ('January','February','March','April','May','June','July','August','September','October','November','December')[$month];
    $hour   = "0$hour"   if $hour   < 10;
    $minute = "0$minute" if $minute < 10;
    $second = "0$second" if $second < 10;
    return ("$month $day, $year","$hour:$minute:$second");
} # sub MakeDateTime

my $URL = $ENV{QUERY_STRING};
$URL =~ s/&[^&]*$//;
$URL = $ENV{HTTP_REFERER} unless $URL =~ /\w/;
my ($Date,$Time) = MakeDateTime;
open W,">$LogLocation" unless open W,">>$LogLocation";
print W time,"\t$Date\t$Time\t$URL\n";
close W;
print "Content-type: image/gif\n\n";
print ClearGIF;
# end of file

Save the file under a name that makes sense to you.

The location of the log file needs to be specified at the only configuration line of the script. The location you specify here must also be specified in the data viewing script.

The Data Viewing Script

Once installed, the data viewing script is very easy to use.

Simply type its URL into your browser, specify the start and end dates for the data you want to view, and click the button. You'll get a nice report.

If you specify no dates, cumulative data for the entire file will be used to generate the report.

The report has four columns.

  1. The left-most column is a colored bar representing the number of views compared to the other pages in the report.

  2. The second column is a number stating the number of recorded page views.

  3. The third column is a percentage representing how often the page was viewed as compared to the total number of page views the report covers.

  4. The last column is the URL of the web page, clickable.

Below the report is a form for generating another report.

Here is the data viewing script.

#!/usr/bin/perl
######################################
#
# Database Scanner for Personal Statistics Gathering Script
# Version 1.0
#
# Monday, September 25, 2006
#
# Created by Will Bontrager
# /contact.shtml
#
# Copyright 2006 Bontrager Connection, LLC
#
# Permission to use this software is granted only 
#   in conjunction with full agreement with the 
#   "BONTRAGER CONNECTION, LLC SOFTWARE LICENSE AGREEMENT". 
#   If agreement is not available online at 
#   https://www.willmaster.com/software/information/software-license-agreement.php
#   then it will be linked to from pages within the 
#   websites of willmaster.com or other domains 
#   owned/operated by Bontrager Connection, LLC.
#
# Usage: See the "Statistics for Syndicated Content" 
#    article at 
#    willmaster.com -- article originally published 
#    in Possibilities ezine.
#
######################################
use strict; # this line may be commented out after testing

# Specify location of log file between quotes 
#    (directory, if specified, must exist with 
#    appropriate permissions). Location must be 
#    identical to location specified in statistics 
#    gathering script.

my $LogLocation = "logs/counterlog.txt";

#
# No other modifications required.
#

use Time::Local;
my %In= ();
my $ME = $0;
$ME =~ s!^.*[/\\]!!;


sub GetMonthNumber
{
	my $m = lc shift;
	return (int($m)-1) if $m =~ /\d/;
	if($m =~ /^ja/ ) { return  0; }
	if($m =~ /^f/  ) { return  1; }
	if($m =~ /^mar/) { return  2; }
	if($m =~ /^ap/ ) { return  3; }
	if($m =~ /^m/  ) { return  4; }
	if($m =~ /^jun/) { return  5; }
	if($m =~ /^j/  ) { return  6; }
	if($m =~ /^a/  ) { return  7; }
	if($m =~ /^s/  ) { return  8; }
	if($m =~ /^o/  ) { return  9; }
	if($m =~ /^n/  ) { return 10; }
	return 11;
} # sub GetMonthNumber



sub MakeDate
{
	my $t = shift;
	$t = time unless $t > 0;
    my ($second,$minute,$hour,$day,$month,$year,$weekday,$yearday,$dst) = localtime($t);
    $year += 1900;
    $month = ('January','February','March','April','May','June','July','August','September','October','November','December')[$month];
    return "$month $day, $year";
} # sub MakeDate



sub CalculateResults
{
	print 'Tip: Bookmark to repeat this scan in the future.';
	my($stime,$etime) = (1,(time+3600));
	if($In{smon} or $In{sday} or $In{syear})
	{
		$In{smon} = $In{smon} =~ /\w/ ? GetMonthNumber($In{smon}) : 11;
		$In{sday} = 1 unless $In{sday} =~ /\d/;
		$In{syear} += 2000 if $In{syear} < 2000;
		$In{syear} -= 1900;
		$stime = timelocal(0,0,0,$In{sday},$In{smon},$In{syear});
	}
	if($In{emon} or $In{eday} or $In{eyear})
	{
		$In{emon} = $In{emon} =~ /\w/ ? GetMonthNumber($In{emon}) : 11;
		$In{eday} = 1 unless $In{eday} =~ /\d/;
		$In{eyear} += 2000 if $In{eyear} < 2000;
		$In{eyear} -= 1900;
		$etime = timelocal(0,0,0,$In{eday},$In{emon},$In{eyear});
	}
	($stime,$etime) = ($etime,$stime) if $etime < $stime;
	$etime += (60 * 60 * 24) - 1;
	my (%url,$realstart,$realend,@line,$haslines) = ();
	open R,"<$LogLocation";
	my $line = <R>;
	while($line < $stime)
	{
		$line = <R>;
		$line =~ s/s*$//s;
		last unless $line;
	}
	@line = split /\t/,$line;
	$realstart = MakeDate $line[0];
	$url{$line[3]}++;
	my $total = 1;
	if($line)
	{
		while($line <= $etime)
		{
			$line = <R>;
			$line =~ s/s*$//s;
			last unless $line;
			@line = split /\t/,$line;
			$url{$line[3]}++;
			$haslines = 1;
			$total++;
		}
	}
	close R;
	$realend = MakeDate $line[0];
	if($haslines)
	{
		my $highestnumber = 1;
		for(keys %url) { $highestnumber = $url{$_} if $url{$_} > $highestnumber; }
		my $multiplicand = 300 / $highestnumber;
		print <<PAGEPART;
<table style="margin-left:200px;margin-top:5px;margin-bottom:10px;" border="0" cellpadding="0" cellspacing="0">
<tr><td align="right">Start Date:</td><td> </td><td><span class="bold">$realstart</span></td></tr>
<tr><td align="right">End Date:</td><td> </td><td><span class="bold">$realend</span></td></tr>
<tr><td align="right">Total Views:</td><td> </td><td><span class="bold">$total</span></td></tr>
</table>
<table border="0" cellpadding="0" cellspacing="5">
PAGEPART
		for my $link (sort keys %url)
		{
			my $length = int $multiplicand * $url{$link};
			my $thispercent = int((($url{$link} / $total) * 1000) + .5) / 10;
			my $url = ($link =~ /\w/) ? qq~<a href="$link">$link</a>~ : '(no JavaScript and no referrer information)';
			print <<PAGEPART;
<tr>
<td align="right"><table class="bar" width="$length" border="0" cellpadding="0" cellspacing="0"><tr width="37" class="bar"><td class="bar"><span class="bar1point"> </span></td></tr></table></td>
<td align="right">$url{$link}</td>
<td align="right">${thispercent}%</td>
<td nowrap>$url</td>
</tr>
PAGEPART
		}
	} # if($total)
	else { print '<p class="bold" align="center">— No records —</p>'; }
	print '</table></td></tr><tr><td>';
} # sub CalculateResults


sub PresentForm
{
	print <<FORM;
<p class="bold">Scan Personal Statistics Log</p>
<p>
When specifying months, type either the month number, 
abbreviation, or spell it out. 
<span class="italic">For example,</span> 
September can be typed as "9", "Sep", or "September".
</p>
<p>
Years can be typed either 2 or 4 digits.
</p>
<p>
To see entire log file, leave dates blank.
</p>
<table border="0" cellpadding="0" cellspacing="0"><tr><td align="right">
<p>
Start date:   
Month <input type="text" name="smon" size="10">   
Day <input type="text" name="sday" size="4">   
Year <input type="text" name="syear" size="6">
</p>
<p>
End date:   
Month <input type="text" name="emon" size="10">   
Day <input type="text" name="eday" size="4">   
Year <input type="text" name="eyear" size="6">
</p>
</td></tr></table>
<p style="padding-left:150px;">
<input type="submit" name="calc" value="Scan">
</p>

FORM
} # sub PresentForm


for(split /&/,$ENV{QUERY_STRING})
{
	my($k,$v) = split /=/,$_,2;
	$In{$k} = $v;
}
print "Content-type: text/html\n\n";
print <<HEADING;
<html><title>Counter Log Scanner</title>
<style type="text/css">
<!--
BODY,TD,P {
	font-family: arial,helvetica,sans-serif; 
	font-size: 12px; 
	font-weight: normal;
	line-height: 18px;
	}
H3        { font-size: 14px; font-weight: bold;   }
.italic   { font-style: italic;  }
.bold     { font-weight: bold;   }
.nowrap   { white-space: nowrap; }
.bar      { font-size: 11px; line-height: 11px; background-color: gold; color: blue; }
A:link    { text-decoration: none; }
A:visited { text-decoration: none; }
A:active  { text-decoration: none; }
-->
</style>
</head>
<body bgcolor="white">
<form method="GET" action="$ME">
<div align="center">
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td width="200" valign="top" align="left"><a href="/software/"><img src="//www.willmaster.com/images/wmlogo_icon.gif" height="50" width="50" border="0"></a></td>
<td width="20"> </td>
<td align="center" valign="bottom">
<h3>Counter Log Scanner</h3>
<h3>Control Panel</h3>
</td>
<td width="20"> </td>
<td width="200"> </p>
</table>
</div>
 
<table align="center" width="500" border="1" cellpadding="20" cellspacing="0"><tr><td>
HEADING
CalculateResults if $In{calc};
PresentForm;
print '</td></tr></table>
</form>
Copyright 2006 Bontrager Connection LLC
</body>
</html>';
# end of file

Save the file under a name that makes sense to you. If the statistics are information no others should have access to, give this script a file name not easily guessable to give yourself a bit of protection.

The location of the log file needs to be specified at the only configuration line in the script. The location must point to the file that the personal statistics gathering script updates.

Installation

Upload both Perl scripts as plain text (not as binary files) with an FTP program. Give the scripts 755 permissions.

Type the URL of both scripts into your browser to verify they work as intended.

After the logging script has been loaded into the browser, there should be a log file where you specified it to be. The data viewing script should find the log file and display the hit.

Once both scripts are working as intended, put the tracking code into some content and try it out.

When the content is loaded into your browser, the logging script should make an entry to record the fact. And the data viewing script should find the entry and display it.

Once all works as it should, the tracking code can be pasted into as many different syndicated content files as you wish, even in the content of normal web pages on your own websites.

Will Bontrager

Was this article helpful to you?
(anonymous form)

Support This Website

Some of our support is from people like you who see the value of all that's offered for FREE at this website.

"Yes, let me contribute."

Amount (USD):

Tap to Choose
Contribution
Method

All information in WillMaster Library articles is presented AS-IS.

We only suggest and recommend what we believe is of value. As remuneration for the time and research involved to provide quality links, we generally use affiliate links when we can. Whenever we link to something not our own, you should assume they are affiliate links or that we benefit in some way.

How Can We Help You? balloons
How Can We Help You?
bullet Custom Programming
bullet Ready-Made Software
bullet Technical Support
bullet Possibilities Newsletter
bullet Website "How-To" Info
bullet Useful Information List

© 1998-2001 William and Mari Bontrager
© 2001-2011 Bontrager Connection, LLC
© 2011-2024 Will Bontrager Software LLC