Email Open Length Tracking with PHP
<p>I have been tracking emails for years using a "beacon" image and for those clients that allow the images to download it has worked great to track how many people have opened the email. </p>

<p>I came across the service "DidTheyReadIt" which shows how long the client actually read the email, I tested it with their free service and it is actually pretty close to the times I opened the email. </p>

<p>I am very curious in how they achieve the ability to track this, I am certain that whatever solution is chosen it will put a lot of load on the server / database and that many of the community will reply with "Stop, No and Dont" but I do want to investigate this and try it out, even if its just enough for me to run a test on the server and say "hell no". </p>

<p>I did some googling and found this article which has a basic solution <a href="http://www.re-cycledair.com/tracking-email-open-time-with-php" rel="nofollow">http://www.re-cycledair.com/tracking-email-open-time-with-php</a></p>

<p>I made a test using sleep() within the beacon image page:</p>

<pre><code>&lt;?php 

set_time_limit(300); //1000 seconds
ignore_user_abort(false);  

$hostname_api = "*";
$database_api = "*";
$username_api = "*";
$password_api = "*";

$api = mysql_pconnect($hostname_api, $username_api, $password_api) or     trigger_error(mysql_error(),E_USER_ERROR);
mysql_select_db($database_api, $api);

$fileName = "logo.png";

$InsertSQL = "INSERT INTO tracker (FileName,Time_Start,Time_End) VALUES   ('$fileName',Now(),Now()+1)";
mysql_select_db($database_api, $api);
$Result1 = mysql_query($InsertSQL, $api) or die(mysql_error());
$TRID = mysql_insert_id();

//Open the file, and send to user.

$fp = fopen($fileName, "r");
header("Content-type: image/png");
header('Content-Length: ' . filesize($fileName));
readfile($fileName);

set_time_limit(60);
$start = time();

for ($i = 0; $i &lt; 59; ++$i) {

// Update Read Time

$UpdateSQL = "UPDATE tracker SET Time_End = Now()  WHERE TRID = '$TRID'";
mysql_select_db($database_api, $api);
$Result1 = mysql_query($UpdateSQL, $api) or die(mysql_error());

time_sleep_until($start + $i + 1);
}

?&gt;
</code></pre>

<p>The problem with the code above (other than updating the database every second) is that once the script runs it continues to run even if the user disconnects (or moves to another email in this case).</p>

<p>I added "ignore_user_abort(false);", however as there is no connection to the mail client and the headers are already written I dont think the "ignore_user_abort(false);" can fire. </p>

<p>I looked at the post <a href="http://stackoverflow.com/questions/2958926/track-mass-email-campaigns">Track mass email campaigns</a> and one up from the bottom "Haragashi" says:</p>

<blockquote>
  <p>"You can simply build a tracking handler which returns the tracking image byte by byte. After every byte flush the response and sleep for a period of time.</p>
  
  <p>If you encounter a stream closed exception the client has closed the e-mail (deleted or changed to another e-mail who knows).</p>
  
  <p>At the time of the exception you know how long the client 'read' the e-mail."</p>
</blockquote>

<p>Does anyone know how I could "simply build a tracking handler" like this or know of a solution I can implement into my code that will force the code to stop running when the user disconnects?</p>
