Skip to content

Commit

Permalink
Merge pull request matomo-org#6847 from piwik/campaign_change_new_visit
Browse files Browse the repository at this point in the history
Create new visit on different campaign info or different referrer website (includes minor refactoring to Referrer dimensions + 2 new INI config options).
  • Loading branch information
Benaka committed Dec 12, 2014
2 parents 7d1b11d + 3a05710 commit 56ef81b
Show file tree
Hide file tree
Showing 15 changed files with 454 additions and 50 deletions.
10 changes: 10 additions & 0 deletions config/global.ini.php
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,16 @@
; Includes by default the GA style campaign keyword parameter utm_term
campaign_keyword_var_name = "pk_kwd,pk_keyword,piwik_kwd,utm_term"

; if set to 1, actions that contain different campaign information from the visitor's ongoing visit will
; be treated as the start of a new visit. This will include situations when campaign information was absent before,
; but is present now.
create_new_visit_when_campaign_changes = 1

; if set to 1, actions that contain different website referrer information from the visitor's ongoing visit
; will be treatedas the start of a new visit. This will include situations when website referrer information was
; absent before, but is present now.
create_new_visit_when_website_referrer_changes = 0

; maximum length of a Page Title or a Page URL recorded in the log_action.name table
page_maximum_length = 1024;

Expand Down
19 changes: 19 additions & 0 deletions core/Plugin/Dimension/VisitDimension.php
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,25 @@ public function onAnyGoalConversion(Request $request, Visitor $visitor, $action)
return false;
}

/**
* This hook is executed by the tracker when determining if an action is the start of a new visit
* or part of an existing one. Derived classes can use it to force new visits based on dimension
* data.
*
* For example, the Campaign dimension in the Referrers plugin will force a new visit if the
* campaign information for the current action is different from the last.
*
* @param Request $request The current tracker request information.
* @param Visitor $visitor The information for the currently recognized visitor.
* @param Action|null $action The current action information (if any).
* @return bool Return true to force a visit, false if otherwise.
* @api
*/
public function shouldForceNewVisit(Request $request, Visitor $visitor, Action $action = null)
{
return false;
}

/**
* Get all visit dimensions that are defined by all activated plugins.
* @return VisitDimension[]
Expand Down
50 changes: 39 additions & 11 deletions core/Tracker/Visit.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,7 @@ public function handle()

$this->visitorInfo = $visitor->getVisitorInfo();

$isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit($visitor);

if (!$isLastActionInTheSameVisit) {
Common::printDebug("Visitor detected, but last action was more than 30 minutes ago...");
}
$isNewVisit = $this->isVisitNew($visitor, $action);

// Known visit when:
// ( - the visitor has the Piwik cookie with the idcookie ID used by Piwik to match the visitor
Expand All @@ -165,9 +161,7 @@ public function handle()
// )
// AND
// - the last page view for this visitor was less than 30 minutes ago @see isLastActionInTheSameVisit()
if ($visitor->isVisitorKnown()
&& $isLastActionInTheSameVisit
) {
if (!$isNewVisit) {
$idReferrerActionUrl = $this->visitorInfo['visit_exit_idaction_url'];
$idReferrerActionName = $this->visitorInfo['visit_exit_idaction_name'];

Expand Down Expand Up @@ -203,9 +197,7 @@ public function handle()
// - the visitor has the Piwik cookie but the last action was performed more than 30 min ago @see isLastActionInTheSameVisit()
// - the visitor doesn't have the Piwik cookie, and couldn't be matched in @see recognizeTheVisitor()
// - the visitor does have the Piwik cookie but the idcookie and idvisit found in the cookie didn't match to any existing visit in the DB
if (!$visitor->isVisitorKnown()
|| !$isLastActionInTheSameVisit
) {
if ($isNewVisit) {
$this->handleNewVisit($visitor, $action, $visitIsConverted);
if (!is_null($action)) {
$action->record($visitor, 0, 0);
Expand Down Expand Up @@ -550,6 +542,16 @@ private function triggerHookOnDimensions($dimensions, $hook, $visitor, $action,
return $valuesToUpdate;
}

private function triggerPredicateHookOnDimensions($dimensions, $hook, Visitor $visitor, Action $action = null)
{
foreach ($dimensions as $dimension) {
if ($dimension->$hook($this->request, $visitor, $action)) {
return true;
}
}
return false;
}

protected function getAllVisitDimensions()
{
$dimensions = VisitDimension::getAllDimensions();
Expand Down Expand Up @@ -598,4 +600,30 @@ protected function insertNewVisit($visit)
{
return $this->getModel()->createVisit($visit);
}

/**
* Determines if the tracker if the current action should be treated as the start of a new visit or
* an action in an existing visit.
*
* @param Visitor $visitor The current visit/visitor information.
* @param Action|null $action The current action being tracked.
* @return bool
*/
public function isVisitNew(Visitor $visitor, Action $action = null)
{
$isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit($visitor);

if (!$isLastActionInTheSameVisit) {
Common::printDebug("Visitor detected, but last action was more than 30 minutes ago...");

return true;
}

$shouldForceNewVisit = $this->triggerPredicateHookOnDimensions($this->getAllVisitDimensions(), 'shouldForceNewVisit', $visitor, $action);
if ($shouldForceNewVisit) {
return true;
}

return !$visitor->isVisitorKnown();
}
}
29 changes: 28 additions & 1 deletion plugins/Referrers/Columns/Base.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ protected function getReferrerInformation($referrerUrl, $currentUrl, $idSite)
return $referrerInformation;
}

protected function getReferrerInformationFromRequest(Request $request)
{
$referrerUrl = $request->getParam('urlref');
$currentUrl = $request->getParam('url');

return $this->getReferrerInformation($referrerUrl, $currentUrl, $request->getIdSite());
}

/**
* Search engine detection
* @return bool
Expand Down Expand Up @@ -399,4 +407,23 @@ protected function setCampaignValuesToLowercase($type, &$name, &$keyword)
}
}

}
protected function isReferrerInformationNew(Visitor $visitor, $information)
{
foreach (array('referer_keyword', 'referer_name', 'referer_type') as $infoName) {
if ($this->hasReferrerColumnChanged($visitor, $information, $infoName)) {
return true;
}
}
return false;
}

protected function hasReferrerColumnChanged(Visitor $visitor, $information, $infoName)
{
return Common::mb_strtolower($visitor->getVisitorColumn($infoName)) != $information[$infoName];
}

protected function doesLastActionHaveSameReferrer(Visitor $visitor, $referrerType)
{
return $visitor->getVisitorColumn('referer_type') == $referrerType;
}
}
51 changes: 48 additions & 3 deletions plugins/Referrers/Columns/Campaign.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,58 @@
*/
namespace Piwik\Plugins\Referrers\Columns;

use Piwik\Columns\Dimension;
use Piwik\Common;
use Piwik\Piwik;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\TrackerConfig;
use Piwik\Tracker\Visitor;

class Campaign extends Dimension
class Campaign extends Base
{
/**
* Obtained from the `[Tracker] create_new_visit_when_campaign_changes` INI config option.
* If true, will create new visits when campaign name changes.
*
* @var bool
*/
protected $createNewVisitWhenCampaignChanges;

public function __construct()
{
$this->createNewVisitWhenCampaignChanges = TrackerConfig::getConfigValue('create_new_visit_when_campaign_changes') == 1;
}

public function getName()
{
return Piwik::translate('Referrers_ColumnCampaign');
}
}

/**
* If we should create a new visit when the campaign changes, check if the campaign info changed and if so
* force the tracker to create a new visit.
*
* @param Request $request
* @param Visitor $visitor
* @param Action|null $action
* @return bool
*/
public function shouldForceNewVisit(Request $request, Visitor $visitor, Action $action = null)
{
if (!$this->createNewVisitWhenCampaignChanges) {
return false;
}

$information = $this->getReferrerInformationFromRequest($request);

if ($information['referer_type'] == Common::REFERRER_TYPE_CAMPAIGN
&& $this->isReferrerInformationNew($visitor, $information)
) {
Common::printDebug("Existing visit detected, but creating new visit because campaign information is different than last action.");

return true;
}

return false;
}
}
5 changes: 1 addition & 4 deletions plugins/Referrers/Columns/Keyword.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,7 @@ public function getName()
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$referrerUrl = $request->getParam('urlref');
$currentUrl = $request->getParam('url');

$information = $this->getReferrerInformation($referrerUrl, $currentUrl, $request->getIdSite());
$information = $this->getReferrerInformationFromRequest($request);

if (!empty($information['referer_keyword'])) {
return substr($information['referer_keyword'], 0, 255);
Expand Down
5 changes: 1 addition & 4 deletions plugins/Referrers/Columns/ReferrerName.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@ protected function configureSegments()
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$referrerUrl = $request->getParam('urlref');
$currentUrl = $request->getParam('url');

$information = $this->getReferrerInformation($referrerUrl, $currentUrl, $request->getIdSite());
$information = $this->getReferrerInformationFromRequest($request);

if (!empty($information['referer_name'])) {

Expand Down
5 changes: 1 addition & 4 deletions plugins/Referrers/Columns/ReferrerType.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,7 @@ public function getName()
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$referrerUrl = $request->getParam('urlref');
$currentUrl = $request->getParam('url');

$information = $this->getReferrerInformation($referrerUrl, $currentUrl, $request->getIdSite());
$information = $this->getReferrerInformationFromRequest($request);

return $information['referer_type'];
}
Expand Down
5 changes: 1 addition & 4 deletions plugins/Referrers/Columns/ReferrerUrl.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,7 @@ protected function configureSegments()
*/
public function onNewVisit(Request $request, Visitor $visitor, $action)
{
$referrerUrl = $request->getParam('urlref');
$currentUrl = $request->getParam('url');

$information = $this->getReferrerInformation($referrerUrl, $currentUrl, $request->getIdSite());
$information = $this->getReferrerInformationFromRequest($request);

return $information['referer_url'];
}
Expand Down
41 changes: 39 additions & 2 deletions plugins/Referrers/Columns/Website.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,50 @@
*/
namespace Piwik\Plugins\Referrers\Columns;

use Piwik\Columns\Dimension;
use Piwik\Common;
use Piwik\Piwik;
use Piwik\Tracker\Action;
use Piwik\Tracker\Request;
use Piwik\Tracker\TrackerConfig;
use Piwik\Tracker\Visitor;

class Website extends Dimension
class Website extends Base
{
/**
* Set using the `[Tracker] create_new_visit_when_website_referrer_changes` INI config option.
* If true, will force new visits if the referrer website changes.
*
* @var bool
*/
protected $createNewVisitWhenWebsiteReferrerChanges;

public function __construct()
{
$this->createNewVisitWhenWebsiteReferrerChanges = TrackerConfig::getConfigValue('create_new_visit_when_website_referrer_changes') == 1;
}

public function getName()
{
return Piwik::translate('General_Website');
}

public function shouldForceNewVisit(Request $request, Visitor $visitor, Action $action = null)
{
if (!$this->createNewVisitWhenWebsiteReferrerChanges) {
return false;
}

$information = $this->getReferrerInformationFromRequest($request);

if ($information['referer_type'] == Common::REFERRER_TYPE_WEBSITE
&& $this->isReferrerInformationNew($visitor, $information)
) {
Common::printDebug("Existing visit detected, but creating new visit because website referrer information is different than last action.");

return true;
}

return false;

}
}
Loading

0 comments on commit 56ef81b

Please sign in to comment.