Collect visitor stats using any image with the Piwik Tracking API
Piwik is an open source web analytics system in PHP and a great alternative to Google Analytics.
It offers simplified tracking via an image tracking code:
<!-- Piwik Image Tracker --> <img src="http://example.org/piwik/piwik.php?idsite=1&rec=1" style="border:0" alt="" /> <!-- End Piwik -->
In some scenarios, you might not want to expose that you are using Piwik analytics, or would like to avoid loading unnecessary resources.
Let’s use the Piwik Tracking API to turn any image into a tracker. This is useful for websites, newsletter stats and email signatures alike.
Prequisites
You need to have a Piwik install running with administrative access. Apache is required to get a “nice” image url.
Step 1 – Setup Piwik
Create a new website in Piwik, which will contain your stats for the image. Make note of the new site ID (Visible in Settings > Websites)
Create a new user and give that user admin rights to the website. Make note of the token_auth for that user. (Under Settings > Users)
Step 2 – Get the PiwikTracker.php Tracking API
You can obtain this file by going to the following URL (Replace example.org with your piwik install path)
http://example.org/piwik/index.php?module=SitesManager&action=downloadPiwikTracker&idSite={$IDSITE}&piwikUrl=http://example.org/piwik/
You can also find a copy of the file here.
Step 3 – Build the tracking code
Pick an image you’d like to use, name it stats.png and put it in a folder on your web server. I am going to use this “thumbs up” clipart. Also put PiwikTracker.php in this folder.
Now, create the file stats_t.php. (Base code below) Change line 3 and 4 to your own site id and the token_auth of the user you created in step 2. Also set your Piwik URL at line 10. If you want to distinguish between multiple tracking images, you can change line 22 to have a different message. That means you can track any number of images using one site in Piwik.
<?php
//Set the id of your piwik site here
$idSite = 1;
$token_auth = 'your user token here';
//Load Piwik Tracker
require_once 'PiwikTracker.php';
//Set the URL path to your Piwik Installation
$t = new PiwikTracker($idSite,'http://example.org/piwik');
//Auth to allow for more API functions
$t->setTokenAuth($token_auth);
//Set correct IP (Should be users, not the web server issuing the request)
$t->setIp($_SERVER['REMOTE_ADDR']);
//Set referrer (if applicable)
if(isset($_SERVER['HTTP_REFERER']))
$t->setUrl($_SERVER['HTTP_REFERER']);
$t->doTrackPageView('Image viewed');
$im = imagecreatefrompng("stats.png");
//For transparency (Alpha blending)
imagealphablending($im, true);
imagesavealpha($im, true);
//Set header
header('Content-Type: image/png');
//Output image
imagepng($im);
//Unload image
imagedestroy($im);
?>
You can set many more visitor details, refer to the reference.
Create a .htaccess file in the same folder. We will use this to rewrite the URL so that we can still use a .png extension for the file. When stats_t.png is called, Apache will instead load stats_t.php , which will run the tracking code.
RewriteEngine On RewriteRule stats_t.png stats_t.php
Your folder structure should now look like this:

Verify that your image is displayed properly in a web browser by navigating to stats_t.png
Verify that Piwik recorded the visit correctly. If it did not, make sure you have entered $token_auth and $idSite correctly.
Step 4 – Display your new tracking image anywhere
Now you can include your image anywhere, like this:
<img src="http://khromov.se/email2/stats_t.png" alt="thumbs up" />
If you would like more information please see the official documentation of the Tracking API.
Let me know if this helped you out or if you have any suggestions or improvements!
Update: Now includes referrer tracking. If the image is used on a page, you will see what page it is used on. (See line 19 and 20 of stats_t.php)
Tags: analytics, google, piwik, statistics, stats, tracking
You can comment below, or link to this permanent URL from your own site.
15/11/2011 at 20:06
Great tutorial on how to track newsletters open rates with Piwik
Would you mind also posting this on the forum.piwik.org ? I’m sure many people would enjoy this tip!
15/11/2011 at 23:51
Thanks Matt!
I have now posted it to the forums here:
http://forum.piwik.org/read.php?2,83123
I wanted to add proper URLs to the image tracker too, but had a security concern. If you have time, feel free to respond to my question here:
http://forum.piwik.org/read.php?2,83122
PS. You have really done a fantastic job on Piwik. Thank you for this great piece of software! DS.
21/12/2011 at 05:12
Hello,
I did same as you told but its not working… Its on evnts.in
http://evnts.in/analytics/ is my piwik installation..
21/12/2011 at 05:19
//Set your tracker URL
$t = new PiwikTracker($idSite,”);
Which address to give here?? of Piwik folder or the new folder where we have stats.png??
22/12/2011 at 01:15
Hi Vivek!
The PiwikTracker takes the site id, and the full URL to your piwik installation. In your case, that would be:
$t = new PiwikTracker($idSite,’http://evnts.in/analytics/‘);
I have simplified the code example, hopefully it is more clear now.
29/12/2011 at 17:43
Excellent post must test that right now a good way to track visibility in FB too if you add some random variable behind the image stats_png?1234
29/12/2011 at 18:07
It’s very easy to append custom ID to image stat. Just do something like…
stats_t.png?id=200
Then in the PHP:
$id = $_GET["id"];
…
$t->doTrackPageView(‘Image viewed with ID: ‘ . $id);
Cheers!
26/01/2012 at 16:55
For some reason the IP given in Piwik is my server IP, any thoughts?
$t->setIp($_SERVER['REMOTE_ADDR']);
26/01/2012 at 17:01
You need administrative permission for the web site to alter the IP this way.
If you have administrative permission for the site with that user, can you try using your global token_auth (API link in Piwik top menu.) and see if that works?
26/01/2012 at 17:08
I just figured it out. I had set my new user to admin rights, but I didn’t see there was a dropdown to select which website those rights belonged to.
Basically I gave admin rights for the right user, to the wrong id_site.
26/01/2012 at 17:32
The user access panel can be a bit unintuitive at first!
Good luck with your project!
26/01/2012 at 17:10
Thank you for the very quick reply btw, and the excellent script!
07/02/2012 at 05:37
Here’s some re-written code that uses expiration headers
setTokenAuth($token_auth);
//Set correct IP (Should be users, not the web server issuing the request)
$t->setIp($_SERVER['REMOTE_ADDR']);
//Set referrer (if applicable)
if(isset($_SERVER['HTTP_REFERER']))
{
$t->setUrl($_SERVER['HTTP_REFERER']);
}
$t->doTrackPageView('Strain Plumbing');
if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == filemtime($file))
{
header('Last-modified: '.date(DATERFC_1123, filemtime($img)), true, 304);
exit;
}
$im = imagecreatefrompng($img);
//For transparency (Alpha blending)
imagealphablending($im, true);
imagesavealpha($im, true);
//Set header
header('Content-Type: image/png');
header('Expires: '.date(DATE_RFC1123, time()+2592000));
header('Last-modified: '.date(DATE_RFC1123, filemtime($img)));
//Output image
imagepng($im);
//Unload image
imagedestroy($im);
07/02/2012 at 14:10
Could you explain the reasoning for this, specifically – why would it be beneficial to instruct the receiving browser to cache the image?
Loading the image multiple times is already correctly labeled as a returning visit (a “pageview”) in Piwik.
07/02/2012 at 14:22
Because YSlow! and PageSpeed complain about images that are not cached. =) If you are using a larger image, why resend it and waste bandwidth each time. Also if you are just capturing the view, then why waste CPU resources rebuilding and outputting the image. of course it’s probably not using up that much CPU for a single instance, but if you have a site getting thousands of hits, it can add up.
07/02/2012 at 14:46
Thanks for the info, I’ll try this out!
Edit:
It seems you are missing some variables, you haven’t specified $file or $img in your example.
You can post a full example to Pastebin or similar and link it here.
07/02/2012 at 16:19
Yeah – should have been $img
Here you go: http://pastebin.com/7PyMYq3m
07/02/2012 at 14:30
Of course thinking about it, you don’t don’t need to use the GD functions, you could do “echo file_get_contents($img);”