Piwik: Tracking Email Openings via API Using PHP

Our Programming Task: Track Email Openings via Piwik and using a Tracking Image

Currently working at a university we have to abide by certain regulations such as FERPA and HIPAA guidelines. As a web developer that currently means I cannot use Google Web Analytics or a majority of the services Google provides (due to Privacy concerns for student data, etc).

In order to still perform Web Analytics we have running an instance of Piwik. Piwik is a great piece of software that is constantly evolving to offer more analytics features, currently Piwik is in the 1.x Release — they are developing a new 2.0 version of Piwik.

Recently we wanted to start tracking Opening of emails that we send out. We actually send out emails to campus students using our own services (eg a Cron job that does mailings from a Drush script for Drupal users), and not a 3rd party provider such as SurveyMonkey, or SendGrid. I typically use Swiftmailer from PHP to send out mass-mailings, I really like its API.

So we already send emails from Drupal and PHP. We want to alter our emails to provide an HTML email that can show an image banner of our department and when the image is loaded tracks that event in Piwik. How can we accomplish this?

The steps we want to complete are as follows:

  1. Generate a banner, or some image we want to load to track user data (typically this is a 1px by 1px tracking gif. Reddit uses this 1px approach for analytics). We will use a bigger banner to be shared in the email and main website.

  2. When the PNG image is loaded, redirect its HTTP request to custom PHP code that performs analytics tracking.

  3. Output the original requested image to the visitor as if no tracking ever occurred.

Implementing the solution

Our Drupal installation is proxied through Nginx to Apache+PHP. Eg, Nginx loads images and static files (and does so better than Apache) while Apache deals with PHP.

For (1) using only Apache we use a rewrite rule to redirect our image request to PHP.

RewriteRule  /campaign-tracking/my-tracking-image.png  /campaign-tracking/tracking.php

In my proxy Nginx->Apache setup we need to tell Nginx about the tracking image in our nginx.conf:

location = /campaign-tracking/my-tracking-image.png {  rewrite ^ /campaign-tracking/tracking.php permanent; }

This way our custom code is executed for tracking of visitors.

Then for (2) and (3) we write some PHP using the Piwik Tracking API specifically the official PHP binding PiwikTracking.php.

Our code looks like this in the file tracking.php:

/**
 * Campaign Tracking page for websites.
 *
 * This webpage is to be used by the project to enable Piwik Analytics
 * tracking of sent emails and any other campaigns we may need.
 *
 * This page requires some setup and know-how on how to use.
 *
 * Requirements:
 *
 * Apache should ignore this directory and file from being processed by Drupal.
 * This is to not load down the server with unnecessary traffic hitting Drupal,
 * database load, etc.
 *
 * This file can be ignored by including the following RewriteCond rule in
 * Apache for the Drupal website:
 *
 *       RewriteCond %{REQUEST_URI} "/piwik/" [OR]
 *       RewriteCond %{REQUEST_URL} "/campaign-tracking/" [OR]
 *
 * This way this resource becomes a simple single file PHP file of work
 * for the webserver, not a full DRUPAL_BOOTSTRAP.
 *
 * TODO: robots.txt entry ?
 *
 * This page can then be called with the following parameters to perform
 * campaign tracking. In general this page will help to build tracking URLs:
 * http://piwik.org/docs/tracking-campaigns/url-builder/
 *
 * https://WEBSITE.COM/campaign-tracking/index.php?pk_campaign=student-notice&pk_kwd=09062013
 *
 * You can call a tracking png as follows as the img-src for an html image tag:
 * https://WEBSITE.COM/campaign-tracking/logo_t.png?pk_campaign=student-notice&pk_kwd=09062013
 *
 *
 * Where pk_campaign is the name of a campaign. And, pk_kwd is a keyword associated to a campaign.
 *
 */

$piwik_service_url = 'https://WEBSITE.COM/piwik/';
$token_auth = '*******************************************';
$idSite = ($_SERVER['SERVER_NAME'] === 'site1.com') ? 1 : NULL;
$idSite = ($_SERVER['SERVER_NAME'] === 'site2.com') ? 7 : NULL;
if (!$idSite) exit;

$input = filter_input_array(INPUT_GET,
    array(
      'pk_campaign' => FILTER_SANITiZE_NUMBER_INT,
      'pk_kwd' => FILTER_SANITiZE_NUMBER_INT
    )
);
$campaign = $input['pk_campaign'][0];
$keyword = $input['pk_kwd'][0];

if (!preg_match('/bot|crawl|slurp|spider/i', $_SERVER['HTTP_USER_AGENT'])) {
  require_once 'PiwikTracker.php';
  $t = new PiwikTracker($idSite, $piwik_service_url);
  $t->setTokenAuth($token_auth);

  $t->setIp($_SERVER['REMOTE_ADDR']);
  $t->setUrl('https://SITENAME.COM/campaign-tracking/index.html?pk_campaign= ' . $campaign . '&pk_kwd=' . $keyword);
  $t->doTrackPageView(Email Campaigns');
}

$im = imagecreatefrompng("logo.png");
//For transparency (Alpha blending)
imagealphablending($im, TRUE);
imagesavealpha($im, TRUE);

header('Content-Type: image/png');
imagepng($im);
imagedestroy($im);

This code is fairly simple PHP that insert values for a Piwik Campaign. It attempts to avoid user agents which appear to not be true human visitors and also looks that all the correct keys are provided.

Looking for quality Drupal Web Hosting? Look no further than Arvixe Web Hosting!

Tags: , , , , , , , , , , , | Posted under Piwik, Webmail | RSS 2.0

Author Spotlight

David Gurba

David Gurba

I am a web programmer currently employed at UCSB. I have been developing web applications professionally for 8+ years now. For the last 5 years I’ve been actively developing websites primarily in PHP using Drupal. I have experience using LAMP and developing data driven websites for clients in aviation, higher education and e-commerce. If you’d like to contact me I can be reached at david.gurba@arvixe.com

Leave a Reply

Your email address will not be published. Required fields are marked *


1 + = 5

You may use these HTML tags and attributes: <a href="" title="" rel=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>