Add tracking cookie

[MAILPOET-1961]
This commit is contained in:
Pavel Dohnal
2019-04-15 15:41:03 +02:00
committed by Ján Mikláš
parent 534dc140f7
commit bdaff6fc30
7 changed files with 114 additions and 18 deletions

View File

@@ -78,8 +78,10 @@ class ContainerConfigurator implements IContainerConfigurator {
// Router
$container->autowire(\MailPoet\Router\Endpoints\CronDaemon::class)->setPublic(true);
$container->autowire(\MailPoet\Router\Endpoints\Subscription::class)->setPublic(true);
$container->autowire(\MailPoet\Router\Endpoints\Track::class)->setPublic(true);
$container->autowire(\MailPoet\Router\Endpoints\ViewInBrowser::class)->setPublic(true);
$container->autowire(\MailPoet\Router\Endpoints\Track::class)->setPublic(true);
$container->autowire(\MailPoet\Statistics\Track\Clicks::class);
$container->autowire(\MailPoet\Statistics\Track\Opens::class);
$container->autowire(\MailPoet\Router\Router::class)
->setArgument('$container', new Reference(ContainerWrapper::class));
// Mailer

View File

@@ -27,14 +27,23 @@ class Track {
'global' => AccessControl::NO_ACCESS_RESTRICTION
);
/** @var Clicks */
private $clicks;
/** @var Opens */
private $opens;
public function __construct(Clicks $clicks, Opens $opens) {
$this->clicks = $clicks;
$this->opens = $opens;
}
function click($data) {
$click_event = new Clicks();
return $click_event->track($this->_processTrackData($data));
return $this->clicks->track($this->_processTrackData($data));
}
function open($data) {
$open_event = new Opens();
return $open_event->track($this->_processTrackData($data));
return $this->opens->track($this->_processTrackData($data));
}
function _processTrackData($data) {

View File

@@ -4,11 +4,22 @@ namespace MailPoet\Statistics\Track;
use MailPoet\Models\StatisticsClicks;
use MailPoet\Newsletter\Shortcodes\Categories\Link;
use MailPoet\Newsletter\Shortcodes\Shortcodes;
use MailPoet\Settings\SettingsController;
use MailPoet\WP\Functions as WPFunctions;
if (!defined('ABSPATH')) exit;
class Clicks {
const REVENUE_TRACKING_COOKIE_EXPIRY = 60 * 60 * 24 * 14;
/** @var SettingsController */
private $settings_controller;
public function __construct(SettingsController $settings_controller) {
$this->settings_controller = $settings_controller;
}
/**
* @param \stdClass|null $data
*/
@@ -24,12 +35,13 @@ class Clicks {
// log statistics only if the action did not come from
// a WP user previewing the newsletter
if (!$wp_user_preview) {
StatisticsClicks::createOrUpdateClickCount(
$statistics_clicks = StatisticsClicks::createOrUpdateClickCount(
$link->id,
$subscriber->id,
$newsletter->id,
$queue->id
);
$this->sendRevenueCookie($statistics_clicks);
// track open event
$open_event = new Opens();
$open_event->track($data, $display_image = false);
@@ -38,6 +50,20 @@ class Clicks {
$this->redirectToUrl($url);
}
private function sendRevenueCookie(StatisticsClicks $clicks) {
if ($this->settings_controller->get('accept_cookie_revenue_tracking')) {
setcookie(
'mailpoet_revenue_tracking',
serialize([
'statistics_clicks' => $clicks->id,
'created_at' => time(),
]),
time() + self::REVENUE_TRACKING_COOKIE_EXPIRY,
'/'
);
}
}
function processUrl($url, $newsletter, $subscriber, $queue, $wp_user_preview) {
if (preg_match('/\[link:(?P<action>.*?)\]/', $url, $shortcode)) {
if (!$shortcode['action']) $this->abort();

View File

@@ -50,6 +50,11 @@ class Settings {
return $this;
}
function withTrackingEnabled() {
$this->settings->set('tracking.enabled', true);
return $this;
}
function withTodayInstallationDate() {
$this->settings->set('installed_at', date("Y-m-d H:i:s"));
}
@@ -84,4 +89,9 @@ class Settings {
$this->settings->set('mta_log.error.error_message', $error_message);
return $this;
}
function withCookieRevenueTracking() {
$this->settings->set('accept_cookie_revenue_tracking', true);
return $this;
}
}

View File

@@ -0,0 +1,40 @@
<?php
namespace MailPoet\Test\Acceptance;
use Codeception\Util\Locator;
use MailPoet\Test\DataFactories\Newsletter;
use MailPoet\Test\DataFactories\Settings;
require_once __DIR__ . '/../DataFactories/Newsletter.php';
require_once __DIR__ . '/../DataFactories/Settings.php';
class RevenueTrackingCookieCest {
function cookieIsStoredOnClick(\AcceptanceTester $I) {
$I->wantTo('Test Revenue cookie is saved');
$newsletter_subject = 'Receive Test';
$newsletter = (new Newsletter())->withSubject($newsletter_subject)->create();
(new Settings())->withCookieRevenueTracking()->withTrackingEnabled();
$segment_name = $I->createListWithSubscriber();
$I->login();
$I->amEditingNewsletter($newsletter->id);
$I->click('Next');
$I->waitForElement('[data-automation-id="newsletter_send_form"]');
$I->selectOptionInSelect2($segment_name);
$I->click('Send');
$I->waitForElement('.mailpoet_progress_label');
$I->logOut();
$I->amOnMailboxAppPage();
$I->waitForText($newsletter_subject);
$I->click(Locator::contains('span.subject', $newsletter_subject));
$I->switchToIframe('preview-html');
$I->click('Read the post');
$I->switchToNextTab();
$I->canSeeCookie('mailpoet_revenue_tracking');
}
}

View File

@@ -9,6 +9,9 @@ use MailPoet\Models\ScheduledTaskSubscriber;
use MailPoet\Models\SendingQueue;
use MailPoet\Models\Subscriber;
use MailPoet\Router\Endpoints\Track;
use MailPoet\Settings\SettingsController;
use MailPoet\Statistics\Track\Clicks;
use MailPoet\Statistics\Track\Opens;
use MailPoet\Tasks\Sending as SendingTask;
class TrackTest extends \MailPoetTest {
@@ -47,7 +50,7 @@ class TrackTest extends \MailPoetTest {
'preview' => false
);
// instantiate class
$this->track = new Track($this->track_data);
$this->track = new Track(new Clicks(new SettingsController()), new Opens());
}
function testItReturnsFalseWhenTrackDataIsMissing() {
@@ -75,7 +78,7 @@ class TrackTest extends \MailPoetTest {
)
);
$data->subscriber->email = 'random@email.com';
$track = Stub::make(new Track(), ['terminate' => function($code) {
$track = Stub::make(Track::class, ['terminate' => function($code) {
expect($code)->equals(403);
}]);
$track->_validateTrackData($data);

View File

@@ -10,6 +10,7 @@ use MailPoet\Models\SendingQueue;
use MailPoet\Models\StatisticsClicks;
use MailPoet\Models\StatisticsOpens;
use MailPoet\Models\Subscriber;
use MailPoet\Settings\SettingsController;
use MailPoet\Statistics\Track\Clicks;
use MailPoet\Tasks\Sending as SendingTask;
@@ -18,6 +19,8 @@ class ClicksTest extends \MailPoetTest {
/** @var Clicks */
private $clicks;
private $settings_controller;
function _before() {
parent::_before();
// create newsletter
@@ -54,12 +57,15 @@ class ClicksTest extends \MailPoetTest {
'preview' => false
);
// instantiate class
$this->clicks = new Clicks();
$this->settings_controller = Stub::makeEmpty(SettingsController::class, [
'get' => false,
], $this);
$this->clicks = new Clicks($this->settings_controller);
}
function testItAbortsWhenTrackDataIsEmptyOrMissingLink() {
// abort function should be called twice:
$clicks = Stub::make($this->clicks, array(
$clicks = Stub::construct($this->clicks, [$this->settings_controller], array(
'abort' => Expected::exactly(2)
), $this);
$data = $this->track_data;
@@ -74,8 +80,8 @@ class ClicksTest extends \MailPoetTest {
$data = $this->track_data;
$data->subscriber->wp_user_id = 99;
$data->preview = true;
$clicks = Stub::make($this->clicks, array(
'redirectToUrl' => null
$clicks = Stub::construct($this->clicks, [$this->settings_controller], array(
'redirectToUrl' => null,
), $this);
$clicks->track($data);
expect(StatisticsClicks::findMany())->isEmpty();
@@ -84,8 +90,8 @@ class ClicksTest extends \MailPoetTest {
function testItTracksClickAndOpenEvent() {
$data = $this->track_data;
$clicks = Stub::make($this->clicks, array(
'redirectToUrl' => null
$clicks = Stub::construct($this->clicks, [$this->settings_controller], array(
'redirectToUrl' => null,
), $this);
$clicks->track($data);
expect(StatisticsClicks::findMany())->notEmpty();
@@ -93,15 +99,15 @@ class ClicksTest extends \MailPoetTest {
}
function testItRedirectsToUrlAfterTracking() {
$clicks = Stub::make($this->clicks, array(
$clicks = Stub::construct($this->clicks, [$this->settings_controller], array(
'redirectToUrl' => Expected::exactly(1)
), $this);
$clicks->track($this->track_data);
}
function testItIncrementsClickEventCount() {
$clicks = Stub::make($this->clicks, array(
'redirectToUrl' => null
$clicks = Stub::construct($this->clicks, [$this->settings_controller], array(
'redirectToUrl' => null,
), $this);
$clicks->track($this->track_data);
expect(StatisticsClicks::findMany()[0]->count)->equals(1);
@@ -121,7 +127,7 @@ class ClicksTest extends \MailPoetTest {
}
function testItFailsToConvertsInvalidShortcodeToUrl() {
$clicks = Stub::make($this->clicks, array(
$clicks = Stub::construct($this->clicks, [$this->settings_controller], array(
'abort' => Expected::exactly(1)
), $this);
// should call abort() method if shortcode action does not exist