Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'core/Tracker/Visit.php')
-rw-r--r--core/Tracker/Visit.php3311
1 files changed, 1598 insertions, 1713 deletions
diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php
index ef8b9e3cee..c4a661ec62 100644
--- a/core/Tracker/Visit.php
+++ b/core/Tracker/Visit.php
@@ -13,9 +13,11 @@
* @package Piwik
* @subpackage Piwik_Tracker
*/
-interface Piwik_Tracker_Visit_Interface {
- function setRequest($requestArray);
- function handle();
+interface Piwik_Tracker_Visit_Interface
+{
+ function setRequest($requestArray);
+
+ function handle();
}
/**
@@ -34,12 +36,12 @@ interface Piwik_Tracker_Visit_Interface {
*/
class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
{
- const UNKNOWN_CODE = 'xx';
-
- /**
- * @var Piwik_Cookie
- */
- protected $cookie = null;
+ const UNKNOWN_CODE = 'xx';
+
+ /**
+ * @var Piwik_Cookie
+ */
+ protected $cookie = null;
protected $visitorInfo = array();
protected $userSettingsInformation = null;
protected $visitorCustomVariables = array();
@@ -53,722 +55,673 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
protected $ip;
protected $authenticated = false;
- // Set to true when we set some custom variables from the cookie
- protected $customVariablesSetFromRequest = false;
-
- /**
- * @var Piwik_Tracker_GoalManager
- */
- protected $goalManager;
-
- public function __construct($forcedIpString = null, $forcedDateTime = null, $authenticated = false)
- {
- $this->timestamp = time();
- if(!empty($forcedDateTime))
- {
- if(!is_numeric($forcedDateTime))
- {
- $forcedDateTime = strtotime($forcedDateTime);
- }
- $this->timestamp = $forcedDateTime;
- }
- $ipString = $forcedIpString;
- if(empty($ipString))
- {
- $ipString = Piwik_IP::getIpFromHeader();
- }
-
- $ip = Piwik_IP::P2N($ipString);
- $this->ip = $ip;
-
- $this->authenticated = $authenticated;
- }
-
- function setForcedVisitorId($visitorId)
- {
- $this->forcedVisitorId = $visitorId;
- }
-
- function setRequest($requestArray)
- {
- $this->request = $requestArray;
-
- $idsite = Piwik_Common::getRequestVar('idsite', 0, 'int', $this->request);
- Piwik_PostEvent('Tracker.setRequest.idSite', $idsite, $requestArray);
- if($idsite <= 0)
- {
- throw new Exception('Invalid idSite');
- }
- $this->idsite = $idsite;
-
- // When the 'url' and referer url parameter are not given, we might be in the 'Simple Image Tracker' mode.
- // The URL can default to the Referer, which will be in this case
- // the URL of the page containing the Simple Image beacon
- if(empty($this->request['urlref'])
- && empty($this->request['url']))
- {
- $this->request['url'] = @$_SERVER['HTTP_REFERER'];
- }
- }
-
- /**
- * Main algorithm to handle the visit.
- *
- * Once we have the visitor information, we have to determine if the visit is a new or a known visit.
- *
- * 1) When the last action was done more than 30min ago,
- * or if the visitor is new, then this is a new visit.
- *
- * 2) If the last action is less than 30min ago, then the same visit is going on.
- * Because the visit goes on, we can get the time spent during the last action.
- *
- * NB:
- * - In the case of a new visit, then the time spent
- * during the last action of the previous visit is unknown.
- *
- * - In the case of a new visit but with a known visitor,
- * we can set the 'returning visitor' flag.
- *
- * In all the cases we set a cookie to the visitor with the new information.
- */
- public function handle()
- {
- // the IP is needed by isExcluded() and GoalManager->recordGoals()
- $this->visitorInfo['location_ip'] = $this->ip;
-
- if($this->isExcluded())
- {
- return;
- }
-
- // Anonymize IP (after testing for IP exclusion)
- $ip = $this->ip;
- Piwik_PostEvent('Tracker.Visit.setVisitorIp', $ip);
- $this->visitorInfo['location_ip'] = $ip;
-
- $this->visitorCustomVariables = self::getCustomVariables($scope = 'visit', $this->request);
- if(!empty($this->visitorCustomVariables))
- {
- printDebug("Visit level Custom Variables: ");
- printDebug($this->visitorCustomVariables);
- $this->customVariablesSetFromRequest = true;
- }
-
- $this->goalManager = new Piwik_Tracker_GoalManager();
-
- $someGoalsConverted = $visitIsConverted = false;
- $idActionUrl = $idActionName = $actionType = false;
- $action = null;
-
- $this->goalManager->init($this->request);
-
- $requestIsManualGoalConversion = ($this->goalManager->idGoal > 0);
- $requestIsEcommerce = $this->goalManager->requestIsEcommerce;
- if($requestIsEcommerce)
- {
- $someGoalsConverted = true;
-
- // Mark the visit as Converted only if it is an order (not for a Cart update)
- if($this->goalManager->isGoalAnOrder)
- {
- $visitIsConverted = true;
- }
- }
- // this request is from the JS call to piwikTracker.trackGoal()
- elseif($requestIsManualGoalConversion)
- {
- $someGoalsConverted = $this->goalManager->detectGoalId($this->idsite);
- $visitIsConverted = $someGoalsConverted;
- // if we find a idgoal in the URL, but then the goal is not valid, this is most likely a fake request
- if(!$someGoalsConverted)
- {
- printDebug('Invalid goal tracking request for goal id = '.$this->goalManager->idGoal);
- unset($this->goalManager);
- return;
- }
- }
- // normal page view, potentially triggering a URL matching goal
- else
- {
- $action = $this->newAction();
- $this->handleAction($action);
- $someGoalsConverted = $this->goalManager->detectGoalsMatchingUrl($this->idsite, $action);
- $visitIsConverted = $someGoalsConverted;
-
- $action->loadIdActionNameAndUrl();
- $idActionUrl = $action->getIdActionUrl();
- if ($idActionUrl !== null) {
- $idActionUrl = (int)$idActionUrl;
- }
- $idActionName = (int)$action->getIdActionName();
- $actionType = $action->getActionType();
- }
-
- // the visitor and session
- $this->recognizeTheVisitor();
-
- $isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit();
-
- if(!$isLastActionInTheSameVisit)
- {
- printDebug("Visitor detected, but last action was more than 30 minutes ago...");
- }
- // Known visit when:
- // ( - the visitor has the Piwik cookie with the idcookie ID used by Piwik to match the visitor
- // OR
- // - the visitor doesn't have the Piwik cookie but could be match using heuristics @see recognizeTheVisitor()
- // )
- // AND
- // - the last page view for this visitor was less than 30 minutes ago @see isLastActionInTheSameVisit()
- if( $this->isVisitorKnown()
- && $isLastActionInTheSameVisit)
- {
- $idRefererActionUrl = $this->visitorInfo['visit_exit_idaction_url'];
- $idRefererActionName = $this->visitorInfo['visit_exit_idaction_name'];
- try {
- $this->handleKnownVisit($idActionUrl, $idActionName, $actionType, $visitIsConverted);
- if(!is_null($action))
- {
- $action->record( $this->visitorInfo['idvisit'],
- $this->visitorInfo['idvisitor'],
- $idRefererActionUrl,
- $idRefererActionName,
- $this->visitorInfo['time_spent_ref_action']
- );
- }
- } catch(Piwik_Tracker_Visit_VisitorNotFoundInDatabase $e) {
-
- // There is an edge case when:
- // - two manual goal conversions happen in the same second
- // - which result in handleKnownVisit throwing the exception
- // because the UPDATE didn't affect any rows (one row was found, but not updated since no field changed)
- // - the exception is caught here and will result in a new visit incorrectly
- // In this case, we cancel the current conversion to be recorded:
- if($requestIsManualGoalConversion
- || $requestIsEcommerce)
- {
- $someGoalsConverted = $visitIsConverted = false;
- }
- // When the row wasn't found in the logs, and this is a pageview or
- // goal matching URL, we force a new visitor
- else
- {
- $this->visitorKnown = false;
- }
- }
- }
-
- // New visit when:
- // - 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(!$this->isVisitorKnown()
- || !$isLastActionInTheSameVisit)
- {
- $this->handleNewVisit($idActionUrl, $idActionName, $actionType, $visitIsConverted);
- if(!is_null($action))
- {
- $action->record( $this->visitorInfo['idvisit'], $this->visitorInfo['idvisitor'], 0, 0, 0 );
- }
- }
-
- // update the cookie with the new visit information
- $this->setThirdPartyCookie();
-
- // record the goals if applicable
- if($someGoalsConverted)
- {
- $refererTimestamp = Piwik_Common::getRequestVar('_refts', 0, 'int', $this->request);
- $refererUrl = Piwik_Common::getRequestVar('_ref', '', 'string', $this->request);
- $refererCampaignName = trim(urldecode(Piwik_Common::getRequestVar('_rcn', '', 'string', $this->request)));
- $refererCampaignKeyword = trim(urldecode(Piwik_Common::getRequestVar('_rck', '', 'string', $this->request)));
-
- $this->goalManager->recordGoals(
- $this->idsite,
- $this->visitorInfo,
- $this->visitorCustomVariables,
- $action,
- $refererTimestamp,
- $refererUrl,
- $refererCampaignName,
- $refererCampaignKeyword,
- $this->getBrowserLanguage()
- );
- }
- unset($this->goalManager);
- unset($action);
- $this->printCookie();
- }
-
- protected function printCookie()
- {
- printDebug($this->cookie);
- }
-
- protected function handleAction($action)
- {
- $action->setIdSite($this->idsite);
- $action->setRequest($this->request);
- $action->setTimestamp($this->getCurrentTimestamp());
- $action->init();
-
- if($this->detectActionIsOutlinkOnAliasHost($action))
- {
- printDebug("Info: The outlink URL host is one of the known host for this website. ");
- }
- if(isset($GLOBALS['PIWIK_TRACKER_DEBUG']) && $GLOBALS['PIWIK_TRACKER_DEBUG'])
- {
- $type = Piwik_Tracker_Action::getActionTypeName($action->getActionType());
- printDebug("Action is a $type,
- Action name = ". $action->getActionName() .",
- Action URL = ". $action->getActionUrl() );
- }
- }
-
- /**
- * In the case of a known visit, we have to do the following actions:
- *
- * 1) Insert the new action
- * 2) Update the visit information
- *
- * This method triggers two events:
- *
- * Tracker.knownVisitorUpdate is triggered before the visit information is updated
- * Event data is an array with the values to be updated (could be changed by plugins)
- *
- * Tracker.knownVisitorInformation is triggered after saving the new visit data
- * Even data is an array with updated information about the visit
- * @param $idActionUrl
- * @param $idActionName
- * @param $actionType
- * @param $visitIsConverted
- * @throws Piwik_Tracker_Visit_VisitorNotFoundInDatabase
- */
- protected function handleKnownVisit($idActionUrl, $idActionName, $actionType, $visitIsConverted)
- {
- // gather information that needs to be updated
- $valuesToUpdate = array();
- $incrementActions = false;
- $sqlActionUpdate = '';
-
- if(!empty($idActionName))
- {
- $valuesToUpdate['visit_exit_idaction_name'] = (int)$idActionName;
- }
- if($idActionUrl !== false)
- {
- $valuesToUpdate['visit_exit_idaction_url'] = $idActionUrl;
- $incrementActions = true;
- }
- if($actionType == Piwik_Tracker_Action::TYPE_SITE_SEARCH)
- {
- $sqlActionUpdate .= "visit_total_searches = visit_total_searches + 1, ";
- $incrementActions = true;
- }
- if($incrementActions)
- {
- $sqlActionUpdate .= "visit_total_actions = visit_total_actions + 1, ";
- }
-
- $datetimeServer = Piwik_Tracker::getDatetimeFromTimestamp($this->getCurrentTimestamp());
- printDebug("Visit is known (IP = ".Piwik_IP::N2P($this->getVisitorIp()).")");
+ // Set to true when we set some custom variables from the cookie
+ protected $customVariablesSetFromRequest = false;
+
+ /**
+ * @var Piwik_Tracker_GoalManager
+ */
+ protected $goalManager;
+
+ public function __construct($forcedIpString = null, $forcedDateTime = null, $authenticated = false)
+ {
+ $this->timestamp = time();
+ if (!empty($forcedDateTime)) {
+ if (!is_numeric($forcedDateTime)) {
+ $forcedDateTime = strtotime($forcedDateTime);
+ }
+ $this->timestamp = $forcedDateTime;
+ }
+ $ipString = $forcedIpString;
+ if (empty($ipString)) {
+ $ipString = Piwik_IP::getIpFromHeader();
+ }
+
+ $ip = Piwik_IP::P2N($ipString);
+ $this->ip = $ip;
+
+ $this->authenticated = $authenticated;
+ }
+
+ function setForcedVisitorId($visitorId)
+ {
+ $this->forcedVisitorId = $visitorId;
+ }
+
+ function setRequest($requestArray)
+ {
+ $this->request = $requestArray;
+
+ $idsite = Piwik_Common::getRequestVar('idsite', 0, 'int', $this->request);
+ Piwik_PostEvent('Tracker.setRequest.idSite', $idsite, $requestArray);
+ if ($idsite <= 0) {
+ throw new Exception('Invalid idSite');
+ }
+ $this->idsite = $idsite;
+
+ // When the 'url' and referer url parameter are not given, we might be in the 'Simple Image Tracker' mode.
+ // The URL can default to the Referer, which will be in this case
+ // the URL of the page containing the Simple Image beacon
+ if (empty($this->request['urlref'])
+ && empty($this->request['url'])
+ ) {
+ $this->request['url'] = @$_SERVER['HTTP_REFERER'];
+ }
+ }
+
+ /**
+ * Main algorithm to handle the visit.
+ *
+ * Once we have the visitor information, we have to determine if the visit is a new or a known visit.
+ *
+ * 1) When the last action was done more than 30min ago,
+ * or if the visitor is new, then this is a new visit.
+ *
+ * 2) If the last action is less than 30min ago, then the same visit is going on.
+ * Because the visit goes on, we can get the time spent during the last action.
+ *
+ * NB:
+ * - In the case of a new visit, then the time spent
+ * during the last action of the previous visit is unknown.
+ *
+ * - In the case of a new visit but with a known visitor,
+ * we can set the 'returning visitor' flag.
+ *
+ * In all the cases we set a cookie to the visitor with the new information.
+ */
+ public function handle()
+ {
+ // the IP is needed by isExcluded() and GoalManager->recordGoals()
+ $this->visitorInfo['location_ip'] = $this->ip;
+
+ if ($this->isExcluded()) {
+ return;
+ }
+
+ // Anonymize IP (after testing for IP exclusion)
+ $ip = $this->ip;
+ Piwik_PostEvent('Tracker.Visit.setVisitorIp', $ip);
+ $this->visitorInfo['location_ip'] = $ip;
+
+ $this->visitorCustomVariables = self::getCustomVariables($scope = 'visit', $this->request);
+ if (!empty($this->visitorCustomVariables)) {
+ printDebug("Visit level Custom Variables: ");
+ printDebug($this->visitorCustomVariables);
+ $this->customVariablesSetFromRequest = true;
+ }
+
+ $this->goalManager = new Piwik_Tracker_GoalManager();
+
+ $someGoalsConverted = $visitIsConverted = false;
+ $idActionUrl = $idActionName = $actionType = false;
+ $action = null;
+
+ $this->goalManager->init($this->request);
+
+ $requestIsManualGoalConversion = ($this->goalManager->idGoal > 0);
+ $requestIsEcommerce = $this->goalManager->requestIsEcommerce;
+ if ($requestIsEcommerce) {
+ $someGoalsConverted = true;
+
+ // Mark the visit as Converted only if it is an order (not for a Cart update)
+ if ($this->goalManager->isGoalAnOrder) {
+ $visitIsConverted = true;
+ }
+ } // this request is from the JS call to piwikTracker.trackGoal()
+ elseif ($requestIsManualGoalConversion) {
+ $someGoalsConverted = $this->goalManager->detectGoalId($this->idsite);
+ $visitIsConverted = $someGoalsConverted;
+ // if we find a idgoal in the URL, but then the goal is not valid, this is most likely a fake request
+ if (!$someGoalsConverted) {
+ printDebug('Invalid goal tracking request for goal id = ' . $this->goalManager->idGoal);
+ unset($this->goalManager);
+ return;
+ }
+ } // normal page view, potentially triggering a URL matching goal
+ else {
+ $action = $this->newAction();
+ $this->handleAction($action);
+ $someGoalsConverted = $this->goalManager->detectGoalsMatchingUrl($this->idsite, $action);
+ $visitIsConverted = $someGoalsConverted;
+
+ $action->loadIdActionNameAndUrl();
+ $idActionUrl = $action->getIdActionUrl();
+ if ($idActionUrl !== null) {
+ $idActionUrl = (int)$idActionUrl;
+ }
+ $idActionName = (int)$action->getIdActionName();
+ $actionType = $action->getActionType();
+ }
+
+ // the visitor and session
+ $this->recognizeTheVisitor();
+
+ $isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit();
+
+ if (!$isLastActionInTheSameVisit) {
+ printDebug("Visitor detected, but last action was more than 30 minutes ago...");
+ }
+ // Known visit when:
+ // ( - the visitor has the Piwik cookie with the idcookie ID used by Piwik to match the visitor
+ // OR
+ // - the visitor doesn't have the Piwik cookie but could be match using heuristics @see recognizeTheVisitor()
+ // )
+ // AND
+ // - the last page view for this visitor was less than 30 minutes ago @see isLastActionInTheSameVisit()
+ if ($this->isVisitorKnown()
+ && $isLastActionInTheSameVisit
+ ) {
+ $idRefererActionUrl = $this->visitorInfo['visit_exit_idaction_url'];
+ $idRefererActionName = $this->visitorInfo['visit_exit_idaction_name'];
+ try {
+ $this->handleKnownVisit($idActionUrl, $idActionName, $actionType, $visitIsConverted);
+ if (!is_null($action)) {
+ $action->record($this->visitorInfo['idvisit'],
+ $this->visitorInfo['idvisitor'],
+ $idRefererActionUrl,
+ $idRefererActionName,
+ $this->visitorInfo['time_spent_ref_action']
+ );
+ }
+ } catch (Piwik_Tracker_Visit_VisitorNotFoundInDatabase $e) {
+
+ // There is an edge case when:
+ // - two manual goal conversions happen in the same second
+ // - which result in handleKnownVisit throwing the exception
+ // because the UPDATE didn't affect any rows (one row was found, but not updated since no field changed)
+ // - the exception is caught here and will result in a new visit incorrectly
+ // In this case, we cancel the current conversion to be recorded:
+ if ($requestIsManualGoalConversion
+ || $requestIsEcommerce
+ ) {
+ $someGoalsConverted = $visitIsConverted = false;
+ } // When the row wasn't found in the logs, and this is a pageview or
+ // goal matching URL, we force a new visitor
+ else {
+ $this->visitorKnown = false;
+ }
+ }
+ }
+
+ // New visit when:
+ // - 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 (!$this->isVisitorKnown()
+ || !$isLastActionInTheSameVisit
+ ) {
+ $this->handleNewVisit($idActionUrl, $idActionName, $actionType, $visitIsConverted);
+ if (!is_null($action)) {
+ $action->record($this->visitorInfo['idvisit'], $this->visitorInfo['idvisitor'], 0, 0, 0);
+ }
+ }
+
+ // update the cookie with the new visit information
+ $this->setThirdPartyCookie();
+
+ // record the goals if applicable
+ if ($someGoalsConverted) {
+ $refererTimestamp = Piwik_Common::getRequestVar('_refts', 0, 'int', $this->request);
+ $refererUrl = Piwik_Common::getRequestVar('_ref', '', 'string', $this->request);
+ $refererCampaignName = trim(urldecode(Piwik_Common::getRequestVar('_rcn', '', 'string', $this->request)));
+ $refererCampaignKeyword = trim(urldecode(Piwik_Common::getRequestVar('_rck', '', 'string', $this->request)));
+
+ $this->goalManager->recordGoals(
+ $this->idsite,
+ $this->visitorInfo,
+ $this->visitorCustomVariables,
+ $action,
+ $refererTimestamp,
+ $refererUrl,
+ $refererCampaignName,
+ $refererCampaignKeyword,
+ $this->getBrowserLanguage()
+ );
+ }
+ unset($this->goalManager);
+ unset($action);
+ $this->printCookie();
+ }
+
+ protected function printCookie()
+ {
+ printDebug($this->cookie);
+ }
+
+ protected function handleAction($action)
+ {
+ $action->setIdSite($this->idsite);
+ $action->setRequest($this->request);
+ $action->setTimestamp($this->getCurrentTimestamp());
+ $action->init();
+
+ if ($this->detectActionIsOutlinkOnAliasHost($action)) {
+ printDebug("Info: The outlink URL host is one of the known host for this website. ");
+ }
+ if (isset($GLOBALS['PIWIK_TRACKER_DEBUG']) && $GLOBALS['PIWIK_TRACKER_DEBUG']) {
+ $type = Piwik_Tracker_Action::getActionTypeName($action->getActionType());
+ printDebug("Action is a $type,
+ Action name = " . $action->getActionName() . ",
+ Action URL = " . $action->getActionUrl());
+ }
+ }
+
+ /**
+ * In the case of a known visit, we have to do the following actions:
+ *
+ * 1) Insert the new action
+ * 2) Update the visit information
+ *
+ * This method triggers two events:
+ *
+ * Tracker.knownVisitorUpdate is triggered before the visit information is updated
+ * Event data is an array with the values to be updated (could be changed by plugins)
+ *
+ * Tracker.knownVisitorInformation is triggered after saving the new visit data
+ * Even data is an array with updated information about the visit
+ * @param $idActionUrl
+ * @param $idActionName
+ * @param $actionType
+ * @param $visitIsConverted
+ * @throws Piwik_Tracker_Visit_VisitorNotFoundInDatabase
+ */
+ protected function handleKnownVisit($idActionUrl, $idActionName, $actionType, $visitIsConverted)
+ {
+ // gather information that needs to be updated
+ $valuesToUpdate = array();
+ $incrementActions = false;
+ $sqlActionUpdate = '';
+
+ if (!empty($idActionName)) {
+ $valuesToUpdate['visit_exit_idaction_name'] = (int)$idActionName;
+ }
+ if ($idActionUrl !== false) {
+ $valuesToUpdate['visit_exit_idaction_url'] = $idActionUrl;
+ $incrementActions = true;
+ }
+ if ($actionType == Piwik_Tracker_Action::TYPE_SITE_SEARCH) {
+ $sqlActionUpdate .= "visit_total_searches = visit_total_searches + 1, ";
+ $incrementActions = true;
+ }
+ if ($incrementActions) {
+ $sqlActionUpdate .= "visit_total_actions = visit_total_actions + 1, ";
+ }
+
+ $datetimeServer = Piwik_Tracker::getDatetimeFromTimestamp($this->getCurrentTimestamp());
+ printDebug("Visit is known (IP = " . Piwik_IP::N2P($this->getVisitorIp()) . ")");
// Add 1 so it's always > 0
- $visitTotalTime = 1 + $this->getCurrentTimestamp() - $this->visitorInfo['visit_first_action_time'];
- $valuesToUpdate['visit_last_action_time'] = $datetimeServer;
- $valuesToUpdate['visit_total_time'] = self::cleanupVisitTotalTime($visitTotalTime);
-
- // Goal conversion
- if($visitIsConverted)
- {
- $valuesToUpdate['visit_goal_converted'] = 1;
- // If a pageview and goal conversion in the same second, with previously a goal conversion recorded
- // the request would not "update" the row since all values are the same as previous
- // therefore the request below throws exception, instead we make sure the UPDATE will affect the row
- $valuesToUpdate['visit_total_time'] = self::cleanupVisitTotalTime(
- $valuesToUpdate['visit_total_time']
- + $this->goalManager->idGoal
- // +2 to offset idgoal=-1 and idgoal=0
- + 2 );
- }
-
- // Might update the idvisitor when it was forced or overwritten for this visit
- if(strlen($this->visitorInfo['idvisitor']) == Piwik_Tracker::LENGTH_BINARY_ID)
- {
- $valuesToUpdate['idvisitor'] = $this->visitorInfo['idvisitor'];
- }
-
- // Ecommerce buyer status
- $valuesToUpdate['visit_goal_buyer'] = $this->goalManager->getBuyerType($this->visitorInfo['visit_goal_buyer']);
-
- // Custom Variables overwrite previous values on each page view
- $valuesToUpdate = array_merge($valuesToUpdate, $this->visitorCustomVariables);
-
- // trigger event before update
- Piwik_PostEvent('Tracker.knownVisitorUpdate', $valuesToUpdate);
-
- // Will be updated in cookie
- $timeSpentRefererAction = $this->getCurrentTimestamp() - $this->visitorInfo['visit_last_action_time'];
- if($timeSpentRefererAction > Piwik_Config::getInstance()->Tracker['visit_standard_length'])
- {
- $timeSpentRefererAction = 0;
- }
- $this->visitorInfo['time_spent_ref_action'] = $timeSpentRefererAction;
-
- // update visitorInfo
- foreach($valuesToUpdate AS $name => $value)
- {
- $this->visitorInfo[$name] = $value;
- }
-
- // build sql query
- $updateParts = $sqlBind = array();
-
- foreach($valuesToUpdate AS $name => $value)
- {
- $updateParts[] = $name." = ?";
- $sqlBind[] = $value;
- }
- $sqlQuery = "UPDATE ". Piwik_Common::prefixTable('log_visit')."
- SET $sqlActionUpdate ".implode($updateParts, ', ')."
+ $visitTotalTime = 1 + $this->getCurrentTimestamp() - $this->visitorInfo['visit_first_action_time'];
+ $valuesToUpdate['visit_last_action_time'] = $datetimeServer;
+ $valuesToUpdate['visit_total_time'] = self::cleanupVisitTotalTime($visitTotalTime);
+
+ // Goal conversion
+ if ($visitIsConverted) {
+ $valuesToUpdate['visit_goal_converted'] = 1;
+ // If a pageview and goal conversion in the same second, with previously a goal conversion recorded
+ // the request would not "update" the row since all values are the same as previous
+ // therefore the request below throws exception, instead we make sure the UPDATE will affect the row
+ $valuesToUpdate['visit_total_time'] = self::cleanupVisitTotalTime(
+ $valuesToUpdate['visit_total_time']
+ + $this->goalManager->idGoal
+ // +2 to offset idgoal=-1 and idgoal=0
+ + 2);
+ }
+
+ // Might update the idvisitor when it was forced or overwritten for this visit
+ if (strlen($this->visitorInfo['idvisitor']) == Piwik_Tracker::LENGTH_BINARY_ID) {
+ $valuesToUpdate['idvisitor'] = $this->visitorInfo['idvisitor'];
+ }
+
+ // Ecommerce buyer status
+ $valuesToUpdate['visit_goal_buyer'] = $this->goalManager->getBuyerType($this->visitorInfo['visit_goal_buyer']);
+
+ // Custom Variables overwrite previous values on each page view
+ $valuesToUpdate = array_merge($valuesToUpdate, $this->visitorCustomVariables);
+
+ // trigger event before update
+ Piwik_PostEvent('Tracker.knownVisitorUpdate', $valuesToUpdate);
+
+ // Will be updated in cookie
+ $timeSpentRefererAction = $this->getCurrentTimestamp() - $this->visitorInfo['visit_last_action_time'];
+ if ($timeSpentRefererAction > Piwik_Config::getInstance()->Tracker['visit_standard_length']) {
+ $timeSpentRefererAction = 0;
+ }
+ $this->visitorInfo['time_spent_ref_action'] = $timeSpentRefererAction;
+
+ // update visitorInfo
+ foreach ($valuesToUpdate AS $name => $value) {
+ $this->visitorInfo[$name] = $value;
+ }
+
+ // build sql query
+ $updateParts = $sqlBind = array();
+
+ foreach ($valuesToUpdate AS $name => $value) {
+ $updateParts[] = $name . " = ?";
+ $sqlBind[] = $value;
+ }
+ $sqlQuery = "UPDATE " . Piwik_Common::prefixTable('log_visit') . "
+ SET $sqlActionUpdate " . implode($updateParts, ', ') . "
WHERE idsite = ?
AND idvisit = ?";
- array_push($sqlBind, $this->idsite, (int)$this->visitorInfo['idvisit'] );
-
- $result = Piwik_Tracker::getDatabase()->query($sqlQuery, $sqlBind);
-
- $this->visitorInfo['visit_last_action_time'] = $this->getCurrentTimestamp();
-
- // Debug output
- if(isset($valuesToUpdate['idvisitor']))
- {
- $valuesToUpdate['idvisitor'] = bin2hex($valuesToUpdate['idvisitor']);
- }
- printDebug('Updating existing visit: '. var_export($valuesToUpdate, true) );
-
- if(Piwik_Tracker::getDatabase()->rowCount($result) == 0)
- {
- printDebug("Visitor with this idvisit wasn't found in the DB.");
- printDebug("$sqlQuery --- ");printDebug($sqlBind);
- throw new Piwik_Tracker_Visit_VisitorNotFoundInDatabase(
- "The visitor with idvisitor=".bin2hex($this->visitorInfo['idvisitor'])." and idvisit=".$this->visitorInfo['idvisit']
- ." wasn't found in the DB, we fallback to a new visitor");
- }
-
- Piwik_PostEvent('Tracker.knownVisitorInformation', $this->visitorInfo);
- }
-
- protected function isTimestampValid($time)
- {
- return $time <= $this->getCurrentTimestamp()
- && $time > $this->getCurrentTimestamp() - 10*365*86400;
- }
-
- /**
- * In the case of a new visit, we have to do the following actions:
- *
- * 1) Insert the new action
- *
- * 2) Insert the visit information
- * @param $idActionUrl
- * @param $idActionName
- * @param $actionType
- * @param $visitIsConverted
- */
- protected function handleNewVisit($idActionUrl, $idActionName, $actionType, $visitIsConverted)
- {
- printDebug("New Visit (IP = ".Piwik_IP::N2P($this->getVisitorIp()).")");
-
- $localTimes = array(
- 'h' => (string) Piwik_Common::getRequestVar( 'h', $this->getCurrentDate("H"), 'int', $this->request),
- 'i' => (string) Piwik_Common::getRequestVar( 'm', $this->getCurrentDate("i"), 'int', $this->request),
- 's' => (string) Piwik_Common::getRequestVar( 's', $this->getCurrentDate("s"), 'int', $this->request)
- );
- foreach($localTimes as $k => $time)
- {
- if(strlen($time) == 1)
- {
- $localTimes[$k] = '0' . $time;
- }
- }
- $localTime = $localTimes['h'] .':'. $localTimes['i'] .':'. $localTimes['s'];
-
- $idcookie = $this->getVisitorIdcookie();
-
- $defaultTimeOnePageVisit = Piwik_Config::getInstance()->Tracker['default_time_one_page_visit'];
-
- // Days since first visit
- $cookieFirstVisitTimestamp = Piwik_Common::getRequestVar('_idts', 0, 'int', $this->request);
- if(!$this->isTimestampValid($cookieFirstVisitTimestamp))
- {
- $cookieFirstVisitTimestamp = $this->getCurrentTimestamp();
- }
- $daysSinceFirstVisit = round(($this->getCurrentTimestamp() - $cookieFirstVisitTimestamp)/86400, $precision = 0);
- if($daysSinceFirstVisit < 0) $daysSinceFirstVisit = 0;
-
- // Number of Visits
- $visitCount = Piwik_Common::getRequestVar('_idvc', 1, 'int', $this->request);
- if($visitCount < 1) $visitCount = 1;
-
- // Days since last visit
- $daysSinceLastVisit = 0;
- $lastVisitTimestamp = Piwik_Common::getRequestVar('_viewts', 0, 'int', $this->request);
- if($this->isTimestampValid($lastVisitTimestamp))
- {
- $daysSinceLastVisit = round(($this->getCurrentTimestamp() - $lastVisitTimestamp)/86400, $precision = 0);
- if($daysSinceLastVisit < 0) $daysSinceLastVisit = 0;
- }
-
- $daysSinceLastOrder = 0;
- $isReturningCustomer = false;
- $lastOrderTimestamp = Piwik_Common::getRequestVar('_ects', 0, 'int', $this->request);
- if($this->isTimestampValid($lastOrderTimestamp))
- {
- $daysSinceLastOrder = round(($this->getCurrentTimestamp() - $lastOrderTimestamp)/86400, $precision = 0);
- if($daysSinceLastOrder < 0)
- {
- $daysSinceLastOrder = 0;
- }
- $isReturningCustomer = true;
- }
-
- // User settings
- $userInfo = $this->getUserSettingsInformation();
-
- // Referrer data
- $referrer = new Piwik_Tracker_Visit_Referer();
- $refererUrl = Piwik_Common::getRequestVar( 'urlref', '', 'string', $this->request);
- $currentUrl = Piwik_Common::getRequestVar( 'url', '', 'string', $this->request);
- $refererInfo = $referrer->getRefererInformation($refererUrl, $currentUrl, $this->idsite);
-
- $visitorReturning = $isReturningCustomer
- ? 2 /* Returning customer */
- : ($visitCount > 1 || $this->isVisitorKnown() || $daysSinceLastVisit > 0
- ? 1 /* Returning */
- : 0 /* New */ );
- /**
- * Save the visitor
- */
- $this->visitorInfo = array(
- 'idsite' => $this->idsite,
- 'visitor_localtime' => $localTime,
- 'idvisitor' => $idcookie,
- 'visitor_returning' => $visitorReturning,
- 'visitor_count_visits' => $visitCount,
- 'visitor_days_since_last' => $daysSinceLastVisit,
- 'visitor_days_since_order' => $daysSinceLastOrder,
- 'visitor_days_since_first' => $daysSinceFirstVisit,
- 'visit_first_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($this->getCurrentTimestamp()),
- 'visit_last_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($this->getCurrentTimestamp()),
- 'visit_entry_idaction_url' => (int)$idActionUrl,
- 'visit_entry_idaction_name' => (int)$idActionName,
- 'visit_exit_idaction_url' => (int)$idActionUrl,
- 'visit_exit_idaction_name' => (int)$idActionName,
- 'visit_total_actions' => in_array($actionType,
- array(Piwik_Tracker_Action::TYPE_ACTION_URL,
- Piwik_Tracker_Action::TYPE_DOWNLOAD,
- Piwik_Tracker_Action::TYPE_OUTLINK,
- Piwik_Tracker_Action::TYPE_SITE_SEARCH))
- ? 1 : 0, // if visit starts with something else (e.g. ecommerce order), don't record as an action
- 'visit_total_searches' => $actionType == Piwik_Tracker_Action::TYPE_SITE_SEARCH ? 1 : 0,
- 'visit_total_time' => self::cleanupVisitTotalTime($defaultTimeOnePageVisit),
- 'visit_goal_converted' => $visitIsConverted ? 1: 0,
- 'visit_goal_buyer' => $this->goalManager->getBuyerType(),
- 'referer_type' => $refererInfo['referer_type'],
- 'referer_name' => $refererInfo['referer_name'],
- 'referer_url' => $refererInfo['referer_url'],
- 'referer_keyword' => $refererInfo['referer_keyword'],
- 'config_id' => $userInfo['config_id'],
- 'config_os' => $userInfo['config_os'],
- 'config_browser_name' => $userInfo['config_browser_name'],
- 'config_browser_version' => $userInfo['config_browser_version'],
- 'config_resolution' => $userInfo['config_resolution'],
- 'config_pdf' => $userInfo['config_pdf'],
- 'config_flash' => $userInfo['config_flash'],
- 'config_java' => $userInfo['config_java'],
- 'config_director' => $userInfo['config_director'],
- 'config_quicktime' => $userInfo['config_quicktime'],
- 'config_realplayer' => $userInfo['config_realplayer'],
- 'config_windowsmedia' => $userInfo['config_windowsmedia'],
- 'config_gears' => $userInfo['config_gears'],
- 'config_silverlight' => $userInfo['config_silverlight'],
- 'config_cookie' => $userInfo['config_cookie'],
- 'location_ip' => $this->getVisitorIp(),
- 'location_browser_lang' => $userInfo['location_browser_lang'],
- );
-
- // add optional location components
- $location = $this->getVisitorLocation($userInfo['location_browser_lang']);
- $this->updateVisitInfoWithLocation($location);
-
- // Add Custom variable key,value to the visitor array
- $this->visitorInfo = array_merge($this->visitorInfo, $this->visitorCustomVariables);
-
- Piwik_PostEvent('Tracker.newVisitorInformation', $this->visitorInfo);
-
- $debugVisitInfo = $this->visitorInfo;
- $debugVisitInfo['idvisitor'] = bin2hex($debugVisitInfo['idvisitor']);
- $debugVisitInfo['config_id'] = bin2hex($debugVisitInfo['config_id']);
- printDebug($debugVisitInfo);
-
- $this->saveVisitorInformation();
- }
+ array_push($sqlBind, $this->idsite, (int)$this->visitorInfo['idvisit']);
+
+ $result = Piwik_Tracker::getDatabase()->query($sqlQuery, $sqlBind);
+
+ $this->visitorInfo['visit_last_action_time'] = $this->getCurrentTimestamp();
+
+ // Debug output
+ if (isset($valuesToUpdate['idvisitor'])) {
+ $valuesToUpdate['idvisitor'] = bin2hex($valuesToUpdate['idvisitor']);
+ }
+ printDebug('Updating existing visit: ' . var_export($valuesToUpdate, true));
+
+ if (Piwik_Tracker::getDatabase()->rowCount($result) == 0) {
+ printDebug("Visitor with this idvisit wasn't found in the DB.");
+ printDebug("$sqlQuery --- ");
+ printDebug($sqlBind);
+ throw new Piwik_Tracker_Visit_VisitorNotFoundInDatabase(
+ "The visitor with idvisitor=" . bin2hex($this->visitorInfo['idvisitor']) . " and idvisit=" . $this->visitorInfo['idvisit']
+ . " wasn't found in the DB, we fallback to a new visitor");
+ }
+
+ Piwik_PostEvent('Tracker.knownVisitorInformation', $this->visitorInfo);
+ }
+
+ protected function isTimestampValid($time)
+ {
+ return $time <= $this->getCurrentTimestamp()
+ && $time > $this->getCurrentTimestamp() - 10 * 365 * 86400;
+ }
+
+ /**
+ * In the case of a new visit, we have to do the following actions:
+ *
+ * 1) Insert the new action
+ *
+ * 2) Insert the visit information
+ * @param $idActionUrl
+ * @param $idActionName
+ * @param $actionType
+ * @param $visitIsConverted
+ */
+ protected function handleNewVisit($idActionUrl, $idActionName, $actionType, $visitIsConverted)
+ {
+ printDebug("New Visit (IP = " . Piwik_IP::N2P($this->getVisitorIp()) . ")");
+
+ $localTimes = array(
+ 'h' => (string)Piwik_Common::getRequestVar('h', $this->getCurrentDate("H"), 'int', $this->request),
+ 'i' => (string)Piwik_Common::getRequestVar('m', $this->getCurrentDate("i"), 'int', $this->request),
+ 's' => (string)Piwik_Common::getRequestVar('s', $this->getCurrentDate("s"), 'int', $this->request)
+ );
+ foreach ($localTimes as $k => $time) {
+ if (strlen($time) == 1) {
+ $localTimes[$k] = '0' . $time;
+ }
+ }
+ $localTime = $localTimes['h'] . ':' . $localTimes['i'] . ':' . $localTimes['s'];
+
+ $idcookie = $this->getVisitorIdcookie();
+
+ $defaultTimeOnePageVisit = Piwik_Config::getInstance()->Tracker['default_time_one_page_visit'];
+
+ // Days since first visit
+ $cookieFirstVisitTimestamp = Piwik_Common::getRequestVar('_idts', 0, 'int', $this->request);
+ if (!$this->isTimestampValid($cookieFirstVisitTimestamp)) {
+ $cookieFirstVisitTimestamp = $this->getCurrentTimestamp();
+ }
+ $daysSinceFirstVisit = round(($this->getCurrentTimestamp() - $cookieFirstVisitTimestamp) / 86400, $precision = 0);
+ if ($daysSinceFirstVisit < 0) $daysSinceFirstVisit = 0;
+
+ // Number of Visits
+ $visitCount = Piwik_Common::getRequestVar('_idvc', 1, 'int', $this->request);
+ if ($visitCount < 1) $visitCount = 1;
+
+ // Days since last visit
+ $daysSinceLastVisit = 0;
+ $lastVisitTimestamp = Piwik_Common::getRequestVar('_viewts', 0, 'int', $this->request);
+ if ($this->isTimestampValid($lastVisitTimestamp)) {
+ $daysSinceLastVisit = round(($this->getCurrentTimestamp() - $lastVisitTimestamp) / 86400, $precision = 0);
+ if ($daysSinceLastVisit < 0) $daysSinceLastVisit = 0;
+ }
+
+ $daysSinceLastOrder = 0;
+ $isReturningCustomer = false;
+ $lastOrderTimestamp = Piwik_Common::getRequestVar('_ects', 0, 'int', $this->request);
+ if ($this->isTimestampValid($lastOrderTimestamp)) {
+ $daysSinceLastOrder = round(($this->getCurrentTimestamp() - $lastOrderTimestamp) / 86400, $precision = 0);
+ if ($daysSinceLastOrder < 0) {
+ $daysSinceLastOrder = 0;
+ }
+ $isReturningCustomer = true;
+ }
+
+ // User settings
+ $userInfo = $this->getUserSettingsInformation();
+
+ // Referrer data
+ $referrer = new Piwik_Tracker_Visit_Referer();
+ $refererUrl = Piwik_Common::getRequestVar('urlref', '', 'string', $this->request);
+ $currentUrl = Piwik_Common::getRequestVar('url', '', 'string', $this->request);
+ $refererInfo = $referrer->getRefererInformation($refererUrl, $currentUrl, $this->idsite);
+
+ $visitorReturning = $isReturningCustomer
+ ? 2 /* Returning customer */
+ : ($visitCount > 1 || $this->isVisitorKnown() || $daysSinceLastVisit > 0
+ ? 1 /* Returning */
+ : 0 /* New */);
+ /**
+ * Save the visitor
+ */
+ $this->visitorInfo = array(
+ 'idsite' => $this->idsite,
+ 'visitor_localtime' => $localTime,
+ 'idvisitor' => $idcookie,
+ 'visitor_returning' => $visitorReturning,
+ 'visitor_count_visits' => $visitCount,
+ 'visitor_days_since_last' => $daysSinceLastVisit,
+ 'visitor_days_since_order' => $daysSinceLastOrder,
+ 'visitor_days_since_first' => $daysSinceFirstVisit,
+ 'visit_first_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($this->getCurrentTimestamp()),
+ 'visit_last_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($this->getCurrentTimestamp()),
+ 'visit_entry_idaction_url' => (int)$idActionUrl,
+ 'visit_entry_idaction_name' => (int)$idActionName,
+ 'visit_exit_idaction_url' => (int)$idActionUrl,
+ 'visit_exit_idaction_name' => (int)$idActionName,
+ 'visit_total_actions' => in_array($actionType,
+ array(Piwik_Tracker_Action::TYPE_ACTION_URL,
+ Piwik_Tracker_Action::TYPE_DOWNLOAD,
+ Piwik_Tracker_Action::TYPE_OUTLINK,
+ Piwik_Tracker_Action::TYPE_SITE_SEARCH))
+ ? 1 : 0, // if visit starts with something else (e.g. ecommerce order), don't record as an action
+ 'visit_total_searches' => $actionType == Piwik_Tracker_Action::TYPE_SITE_SEARCH ? 1 : 0,
+ 'visit_total_time' => self::cleanupVisitTotalTime($defaultTimeOnePageVisit),
+ 'visit_goal_converted' => $visitIsConverted ? 1 : 0,
+ 'visit_goal_buyer' => $this->goalManager->getBuyerType(),
+ 'referer_type' => $refererInfo['referer_type'],
+ 'referer_name' => $refererInfo['referer_name'],
+ 'referer_url' => $refererInfo['referer_url'],
+ 'referer_keyword' => $refererInfo['referer_keyword'],
+ 'config_id' => $userInfo['config_id'],
+ 'config_os' => $userInfo['config_os'],
+ 'config_browser_name' => $userInfo['config_browser_name'],
+ 'config_browser_version' => $userInfo['config_browser_version'],
+ 'config_resolution' => $userInfo['config_resolution'],
+ 'config_pdf' => $userInfo['config_pdf'],
+ 'config_flash' => $userInfo['config_flash'],
+ 'config_java' => $userInfo['config_java'],
+ 'config_director' => $userInfo['config_director'],
+ 'config_quicktime' => $userInfo['config_quicktime'],
+ 'config_realplayer' => $userInfo['config_realplayer'],
+ 'config_windowsmedia' => $userInfo['config_windowsmedia'],
+ 'config_gears' => $userInfo['config_gears'],
+ 'config_silverlight' => $userInfo['config_silverlight'],
+ 'config_cookie' => $userInfo['config_cookie'],
+ 'location_ip' => $this->getVisitorIp(),
+ 'location_browser_lang' => $userInfo['location_browser_lang'],
+ );
+
+ // add optional location components
+ $location = $this->getVisitorLocation($userInfo['location_browser_lang']);
+ $this->updateVisitInfoWithLocation($location);
+
+ // Add Custom variable key,value to the visitor array
+ $this->visitorInfo = array_merge($this->visitorInfo, $this->visitorCustomVariables);
+
+ Piwik_PostEvent('Tracker.newVisitorInformation', $this->visitorInfo);
+
+ $debugVisitInfo = $this->visitorInfo;
+ $debugVisitInfo['idvisitor'] = bin2hex($debugVisitInfo['idvisitor']);
+ $debugVisitInfo['config_id'] = bin2hex($debugVisitInfo['config_id']);
+ printDebug($debugVisitInfo);
+
+ $this->saveVisitorInformation();
+ }
static private function cleanupVisitTotalTime($t)
{
$t = (int)$t;
$smallintMysqlLimit = 65534;
- if($t > $smallintMysqlLimit) {
+ if ($t > $smallintMysqlLimit) {
$t = $smallintMysqlLimit;
}
return $t;
}
-
- /**
- * Returns the location of the visitor, based on the visitor's IP and browser language.
- *
- * @param string $browserLang
- * @return array See Piwik_UserCountry_LocationProvider::getLocation for more info.
- */
- private function getVisitorLocation( $browserLang )
- {
- $location = array();
- $userInfo = array('lang' => $browserLang, 'ip' => Piwik_IP::N2P($this->getVisitorIp()));
- Piwik_PostEvent('Tracker.getVisitorLocation', $location, $userInfo);
-
- if($this->authenticated)
- {
- // check for location override query parameters (ie, lat, long, country, region, city)
- $locationOverrideParams = array(
- 'country' => array('string', Piwik_UserCountry_LocationProvider::COUNTRY_CODE_KEY),
- 'region' => array('string', Piwik_UserCountry_LocationProvider::REGION_CODE_KEY),
- 'city' => array('string', Piwik_UserCountry_LocationProvider::CITY_NAME_KEY),
- 'lat' => array('float', Piwik_UserCountry_LocationProvider::LATITUDE_KEY),
- 'long' => array('float', Piwik_UserCountry_LocationProvider::LONGITUDE_KEY),
- );
- foreach ($locationOverrideParams as $queryParamName => $info)
- {
- list($type, $locationResultKey) = $info;
-
- $value = Piwik_Common::getRequestVar($queryParamName, false, $type, $this->request);
- if (!empty($value))
- {
- $location[$locationResultKey] = $value;
- }
- }
- }
-
- if (empty($location['country_code'])) // sanity check
- {
- $location['country_code'] = self::UNKNOWN_CODE;
- }
-
- return $location;
- }
-
- /**
- * Sets visitor info array with location info.
- *
- * @param array $location See Piwik_UserCountry_LocationProvider::getLocation for more info.
- */
- private function updateVisitInfoWithLocation( $location )
- {
- static $logVisitToLowerLocationMapping = array(
- 'location_country' => Piwik_UserCountry_LocationProvider::COUNTRY_CODE_KEY,
- );
-
- static $logVisitToLocationMapping = array(
- 'location_region' => Piwik_UserCountry_LocationProvider::REGION_CODE_KEY,
- 'location_city' => Piwik_UserCountry_LocationProvider::CITY_NAME_KEY,
- 'location_latitude' => Piwik_UserCountry_LocationProvider::LATITUDE_KEY,
- 'location_longitude' => Piwik_UserCountry_LocationProvider::LONGITUDE_KEY,
- );
-
- foreach ($logVisitToLowerLocationMapping as $column => $locationKey)
- {
- if (!empty($location[$locationKey]))
- {
- $this->visitorInfo[$column] = strtolower($location[$locationKey]);
- }
- }
-
- foreach ($logVisitToLocationMapping as $column => $locationKey)
- {
- if (!empty($location[$locationKey]))
- {
- $this->visitorInfo[$column] = $location[$locationKey];
- }
- }
-
- // if the location has provider/organization info, set it
- if (!empty($location[Piwik_UserCountry_LocationProvider::ISP_KEY]))
- {
- $providerValue = $location[Piwik_UserCountry_LocationProvider::ISP_KEY];
-
- // if the org is set and not the same as the isp, add it to the provider value
- if (!empty($location[Piwik_UserCountry_LocationProvider::ORG_KEY])
- && $location[Piwik_UserCountry_LocationProvider::ORG_KEY] != $providerValue)
- {
- $providerValue .= ' - ' . $location[Piwik_UserCountry_LocationProvider::ORG_KEY];
- }
- }
- else if (!empty($location[Piwik_UserCountry_LocationProvider::ORG_KEY]))
- {
- $providerValue = $location[Piwik_UserCountry_LocationProvider::ORG_KEY];
- }
-
- if (isset($providerValue))
- {
- $this->visitorInfo['location_provider'] = $providerValue;
- }
- }
-
- /**
- * Save new visitor information to log_visit table.
- * Provides pre- and post- event hooks (Tracker.saveVisitorInformation and Tracker.saveVisitorInformation.end) for plugins
- */
- protected function saveVisitorInformation()
- {
- Piwik_PostEvent('Tracker.saveVisitorInformation', $this->visitorInfo);
-
- $this->visitorInfo['location_browser_lang'] = substr($this->visitorInfo['location_browser_lang'], 0, 20);
- $this->visitorInfo['referer_name'] = substr($this->visitorInfo['referer_name'], 0, 70);
- $this->visitorInfo['referer_keyword'] = substr($this->visitorInfo['referer_keyword'], 0, 255);
- $this->visitorInfo['config_resolution'] = substr($this->visitorInfo['config_resolution'], 0, 9);
-
- $fields = implode(", ", array_keys($this->visitorInfo));
- $values = Piwik_Common::getSqlStringFieldsArray($this->visitorInfo);
-
- $sql = "INSERT INTO ".Piwik_Common::prefixTable('log_visit'). " ($fields) VALUES ($values)";
- $bind = array_values($this->visitorInfo);
- Piwik_Tracker::getDatabase()->query( $sql, $bind);
-
- $idVisit = Piwik_Tracker::getDatabase()->lastInsertId();
- $this->visitorInfo['idvisit'] = $idVisit;
-
- $this->visitorInfo['visit_first_action_time'] = $this->getCurrentTimestamp();
- $this->visitorInfo['visit_last_action_time'] = $this->getCurrentTimestamp();
-
- Piwik_PostEvent('Tracker.saveVisitorInformation.end', $this->visitorInfo);
- }
-
- /**
- * Returns visitor cookie
- *
- * @return binary
- */
- protected function getVisitorIdcookie()
- {
- if($this->isVisitorKnown())
- {
- return $this->visitorInfo['idvisitor'];
- }
- // If the visitor had a first party ID cookie, then we use this value
- if(!empty($this->visitorInfo['idvisitor'])
- && strlen($this->visitorInfo['idvisitor']) == Piwik_Tracker::LENGTH_BINARY_ID)
- {
- return $this->visitorInfo['idvisitor'];
- }
+
+ /**
+ * Returns the location of the visitor, based on the visitor's IP and browser language.
+ *
+ * @param string $browserLang
+ * @return array See Piwik_UserCountry_LocationProvider::getLocation for more info.
+ */
+ private function getVisitorLocation($browserLang)
+ {
+ $location = array();
+ $userInfo = array('lang' => $browserLang, 'ip' => Piwik_IP::N2P($this->getVisitorIp()));
+ Piwik_PostEvent('Tracker.getVisitorLocation', $location, $userInfo);
+
+ if ($this->authenticated) {
+ // check for location override query parameters (ie, lat, long, country, region, city)
+ $locationOverrideParams = array(
+ 'country' => array('string', Piwik_UserCountry_LocationProvider::COUNTRY_CODE_KEY),
+ 'region' => array('string', Piwik_UserCountry_LocationProvider::REGION_CODE_KEY),
+ 'city' => array('string', Piwik_UserCountry_LocationProvider::CITY_NAME_KEY),
+ 'lat' => array('float', Piwik_UserCountry_LocationProvider::LATITUDE_KEY),
+ 'long' => array('float', Piwik_UserCountry_LocationProvider::LONGITUDE_KEY),
+ );
+ foreach ($locationOverrideParams as $queryParamName => $info) {
+ list($type, $locationResultKey) = $info;
+
+ $value = Piwik_Common::getRequestVar($queryParamName, false, $type, $this->request);
+ if (!empty($value)) {
+ $location[$locationResultKey] = $value;
+ }
+ }
+ }
+
+ if (empty($location['country_code'])) // sanity check
+ {
+ $location['country_code'] = self::UNKNOWN_CODE;
+ }
+
+ return $location;
+ }
+
+ /**
+ * Sets visitor info array with location info.
+ *
+ * @param array $location See Piwik_UserCountry_LocationProvider::getLocation for more info.
+ */
+ private function updateVisitInfoWithLocation($location)
+ {
+ static $logVisitToLowerLocationMapping = array(
+ 'location_country' => Piwik_UserCountry_LocationProvider::COUNTRY_CODE_KEY,
+ );
+
+ static $logVisitToLocationMapping = array(
+ 'location_region' => Piwik_UserCountry_LocationProvider::REGION_CODE_KEY,
+ 'location_city' => Piwik_UserCountry_LocationProvider::CITY_NAME_KEY,
+ 'location_latitude' => Piwik_UserCountry_LocationProvider::LATITUDE_KEY,
+ 'location_longitude' => Piwik_UserCountry_LocationProvider::LONGITUDE_KEY,
+ );
+
+ foreach ($logVisitToLowerLocationMapping as $column => $locationKey) {
+ if (!empty($location[$locationKey])) {
+ $this->visitorInfo[$column] = strtolower($location[$locationKey]);
+ }
+ }
+
+ foreach ($logVisitToLocationMapping as $column => $locationKey) {
+ if (!empty($location[$locationKey])) {
+ $this->visitorInfo[$column] = $location[$locationKey];
+ }
+ }
+
+ // if the location has provider/organization info, set it
+ if (!empty($location[Piwik_UserCountry_LocationProvider::ISP_KEY])) {
+ $providerValue = $location[Piwik_UserCountry_LocationProvider::ISP_KEY];
+
+ // if the org is set and not the same as the isp, add it to the provider value
+ if (!empty($location[Piwik_UserCountry_LocationProvider::ORG_KEY])
+ && $location[Piwik_UserCountry_LocationProvider::ORG_KEY] != $providerValue
+ ) {
+ $providerValue .= ' - ' . $location[Piwik_UserCountry_LocationProvider::ORG_KEY];
+ }
+ } else if (!empty($location[Piwik_UserCountry_LocationProvider::ORG_KEY])) {
+ $providerValue = $location[Piwik_UserCountry_LocationProvider::ORG_KEY];
+ }
+
+ if (isset($providerValue)) {
+ $this->visitorInfo['location_provider'] = $providerValue;
+ }
+ }
+
+ /**
+ * Save new visitor information to log_visit table.
+ * Provides pre- and post- event hooks (Tracker.saveVisitorInformation and Tracker.saveVisitorInformation.end) for plugins
+ */
+ protected function saveVisitorInformation()
+ {
+ Piwik_PostEvent('Tracker.saveVisitorInformation', $this->visitorInfo);
+
+ $this->visitorInfo['location_browser_lang'] = substr($this->visitorInfo['location_browser_lang'], 0, 20);
+ $this->visitorInfo['referer_name'] = substr($this->visitorInfo['referer_name'], 0, 70);
+ $this->visitorInfo['referer_keyword'] = substr($this->visitorInfo['referer_keyword'], 0, 255);
+ $this->visitorInfo['config_resolution'] = substr($this->visitorInfo['config_resolution'], 0, 9);
+
+ $fields = implode(", ", array_keys($this->visitorInfo));
+ $values = Piwik_Common::getSqlStringFieldsArray($this->visitorInfo);
+
+ $sql = "INSERT INTO " . Piwik_Common::prefixTable('log_visit') . " ($fields) VALUES ($values)";
+ $bind = array_values($this->visitorInfo);
+ Piwik_Tracker::getDatabase()->query($sql, $bind);
+
+ $idVisit = Piwik_Tracker::getDatabase()->lastInsertId();
+ $this->visitorInfo['idvisit'] = $idVisit;
+
+ $this->visitorInfo['visit_first_action_time'] = $this->getCurrentTimestamp();
+ $this->visitorInfo['visit_last_action_time'] = $this->getCurrentTimestamp();
+
+ Piwik_PostEvent('Tracker.saveVisitorInformation.end', $this->visitorInfo);
+ }
+
+ /**
+ * Returns visitor cookie
+ *
+ * @return binary
+ */
+ protected function getVisitorIdcookie()
+ {
+ if ($this->isVisitorKnown()) {
+ return $this->visitorInfo['idvisitor'];
+ }
+ // If the visitor had a first party ID cookie, then we use this value
+ if (!empty($this->visitorInfo['idvisitor'])
+ && strlen($this->visitorInfo['idvisitor']) == Piwik_Tracker::LENGTH_BINARY_ID
+ ) {
+ return $this->visitorInfo['idvisitor'];
+ }
return Piwik_Common::hex2bin($this->generateUniqueVisitorId());
}
@@ -782,333 +735,310 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
}
/**
- * Returns the visitor's IP address
- *
- * @return long
- */
- protected function getVisitorIp()
- {
- return $this->visitorInfo['location_ip'];
- }
-
- /**
- * Returns the visitor's browser (user agent)
- *
- * @return string
- */
- static public function getUserAgent($request)
- {
- $default = @$_SERVER['HTTP_USER_AGENT'];
- return Piwik_Common::getRequestVar('ua', is_null($default) ? false : $default, 'string', $request);
- }
-
- /**
- * Returns the language the visitor is viewing.
- *
- * @return string browser language code, eg. "en-gb,en;q=0.5"
- */
- protected function getBrowserLanguage()
- {
- return Piwik_Common::getRequestVar('lang', Piwik_Common::getBrowserLanguage(), 'string', $this->request);
- }
-
- /**
- * Returns the current date in the "Y-m-d" PHP format
- *
- * @param string $format
- * @return string
- */
- protected function getCurrentDate( $format = "Y-m-d")
- {
- return date($format, $this->getCurrentTimestamp() );
- }
-
- /**
- * Returns the current Timestamp
- *
- * @return int
- */
- protected function getCurrentTimestamp()
- {
- return $this->timestamp;
- }
-
- /**
- * Test if the current visitor is excluded from the statistics.
- *
- * Plugins can for example exclude visitors based on the
- * - IP
- * - If a given cookie is found
- *
- * @return bool True if the visit must not be saved, false otherwise
- */
- protected function isExcluded()
- {
- $excluded = false;
-
- $ip = $this->getVisitorIp();
- $ua = $this->getUserAgent($this->request);
-
- /*
- * Live/Bing/MSN bot and Googlebot are evolving to detect cloaked websites.
- * As a result, these sophisticated bots exhibit characteristics of
- * browsers (cookies enabled, executing JavaScript, etc).
- */
- $allowBots = Piwik_Common::getRequestVar('bots', false) != false;
- if ( !$allowBots
- && (strpos($ua, 'Googlebot') !== false // Googlebot
- || strpos($ua, 'Google Web Preview') !== false // Google Instant
- || strpos($ua, 'bingbot') !== false // Bingbot
- || strpos($ua, 'YottaaMonitor') !== false // Yottaa
- || Piwik_IP::isIpInRange($ip,
- array(
- // Live/Bing/MSN
- '64.4.0.0/18',
- '65.52.0.0/14',
- '157.54.0.0/15',
- '157.56.0.0/14',
- '157.60.0.0/16',
- '207.46.0.0/16',
- '207.68.128.0/18',
- '207.68.192.0/20',
- '131.253.26.0/20',
- '131.253.24.0/20',
- // Yahoo
- '72.30.198.0/20',
- '72.30.196.0/20',
- '98.137.207.0/20',
- // Chinese bot hammering websites
- '1.202.218.8'
- ))))
- {
- printDebug('Search bot detected, visit excluded');
- $excluded = true;
- }
-
- /*
- * Requests built with piwik.js will contain a rec=1 parameter. This is used as
- * an indication that the request is made by a JS enabled device. By default, Piwik
- * doesn't track non-JS visitors.
- */
- if(!$excluded)
- {
- $parameterForceRecord = 'rec';
- $toRecord = Piwik_Common::getRequestVar($parameterForceRecord, false, 'int', $this->request);
- if(!$toRecord)
- {
- printDebug(@$_SERVER['REQUEST_METHOD'].' parameter '.$parameterForceRecord.' not found in URL, request excluded');
- $excluded = true;
- printDebug("'$parameterForceRecord' parameter not found.");
- }
- }
-
- /* custom filters can override the built-in filters above */
- Piwik_PostEvent('Tracker.Visit.isExcluded', $excluded);
-
- /*
- * Following exclude operations happen after the hook.
- * These are of higher priority and should not be overwritten by plugins.
- */
-
- // Checking if the Piwik ignore cookie is set
- if(!$excluded)
- {
- $excluded = $this->isIgnoreCookieFound();
- if($excluded)
- {
- printDebug("Ignore cookie found.");
- }
- }
-
- // Checking for excluded IPs
- if(!$excluded)
- {
- $excluded = $this->isVisitorIpExcluded($ip);
- if($excluded)
- {
- printDebug("IP excluded.");
- }
- }
-
- // Check if user agent should be excluded
- if (!$excluded)
- {
- $excluded = $this->isUserAgentExcluded($ua);
- if ($excluded)
- {
- printDebug("User agent excluded.");
- }
- }
-
- if(!$excluded)
- {
- if( (isset($_SERVER["HTTP_X_PURPOSE"])
- && in_array($_SERVER["HTTP_X_PURPOSE"], array("preview", "instant")))
- || (isset($_SERVER['HTTP_X_MOZ'])
- && $_SERVER['HTTP_X_MOZ'] == "prefetch"))
- {
- $excluded = true;
- printDebug("Prefetch request detected, not a real visit so we Ignore this visit/pageview");
- }
- }
-
- if($excluded)
- {
- printDebug("Visitor excluded.");
- return true;
- }
-
- return false;
- }
-
- /**
- * Looks for the ignore cookie that users can set in the Piwik admin screen.
- * @return bool
- */
- protected function isIgnoreCookieFound()
- {
- if(Piwik_Tracker_IgnoreCookie::isIgnoreCookieFound())
- {
- printDebug('Piwik ignore cookie was found, visit not tracked.');
- return true;
- }
- return false;
- }
-
- /**
- * Checks if the visitor ip is in the excluded list
- *
- * @param string $ip Long IP
- * @return bool
- */
- protected function isVisitorIpExcluded($ip)
- {
- $websiteAttributes = Piwik_Tracker_Cache::getCacheWebsiteAttributes( $this->idsite );
- if(!empty($websiteAttributes['excluded_ips']))
- {
- if(Piwik_IP::isIpInRange($ip, $websiteAttributes['excluded_ips']))
- {
- printDebug('Visitor IP '.Piwik_IP::N2P($ip).' is excluded from being tracked');
- return true;
- }
- }
- return false;
- }
-
- /**
- * Returns true if the specified user agent should be excluded for the current site or not.
- *
- * Visits whose user agent string contains one of the excluded_user_agents strings for the
- * site being tracked (or one of the global strings) will be excluded.
- *
- * @param string $ua The user agent string.
- * @return bool
- */
- protected function isUserAgentExcluded( $ua )
- {
- $websiteAttributes = Piwik_Tracker_Cache::getCacheWebsiteAttributes($this->idsite);
- if (!empty($websiteAttributes['excluded_user_agents']))
- {
- foreach ($websiteAttributes['excluded_user_agents'] as $excludedUserAgent)
- {
- // if the excluded user agent string part is in this visit's user agent, this visit should be excluded
- if (stripos($ua, $excludedUserAgent) !== false)
- {
- return true;
- }
- }
- }
- return false;
- }
-
- /**
- * Returns the cookie name used for the Piwik Tracker cookie
- *
- * @return string
- */
- protected function getCookieName()
- {
- return Piwik_Config::getInstance()->Tracker['cookie_name'];
- }
-
- /**
- * Returns the cookie expiration date.
- *
- * @return int
- */
- protected function getCookieExpire()
- {
- return $this->getCurrentTimestamp() + Piwik_Config::getInstance()->Tracker['cookie_expire'];
- }
-
- /**
- * Returns cookie path
- *
- * @return string
- */
- protected function getCookiePath()
- {
- return Piwik_Config::getInstance()->Tracker['cookie_path'];
- }
-
- protected function shouldUseThirdPartyCookie()
- {
- return (bool)Piwik_Config::getInstance()->Tracker['use_third_party_id_cookie'];
- }
-
- /**
- * Is the request for a known VisitorId, based on 1st party, 3rd party (optional) cookies or Tracking API forced Visitor ID
- * @throws Exception
- */
- protected function assignVisitorIdFromRequest()
- {
- $found = false;
-
- // Was a Visitor ID "forced" (@see Tracking API setVisitorId()) for this request?
- $idVisitor = $this->getForcedVisitorId();
- if(!empty($idVisitor))
- {
- if(strlen($idVisitor) != Piwik_Tracker::LENGTH_HEX_ID_STRING)
- {
- throw new Exception("Visitor ID (cid) $idVisitor must be ".Piwik_Tracker::LENGTH_HEX_ID_STRING." characters long");
- }
- printDebug("Request will be recorded for this idvisitor = ".$idVisitor);
- $found = true;
- }
-
- // - If set to use 3rd party cookies for Visit ID, read the cookie
- if(!$found)
- {
- // - By default, reads the first party cookie ID
- $useThirdPartyCookie = $this->shouldUseThirdPartyCookie();
- if($useThirdPartyCookie)
- {
- $idVisitor = $this->cookie->get(0);
- if($idVisitor !== false
- && strlen($idVisitor) == Piwik_Tracker::LENGTH_HEX_ID_STRING)
- {
- $found = true;
- }
- }
- }
- // If a third party cookie was not found, we default to the first party cookie
- if(!$found)
- {
- $idVisitor = Piwik_Common::getRequestVar('_id', '', 'string', $this->request);
- $found = strlen($idVisitor) >= Piwik_Tracker::LENGTH_HEX_ID_STRING;
- }
-
- if( $found )
- {
- $truncated = substr($idVisitor, 0, Piwik_Tracker::LENGTH_HEX_ID_STRING);
- $binVisitorId = @Piwik_Common::hex2bin($truncated);
- if(!empty($binVisitorId))
- {
- $this->visitorInfo['idvisitor'] = $binVisitorId;
- }
-
- }
- }
+ * Returns the visitor's IP address
+ *
+ * @return long
+ */
+ protected function getVisitorIp()
+ {
+ return $this->visitorInfo['location_ip'];
+ }
+
+ /**
+ * Returns the visitor's browser (user agent)
+ *
+ * @return string
+ */
+ static public function getUserAgent($request)
+ {
+ $default = @$_SERVER['HTTP_USER_AGENT'];
+ return Piwik_Common::getRequestVar('ua', is_null($default) ? false : $default, 'string', $request);
+ }
+
+ /**
+ * Returns the language the visitor is viewing.
+ *
+ * @return string browser language code, eg. "en-gb,en;q=0.5"
+ */
+ protected function getBrowserLanguage()
+ {
+ return Piwik_Common::getRequestVar('lang', Piwik_Common::getBrowserLanguage(), 'string', $this->request);
+ }
+
+ /**
+ * Returns the current date in the "Y-m-d" PHP format
+ *
+ * @param string $format
+ * @return string
+ */
+ protected function getCurrentDate($format = "Y-m-d")
+ {
+ return date($format, $this->getCurrentTimestamp());
+ }
+
+ /**
+ * Returns the current Timestamp
+ *
+ * @return int
+ */
+ protected function getCurrentTimestamp()
+ {
+ return $this->timestamp;
+ }
+
+ /**
+ * Test if the current visitor is excluded from the statistics.
+ *
+ * Plugins can for example exclude visitors based on the
+ * - IP
+ * - If a given cookie is found
+ *
+ * @return bool True if the visit must not be saved, false otherwise
+ */
+ protected function isExcluded()
+ {
+ $excluded = false;
+
+ $ip = $this->getVisitorIp();
+ $ua = $this->getUserAgent($this->request);
+
+ /*
+ * Live/Bing/MSN bot and Googlebot are evolving to detect cloaked websites.
+ * As a result, these sophisticated bots exhibit characteristics of
+ * browsers (cookies enabled, executing JavaScript, etc).
+ */
+ $allowBots = Piwik_Common::getRequestVar('bots', false) != false;
+ if (!$allowBots
+ && (strpos($ua, 'Googlebot') !== false // Googlebot
+ || strpos($ua, 'Google Web Preview') !== false // Google Instant
+ || strpos($ua, 'bingbot') !== false // Bingbot
+ || strpos($ua, 'YottaaMonitor') !== false // Yottaa
+ || Piwik_IP::isIpInRange($ip,
+ array(
+ // Live/Bing/MSN
+ '64.4.0.0/18',
+ '65.52.0.0/14',
+ '157.54.0.0/15',
+ '157.56.0.0/14',
+ '157.60.0.0/16',
+ '207.46.0.0/16',
+ '207.68.128.0/18',
+ '207.68.192.0/20',
+ '131.253.26.0/20',
+ '131.253.24.0/20',
+ // Yahoo
+ '72.30.198.0/20',
+ '72.30.196.0/20',
+ '98.137.207.0/20',
+ // Chinese bot hammering websites
+ '1.202.218.8'
+ )))
+ ) {
+ printDebug('Search bot detected, visit excluded');
+ $excluded = true;
+ }
+
+ /*
+ * Requests built with piwik.js will contain a rec=1 parameter. This is used as
+ * an indication that the request is made by a JS enabled device. By default, Piwik
+ * doesn't track non-JS visitors.
+ */
+ if (!$excluded) {
+ $parameterForceRecord = 'rec';
+ $toRecord = Piwik_Common::getRequestVar($parameterForceRecord, false, 'int', $this->request);
+ if (!$toRecord) {
+ printDebug(@$_SERVER['REQUEST_METHOD'] . ' parameter ' . $parameterForceRecord . ' not found in URL, request excluded');
+ $excluded = true;
+ printDebug("'$parameterForceRecord' parameter not found.");
+ }
+ }
+
+ /* custom filters can override the built-in filters above */
+ Piwik_PostEvent('Tracker.Visit.isExcluded', $excluded);
+
+ /*
+ * Following exclude operations happen after the hook.
+ * These are of higher priority and should not be overwritten by plugins.
+ */
+
+ // Checking if the Piwik ignore cookie is set
+ if (!$excluded) {
+ $excluded = $this->isIgnoreCookieFound();
+ if ($excluded) {
+ printDebug("Ignore cookie found.");
+ }
+ }
+
+ // Checking for excluded IPs
+ if (!$excluded) {
+ $excluded = $this->isVisitorIpExcluded($ip);
+ if ($excluded) {
+ printDebug("IP excluded.");
+ }
+ }
+
+ // Check if user agent should be excluded
+ if (!$excluded) {
+ $excluded = $this->isUserAgentExcluded($ua);
+ if ($excluded) {
+ printDebug("User agent excluded.");
+ }
+ }
+
+ if (!$excluded) {
+ if ((isset($_SERVER["HTTP_X_PURPOSE"])
+ && in_array($_SERVER["HTTP_X_PURPOSE"], array("preview", "instant")))
+ || (isset($_SERVER['HTTP_X_MOZ'])
+ && $_SERVER['HTTP_X_MOZ'] == "prefetch")
+ ) {
+ $excluded = true;
+ printDebug("Prefetch request detected, not a real visit so we Ignore this visit/pageview");
+ }
+ }
+
+ if ($excluded) {
+ printDebug("Visitor excluded.");
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Looks for the ignore cookie that users can set in the Piwik admin screen.
+ * @return bool
+ */
+ protected function isIgnoreCookieFound()
+ {
+ if (Piwik_Tracker_IgnoreCookie::isIgnoreCookieFound()) {
+ printDebug('Piwik ignore cookie was found, visit not tracked.');
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Checks if the visitor ip is in the excluded list
+ *
+ * @param string $ip Long IP
+ * @return bool
+ */
+ protected function isVisitorIpExcluded($ip)
+ {
+ $websiteAttributes = Piwik_Tracker_Cache::getCacheWebsiteAttributes($this->idsite);
+ if (!empty($websiteAttributes['excluded_ips'])) {
+ if (Piwik_IP::isIpInRange($ip, $websiteAttributes['excluded_ips'])) {
+ printDebug('Visitor IP ' . Piwik_IP::N2P($ip) . ' is excluded from being tracked');
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if the specified user agent should be excluded for the current site or not.
+ *
+ * Visits whose user agent string contains one of the excluded_user_agents strings for the
+ * site being tracked (or one of the global strings) will be excluded.
+ *
+ * @param string $ua The user agent string.
+ * @return bool
+ */
+ protected function isUserAgentExcluded($ua)
+ {
+ $websiteAttributes = Piwik_Tracker_Cache::getCacheWebsiteAttributes($this->idsite);
+ if (!empty($websiteAttributes['excluded_user_agents'])) {
+ foreach ($websiteAttributes['excluded_user_agents'] as $excludedUserAgent) {
+ // if the excluded user agent string part is in this visit's user agent, this visit should be excluded
+ if (stripos($ua, $excludedUserAgent) !== false) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Returns the cookie name used for the Piwik Tracker cookie
+ *
+ * @return string
+ */
+ protected function getCookieName()
+ {
+ return Piwik_Config::getInstance()->Tracker['cookie_name'];
+ }
+
+ /**
+ * Returns the cookie expiration date.
+ *
+ * @return int
+ */
+ protected function getCookieExpire()
+ {
+ return $this->getCurrentTimestamp() + Piwik_Config::getInstance()->Tracker['cookie_expire'];
+ }
+
+ /**
+ * Returns cookie path
+ *
+ * @return string
+ */
+ protected function getCookiePath()
+ {
+ return Piwik_Config::getInstance()->Tracker['cookie_path'];
+ }
+
+ protected function shouldUseThirdPartyCookie()
+ {
+ return (bool)Piwik_Config::getInstance()->Tracker['use_third_party_id_cookie'];
+ }
+
+ /**
+ * Is the request for a known VisitorId, based on 1st party, 3rd party (optional) cookies or Tracking API forced Visitor ID
+ * @throws Exception
+ */
+ protected function assignVisitorIdFromRequest()
+ {
+ $found = false;
+
+ // Was a Visitor ID "forced" (@see Tracking API setVisitorId()) for this request?
+ $idVisitor = $this->getForcedVisitorId();
+ if (!empty($idVisitor)) {
+ if (strlen($idVisitor) != Piwik_Tracker::LENGTH_HEX_ID_STRING) {
+ throw new Exception("Visitor ID (cid) $idVisitor must be " . Piwik_Tracker::LENGTH_HEX_ID_STRING . " characters long");
+ }
+ printDebug("Request will be recorded for this idvisitor = " . $idVisitor);
+ $found = true;
+ }
+
+ // - If set to use 3rd party cookies for Visit ID, read the cookie
+ if (!$found) {
+ // - By default, reads the first party cookie ID
+ $useThirdPartyCookie = $this->shouldUseThirdPartyCookie();
+ if ($useThirdPartyCookie) {
+ $idVisitor = $this->cookie->get(0);
+ if ($idVisitor !== false
+ && strlen($idVisitor) == Piwik_Tracker::LENGTH_HEX_ID_STRING
+ ) {
+ $found = true;
+ }
+ }
+ }
+ // If a third party cookie was not found, we default to the first party cookie
+ if (!$found) {
+ $idVisitor = Piwik_Common::getRequestVar('_id', '', 'string', $this->request);
+ $found = strlen($idVisitor) >= Piwik_Tracker::LENGTH_HEX_ID_STRING;
+ }
+
+ if ($found) {
+ $truncated = substr($idVisitor, 0, Piwik_Tracker::LENGTH_HEX_ID_STRING);
+ $binVisitorId = @Piwik_Common::hex2bin($truncated);
+ if (!empty($binVisitorId)) {
+ $this->visitorInfo['idvisitor'] = $binVisitorId;
+ }
+
+ }
+ }
protected function getForcedVisitorId()
{
@@ -1116,49 +1046,45 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
}
/**
- * This methods tries to see if the visitor has visited the website before.
- *
- * We have to split the visitor into one of the category
- * - Known visitor
- * - New visitor
- */
- protected function recognizeTheVisitor()
- {
- $this->visitorKnown = false;
- $this->setCookie( new Piwik_Cookie(
- $this->getCookieName(),
- $this->getCookieExpire(),
- $this->getCookiePath()) );
- $this->printCookie();
-
- $userInfo = $this->getUserSettingsInformation();
- $configId = $userInfo['config_id'];
-
- $this->assignVisitorIdFromRequest();
- $isVisitorIdToLookup = !empty($this->visitorInfo['idvisitor']);
-
- if($isVisitorIdToLookup)
- {
- printDebug("Matching visitors with: visitorId=".bin2hex($this->visitorInfo['idvisitor'])." OR configId=".bin2hex($configId));
- }
- else
- {
- printDebug("Visitor doesn't have the piwik cookie...");
- }
-
- $selectCustomVariables = '';
- // No custom var were found in the request, so let's copy the previous one in a potential conversion later
- if(!$this->customVariablesSetFromRequest)
- {
- $selectCustomVariables = ',
+ * This methods tries to see if the visitor has visited the website before.
+ *
+ * We have to split the visitor into one of the category
+ * - Known visitor
+ * - New visitor
+ */
+ protected function recognizeTheVisitor()
+ {
+ $this->visitorKnown = false;
+ $this->setCookie(new Piwik_Cookie(
+ $this->getCookieName(),
+ $this->getCookieExpire(),
+ $this->getCookiePath()));
+ $this->printCookie();
+
+ $userInfo = $this->getUserSettingsInformation();
+ $configId = $userInfo['config_id'];
+
+ $this->assignVisitorIdFromRequest();
+ $isVisitorIdToLookup = !empty($this->visitorInfo['idvisitor']);
+
+ if ($isVisitorIdToLookup) {
+ printDebug("Matching visitors with: visitorId=" . bin2hex($this->visitorInfo['idvisitor']) . " OR configId=" . bin2hex($configId));
+ } else {
+ printDebug("Visitor doesn't have the piwik cookie...");
+ }
+
+ $selectCustomVariables = '';
+ // No custom var were found in the request, so let's copy the previous one in a potential conversion later
+ if (!$this->customVariablesSetFromRequest) {
+ $selectCustomVariables = ',
custom_var_k1, custom_var_v1,
custom_var_k2, custom_var_v2,
custom_var_k3, custom_var_v3,
custom_var_k4, custom_var_v4,
custom_var_k5, custom_var_v5';
- }
-
- $select = "SELECT idvisitor,
+ }
+
+ $select = "SELECT idvisitor,
visit_last_action_time,
visit_first_action_time,
idvisit,
@@ -1179,9 +1105,9 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
visit_goal_buyer
$selectCustomVariables
";
- $from = "FROM ".Piwik_Common::prefixTable('log_visit');
+ $from = "FROM " . Piwik_Common::prefixTable('log_visit');
- $bindSql = array();
+ $bindSql = array();
$timeLookBack = $this->getWindowLookupPreviousVisit();
@@ -1189,142 +1115,132 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$shouldMatchOneFieldOnly = $this->shouldLookupOneVisitorFieldOnly($isVisitorIdToLookup);
// Two use cases:
- // 1) there is no visitor ID so we try to match only on config_id (heuristics)
- // Possible causes of no visitor ID: no browser cookie support, direct Tracking API request without visitor ID passed, etc.
- // We can use config_id heuristics to try find the visitor in the past, there is a risk to assign
- // this page view to the wrong visitor, but this is better than creating artificial visits.
- // 2) there is a visitor ID and we trust it (config setting trust_visitors_cookies, OR it was set using &cid= in tracking API),
+ // 1) there is no visitor ID so we try to match only on config_id (heuristics)
+ // Possible causes of no visitor ID: no browser cookie support, direct Tracking API request without visitor ID passed, etc.
+ // We can use config_id heuristics to try find the visitor in the past, there is a risk to assign
+ // this page view to the wrong visitor, but this is better than creating artificial visits.
+ // 2) there is a visitor ID and we trust it (config setting trust_visitors_cookies, OR it was set using &cid= in tracking API),
// and in these cases, we force to look up this visitor id
- if($shouldMatchOneFieldOnly)
- {
- $where = "visit_last_action_time >= ? AND idsite = ?";
- $bindSql[] = $timeLookBack;
- $bindSql[] = $this->idsite;
- if(!$isVisitorIdToLookup)
- {
- $where .= ' AND config_id = ?';
- $bindSql[] = $configId;
- }
- else
- {
- $where .= ' AND idvisitor = ?';
- $bindSql[] = $this->visitorInfo['idvisitor'];
- }
-
- $sql = "$select
+ if ($shouldMatchOneFieldOnly) {
+ $where = "visit_last_action_time >= ? AND idsite = ?";
+ $bindSql[] = $timeLookBack;
+ $bindSql[] = $this->idsite;
+ if (!$isVisitorIdToLookup) {
+ $where .= ' AND config_id = ?';
+ $bindSql[] = $configId;
+ } else {
+ $where .= ' AND idvisitor = ?';
+ $bindSql[] = $this->visitorInfo['idvisitor'];
+ }
+
+ $sql = "$select
$from
- WHERE ".$where."
+ WHERE " . $where . "
ORDER BY visit_last_action_time DESC
LIMIT 1";
- }
- // We have a config_id AND a visitor_id. We match on either of these.
- // Why do we also match on config_id?
- // we do not trust the visitor ID only. Indeed, some browsers, or browser addons,
- // cause the visitor id from the 1st party cookie to be different on each page view!
- // It is not acceptable to create a new visit every time such browser does a page view,
- // so we also backup by searching for matching config_id.
- // We use a UNION here so that each sql query uses its own INDEX
- else
- {
- $whereSameBothQueries = "visit_last_action_time >= ? AND idsite = ?";
-
-
- // will use INDEX index_idsite_config_datetime (idsite, config_id, visit_last_action_time)
- $bindSql[] = $timeLookBack;
- $bindSql[] = $this->idsite;
- $where = ' AND config_id = ?';
- $bindSql[] = $configId;
- $sqlConfigId = "$select ,
+ } // We have a config_id AND a visitor_id. We match on either of these.
+ // Why do we also match on config_id?
+ // we do not trust the visitor ID only. Indeed, some browsers, or browser addons,
+ // cause the visitor id from the 1st party cookie to be different on each page view!
+ // It is not acceptable to create a new visit every time such browser does a page view,
+ // so we also backup by searching for matching config_id.
+ // We use a UNION here so that each sql query uses its own INDEX
+ else {
+ $whereSameBothQueries = "visit_last_action_time >= ? AND idsite = ?";
+
+
+ // will use INDEX index_idsite_config_datetime (idsite, config_id, visit_last_action_time)
+ $bindSql[] = $timeLookBack;
+ $bindSql[] = $this->idsite;
+ $where = ' AND config_id = ?';
+ $bindSql[] = $configId;
+ $sqlConfigId = "$select ,
0 as priority
$from
WHERE $whereSameBothQueries $where
ORDER BY visit_last_action_time DESC
LIMIT 1
";
-
- // will use INDEX index_idsite_idvisitor (idsite, idvisitor)
- $bindSql[] = $timeLookBack;
- $bindSql[] = $this->idsite;
- $where = ' AND idvisitor = ?';
- $bindSql[] = $this->visitorInfo['idvisitor'];
- $sqlVisitorId = "$select ,
+
+ // will use INDEX index_idsite_idvisitor (idsite, idvisitor)
+ $bindSql[] = $timeLookBack;
+ $bindSql[] = $this->idsite;
+ $where = ' AND idvisitor = ?';
+ $bindSql[] = $this->visitorInfo['idvisitor'];
+ $sqlVisitorId = "$select ,
1 as priority
$from
WHERE $whereSameBothQueries $where
LIMIT 1
";
-
- // We join both queries and favor the one matching the visitor_id if it did match
- $sql = " ( $sqlConfigId )
+
+ // We join both queries and favor the one matching the visitor_id if it did match
+ $sql = " ( $sqlConfigId )
UNION
( $sqlVisitorId )
ORDER BY priority DESC
LIMIT 1";
- }
-
-
- $visitRow = Piwik_Tracker::getDatabase()->fetch($sql, $bindSql);
-
- if( !Piwik_Config::getInstance()->Debug['tracker_always_new_visitor']
- && $visitRow
- && count($visitRow) > 0)
- {
- // These values will be used throughout the request
- $this->visitorInfo['visit_last_action_time'] = strtotime($visitRow['visit_last_action_time']);
- $this->visitorInfo['visit_first_action_time'] = strtotime($visitRow['visit_first_action_time']);
-
- // We always keep the first idvisitor seen for this visit (so that all page views for this visit have the same idvisitor)
- $this->visitorInfo['idvisitor'] = $visitRow['idvisitor'];
- $this->visitorInfo['idvisit'] = $visitRow['idvisit'];
- $this->visitorInfo['visit_exit_idaction_url'] = $visitRow['visit_exit_idaction_url'];
- $this->visitorInfo['visit_exit_idaction_name'] = $visitRow['visit_exit_idaction_name'];
- $this->visitorInfo['visitor_returning'] = $visitRow['visitor_returning'];
- $this->visitorInfo['visitor_days_since_first'] = $visitRow['visitor_days_since_first'];
- $this->visitorInfo['visitor_days_since_order'] = $visitRow['visitor_days_since_order'];
- $this->visitorInfo['visitor_count_visits'] = $visitRow['visitor_count_visits'];
- $this->visitorInfo['visit_goal_buyer'] = $visitRow['visit_goal_buyer'];
- $this->visitorInfo['location_country'] = $visitRow['location_country'];
- $this->visitorInfo['location_region'] = $visitRow['location_region'];
- $this->visitorInfo['location_city'] = $visitRow['location_city'];
- $this->visitorInfo['location_latitude'] = $visitRow['location_latitude'];
- $this->visitorInfo['location_longitude'] = $visitRow['location_longitude'];
-
- // Referer information will be potentially used for Goal Conversion attribution
- $this->visitorInfo['referer_name'] = $visitRow['referer_name'];
- $this->visitorInfo['referer_keyword'] = $visitRow['referer_keyword'];
- $this->visitorInfo['referer_type'] = $visitRow['referer_type'];
-
- // Custom Variables copied from Visit in potential later conversion
- if(!empty($selectCustomVariables))
- {
- for($i=1; $i<=Piwik_Tracker::MAX_CUSTOM_VARIABLES; $i++)
- {
- if(isset($visitRow['custom_var_k'.$i])
- && strlen($visitRow['custom_var_k'.$i]))
- {
- $this->visitorInfo['custom_var_k'.$i] = $visitRow['custom_var_k'.$i];
- }
- if(isset($visitRow['custom_var_v'.$i])
- && strlen($visitRow['custom_var_v'.$i]))
- {
- $this->visitorInfo['custom_var_v'.$i] = $visitRow['custom_var_v'.$i];
- }
- }
- }
-
- $this->visitorKnown = true;
- printDebug("The visitor is known (idvisitor = ".bin2hex($this->visitorInfo['idvisitor']).",
- config_id = ".bin2hex($configId).",
+ }
+
+
+ $visitRow = Piwik_Tracker::getDatabase()->fetch($sql, $bindSql);
+
+ if (!Piwik_Config::getInstance()->Debug['tracker_always_new_visitor']
+ && $visitRow
+ && count($visitRow) > 0
+ ) {
+ // These values will be used throughout the request
+ $this->visitorInfo['visit_last_action_time'] = strtotime($visitRow['visit_last_action_time']);
+ $this->visitorInfo['visit_first_action_time'] = strtotime($visitRow['visit_first_action_time']);
+
+ // We always keep the first idvisitor seen for this visit (so that all page views for this visit have the same idvisitor)
+ $this->visitorInfo['idvisitor'] = $visitRow['idvisitor'];
+ $this->visitorInfo['idvisit'] = $visitRow['idvisit'];
+ $this->visitorInfo['visit_exit_idaction_url'] = $visitRow['visit_exit_idaction_url'];
+ $this->visitorInfo['visit_exit_idaction_name'] = $visitRow['visit_exit_idaction_name'];
+ $this->visitorInfo['visitor_returning'] = $visitRow['visitor_returning'];
+ $this->visitorInfo['visitor_days_since_first'] = $visitRow['visitor_days_since_first'];
+ $this->visitorInfo['visitor_days_since_order'] = $visitRow['visitor_days_since_order'];
+ $this->visitorInfo['visitor_count_visits'] = $visitRow['visitor_count_visits'];
+ $this->visitorInfo['visit_goal_buyer'] = $visitRow['visit_goal_buyer'];
+ $this->visitorInfo['location_country'] = $visitRow['location_country'];
+ $this->visitorInfo['location_region'] = $visitRow['location_region'];
+ $this->visitorInfo['location_city'] = $visitRow['location_city'];
+ $this->visitorInfo['location_latitude'] = $visitRow['location_latitude'];
+ $this->visitorInfo['location_longitude'] = $visitRow['location_longitude'];
+
+ // Referer information will be potentially used for Goal Conversion attribution
+ $this->visitorInfo['referer_name'] = $visitRow['referer_name'];
+ $this->visitorInfo['referer_keyword'] = $visitRow['referer_keyword'];
+ $this->visitorInfo['referer_type'] = $visitRow['referer_type'];
+
+ // Custom Variables copied from Visit in potential later conversion
+ if (!empty($selectCustomVariables)) {
+ for ($i = 1; $i <= Piwik_Tracker::MAX_CUSTOM_VARIABLES; $i++) {
+ if (isset($visitRow['custom_var_k' . $i])
+ && strlen($visitRow['custom_var_k' . $i])
+ ) {
+ $this->visitorInfo['custom_var_k' . $i] = $visitRow['custom_var_k' . $i];
+ }
+ if (isset($visitRow['custom_var_v' . $i])
+ && strlen($visitRow['custom_var_v' . $i])
+ ) {
+ $this->visitorInfo['custom_var_v' . $i] = $visitRow['custom_var_v' . $i];
+ }
+ }
+ }
+
+ $this->visitorKnown = true;
+ printDebug("The visitor is known (idvisitor = " . bin2hex($this->visitorInfo['idvisitor']) . ",
+ config_id = " . bin2hex($configId) . ",
idvisit = {$this->visitorInfo['idvisit']},
- last action = ".date("r", $this->visitorInfo['visit_last_action_time']).",
- first action = ".date("r", $this->visitorInfo['visit_first_action_time']) .",
- visit_goal_buyer' = ".$this->visitorInfo['visit_goal_buyer'].")");
- }
- else
- {
- printDebug("The visitor was not matched with an existing visitor...");
- }
- }
+ last action = " . date("r", $this->visitorInfo['visit_last_action_time']) . ",
+ first action = " . date("r", $this->visitorInfo['visit_first_action_time']) . ",
+ visit_goal_buyer' = " . $this->visitorInfo['visit_goal_buyer'] . ")");
+ } else {
+ printDebug("The visitor was not matched with an existing visitor...");
+ }
+ }
/**
* By default, we look back 30 minutes to find a previous visitor (for performance reasons).
@@ -1356,280 +1272,266 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$isForcedVisitorIdMustMatch = ($this->getForcedVisitorId() != null);
$shouldMatchOneFieldOnly = (($isVisitorIdToLookup && $trustCookiesOnly)
- || $isForcedVisitorIdMustMatch
- || !$isVisitorIdToLookup);
+ || $isForcedVisitorIdMustMatch
+ || !$isVisitorIdToLookup);
return $shouldMatchOneFieldOnly;
}
static public function getCustomVariables($scope, $request)
- {
- if($scope == 'visit') {
- $parameter = '_cvar';
- } else {
- $parameter = 'cvar';
- }
-
- $customVar = Piwik_Common::unsanitizeInputValues(Piwik_Common::getRequestVar($parameter, '', 'json', $request));
- if(!is_array($customVar))
- {
- return array();
- }
- $customVariables = array();
- foreach($customVar as $id => $keyValue)
- {
- $id = (int)$id;
- if($id < 1
- || $id > Piwik_Tracker::MAX_CUSTOM_VARIABLES
- || count($keyValue) != 2
- || (!is_string($keyValue[0]) && !is_numeric($keyValue[0]))
- )
- {
- printDebug("Invalid custom variables detected (id=$id)");
- continue;
- }
- if(strlen($keyValue[1]) == 0)
- {
- $keyValue[1] = "";
- }
- // We keep in the URL when Custom Variable have empty names
- // and values, as it means they can be deleted server side
-
- $key = self::truncateCustomVariable($keyValue[0]);
- $value = self::truncateCustomVariable($keyValue[1]);
- $customVariables['custom_var_k'.$id] = $key;
- $customVariables['custom_var_v'.$id] = $value;
- }
-
- return $customVariables;
- }
-
- static public function truncateCustomVariable($input)
- {
- return substr(trim($input), 0, Piwik_Tracker::MAX_LENGTH_CUSTOM_VARIABLE);
- }
-
- /**
- * Gets the UserSettings information and returns them in an array of name => value
- *
- * @return array
- */
- protected function getUserSettingsInformation()
- {
- // we already called this method before, simply returns the result
- if(is_array($this->userSettingsInformation))
- {
- return $this->userSettingsInformation;
- }
- require_once PIWIK_INCLUDE_PATH . '/libs/UserAgentParser/UserAgentParser.php';
-
- $plugin_Flash = Piwik_Common::getRequestVar( 'fla', 0, 'int', $this->request);
- $plugin_Java = Piwik_Common::getRequestVar( 'java', 0, 'int', $this->request);
- $plugin_Director = Piwik_Common::getRequestVar( 'dir', 0, 'int', $this->request);
- $plugin_Quicktime = Piwik_Common::getRequestVar( 'qt', 0, 'int', $this->request);
- $plugin_RealPlayer = Piwik_Common::getRequestVar( 'realp', 0, 'int', $this->request);
- $plugin_PDF = Piwik_Common::getRequestVar( 'pdf', 0, 'int', $this->request);
- $plugin_WindowsMedia = Piwik_Common::getRequestVar( 'wma', 0, 'int', $this->request);
- $plugin_Gears = Piwik_Common::getRequestVar( 'gears', 0, 'int', $this->request);
- $plugin_Silverlight = Piwik_Common::getRequestVar( 'ag', 0, 'int', $this->request);
- $plugin_Cookie = Piwik_Common::getRequestVar( 'cookie', 0, 'int', $this->request);
-
- $userAgent = $this->getUserAgent($this->request);
- $aBrowserInfo = UserAgentParser::getBrowser($userAgent);
-
- $browserName = ($aBrowserInfo !== false && $aBrowserInfo['id'] !== false) ? $aBrowserInfo['id'] : 'UNK';
- $browserVersion = ($aBrowserInfo !== false && $aBrowserInfo['version'] !== false) ? $aBrowserInfo['version'] : '';
-
- $os = UserAgentParser::getOperatingSystem($userAgent);
- $os = $os === false ? 'UNK' : $os['id'];
-
- $resolution = Piwik_Common::getRequestVar('res', 'unknown', 'string', $this->request);
-
- $browserLang = $this->getBrowserLanguage();
-
- $configurationHash = $this->getConfigHash(
- $os,
- $browserName,
- $browserVersion,
- $resolution,
- $plugin_Flash,
- $plugin_Java,
- $plugin_Director,
- $plugin_Quicktime,
- $plugin_RealPlayer,
- $plugin_PDF,
- $plugin_WindowsMedia,
- $plugin_Gears,
- $plugin_Silverlight,
- $plugin_Cookie,
- $this->getVisitorIp(),
- $browserLang);
-
- $this->userSettingsInformation = array(
- 'config_id' => $configurationHash,
- 'config_os' => $os,
- 'config_browser_name' => $browserName,
- 'config_browser_version' => $browserVersion,
- 'config_resolution' => $resolution,
- 'config_pdf' => $plugin_PDF,
- 'config_flash' => $plugin_Flash,
- 'config_java' => $plugin_Java,
- 'config_director' => $plugin_Director,
- 'config_quicktime' => $plugin_Quicktime,
- 'config_realplayer' => $plugin_RealPlayer,
- 'config_windowsmedia' => $plugin_WindowsMedia,
- 'config_gears' => $plugin_Gears,
- 'config_silverlight' => $plugin_Silverlight,
- 'config_cookie' => $plugin_Cookie,
- 'location_browser_lang' => $browserLang,
- );
-
- return $this->userSettingsInformation;
- }
-
- /**
- * Returns true if the last action was done during the last 30 minutes
- * @return bool
- */
- protected function isLastActionInTheSameVisit()
- {
- return isset($this->visitorInfo['visit_last_action_time'])
- && ($this->visitorInfo['visit_last_action_time']
- > ($this->getCurrentTimestamp() - Piwik_Config::getInstance()->Tracker['visit_standard_length']));
- }
-
- /**
- * Returns true if the recognizeTheVisitor() method did recognize the visitor
- * @return bool
- */
- protected function isVisitorKnown()
- {
- return $this->visitorKnown === true;
- }
-
- /**
- * Update the cookie information.
- */
- protected function setThirdPartyCookie()
- {
- if(!$this->shouldUseThirdPartyCookie())
- {
- return;
- }
- printDebug("We manage the cookie...");
-
- // idcookie has been generated in handleNewVisit or we simply propagate the old value
- $this->cookie->set(0, bin2hex($this->visitorInfo['idvisitor']) );
- $this->cookie->save();
- }
-
- /**
- * Returns an object able to handle the current action
- * Plugins can return an override Action that for example, does not record the action in the DB
- *
- * @throws Exception
- * @return Piwik_Tracker_Action child or fake but with same public interface
- */
- protected function newAction()
- {
- $action = null;
- Piwik_PostEvent('Tracker.newAction', $action);
-
- if(is_null($action))
- {
- $action = new Piwik_Tracker_Action();
- }
- elseif(!($action instanceof Piwik_Tracker_Action_Interface))
- {
- throw new Exception("The Action object set in the plugin must implement the interface Piwik_Tracker_Action_Interface");
- }
- return $action;
- }
-
- /**
- * Detect whether action is an outlink given host aliases
- *
- * @param Piwik_Tracker_Action_Interface $action
- * @return bool true if the outlink the visitor clicked on points to one of the known hosts for this website
- */
- protected function detectActionIsOutlinkOnAliasHost(Piwik_Tracker_Action_Interface $action)
- {
- if($action->getActionType() != Piwik_Tracker_Action_Interface::TYPE_OUTLINK)
- {
- return false;
- }
- $decodedActionUrl = $action->getActionUrl();
- $actionUrlParsed = @parse_url($decodedActionUrl);
- if(!isset($actionUrlParsed['host']))
- {
- return false;
- }
- return Piwik_Tracker_Visit::isHostKnownAliasHost($actionUrlParsed['host'], $this->idsite);
- }
-
- /**
- * Returns a 64-bit hash of all the configuration settings
- * @param $os
- * @param $browserName
- * @param $browserVersion
- * @param $resolution
- * @param $plugin_Flash
- * @param $plugin_Java
- * @param $plugin_Director
- * @param $plugin_Quicktime
- * @param $plugin_RealPlayer
- * @param $plugin_PDF
- * @param $plugin_WindowsMedia
- * @param $plugin_Gears
- * @param $plugin_Silverlight
- * @param $plugin_Cookie
- * @param $ip
- * @param $browserLang
- * @return string
- */
- protected function getConfigHash( $os, $browserName, $browserVersion, $resolution, $plugin_Flash, $plugin_Java, $plugin_Director, $plugin_Quicktime, $plugin_RealPlayer, $plugin_PDF, $plugin_WindowsMedia, $plugin_Gears, $plugin_Silverlight, $plugin_Cookie, $ip, $browserLang)
- {
- $hash = md5( $os . $browserName . $browserVersion . $plugin_Flash . $plugin_Java . $plugin_Director . $plugin_Quicktime . $plugin_RealPlayer . $plugin_PDF . $plugin_WindowsMedia . $plugin_Gears . $plugin_Silverlight . $plugin_Cookie . $ip . $browserLang, $raw_output = true );
- return Piwik_Common::substr( $hash, 0, Piwik_Tracker::LENGTH_BINARY_ID );
- }
-
- /**
- * Returns either
- * - "-1" for a known visitor
- * - at least 16 char identifier in hex @see Piwik_Common::generateUniqId()
- * @return int|string
- */
- protected function getVisitorUniqueId()
- {
- if($this->isVisitorKnown())
- {
- return -1;
- }
- return Piwik_Common::generateUniqId();
- }
-
- protected function setCookie( $cookie )
- {
- $this->cookie = $cookie;
- }
-
- // is the referer host any of the registered URLs for this website?
- static public function isHostKnownAliasHost($urlHost, $idSite)
- {
- $websiteData = Piwik_Tracker_Cache::getCacheWebsiteAttributes($idSite);
- if(isset($websiteData['hosts']))
- {
- $canonicalHosts = array();
- foreach($websiteData['hosts'] as $host) {
- $canonicalHosts[] = str_replace('www.', '' , mb_strtolower($host, 'UTF-8'));
- }
- $canonicalHost = str_replace('www.', '', mb_strtolower($urlHost, 'UTF-8'));
- if(in_array($canonicalHost, $canonicalHosts))
- {
- return true;
- }
- }
- return false;
- }
+ {
+ if ($scope == 'visit') {
+ $parameter = '_cvar';
+ } else {
+ $parameter = 'cvar';
+ }
+
+ $customVar = Piwik_Common::unsanitizeInputValues(Piwik_Common::getRequestVar($parameter, '', 'json', $request));
+ if (!is_array($customVar)) {
+ return array();
+ }
+ $customVariables = array();
+ foreach ($customVar as $id => $keyValue) {
+ $id = (int)$id;
+ if ($id < 1
+ || $id > Piwik_Tracker::MAX_CUSTOM_VARIABLES
+ || count($keyValue) != 2
+ || (!is_string($keyValue[0]) && !is_numeric($keyValue[0]))
+ ) {
+ printDebug("Invalid custom variables detected (id=$id)");
+ continue;
+ }
+ if (strlen($keyValue[1]) == 0) {
+ $keyValue[1] = "";
+ }
+ // We keep in the URL when Custom Variable have empty names
+ // and values, as it means they can be deleted server side
+
+ $key = self::truncateCustomVariable($keyValue[0]);
+ $value = self::truncateCustomVariable($keyValue[1]);
+ $customVariables['custom_var_k' . $id] = $key;
+ $customVariables['custom_var_v' . $id] = $value;
+ }
+
+ return $customVariables;
+ }
+
+ static public function truncateCustomVariable($input)
+ {
+ return substr(trim($input), 0, Piwik_Tracker::MAX_LENGTH_CUSTOM_VARIABLE);
+ }
+
+ /**
+ * Gets the UserSettings information and returns them in an array of name => value
+ *
+ * @return array
+ */
+ protected function getUserSettingsInformation()
+ {
+ // we already called this method before, simply returns the result
+ if (is_array($this->userSettingsInformation)) {
+ return $this->userSettingsInformation;
+ }
+ require_once PIWIK_INCLUDE_PATH . '/libs/UserAgentParser/UserAgentParser.php';
+
+ $plugin_Flash = Piwik_Common::getRequestVar('fla', 0, 'int', $this->request);
+ $plugin_Java = Piwik_Common::getRequestVar('java', 0, 'int', $this->request);
+ $plugin_Director = Piwik_Common::getRequestVar('dir', 0, 'int', $this->request);
+ $plugin_Quicktime = Piwik_Common::getRequestVar('qt', 0, 'int', $this->request);
+ $plugin_RealPlayer = Piwik_Common::getRequestVar('realp', 0, 'int', $this->request);
+ $plugin_PDF = Piwik_Common::getRequestVar('pdf', 0, 'int', $this->request);
+ $plugin_WindowsMedia = Piwik_Common::getRequestVar('wma', 0, 'int', $this->request);
+ $plugin_Gears = Piwik_Common::getRequestVar('gears', 0, 'int', $this->request);
+ $plugin_Silverlight = Piwik_Common::getRequestVar('ag', 0, 'int', $this->request);
+ $plugin_Cookie = Piwik_Common::getRequestVar('cookie', 0, 'int', $this->request);
+
+ $userAgent = $this->getUserAgent($this->request);
+ $aBrowserInfo = UserAgentParser::getBrowser($userAgent);
+
+ $browserName = ($aBrowserInfo !== false && $aBrowserInfo['id'] !== false) ? $aBrowserInfo['id'] : 'UNK';
+ $browserVersion = ($aBrowserInfo !== false && $aBrowserInfo['version'] !== false) ? $aBrowserInfo['version'] : '';
+
+ $os = UserAgentParser::getOperatingSystem($userAgent);
+ $os = $os === false ? 'UNK' : $os['id'];
+
+ $resolution = Piwik_Common::getRequestVar('res', 'unknown', 'string', $this->request);
+
+ $browserLang = $this->getBrowserLanguage();
+
+ $configurationHash = $this->getConfigHash(
+ $os,
+ $browserName,
+ $browserVersion,
+ $resolution,
+ $plugin_Flash,
+ $plugin_Java,
+ $plugin_Director,
+ $plugin_Quicktime,
+ $plugin_RealPlayer,
+ $plugin_PDF,
+ $plugin_WindowsMedia,
+ $plugin_Gears,
+ $plugin_Silverlight,
+ $plugin_Cookie,
+ $this->getVisitorIp(),
+ $browserLang);
+
+ $this->userSettingsInformation = array(
+ 'config_id' => $configurationHash,
+ 'config_os' => $os,
+ 'config_browser_name' => $browserName,
+ 'config_browser_version' => $browserVersion,
+ 'config_resolution' => $resolution,
+ 'config_pdf' => $plugin_PDF,
+ 'config_flash' => $plugin_Flash,
+ 'config_java' => $plugin_Java,
+ 'config_director' => $plugin_Director,
+ 'config_quicktime' => $plugin_Quicktime,
+ 'config_realplayer' => $plugin_RealPlayer,
+ 'config_windowsmedia' => $plugin_WindowsMedia,
+ 'config_gears' => $plugin_Gears,
+ 'config_silverlight' => $plugin_Silverlight,
+ 'config_cookie' => $plugin_Cookie,
+ 'location_browser_lang' => $browserLang,
+ );
+
+ return $this->userSettingsInformation;
+ }
+
+ /**
+ * Returns true if the last action was done during the last 30 minutes
+ * @return bool
+ */
+ protected function isLastActionInTheSameVisit()
+ {
+ return isset($this->visitorInfo['visit_last_action_time'])
+ && ($this->visitorInfo['visit_last_action_time']
+ > ($this->getCurrentTimestamp() - Piwik_Config::getInstance()->Tracker['visit_standard_length']));
+ }
+
+ /**
+ * Returns true if the recognizeTheVisitor() method did recognize the visitor
+ * @return bool
+ */
+ protected function isVisitorKnown()
+ {
+ return $this->visitorKnown === true;
+ }
+
+ /**
+ * Update the cookie information.
+ */
+ protected function setThirdPartyCookie()
+ {
+ if (!$this->shouldUseThirdPartyCookie()) {
+ return;
+ }
+ printDebug("We manage the cookie...");
+
+ // idcookie has been generated in handleNewVisit or we simply propagate the old value
+ $this->cookie->set(0, bin2hex($this->visitorInfo['idvisitor']));
+ $this->cookie->save();
+ }
+
+ /**
+ * Returns an object able to handle the current action
+ * Plugins can return an override Action that for example, does not record the action in the DB
+ *
+ * @throws Exception
+ * @return Piwik_Tracker_Action child or fake but with same public interface
+ */
+ protected function newAction()
+ {
+ $action = null;
+ Piwik_PostEvent('Tracker.newAction', $action);
+
+ if (is_null($action)) {
+ $action = new Piwik_Tracker_Action();
+ } elseif (!($action instanceof Piwik_Tracker_Action_Interface)) {
+ throw new Exception("The Action object set in the plugin must implement the interface Piwik_Tracker_Action_Interface");
+ }
+ return $action;
+ }
+
+ /**
+ * Detect whether action is an outlink given host aliases
+ *
+ * @param Piwik_Tracker_Action_Interface $action
+ * @return bool true if the outlink the visitor clicked on points to one of the known hosts for this website
+ */
+ protected function detectActionIsOutlinkOnAliasHost(Piwik_Tracker_Action_Interface $action)
+ {
+ if ($action->getActionType() != Piwik_Tracker_Action_Interface::TYPE_OUTLINK) {
+ return false;
+ }
+ $decodedActionUrl = $action->getActionUrl();
+ $actionUrlParsed = @parse_url($decodedActionUrl);
+ if (!isset($actionUrlParsed['host'])) {
+ return false;
+ }
+ return Piwik_Tracker_Visit::isHostKnownAliasHost($actionUrlParsed['host'], $this->idsite);
+ }
+
+ /**
+ * Returns a 64-bit hash of all the configuration settings
+ * @param $os
+ * @param $browserName
+ * @param $browserVersion
+ * @param $resolution
+ * @param $plugin_Flash
+ * @param $plugin_Java
+ * @param $plugin_Director
+ * @param $plugin_Quicktime
+ * @param $plugin_RealPlayer
+ * @param $plugin_PDF
+ * @param $plugin_WindowsMedia
+ * @param $plugin_Gears
+ * @param $plugin_Silverlight
+ * @param $plugin_Cookie
+ * @param $ip
+ * @param $browserLang
+ * @return string
+ */
+ protected function getConfigHash($os, $browserName, $browserVersion, $resolution, $plugin_Flash, $plugin_Java, $plugin_Director, $plugin_Quicktime, $plugin_RealPlayer, $plugin_PDF, $plugin_WindowsMedia, $plugin_Gears, $plugin_Silverlight, $plugin_Cookie, $ip, $browserLang)
+ {
+ $hash = md5($os . $browserName . $browserVersion . $plugin_Flash . $plugin_Java . $plugin_Director . $plugin_Quicktime . $plugin_RealPlayer . $plugin_PDF . $plugin_WindowsMedia . $plugin_Gears . $plugin_Silverlight . $plugin_Cookie . $ip . $browserLang, $raw_output = true);
+ return Piwik_Common::substr($hash, 0, Piwik_Tracker::LENGTH_BINARY_ID);
+ }
+
+ /**
+ * Returns either
+ * - "-1" for a known visitor
+ * - at least 16 char identifier in hex @see Piwik_Common::generateUniqId()
+ * @return int|string
+ */
+ protected function getVisitorUniqueId()
+ {
+ if ($this->isVisitorKnown()) {
+ return -1;
+ }
+ return Piwik_Common::generateUniqId();
+ }
+
+ protected function setCookie($cookie)
+ {
+ $this->cookie = $cookie;
+ }
+
+ // is the referer host any of the registered URLs for this website?
+ static public function isHostKnownAliasHost($urlHost, $idSite)
+ {
+ $websiteData = Piwik_Tracker_Cache::getCacheWebsiteAttributes($idSite);
+ if (isset($websiteData['hosts'])) {
+ $canonicalHosts = array();
+ foreach ($websiteData['hosts'] as $host) {
+ $canonicalHosts[] = str_replace('www.', '', mb_strtolower($host, 'UTF-8'));
+ }
+ $canonicalHost = str_replace('www.', '', mb_strtolower($urlHost, 'UTF-8'));
+ if (in_array($canonicalHost, $canonicalHosts)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
@@ -1638,273 +1540,256 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
*/
class Piwik_Tracker_Visit_Referer
{
- // @see detect*() referer methods
- protected $typeRefererAnalyzed;
- protected $nameRefererAnalyzed;
- protected $keywordRefererAnalyzed;
- protected $refererHost;
- protected $refererUrl;
- protected $refererUrlParse;
- protected $currentUrlParse;
- protected $idsite;
-
- // Used to prefix when a adsense referer is detected
- const LABEL_PREFIX_ADSENSE_KEYWORD = '(adsense) ';
-
-
- /**
- * Returns an array containing the following information:
- * - referer_type
- * - direct -- absence of referer URL OR referer URL has the same host
- * - site -- based on the referer URL
- * - search_engine -- based on the referer URL
- * - campaign -- based on campaign URL parameter
- *
- * - referer_name
- * - ()
- * - piwik.net -- site host name
- * - google.fr -- search engine host name
- * - adwords-search -- campaign name
- *
- * - referer_keyword
- * - ()
- * - ()
- * - my keyword
- * - my paid keyword
- * - ()
- * - ()
- *
- * - referer_url : the same for all the referer types
- *
- * @param $refererUrl must be URL Encoded
- * @param $currentUrl
- * @param $idSite
- * @return array
- */
- public function getRefererInformation($refererUrl, $currentUrl, $idSite)
- {
- $this->idsite = $idSite;
-
- // default values for the referer_* fields
- $refererUrl = Piwik_Common::unsanitizeInputValue($refererUrl);
- if(!empty($refererUrl)
- && !Piwik_Common::isLookLikeUrl($refererUrl))
- {
- $refererUrl = '';
- }
-
- $currentUrl = Piwik_Tracker_Action::cleanupUrl($currentUrl);
-
- $this->refererUrl = $refererUrl;
- $this->refererUrlParse = @parse_url($this->refererUrl);
- $this->currentUrlParse = @parse_url($currentUrl);
- $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_DIRECT_ENTRY;
- $this->nameRefererAnalyzed = '';
- $this->keywordRefererAnalyzed = '';
- $this->refererHost = '';
-
- if(isset($this->refererUrlParse['host']))
- {
- $this->refererHost = $this->refererUrlParse['host'];
- }
-
- $refererDetected = false;
-
- if( !empty($this->currentUrlParse['host'])
- && $this->detectRefererCampaign() )
- {
- $refererDetected = true;
- }
-
- if(!$refererDetected)
- {
- if( $this->detectRefererDirectEntry()
- || $this->detectRefererSearchEngine() )
- {
- $refererDetected = true;
- }
- }
-
- if(!empty($this->refererHost)
- && !$refererDetected)
- {
- $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_WEBSITE;
- $this->nameRefererAnalyzed = mb_strtolower($this->refererHost, 'UTF-8');
- }
-
- $refererInformation = array(
- 'referer_type' => $this->typeRefererAnalyzed,
- 'referer_name' => $this->nameRefererAnalyzed,
- 'referer_keyword' => $this->keywordRefererAnalyzed,
- 'referer_url' => $this->refererUrl,
- );
-
- return $refererInformation;
- }
-
- /**
- * Search engine detection
+ // @see detect*() referer methods
+ protected $typeRefererAnalyzed;
+ protected $nameRefererAnalyzed;
+ protected $keywordRefererAnalyzed;
+ protected $refererHost;
+ protected $refererUrl;
+ protected $refererUrlParse;
+ protected $currentUrlParse;
+ protected $idsite;
+
+ // Used to prefix when a adsense referer is detected
+ const LABEL_PREFIX_ADSENSE_KEYWORD = '(adsense) ';
+
+
+ /**
+ * Returns an array containing the following information:
+ * - referer_type
+ * - direct -- absence of referer URL OR referer URL has the same host
+ * - site -- based on the referer URL
+ * - search_engine -- based on the referer URL
+ * - campaign -- based on campaign URL parameter
+ *
+ * - referer_name
+ * - ()
+ * - piwik.net -- site host name
+ * - google.fr -- search engine host name
+ * - adwords-search -- campaign name
+ *
+ * - referer_keyword
+ * - ()
+ * - ()
+ * - my keyword
+ * - my paid keyword
+ * - ()
+ * - ()
+ *
+ * - referer_url : the same for all the referer types
+ *
+ * @param $refererUrl must be URL Encoded
+ * @param $currentUrl
+ * @param $idSite
+ * @return array
+ */
+ public function getRefererInformation($refererUrl, $currentUrl, $idSite)
+ {
+ $this->idsite = $idSite;
+
+ // default values for the referer_* fields
+ $refererUrl = Piwik_Common::unsanitizeInputValue($refererUrl);
+ if (!empty($refererUrl)
+ && !Piwik_Common::isLookLikeUrl($refererUrl)
+ ) {
+ $refererUrl = '';
+ }
+
+ $currentUrl = Piwik_Tracker_Action::cleanupUrl($currentUrl);
+
+ $this->refererUrl = $refererUrl;
+ $this->refererUrlParse = @parse_url($this->refererUrl);
+ $this->currentUrlParse = @parse_url($currentUrl);
+ $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_DIRECT_ENTRY;
+ $this->nameRefererAnalyzed = '';
+ $this->keywordRefererAnalyzed = '';
+ $this->refererHost = '';
+
+ if (isset($this->refererUrlParse['host'])) {
+ $this->refererHost = $this->refererUrlParse['host'];
+ }
+
+ $refererDetected = false;
+
+ if (!empty($this->currentUrlParse['host'])
+ && $this->detectRefererCampaign()
+ ) {
+ $refererDetected = true;
+ }
+
+ if (!$refererDetected) {
+ if ($this->detectRefererDirectEntry()
+ || $this->detectRefererSearchEngine()
+ ) {
+ $refererDetected = true;
+ }
+ }
+
+ if (!empty($this->refererHost)
+ && !$refererDetected
+ ) {
+ $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_WEBSITE;
+ $this->nameRefererAnalyzed = mb_strtolower($this->refererHost, 'UTF-8');
+ }
+
+ $refererInformation = array(
+ 'referer_type' => $this->typeRefererAnalyzed,
+ 'referer_name' => $this->nameRefererAnalyzed,
+ 'referer_keyword' => $this->keywordRefererAnalyzed,
+ 'referer_url' => $this->refererUrl,
+ );
+
+ return $refererInformation;
+ }
+
+ /**
+ * Search engine detection
* @return bool
- */
- protected function detectRefererSearchEngine()
- {
- $searchEngineInformation = Piwik_Common::extractSearchEngineInformationFromUrl($this->refererUrl);
- Piwik_PostEvent('Tracker.detectRefererSearchEngine', $searchEngineInformation, $this->refererUrl);
- if($searchEngineInformation === false)
- {
- return false;
- }
- $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_SEARCH_ENGINE;
- $this->nameRefererAnalyzed = $searchEngineInformation['name'];
- $this->keywordRefererAnalyzed = $searchEngineInformation['keywords'];
- return true;
- }
+ */
+ protected function detectRefererSearchEngine()
+ {
+ $searchEngineInformation = Piwik_Common::extractSearchEngineInformationFromUrl($this->refererUrl);
+ Piwik_PostEvent('Tracker.detectRefererSearchEngine', $searchEngineInformation, $this->refererUrl);
+ if ($searchEngineInformation === false) {
+ return false;
+ }
+ $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_SEARCH_ENGINE;
+ $this->nameRefererAnalyzed = $searchEngineInformation['name'];
+ $this->keywordRefererAnalyzed = $searchEngineInformation['keywords'];
+ return true;
+ }
/**
* @param string $string
* @return bool
*/
protected function detectCampaignFromString($string)
- {
- foreach($this->campaignNames as $campaignNameParameter)
- {
- $campaignName = trim(urldecode(Piwik_Common::getParameterFromQueryString($string, $campaignNameParameter)));
- if( !empty($campaignName))
- {
- break;
- }
- }
-
- if(!empty($campaignName))
- {
- $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_CAMPAIGN;
- $this->nameRefererAnalyzed = $campaignName;
-
- foreach($this->campaignKeywords as $campaignKeywordParameter)
- {
- $campaignKeyword = Piwik_Common::getParameterFromQueryString($string, $campaignKeywordParameter);
- if( !empty($campaignKeyword))
- {
- $this->keywordRefererAnalyzed = trim(urldecode($campaignKeyword));
- break;
- }
- }
-
- // if the campaign keyword is empty, try to get a keyword from the referrer URL
- if (empty($this->keywordRefererAnalyzed))
- {
- // Set the Campaign keyword to the keyword found in the Referer URL if any
- $referrerUrlInfo = Piwik_Common::extractSearchEngineInformationFromUrl($this->refererUrl);
- if (!empty($referrerUrlInfo['keywords']))
- {
- $this->keywordRefererAnalyzed = $referrerUrlInfo['keywords'];
- }
-
- // Set the keyword, to the hostname found, in a Adsense Referer URL '&url=' parameter
- if(empty($this->keywordRefererAnalyzed)
- && !empty($this->refererUrlParse['query'])
- && !empty($this->refererHost)
- && (strpos($this->refererHost, 'google') !== false || strpos($this->refererHost,'doubleclick') !== false)
- )
- {
- // This parameter sometimes is found & contains the page with the adsense ad bringing visitor to our site
- $adsenseReferrerParameter = 'url';
- $value = trim(urldecode(Piwik_Common::getParameterFromQueryString($this->refererUrlParse['query'], $adsenseReferrerParameter)));
- if(!empty($value))
- {
- $parsedAdsenseReferrerUrl = parse_url($value);
- if(!empty($parsedAdsenseReferrerUrl['host']))
- {
- $this->keywordRefererAnalyzed = self::LABEL_PREFIX_ADSENSE_KEYWORD . $parsedAdsenseReferrerUrl['host'];
- }
- }
- }
-
- // or we default to the referrer hostname otherwise
- if(empty($this->keywordRefererAnalyzed))
- {
- $this->keywordRefererAnalyzed = $this->refererHost;
- }
- }
-
- return true;
- }
- return false;
- }
-
- /**
- * Campaign analysis
+ {
+ foreach ($this->campaignNames as $campaignNameParameter) {
+ $campaignName = trim(urldecode(Piwik_Common::getParameterFromQueryString($string, $campaignNameParameter)));
+ if (!empty($campaignName)) {
+ break;
+ }
+ }
+
+ if (!empty($campaignName)) {
+ $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_CAMPAIGN;
+ $this->nameRefererAnalyzed = $campaignName;
+
+ foreach ($this->campaignKeywords as $campaignKeywordParameter) {
+ $campaignKeyword = Piwik_Common::getParameterFromQueryString($string, $campaignKeywordParameter);
+ if (!empty($campaignKeyword)) {
+ $this->keywordRefererAnalyzed = trim(urldecode($campaignKeyword));
+ break;
+ }
+ }
+
+ // if the campaign keyword is empty, try to get a keyword from the referrer URL
+ if (empty($this->keywordRefererAnalyzed)) {
+ // Set the Campaign keyword to the keyword found in the Referer URL if any
+ $referrerUrlInfo = Piwik_Common::extractSearchEngineInformationFromUrl($this->refererUrl);
+ if (!empty($referrerUrlInfo['keywords'])) {
+ $this->keywordRefererAnalyzed = $referrerUrlInfo['keywords'];
+ }
+
+ // Set the keyword, to the hostname found, in a Adsense Referer URL '&url=' parameter
+ if (empty($this->keywordRefererAnalyzed)
+ && !empty($this->refererUrlParse['query'])
+ && !empty($this->refererHost)
+ && (strpos($this->refererHost, 'google') !== false || strpos($this->refererHost, 'doubleclick') !== false)
+ ) {
+ // This parameter sometimes is found & contains the page with the adsense ad bringing visitor to our site
+ $adsenseReferrerParameter = 'url';
+ $value = trim(urldecode(Piwik_Common::getParameterFromQueryString($this->refererUrlParse['query'], $adsenseReferrerParameter)));
+ if (!empty($value)) {
+ $parsedAdsenseReferrerUrl = parse_url($value);
+ if (!empty($parsedAdsenseReferrerUrl['host'])) {
+ $this->keywordRefererAnalyzed = self::LABEL_PREFIX_ADSENSE_KEYWORD . $parsedAdsenseReferrerUrl['host'];
+ }
+ }
+ }
+
+ // or we default to the referrer hostname otherwise
+ if (empty($this->keywordRefererAnalyzed)) {
+ $this->keywordRefererAnalyzed = $this->refererHost;
+ }
+ }
+
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Campaign analysis
* @return bool
- */
- protected function detectRefererCampaign()
- {
- if(!isset($this->currentUrlParse['query'])
- && !isset($this->currentUrlParse['fragment']))
- {
- return false;
- }
- $campaignParameters = Piwik_Common::getCampaignParameters();
- $this->campaignNames = $campaignParameters[0];
- $this->campaignKeywords = $campaignParameters[1];
-
- $found = false;
-
- // 1) Detect campaign from query string
- if(isset($this->currentUrlParse['query']))
- {
- $found = $this->detectCampaignFromString($this->currentUrlParse['query']);
- }
-
- // 2) Detect from fragment #hash
- if(!$found
- && isset($this->currentUrlParse['fragment']))
- {
- $found = $this->detectCampaignFromString($this->currentUrlParse['fragment']);
- }
- return $found;
- }
-
- /**
- * We have previously tried to detect the campaign variables in the URL
- * so at this stage, if the referer host is the current host,
- * or if the referer host is any of the registered URL for this website,
- * it is considered a direct entry
+ */
+ protected function detectRefererCampaign()
+ {
+ if (!isset($this->currentUrlParse['query'])
+ && !isset($this->currentUrlParse['fragment'])
+ ) {
+ return false;
+ }
+ $campaignParameters = Piwik_Common::getCampaignParameters();
+ $this->campaignNames = $campaignParameters[0];
+ $this->campaignKeywords = $campaignParameters[1];
+
+ $found = false;
+
+ // 1) Detect campaign from query string
+ if (isset($this->currentUrlParse['query'])) {
+ $found = $this->detectCampaignFromString($this->currentUrlParse['query']);
+ }
+
+ // 2) Detect from fragment #hash
+ if (!$found
+ && isset($this->currentUrlParse['fragment'])
+ ) {
+ $found = $this->detectCampaignFromString($this->currentUrlParse['fragment']);
+ }
+ return $found;
+ }
+
+ /**
+ * We have previously tried to detect the campaign variables in the URL
+ * so at this stage, if the referer host is the current host,
+ * or if the referer host is any of the registered URL for this website,
+ * it is considered a direct entry
* @return bool
- */
- protected function detectRefererDirectEntry()
- {
- if(!empty($this->refererHost))
- {
- // is the referer host the current host?
- if(isset($this->currentUrlParse['host']))
- {
- $currentHost = mb_strtolower($this->currentUrlParse['host'], 'UTF-8');
- if($currentHost == mb_strtolower($this->refererHost, 'UTF-8'))
- {
- $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_DIRECT_ENTRY;
- return true;
- }
- }
- if(Piwik_Tracker_Visit::isHostKnownAliasHost($this->refererHost, $this->idsite))
- {
- $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_DIRECT_ENTRY;
- return true;
- }
- }
- return false;
- }
+ */
+ protected function detectRefererDirectEntry()
+ {
+ if (!empty($this->refererHost)) {
+ // is the referer host the current host?
+ if (isset($this->currentUrlParse['host'])) {
+ $currentHost = mb_strtolower($this->currentUrlParse['host'], 'UTF-8');
+ if ($currentHost == mb_strtolower($this->refererHost, 'UTF-8')) {
+ $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_DIRECT_ENTRY;
+ return true;
+ }
+ }
+ if (Piwik_Tracker_Visit::isHostKnownAliasHost($this->refererHost, $this->idsite)) {
+ $this->typeRefererAnalyzed = Piwik_Common::REFERER_TYPE_DIRECT_ENTRY;
+ return true;
+ }
+ }
+ return false;
+ }
}
/**
* @package Piwik
* @subpackage Piwik_Tracker
*/
-class Piwik_Tracker_Visit_VisitorNotFoundInDatabase extends Exception {
+class Piwik_Tracker_Visit_VisitorNotFoundInDatabase extends Exception
+{
}
/**
* @package Piwik
* @subpackage Piwik_Tracker
*/
-class Piwik_Tracker_Visit_Excluded extends Exception {
+class Piwik_Tracker_Visit_Excluded extends Exception
+{
}