Monthly Archives: March 2011

Tracking Email Open Time with PHP

You can download my code for this article here.
Some time ago I had great aspirations of launching a web company that does email tracking and analytics. One of the things that I really wanted to figure out but wasn’t well documented on the web was how to track how long a user had a particular email open. When a company like MailChimp wants to track emails that they are sending out, they put a small image in the email called a “beacon”. When the user opens the email, the beacon image is requested from the server. The server sends the image, but not before it gathers information about the computer requesting it. The works great for checking if an email was opened, or what platform the person is on, but it doesn’t work at all for determining how long the email was open for.

One option that came to mind for checking the open time of an email was long polling.  Long polling (in this case) would use Javascript to contact the server every X seconds after the email was loaded.  Using those requests, it’d be trivial to find out how long it was open for.  Unfortunately, most (if not all) email clients don’t allow the execution of Javascript within emails, so that idea was completely sank.  The only option I had left was to use the beacon image to somehow determine open time.

The only option I could think of for using the image beacon without any Javascript was to redirect the image back to itself.  After much trial and error, I came up with the following.

//Open the file, and send to user.
$fileName = "../img/beacon.gif";
$fp = fopen($fileName, "r");
header("Content-type: image/gif");
while(!feof($fp)) {
    //Do a redirect for the timing.?
    sleep(2);
    if(isset($_GET['clientID'])) {
    	$redirect = $_SERVER['REQUEST_URI'];
    } else {
    	$redirect = $_SERVER['REQUEST_URI'] . "?clientID=" . $clientID;
    }
    header("Location: $redirect");
}

So what’s happening in this code?  First of all, we’re opening a small GIF file that we’re going to pretend to send to the user.  The second step is to send a header for an image file to the user so that their mail client expects one to be delivered.  This step is important because if the header isn’t sent, the browser/mail client will close the connection.  After that, you make the request sleep for a few seconds (as few or as many as you want depending on how granular you want your timing data to be) and then redirect back to the same page.  The “if” statement within the while loop is there so you can identify incoming requests and log the data accordingly.

So there you have it.  If you’ve ever wondered how people track the open time of an email, it’s probably a method very similar to this.  The only caveat to this method is that it relies on the user loading images in an email.  However, if you have a large enough sample you can just take the average open time from the users that did open it and be fairly confident with that.

Note: There has been some discussion over on Stack Overflow about this article. You may find it helpful.

 

If you liked this article, then you may like:

  • PHP Dark Arts: Multi-Processing (Part 1)
  • PHP Dark Arts: Multi-Processing (Part 2)
  • PHP Dark Arts: Shared Memory Segments (IPC)
  • PHP Dark Arts: Semaphores
  • PHP Dark Arts: GUI Programming with GTK
  • PHP Dark Arts: Sockets
  • PHP Dark Arts: Daemonizing a Process