- Implements open tracking
This commit is contained in:
@ -84,6 +84,7 @@ class Initializer {
|
|||||||
$newsletter_links = Env::$db_prefix . 'newsletter_links';
|
$newsletter_links = Env::$db_prefix . 'newsletter_links';
|
||||||
$statistics_newsletters = Env::$db_prefix . 'statistics_newsletters';
|
$statistics_newsletters = Env::$db_prefix . 'statistics_newsletters';
|
||||||
$statistics_clicks = Env::$db_prefix . 'statistics_clicks';
|
$statistics_clicks = Env::$db_prefix . 'statistics_clicks';
|
||||||
|
$statistics_opens = Env::$db_prefix . 'statistics_opens';
|
||||||
|
|
||||||
define('MP_SETTINGS_TABLE', $settings);
|
define('MP_SETTINGS_TABLE', $settings);
|
||||||
define('MP_SEGMENTS_TABLE', $segments);
|
define('MP_SEGMENTS_TABLE', $segments);
|
||||||
@ -101,6 +102,7 @@ class Initializer {
|
|||||||
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
define('MP_NEWSLETTER_OPTION_TABLE', $newsletter_option);
|
||||||
define('MP_STATISTICS_NEWSLETTERS_TABLE', $statistics_newsletters);
|
define('MP_STATISTICS_NEWSLETTERS_TABLE', $statistics_newsletters);
|
||||||
define('MP_STATISTICS_CLICKS_TABLE', $statistics_clicks);
|
define('MP_STATISTICS_CLICKS_TABLE', $statistics_clicks);
|
||||||
|
define('MP_STATISTICS_OPENS_TABLE', $statistics_opens);
|
||||||
}
|
}
|
||||||
|
|
||||||
function runMigrator() {
|
function runMigrator() {
|
||||||
|
@ -26,6 +26,7 @@ class Migrator {
|
|||||||
'forms',
|
'forms',
|
||||||
'statistics_newsletters',
|
'statistics_newsletters',
|
||||||
'statistics_clicks',
|
'statistics_clicks',
|
||||||
|
'statistics_opens'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,6 +294,20 @@ class Migrator {
|
|||||||
return $this->sqlify(__FUNCTION__, $attributes);
|
return $this->sqlify(__FUNCTION__, $attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function statistics_opens() {
|
||||||
|
$attributes = array(
|
||||||
|
'id mediumint(9) NOT NULL AUTO_INCREMENT,',
|
||||||
|
'newsletter_id mediumint(9) NOT NULL,',
|
||||||
|
'subscriber_id mediumint(9) NOT NULL,',
|
||||||
|
'queue_id mediumint(9) NOT NULL,',
|
||||||
|
'created_at TIMESTAMP NOT NULL DEFAULT 0,',
|
||||||
|
'deleted_at TIMESTAMP NULL DEFAULT NULL,',
|
||||||
|
'updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,',
|
||||||
|
'PRIMARY KEY (id)',
|
||||||
|
);
|
||||||
|
return $this->sqlify(__FUNCTION__, $attributes);
|
||||||
|
}
|
||||||
|
|
||||||
private function sqlify($model, $attributes) {
|
private function sqlify($model, $attributes) {
|
||||||
$table = $this->prefix . $model;
|
$table = $this->prefix . $model;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
namespace MailPoet\Config;
|
namespace MailPoet\Config;
|
||||||
|
|
||||||
use MailPoet\Cron\Daemon;
|
use MailPoet\Cron\Daemon;
|
||||||
|
use MailPoet\Statistics\Track\Opens;
|
||||||
use MailPoet\Subscription;
|
use MailPoet\Subscription;
|
||||||
use MailPoet\Statistics\Track\Clicks;
|
use MailPoet\Statistics\Track\Clicks;
|
||||||
use MailPoet\Util\Helpers;
|
use MailPoet\Util\Helpers;
|
||||||
@ -54,6 +55,9 @@ class PublicAPI {
|
|||||||
if($this->action === 'click') {
|
if($this->action === 'click') {
|
||||||
$track_class = new Clicks($this->data);
|
$track_class = new Clicks($this->data);
|
||||||
}
|
}
|
||||||
|
if($this->action === 'open') {
|
||||||
|
$track_class = new Opens($this->data);
|
||||||
|
}
|
||||||
if(!isset($track_class)) return;
|
if(!isset($track_class)) return;
|
||||||
$track_class->track();
|
$track_class->track();
|
||||||
} catch(\Exception $e) {
|
} catch(\Exception $e) {
|
||||||
|
@ -9,6 +9,7 @@ use MailPoet\Models\Setting;
|
|||||||
use MailPoet\Models\StatisticsNewsletters;
|
use MailPoet\Models\StatisticsNewsletters;
|
||||||
use MailPoet\Models\Subscriber;
|
use MailPoet\Models\Subscriber;
|
||||||
use MailPoet\Newsletter\Links\Links;
|
use MailPoet\Newsletter\Links\Links;
|
||||||
|
use MailPoet\Newsletter\Renderer\PostProcess\OpenTracking;
|
||||||
use MailPoet\Newsletter\Renderer\Renderer;
|
use MailPoet\Newsletter\Renderer\Renderer;
|
||||||
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
use MailPoet\Newsletter\Shortcodes\Shortcodes;
|
||||||
use MailPoet\Util\Helpers;
|
use MailPoet\Util\Helpers;
|
||||||
@ -74,6 +75,10 @@ class SendingQueue {
|
|||||||
// check if newsletter has been rendered, in which case return its contents
|
// check if newsletter has been rendered, in which case return its contents
|
||||||
// or render and save for future reuse
|
// or render and save for future reuse
|
||||||
if($queue->newsletter_rendered_body === null) {
|
if($queue->newsletter_rendered_body === null) {
|
||||||
|
// insert tracking code
|
||||||
|
add_filter('mailpoet_rendering_post_process', function($template) {
|
||||||
|
return OpenTracking::process($template);
|
||||||
|
});
|
||||||
// render newsletter
|
// render newsletter
|
||||||
$rendered_newsletter = $this->renderNewsletter($newsletter);
|
$rendered_newsletter = $this->renderNewsletter($newsletter);
|
||||||
if((boolean) Setting::getValue('tracking.enabled')) {
|
if((boolean) Setting::getValue('tracking.enabled')) {
|
||||||
|
@ -3,8 +3,8 @@ namespace MailPoet\Models;
|
|||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class StatisticsClicks extends Model {
|
class StatisticsOpens extends Model {
|
||||||
public static $_table = MP_STATISTICS_CLICKS_TABLE;
|
public static $_table = MP_STATISTICS_OPENS_TABLE;
|
||||||
|
|
||||||
function __construct() {
|
function __construct() {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
@ -2,12 +2,14 @@
|
|||||||
namespace MailPoet\Newsletter\Renderer\PostProcess;
|
namespace MailPoet\Newsletter\Renderer\PostProcess;
|
||||||
|
|
||||||
class OpenTracking {
|
class OpenTracking {
|
||||||
static function process($template, $user_id) {
|
static function process($template) {
|
||||||
$DOM = new \pQuery();
|
$DOM = new \pQuery();
|
||||||
|
$DOM = $DOM->parseStr($template);
|
||||||
$template = $DOM->query('body');
|
$template = $DOM->query('body');
|
||||||
$open_tracking_link = sprintf(
|
$open_tracking_link = sprintf(
|
||||||
'<img alt="" src="%s/?mailpoet&endpoint=track&action=open&data=[mailpoet_data]',
|
'<img alt="" class="" src="%s/%s"/>',
|
||||||
home_url()
|
home_url(),
|
||||||
|
htmlentities('?mailpoet&endpoint=track&action=open&data=[mailpoet_data]')
|
||||||
);
|
);
|
||||||
$template->html($template->html() . $open_tracking_link);
|
$template->html($template->html() . $open_tracking_link);
|
||||||
return $DOM->__toString();
|
return $DOM->__toString();
|
||||||
|
@ -1,60 +1,39 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace MailPoet\Statistics\Track;
|
namespace MailPoet\Statistics\Track;
|
||||||
|
|
||||||
use MailPoet\Models\NewsletterLink;
|
use MailPoet\Models\StatisticsOpens;
|
||||||
use MailPoet\Models\StatisticsClicks;
|
|
||||||
use MailPoet\Models\Subscriber;
|
use MailPoet\Models\Subscriber;
|
||||||
use MailPoet\Subscription\Url as SubscriptionUrl;
|
|
||||||
use MailPoet\Util\Helpers;
|
|
||||||
|
|
||||||
if(!defined('ABSPATH')) exit;
|
if(!defined('ABSPATH')) exit;
|
||||||
|
|
||||||
class Opens {
|
class Opens {
|
||||||
public $url;
|
public $data;
|
||||||
|
|
||||||
function __construct($url) {
|
function __construct($data) {
|
||||||
$this->url = $url;
|
$this->data = $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
function track($url = false) {
|
function track($data = false) {
|
||||||
$url = ($url) ? $url : $this->url;
|
$data = ($data) ? $data : $this->data;
|
||||||
if(!preg_match('/\d+-\d+-\d+$/', $url)) $this->abort();
|
if(!preg_match('/\d+-\d+-\d+/', $data)) $this->abort();
|
||||||
list ($newsletter_id, $subscriber_id, $queue_id) = explode('-', $url);
|
list ($newsletter_id, $subscriber_id, $queue_id) = explode('-', $data);
|
||||||
$subscriber = Subscriber::findOne($subscriber_id);
|
$subscriber = Subscriber::findOne($subscriber_id);
|
||||||
if(!$subscriber) return;
|
if(!$subscriber) return;
|
||||||
$statistics = StatisticsOpens::where('link_id', $link->id)
|
$statistics = StatisticsOpens::where('subscriber_id', $subscriber_id)
|
||||||
->where('subscriber_id', $subscriber_id)
|
|
||||||
->where('newsletter_id', $newsletter_id)
|
->where('newsletter_id', $newsletter_id)
|
||||||
->where('queue_id', $queue_id)
|
->where('queue_id', $queue_id)
|
||||||
->findOne();
|
->findOne();
|
||||||
if(!$statistics) {
|
if(!$statistics) {
|
||||||
$statistics = StatisticsClicks::create();
|
$statistics = StatisticsOpens::create();
|
||||||
$statistics->newsletter_id = $newsletter_id;
|
$statistics->newsletter_id = $newsletter_id;
|
||||||
$statistics->link_id = $link->id;
|
|
||||||
$statistics->subscriber_id = $subscriber_id;
|
$statistics->subscriber_id = $subscriber_id;
|
||||||
$statistics->queue_id = $queue_id;
|
$statistics->queue_id = $queue_id;
|
||||||
$statistics->count = 1;
|
|
||||||
$statistics->save();
|
|
||||||
} else {
|
|
||||||
$statistics->count++;
|
|
||||||
$statistics->save();
|
$statistics->save();
|
||||||
}
|
}
|
||||||
$url = (preg_match('/\[subscription:.*?\]/', $link->url)) ?
|
header('Content-Type: image/gif');
|
||||||
$this->processSubscriptionUrl($link->url, $subscriber) :
|
// return 1x1 pixel transparent gif image
|
||||||
$link->url;
|
echo "\x47\x49\x46\x38\x37\x61\x1\x0\x1\x0\x80\x0\x0\xfc\x6a\x6c\x0\x0\x0\x2c\x0\x0\x0\x0\x1\x0\x1\x0\x0\x2\x2\x44\x1\x0\x3b";
|
||||||
header('Location: ' . $url, true, 302);
|
exit;
|
||||||
}
|
|
||||||
|
|
||||||
function processSubscriptionUrl($url, $subscriber) {
|
|
||||||
preg_match('/\[subscription:(.*?)\]/', $url, $match);
|
|
||||||
$action = $match[1];
|
|
||||||
if(preg_match('/unsubscribe/', $action)) {
|
|
||||||
$url = SubscriptionUrl::getUnsubscribeUrl($subscriber);
|
|
||||||
}
|
|
||||||
if(preg_match('/manage/', $action)) {
|
|
||||||
$url = SubscriptionUrl::getManageUrl($subscriber);
|
|
||||||
}
|
|
||||||
return $url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function abort() {
|
private function abort() {
|
||||||
|
Reference in New Issue
Block a user