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.php245
1 files changed, 178 insertions, 67 deletions
diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php
index 18c636f483..b216f742e7 100644
--- a/core/Tracker/Visit.php
+++ b/core/Tracker/Visit.php
@@ -59,9 +59,10 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$this->request = $requestArray;
$idsite = Piwik_Common::getRequestVar('idsite', 0, 'int', $this->request);
+ Piwik_PostEvent('Tracker.setRequest.idSite', $idsite);
if($idsite <= 0)
{
- throw new Exception("The 'idsite' in the request is invalid.");
+ throw new Exception(Piwik_TranslateException('General_ExceptionInvalidIdsite'));
}
$this->idsite = $idsite;
}
@@ -88,6 +89,9 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
*/
public function handle()
{
+ // the IP is needed by isExcluded() and GoalManager->recordGoals()
+ $this->visitorInfo['location_ip'] = Piwik_Common::getIp();
+
if($this->isExcluded())
{
return;
@@ -106,6 +110,7 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
// 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 = '.$idGoal);
unset($goalManager);
return;
}
@@ -127,9 +132,10 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit();
// 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()
+ // ( - 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()
@@ -232,26 +238,31 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
visit_total_actions = visit_total_actions + 1, ";
$this->visitorInfo['visit_exit_idaction_url'] = $actionUrlId;
}
- $result = Piwik_Tracker::getDatabase()->query("/* SHARDING_ID_SITE = ". $this->idsite ." */
+ $sqlQuery = "/* SHARDING_ID_SITE = ". $this->idsite ." */
UPDATE ". Piwik_Common::prefixTable('log_visit')."
SET $sqlActionIdUpdate
$sqlUpdateGoalConverted
visit_last_action_time = ?,
- visit_total_time = UNIX_TIMESTAMP(visit_last_action_time) - UNIX_TIMESTAMP(visit_first_action_time)
- WHERE idvisit = ?
+ visit_total_time = ?
+ WHERE idsite = ?
+ AND idvisit = ?
AND visitor_idcookie = ?
- LIMIT 1",
- array( $datetimeServer,
- $this->visitorInfo['idvisit'],
- $this->visitorInfo['visitor_idcookie'] )
- );
+ LIMIT 1";
+ $sqlBind = array( $datetimeServer,
+ $visitTotalTime = $this->getCurrentTimestamp() - $this->visitorInfo['visit_first_action_time'],
+ $this->idsite,
+ $this->visitorInfo['idvisit'],
+ $this->visitorInfo['visitor_idcookie'] );
+
+ $result = Piwik_Tracker::getDatabase()->query($sqlQuery, $sqlBind);
+
+ printDebug('Updating visitor with idvisit='.$this->visitorInfo['idvisit'].', setting visit_last_action_time='.$datetimeServer.' and visit_total_time='.$visitTotalTime);
if(Piwik_Tracker::getDatabase()->rowCount($result) == 0)
{
throw new Piwik_Tracker_Visit_VisitorNotFoundInDatabase("The visitor with visitor_idcookie=".$this->visitorInfo['visitor_idcookie']." and idvisit=".$this->visitorInfo['idvisit']." wasn't found in the DB, we fallback to a new visitor");
}
$this->visitorInfo['idsite'] = $this->idsite;
- $this->visitorInfo['visit_server_date'] = $this->getCurrentDate();
// will be updated in cookie
$this->visitorInfo['time_spent_ref_action'] = $serverTime - $this->visitorInfo['visit_last_action_time'];
@@ -275,7 +286,6 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
.':'. Piwik_Common::getRequestVar( 'm', $this->getCurrentDate("i"), 'int', $this->request)
.':'. Piwik_Common::getRequestVar( 's', $this->getCurrentDate("s"), 'int', $this->request);
$serverTime = $this->getCurrentTimestamp();
- $serverDate = $this->getCurrentDate();
$idcookie = $this->getVisitorIdcookie();
$returningVisitor = $this->isVisitorKnown() ? 1 : 0;
@@ -283,47 +293,49 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$defaultTimeOnePageVisit = Piwik_Tracker_Config::getInstance()->Tracker['default_time_one_page_visit'];
$userInfo = $this->getUserSettingsInformation();
- $country = Piwik_Common::getCountry($userInfo['location_browser_lang'], $enableLanguageToCountryGuess = Piwik_Tracker_Config::getInstance()->Tracker['enable_language_to_country_guess']);
+ $country = Piwik_Common::getCountry($userInfo['location_browser_lang'],
+ $enableLanguageToCountryGuess = Piwik_Tracker_Config::getInstance()->Tracker['enable_language_to_country_guess'],
+ $this->getVisitorIp());
$refererInfo = $this->getRefererInformation();
/**
* Save the visitor
*/
$this->visitorInfo = array(
- 'idsite' => $this->idsite,
- 'visitor_localtime' => $localTime,
- 'visitor_idcookie' => $idcookie,
- 'visitor_returning' => $returningVisitor,
- 'visit_first_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($serverTime),
- 'visit_last_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($serverTime),
- 'visit_server_date' => $serverDate,
- 'visit_entry_idaction_url' => $actionUrlId,
- 'visit_exit_idaction_url' => $actionUrlId,
- 'visit_total_actions' => 1,
- 'visit_total_time' => $defaultTimeOnePageVisit,
- 'visit_goal_converted' => $someGoalsConverted ? 1: 0,
- 'referer_type' => $refererInfo['referer_type'],
- 'referer_name' => $refererInfo['referer_name'],
- 'referer_url' => $refererInfo['referer_url'],
- 'referer_keyword' => $refererInfo['referer_keyword'],
- 'config_md5config' => $userInfo['config_md5config'],
- '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' => $userInfo['location_ip'],
- 'location_browser_lang' => $userInfo['location_browser_lang'],
- 'location_country' => $country,
+ 'idsite' => $this->idsite,
+ 'visitor_localtime' => $localTime,
+ 'visitor_idcookie' => $idcookie,
+ 'visitor_returning' => $returningVisitor,
+ 'visit_server_date' => $this->getCurrentDate(),
+ 'visit_first_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($serverTime),
+ 'visit_last_action_time' => Piwik_Tracker::getDatetimeFromTimestamp($serverTime),
+ 'visit_entry_idaction_url' => $actionUrlId,
+ 'visit_exit_idaction_url' => $actionUrlId,
+ 'visit_total_actions' => 1,
+ 'visit_total_time' => $defaultTimeOnePageVisit,
+ 'visit_goal_converted' => $someGoalsConverted ? 1: 0,
+ 'referer_type' => $refererInfo['referer_type'],
+ 'referer_name' => $refererInfo['referer_name'],
+ 'referer_url' => $refererInfo['referer_url'],
+ 'referer_keyword' => $refererInfo['referer_keyword'],
+ 'config_md5config' => $userInfo['config_md5config'],
+ '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'],
+ 'location_country' => $country,
);
Piwik_PostEvent('Tracker.newVisitorInformation', $this->visitorInfo);
@@ -389,8 +401,9 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
*/
protected function getVisitorIp()
{
- return Piwik_Common::getIp();
+ return $this->visitorInfo['location_ip'];
}
+
/**
* Returns the visitor's browser (user agent)
@@ -433,20 +446,62 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
*/
protected function isExcluded()
{
+ $excluded = false;
+
$ip = $this->getVisitorIp();
$ua = $this->getUserAgent();
/*
- * Live/Bing bot and Googlebot are evolving to detect cloaked websites.
+ * 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).
*/
- $excluded = preg_match('/65\.55/', long2ip($ip)) // Live/Bing
- || preg_match('/Googlebot/', $ua); // Googlebot
-
- /* custom filters can override the built-in filter above */
+ $dotIp = long2ip($ip);
+ if (strpos($dotIp, '65.55') === 0 // Live/Bing
+ || strpos($dotIp, '207.46') === 0 // MSN
+ || strpos($ua, 'Googlebot') !== false) // Googlebot
+ {
+ 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');
+ if(!$toRecord)
+ {
+ printDebug('GET parameter '.$parameterForceRecord.' not found in URL, request excluded');
+ $excluded = true;
+ }
+ }
+
+ /* 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();
+ }
+
+ // Checking for excluded IPs
+ if(!$excluded)
+ {
+ $excluded = $this->isVisitorIpExcluded($ip);
+ }
+
if($excluded)
{
printDebug("Visitor excluded.");
@@ -455,8 +510,47 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
return false;
}
+
+ /**
+ * Looks for the ignore cookie that users can set in the Piwik admin screen.
+ * @return bool
+ */
+ protected function isIgnoreCookieFound()
+ {
+ $cookie = new Piwik_Cookie($this->getIgnoreVisitsCookieName());
+ if($cookie->isCookieFound())
+ {
+ printDebug('Piwik ignore cookie was found, visit not tracked.');
+ return true;
+ }
+ return false;
+ }
/**
+ * Checks if the visitor ip is in the excluded list
+ *
+ * @param $ip Long IP
+ * @return bool
+ */
+ protected function isVisitorIpExcluded($ip)
+ {
+ $websiteAttributes = Piwik_Common::getCacheWebsiteAttributes( $this->idsite );
+ if(!empty($websiteAttributes['excluded_ips']))
+ {
+ foreach($websiteAttributes['excluded_ips'] as $ipRange)
+ {
+ if($ip >= $ipRange[0]
+ && $ip <= $ipRange[1])
+ {
+ printDebug('Visitor IP '.long2ip($ip).' is excluded from being tracked');
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
* Returns the cookie name used for the Piwik Tracker cookie
*
* @return string
@@ -467,13 +561,33 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
}
/**
+ * Returns the cookie name used to ignore/exclude webmaster visits
+ *
+ * @return string
+ */
+ protected function getIgnoreVisitsCookieName()
+ {
+ return Piwik_Tracker_Config::getInstance()->Tracker['ignore_visits_cookie_name'];
+ }
+
+ /**
* Returns the cookie expiration date.
*
* @return int
*/
protected function getCookieExpire()
{
- return time() + Piwik_Tracker_Config::getInstance()->Tracker['cookie_expire'];
+ return $this->getCurrentTimestamp() + Piwik_Tracker_Config::getInstance()->Tracker['cookie_expire'];
+ }
+
+ /**
+ * Returns cookie path
+ *
+ * @return string
+ */
+ protected function getCookiePath()
+ {
+ return Piwik_Tracker_Config::getInstance()->Tracker['cookie_path'];
}
/**
@@ -508,7 +622,7 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
protected function recognizeTheVisitor()
{
$this->visitorKnown = false;
- $this->setCookie( new Piwik_Cookie( $this->getCookieName(), $this->getCookieExpire() ) );
+ $this->setCookie( new Piwik_Cookie( $this->getCookieName(), $this->getCookieExpire(), $this->getCookiePath() ) );
/*
* Case the visitor has the piwik cookie.
@@ -551,8 +665,8 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$visitRow = Piwik_Tracker::getDatabase()->fetch(
" SELECT visitor_idcookie,
- UNIX_TIMESTAMP(visit_last_action_time) as visit_last_action_time,
- UNIX_TIMESTAMP(visit_first_action_time) as visit_first_action_time,
+ visit_last_action_time,
+ visit_first_action_time,
idvisit,
visit_exit_idaction_url
FROM ".Piwik_Common::prefixTable('log_visit').
@@ -566,14 +680,14 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
&& count($visitRow) > 0)
{
$this->visitorInfo['visitor_idcookie'] = $visitRow['visitor_idcookie'];
- $this->visitorInfo['visit_last_action_time'] = $visitRow['visit_last_action_time'];
- $this->visitorInfo['visit_first_action_time'] = $visitRow['visit_first_action_time'];
+ $this->visitorInfo['visit_last_action_time'] = strtotime($visitRow['visit_last_action_time']);
+ $this->visitorInfo['visit_first_action_time'] = strtotime($visitRow['visit_first_action_time']);
$this->visitorInfo['idvisit'] = $visitRow['idvisit'];
$this->visitorInfo['visit_exit_idaction_url'] = $visitRow['visit_exit_idaction_url'];
$this->visitorKnown = true;
- printDebug("The visitor is known because of his userSettings+IP (idcookie = {$visitRow['visitor_idcookie']}, idvisit = {$this->visitorInfo['idvisit']}, last action = ".date("r", $this->visitorInfo['visit_last_action_time']).") ");
+ printDebug("The visitor is known because of his userSettings+IP (idcookie = {$visitRow['visitor_idcookie']}, idvisit = {$this->visitorInfo['idvisit']}, last action = ".date("r", $this->visitorInfo['visit_last_action_time']).", first action = ".date("r", $this->visitorInfo['visit_first_action_time']) .")");
}
}
}
@@ -614,8 +728,6 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$resolution = Piwik_Common::getRequestVar('res', 'unknown', 'string', $this->request);
- $ip = $this->getVisitorIp();
-
$browserLang = Piwik_Common::getBrowserLanguage();
$configurationHash = $this->getConfigHash(
@@ -633,7 +745,7 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
$plugin_Gears,
$plugin_Silverlight,
$plugin_Cookie,
- $ip,
+ $this->getVisitorIp(),
$browserLang);
$this->userSettingsInformation = array(
@@ -652,7 +764,6 @@ class Piwik_Tracker_Visit implements Piwik_Tracker_Visit_Interface
'config_gears' => $plugin_Gears,
'config_silverlight' => $plugin_Silverlight,
'config_cookie' => $plugin_Cookie,
- 'location_ip' => $ip,
'location_browser_lang' => $browserLang,
);