6

多年来,我一直使用“信标”图像跟踪电子邮件,对于那些允许下载图像的客户,它可以很好地跟踪有多少人打开了电子邮件。

我遇到了服务“DidTheyReadIt”,它显示了客户实际阅读电子邮件的时间,我用他们的免费服务对其进行了测试,它实际上非常接近我打开电子邮件的时间。

我很好奇他们是如何实现跟踪这一点的,我确信无论选择什么解决方案都会给服务器/数据库带来很大的负载,并且许多社区都会回复“停止,不和不要”但我确实想对此进行调查并尝试一下,即使它足以让我在服务器上运行测试并说“不”。

我做了一些谷歌搜索,发现这篇文章有一个基本的解决方案http://www.re-cycledair.com/tracking-email-open-time-with-php

我在信标图像页面中使用 sleep() 进行了测试:

<?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 < 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);
}

?>

上面代码的问题(除了每秒更新数据库)是,一旦脚本运行,即使用户断开连接(或在这种情况下移动到另一封电子邮件),它也会继续运行。

我添加了“ignore_user_abort(false);”,但是由于没有与邮件客户端的连接并且标题已经写入,我不认为“ignore_user_abort(false);” 可以开火。

我查看了跟踪大量电子邮件活动的帖子,从底部向上的一个“Haragashi”说:

“您可以简单地构建一个跟踪处理程序,该处理程序逐字节返回跟踪图像。每个字节后刷新响应并休眠一段时间。

如果您遇到流关闭异常,则客户端已关闭电子邮件(已删除或更改为另一个知道的电子邮件)。

在异常发生时,您知道客户“阅读”电子邮件的时间。”

有谁知道我如何可以像这样“简单地构建一个跟踪处理程序”,或者知道我可以在我的代码中实现的解决方案,该解决方案将在用户断开连接时强制代码停止运行?

4

2 回答 2

1

我认为问题在于您没有经常进行标头重定向。之所以有必要,是因为一旦脚本开始在 PHP+Apache 中执行,它基本上会忽略客户端,直到完成。如果您每隔 X 秒强制进行一次重定向,它会使服务器重新评估客户端是否仍处于连接状态。如果客户端未连接,则无法强制重定向,因此停止跟踪时间。

当我玩这些东西时,我的代码看起来像:

header("Content-type: image/gif");
while(!feof($fp)) {
    sleep(2);
    if(isset($_GET['clientID'])) {
        $redirect = $_SERVER['REQUEST_URI'];
    } else {
        $redirect = $_SERVER['REQUEST_URI'] . "&clientID=" . $clientID;
    }
    header("Location: $redirect");
    exit;
}

如果设置了客户端 ID,那么在此代码块上方,我将记录读取数据库中信标的尝试。每次服务器强制重定向时,很容易将电子邮件列上的时间增加 2 秒。

于 2012-06-30T12:52:46.727 回答
0

你会不会做更多这样的事情:

<?php
// Time the request
$time = time(); 

// Ignore user aborts and allow the script
// to run forever
ignore_user_abort(true);
set_time_limit(0);

// Run a pointless loop that sometime 
// hopefully will make us click away from 
// page or click the "Stop" button.
while(1)
{
    // Did the connection fail?
    if(connection_status() != CONNECTION_NORMAL)
    {
        break;
    }

    // Sleep for 1 seconds
    sleep(1);
}

// Connention is now terminated, so insert the amount of seconds since start
$duration = time() - $time;
于 2012-06-29T14:19:11.750 回答