Returns the ID from the request in this order:
return from a given User ID,
or from a Tracking API forced Visitor ID,
or from a Visitor ID from 3rd party (optional) cookies,
or from a given Visitor Id from 1st party?
public getVisitorId ( ) |
public function findKnownVisitor($configId, VisitProperties $visitProperties, Request $request) { $idSite = $request->getIdSite(); $idVisitor = $request->getVisitorId(); $isVisitorIdToLookup = !empty($idVisitor); if ($isVisitorIdToLookup) { $visitProperties->setProperty('idvisitor', $idVisitor); Common::printDebug("Matching visitors with: visitorId=" . bin2hex($idVisitor) . " OR configId=" . bin2hex($configId)); } else { Common::printDebug("Visitor doesn't have the piwik cookie..."); } $persistedVisitAttributes = $this->getVisitFieldsPersist(); $shouldMatchOneFieldOnly = $this->shouldLookupOneVisitorFieldOnly($isVisitorIdToLookup, $request); list($timeLookBack, $timeLookAhead) = $this->getWindowLookupThisVisit($request); $visitRow = $this->model->findVisitor($idSite, $configId, $idVisitor, $persistedVisitAttributes, $shouldMatchOneFieldOnly, $isVisitorIdToLookup, $timeLookBack, $timeLookAhead); $isNewVisitForced = $request->getParam('new_visit'); $isNewVisitForced = !empty($isNewVisitForced); $enforceNewVisit = $isNewVisitForced || $this->trackerAlwaysNewVisitor; if (!$enforceNewVisit && $visitRow && count($visitRow) > 0) { // These values will be used throughout the request foreach ($persistedVisitAttributes as $field) { $visitProperties->setProperty($field, $visitRow[$field]); } $visitProperties->setProperty('visit_last_action_time', strtotime($visitRow['visit_last_action_time'])); $visitProperties->setProperty('visit_first_action_time', strtotime($visitRow['visit_first_action_time'])); // Custom Variables copied from Visit in potential later conversion if (!empty($numCustomVarsToRead)) { for ($i = 1; $i <= $numCustomVarsToRead; $i++) { if (isset($visitRow['custom_var_k' . $i]) && strlen($visitRow['custom_var_k' . $i])) { $visitProperties->setProperty('custom_var_k' . $i, $visitRow['custom_var_k' . $i]); } if (isset($visitRow['custom_var_v' . $i]) && strlen($visitRow['custom_var_v' . $i])) { $visitProperties->setProperty('custom_var_v' . $i, $visitRow['custom_var_v' . $i]); } } } Common::printDebug("The visitor is known (idvisitor = " . bin2hex($visitProperties->getProperty('idvisitor')) . ",\n config_id = " . bin2hex($configId) . ",\n idvisit = {$visitProperties->getProperty('idvisit')},\n last action = " . date("r", $visitProperties->getProperty('visit_last_action_time')) . ",\n first action = " . date("r", $visitProperties->getProperty('visit_first_action_time')) . ",\n visit_goal_buyer' = " . $visitProperties->getProperty('visit_goal_buyer') . ")"); return true; } else { Common::printDebug("The visitor was not matched with an existing visitor..."); return false; } }
private function getVisitorIdFromRequest(Tracker\Request $request) { try { $visitorId = $request->getVisitorId(); } catch (InvalidRequestParameterException $e) { $visitorId = null; } if (empty($visitorId)) { // we create a md5 otherwise IP's starting with 1 or 2 would be likely moved into same queue $visitorId = md5($request->getIpString()); } else { $visitorId = bin2hex($visitorId); } return $visitorId; }
/** * 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; $userInfo = $this->getUserSettingsInformation(); $configId = $userInfo['config_id']; $idVisitor = $this->request->getVisitorId(); $isVisitorIdToLookup = !empty($idVisitor); if ($isVisitorIdToLookup) { $this->visitorInfo['idvisitor'] = $idVisitor; Common::printDebug("Matching visitors with: visitorId=" . bin2hex($this->visitorInfo['idvisitor']) . " OR configId=" . bin2hex($configId)); } else { Common::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->visitorCustomVariables) { $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'; } $persistedVisitAttributes = $this->getVisitFieldsPersist(); $selectFields = implode(", ", $persistedVisitAttributes); $select = "SELECT\n visit_last_action_time,\n visit_first_action_time,\n {$selectFields}\n {$selectCustomVariables}\n "; $from = "FROM " . Common::prefixTable('log_visit'); list($timeLookBack, $timeLookAhead) = $this->getWindowLookupThisVisit(); $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, // importing server access logs with import_logs.py, etc. // In this case we use config_id heuristics to try find the visitor in tahhhe 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 $whereCommon = "visit_last_action_time >= ? AND visit_last_action_time <= ? AND idsite = ?"; $bindSql = array($timeLookBack, $timeLookAhead, $this->request->getIdSite()); if ($shouldMatchOneFieldOnly) { if ($isVisitorIdToLookup) { $whereCommon .= ' AND idvisitor = ?'; $bindSql[] = $this->visitorInfo['idvisitor']; } else { $whereCommon .= ' AND config_id = ?'; $bindSql[] = $configId; } $sql = "{$select}\n {$from}\n WHERE " . $whereCommon . "\n ORDER BY visit_last_action_time DESC\n LIMIT 1"; } else { // will use INDEX index_idsite_config_datetime (idsite, config_id, visit_last_action_time) $where = ' AND config_id = ?'; $bindSql[] = $configId; $sqlConfigId = "{$select} ,\n 0 as priority\n {$from}\n WHERE {$whereCommon} {$where}\n ORDER BY visit_last_action_time DESC\n LIMIT 1\n "; // will use INDEX index_idsite_idvisitor (idsite, idvisitor) $bindSql[] = $timeLookBack; $bindSql[] = $timeLookAhead; $bindSql[] = $this->request->getIdSite(); $where = ' AND idvisitor = ?'; $bindSql[] = $this->visitorInfo['idvisitor']; $sqlVisitorId = "{$select} ,\n 1 as priority\n {$from}\n WHERE {$whereCommon} {$where}\n ORDER BY visit_last_action_time DESC\n LIMIT 1\n "; // We join both queries and favor the one matching the visitor_id if it did match $sql = " ( {$sqlConfigId} )\n UNION\n ( {$sqlVisitorId} )\n ORDER BY priority DESC\n LIMIT 1"; } $visitRow = Tracker::getDatabase()->fetch($sql, $bindSql); $isNewVisitForced = $this->request->getParam('new_visit'); $isNewVisitForced = !empty($isNewVisitForced); $newVisitEnforcedAPI = $isNewVisitForced && ($this->request->isAuthenticated() || !Config::getInstance()->Tracker['new_visit_api_requires_admin']); $enforceNewVisit = $newVisitEnforcedAPI || Config::getInstance()->Debug['tracker_always_new_visitor']; if (!$enforceNewVisit && $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']); foreach ($persistedVisitAttributes as $field) { $this->visitorInfo[$field] = $visitRow[$field]; } // Custom Variables copied from Visit in potential later conversion if (!empty($selectCustomVariables)) { for ($i = 1; $i <= 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; Common::printDebug("The visitor is known (idvisitor = " . bin2hex($this->visitorInfo['idvisitor']) . ",\n config_id = " . bin2hex($configId) . ",\n idvisit = {$this->visitorInfo['idvisit']},\n last action = " . date("r", $this->visitorInfo['visit_last_action_time']) . ",\n first action = " . date("r", $this->visitorInfo['visit_first_action_time']) . ",\n visit_goal_buyer' = " . $this->visitorInfo['visit_goal_buyer'] . ")"); //Common::printDebug($this->visitorInfo); } else { Common::printDebug("The visitor was not matched with an existing visitor..."); } }