Here is a simple ClickBank tracking script written in PHP that you can install on any of your websites free of charge. It can be used to track sales from AdWords and sales from EzineArticles and other article directories.
Installation
Installation is simple, just copy the file shown below (after modifying it slightly) up to your web hosting service. If you’re doing EzineArticles-friendly domain serving, install it in the root of the server, otherwise you can just create a new folder and install it there. For example, I might create a folder called “burnthefat” and place the index.php file in there. Any subsequent access to “http://www.mydomain.com/burnthefat/” would invoke the script and do a redirection.
Before uploading the script, be sure to modify the default $affiliateid and $vendorid values. They are currently set to ‘egiguere’ (my primary CB affiliate ID) and ‘burnthefat’ (the vendor ID for Burn the Fat, Feed the Muscle). Set them to appropriate defaults. You can override these settings when invoking the script. (If you’re planning on using the domain with EzineArticles, you MUST set the affiliate and vendor ID values correctly because you can only link to the root of the URL with no parameters.)
Now this is totally optional, but you may also want to add these lines to a .htaccess file that you place in the same directory as the index.php file:
<Files *.log>
order allow,deny
deny from all
</Files>
These lines ensure that no one can download the .csv files the script creates — you’ll have to fetch them yourself using an FTP client. (Like I said, optional…)
Tracking EzineArticles and Other Sites
The script looks at the referrer header and tries to build a tracking ID that incorporates part of the domain name and some kind of unique identifier. For EzineArticles, for example, it uses the “id” field (the article identifier). So you can easily tell which article of yours generated the click. It looks for “id”, “C” (which is used by GoArticles) and “kw”. You can easily modify it to look for other things.
The tracking ID generated in these cases consists of the date and time (in MMDDHHSS format — 8 characters long, i.e. “03091347″), some portion of the domain name (i.e. “ezineartic”), and the article ID (i.e. “672234″). So when you see this show up in your ClickBank report:
03091347ezineartic672234
you’ll know the click came on 13:47 on March 9 from EzineArticles article #672234.
Tracking AdWords Clicks
The script has some built-in features for tracking AdWords clicks, but only if you use a special syntax in your destination URLs, like so:
http://www.yoursite.com/?ag=rf01&nw={ifsearch:s}{ifcontent:c}
&kw={keyword:none}&pl={placement}
This is what the values mean:
ag — an identifier for the ad group or whatever unique thing you want to track, i.e. if you have two different ad texts you might want to assign two different values here
nw — the network being used. Note the special “{ifsearch:s}{ifcontent:c}” syntax. On the search network, the value will end up being “nw=s”, on the content network it will end up being “nw=c”. This is how you tell where the click comes from.
kw — the keyword that triggered the ad, if known, or “none” if not known.
pl — the website the ad was featured on if it’s shown on a third-party site.
As you see, you can pack a lot of information into the destination URL. The script will store all this information in the CSV files it creates and it will use it to create a tracking ID. The tracking ID will start with the date (MMDDHHSS as before) followed by “aw” (for “AdWords”), followed by one character for the network (“s” for search, “c” for content, “u” if unknown), followed by the ad group (the “ag” value), followed by as much of the keyword (the “kw” value) as will fit. (Tracking IDs are limited to 24 characters, remember.)
Other Sources
If the script doesn’t have enough information to create a (semi)human-readable tracking ID, it generates a random number and prefixes it with the date (in MMDDHHSS format) and uses that as the tracking ID.
Overriding Affiliate and Vendor IDs
You can set the affiliate ID and vendor ID explicitly by using the “affiliateid” and “vendorid” query parameters, as in:
http://www.feedthemuscleburnthefat.com/?vendorid=4idiots
This is useful if you want to use the same script for multiple redirections.
Analyzing the Data in Detail
The tracking IDs the script creates are meant to be easily eyeballed in the ClickBank sales report. But if you want to know more about the context of a particular tracking ID, the script stores information in simple CSV (comma-separated value) files that you can easily download and load into a spreadsheet application like Microsoft Excel. A separate file is created for each day, so the clicks for March 8, 2010 are found in “clicks.2010-03-08.csv”, in the same folder as the index.php file.
So when you see a click in your ClickBank sales report and you want to know more about it, look at the first 4 characters of the tracking ID to extract the month and day to know which file to download and open in Excel. The following data is stored, in this order:
The full date and time
The tracking ID
The final affiliate ID
The visitor’s IP address
The full path that was requested, including any parameters
The referrer URL, if any
The user-agent header, if any (useful for discerning robots from humans)
The Script
Here it is. Either download this text file or copy the text below; place the text into a file called index.php and copy it up to your webserver.
<?php
//*************************************************************
//
// ClickBank Tracking Script
// Version 1.0
// Copyright 2010 by Eric Giguere
// ericgiguere@ericgiguere.com
//
// You may use this script for free on as many sites as you want.
// You cannot sell this script or otherwise claim ownership.
// This script is provided as-is, no warranties are implied.
//
// For installation instructions, see
// http://www.memwg.com/clickbank-tracking-script/
//
//*************************************************************
// Modify these values to set your affiliate ID, the vendor ID,
// and any additional data (i.e. '&page=1928') to append to the
// final hoplink after the tracking ID.
//*************************************************************
$affiliateid = $_GET['affiliateid'];
$vendorid = $_GET['vendorid'];
$extra = $_GET['extra'];
if( empty( $affiliateid ) ) $affiliateid = 'egiguere';
if( empty( $vendorid ) ) $vendorid = 'burnthefat';
//*************************************************************
// You shouldn't need to change anything below this point.
//*************************************************************
// Gather information about the visitor.
$ip = $_SERVER['REMOTE_ADDR'];
$referrer = $_SERVER['HTTP_REFERER'];
$browser = $_SERVER['HTTP_USER_AGENT'];
$request = $_SERVER['REQUEST_URI'];
$reqtime = date( 'Y/m/d H:i:s T' );
$logfile = 'clicks.' . date( 'Y-m-d' ) . '.csv';
$prefix = date( 'mdHi' );
$source = '';
$tid = '';
// Check query parameters to determine if we are being called
// from AdWords. If we are, gather the requisite info. If not,
// try to figure out where we're being called from using the
// referrer header.
if( !empty( $_GET['kw'] ) || !empty( $_GET['ag'] ) || !empty( $_GET['nw'] ) ){
$nw = strtolower( $_GET['nw'] );
if( strlen( $nw ) != 1 ){
$nw = 'u';
}
$source = 'aw' . $nw;
$keyword = $_GET['kw'];
$adgroup = $_GET['ag'];
$tid = substr( $prefix . $source . $adgroup . makealphanum( $keyword ), 0, 24 );
}
// If we weren't called from AdWords, check the referrer header and
// see if we can suss out an identifier of some kind and combine it
// with the domain name to create a tracking ID.
if( empty( $tid ) && !empty( $referrer ) ){
$referrerparts = parse_url( trim( $referrer ) );
$host = ( $referrerparts['host'] ? $referrerparts['host'] :
array_shift( explode( '/', $referrerparts['path'], 2 ) ) );
$params = parse_query( $referrerparts['query'] );
$hostparts = preg_split( '/\./', $host );
$tld = count( $hostparts ) - 1;
if( $tld > 0 ){
$domain = $hostparts[$tld-1];
$ids = array( 'id', 'C', 'kw' );
foreach( $ids as $param ){
if( !empty( $params[$param] ) ){
$source = makealphanum( $params[$param] );
}
if( $source ) break;
}
if( !empty( $source ) ){
$tid = $prefix . substr( $domain . $source, -16 );
}
}
}
// Last resort: we weren't able to create a tracking ID, so
// generate a unique string to server as our ID.
if( empty( $tid ) ){
$tid = substr( getfaketid( $prefix ), 0, 24 );
}
$afflink = 'http://' . $affiliateid . '.' . $vendorid .
'.hop.clickbank.net/?tid=' . $tid . $extra;
header( "Location: $afflink" );
// Write out the data to our CSV file
$fp = fopen( $logfile, 'a' );
if( $fp ){
fputs( $fp, logmsg() );
fclose( $fp );
}
//*************************************************************
// Functions used by the code above...
//*************************************************************
// Convert the string to a lower case alphanumeric-only string
function makealphanum( $str ){
return ereg_replace( '[^a-z0-9]', '', strtolower( urldecode( $str ) ) );
}
// Parse a query string into its constituent parts
function parse_query( $var ){
$var = html_entity_decode( $var );
$var = explode( '&', $var );
$arr = array();
foreach( $var as $val ){
$x = explode( '=', $val );
$arr[$x[0]] = $x[1];
}
unset( $val, $x, $var );
return $arr;
}
// Encode URLs for saving in the CSV file by converting
// quotes and commas to URL escapes.
function csvencode( $str ){
$str = str_replace( '"', '%22', $str );
$str = str_replace( ',', '%2C', $str );
return $str;
}
// Create the line of CSV data to append to the log file
function logmsg(){
global $request;
global $ip;
global $referrer;
global $browser;
global $tid;
global $reqtime;
global $afflink;
$msg = "$reqtime,$tid,$afflink,$ip," . csvencode( $request ) . ","
. csvencode( $referrer ) . "," . csvencode( $browser );
return $msg . "\n";
}
// Generate a fake TID with the given prefix.
function getfaketid( $prefix ){
return uniqid( $prefix );
}
?>
Final Thoughts
OK, user-friendly this isn’t, I admit it. It’s very geeky. But if you’re even a bit technically inclined you should be able to install this script and use it. If you have questions about it, please leave them as comments here rather than mailing me, it’ll be more useful for others.
|