/** * 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->request->getIp(); $excluded = new VisitExcluded($this->request, $this->visitorInfo['location_ip']); if ($excluded->isExcluded()) { return; } /** * Triggered after visits are tested for exclusion so plugins can modify the IP address * persisted with a visit. * * This event is primarily used by the **PrivacyManager** plugin to anonymize IP addresses. * * @param string &$ip The visitor's IP address. */ Piwik::postEvent('Tracker.setVisitorIp', array(&$this->visitorInfo['location_ip'])); $this->visitorCustomVariables = $this->request->getCustomVariables($scope = 'visit'); if (!empty($this->visitorCustomVariables)) { Common::printDebug("Visit level Custom Variables: "); Common::printDebug($this->visitorCustomVariables); } $this->goalManager = new GoalManager($this->request); $visitIsConverted = false; $action = null; $isManualGoalConversion = $this->goalManager->isManualGoalConversion(); $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; } } elseif ($isManualGoalConversion) { // this request is from the JS call to piwikTracker.trackGoal() $someGoalsConverted = $this->goalManager->detectGoalId($this->request->getIdSite()); $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) { Common::printDebug('Invalid goal tracking request for goal id = ' . $this->goalManager->idGoal); return; } } else { // normal page view, potentially triggering a URL matching goal $action = Action::factory($this->request); $action->writeDebugInfo(); $someGoalsConverted = $this->goalManager->detectGoalsMatchingUrl($this->request->getIdSite(), $action); $visitIsConverted = $someGoalsConverted; $action->loadIdsFromLogActionTable(); } /*** * Visitor recognition */ $visitorId = $this->getSettingsObject()->getConfigId(); $visitor = new Visitor($this->request, $visitorId, $this->visitorInfo, $this->visitorCustomVariables); $visitor->recognize(); $this->visitorInfo = $visitor->getVisitorInfo(); $isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit($visitor); if (!$isLastActionInTheSameVisit) { Common::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 ($visitor->isVisitorKnown() && $isLastActionInTheSameVisit) { $idReferrerActionUrl = $this->visitorInfo['visit_exit_idaction_url']; $idReferrerActionName = $this->visitorInfo['visit_exit_idaction_name']; try { $this->goalManager->detectIsThereExistingCartInVisit($this->visitorInfo); $this->handleExistingVisit($visitor, $action, $visitIsConverted); if (!is_null($action)) { $action->record($visitor, $idReferrerActionUrl, $idReferrerActionName); } } catch (VisitorNotFoundInDb $e) { // There is an edge case when: // - two manual goal conversions happen in the same second // - which result in handleExistingVisit 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 ($isManualGoalConversion || $requestIsEcommerce) { $someGoalsConverted = $visitIsConverted = false; } else { $visitor->setIsVisitorKnown(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 (!$visitor->isVisitorKnown() || !$isLastActionInTheSameVisit) { $this->handleNewVisit($visitor, $action, $visitIsConverted); if (!is_null($action)) { $action->record($visitor, 0, 0); } } // update the cookie with the new visit information $this->request->setThirdPartyCookie($this->visitorInfo['idvisitor']); // record the goals if applicable if ($someGoalsConverted) { $this->goalManager->recordGoals($visitor, $this->visitorInfo, $this->visitorCustomVariables, $action); } unset($this->goalManager); unset($action); }
public function popout() { header("Access-Control-Allow-Origin: *"); $params = UrlHelper::getArrayFromQueryString($_SERVER['QUERY_STRING']); $request = new Tracker\Request($params); // the IP is needed by isExcluded() and GoalManager->recordGoals() $ip = $request->getIp(); $visitorInfo['location_ip'] = $ip; /** * Triggered after visits are tested for exclusion so plugins can modify the IP address * persisted with a visit. * * This event is primarily used by the **PrivacyManager** plugin to anonymize IP addresses. * * @param string &$ip The visitor's IP address. */ Piwik::postEvent('Tracker.setVisitorIp', array(&$visitorInfo['location_ip'])); /*** * Visitor recognition */ $settings = new Tracker\Settings($request, $visitorInfo['location_ip']); $visitor = new Visitor($request, $settings->getConfigId(), $visitorInfo); $visitor->recognize(); $visitorInfo = $visitor->getVisitorInfo(); if (!isset($visitorInfo['location_browser_lang'])) { return "Who are you ?"; } $idSite = Common::getRequestVar('idsite', null, 'int'); $conversation = new ChatConversation($idSite, bin2hex($visitorInfo['idvisitor'])); /*** * Segment recognition */ foreach (ChatAutomaticMessage::getAll($idSite) as $autoMsg) { $segment = ChatSegment::get($autoMsg['segmentID']); $fetchSegment = new Segment($segment['definition'], array($idSite)); $query = $fetchSegment->getSelectQuery("idvisitor", "log_visit", "log_visit.idvisitor = ?", array($visitorInfo['idvisitor'])); $rows = Db::fetchAll($query['sql'], $query['bind']); if (count($rows) == 0) { continue; } if ($autoMsg['segmentID'] != $segment['idsegment']) { continue; } $getAlreadyReceivedMsg = $conversation->getAutomaticMessageReceivedById($autoMsg['id']); if (count($getAlreadyReceivedMsg) > 0) { // If the AutoMsg is a "one shot" if ($autoMsg['frequency'] == 0) { continue; } if ($autoMsg['frequency'] != 0) { // Now, we gonna try to define when the last AutoMsg received has been sent list($freqTime, $freqScale) = explode('|', $autoMsg['frequency']); if ($freqScale == "w") { $dayMultiplier = 7; } elseif ($freqScale == "m") { $dayMultiplier = 30; } else { $dayMultiplier = 1; } $secToWait = 3600 * 24 * $freqTime * $dayMultiplier; // Is it older than the time range needed to wait ? if ($getAlreadyReceivedMsg[0]['microtime'] + $secToWait > microtime(true)) { continue; } } } $conversation->sendMessage($autoMsg['message'], $autoMsg['transmitter'], $autoMsg['id']); } $view = new View('@Chat/popout.twig'); $view->idvisitor = bin2hex($visitorInfo['idvisitor']); $view->idsite = $idSite; $view->timeLimit = time() - 2 * 60 * 60; $view->isStaffOnline = ChatPiwikUser::isStaffOnline(); $view->siteUrl = ChatSite::getMainUrl($idSite); $view->lang = $visitorInfo['location_browser_lang']; return $view->render(); }