2012-06-29 108 views
6

我一直在使用「信標」圖像跟蹤多年的電子郵件,對於那些允許圖像下載的客戶端,它可以很好地跟蹤有多少人打開了電子郵件。用PHP發送電子郵件打開長度跟蹤

我遇到了「DidTheyReadIt」這項服務,它顯示了客戶實際閱讀電子郵件的時間,我用他們的免費服務對它進行了測試,實際上與我打開電子郵件的時間非常接近。

我很好奇他們如何實現跟蹤這個功能,我確信無論選擇哪種解決方案,它都會在服務器/數據庫上施加很多負擔,並且許多社區將以「停止,不,不「,但我確實想調查一下並嘗試一下,即使它足以讓我在服務器上運行測試並說」不會「。

我做了一些使用Google和發現本文,其具有鹼性溶液http://www.re-cycledair.com/tracking-email-open-time-with-php

我的信標圖像的頁面內使用睡眠()做了一個試驗:

<?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);」可以開火。

我看了看後Track mass email campaigns和一起來從下「Haragashi」說:

「你可以簡單地建立它返回字節跟蹤圖像字節的跟蹤處理後的每一個字節地刷新響應。睡了一段時間。

如果遇到流閉合異常的客戶端已經關閉了電子郵件(刪除或更改到其他電子郵件誰知道)。

在異常時你知道客戶'閱讀'電子郵件多久了。「

有誰知道我可以「簡單地建立一個跟蹤處理」這樣的或知道一個解決方案,我可以實現到我的代碼,這將迫使代碼停止運行在用戶斷開連接的時候?

回答

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秒很容易。

+0

客戶沒有太多的重定向,所以這比理論上的答案更有意義。這也不是OP引用的內容。 – hakre

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; 
+0

感謝您發佈上面的代碼。我試過了,當我在瀏覽器中單擊停止時,插入不會發生在$ duration = $ time() - $ time之後;我試着把睡眠後的db插入(1);它會每秒更新一次,但是如果我停止腳本繼續執行的話。 – jdublu

+0

忽略用戶中止設置爲false,這是有道理的,它不會停止,直到超時也沒有設置。 –

+1

也會每次發送一個字節,否則PHP將不會注意到連接是否關閉。創建一些流量。 – hakre