/**
  * @param Request $request
  * @param Visitor $visitor
  * @param Action|null $action
  * @return mixed
  */
 public function onNewVisit(Request $request, Visitor $visitor, $action)
 {
     $visitCount = $request->getVisitCount();
     $daysSinceLastVisit = $request->getDaysSinceLastVisit();
     $daysSinceLastOrder = $request->getDaysSinceLastOrder();
     $isReturningCustomer = $daysSinceLastOrder !== false;
     if ($isReturningCustomer) {
         return self::IS_RETURNING_CUSTOMER;
     }
     if ($visitCount > 1 || $visitor->isVisitorKnown() || $daysSinceLastVisit > 0) {
         return self::IS_RETURNING;
     }
     return self::IS_NEW;
 }
示例#2
0
 /**
  * @param Request $request
  * @param Visitor $visitor
  * @param Action|null $action
  * @return int
  */
 public function onConvertedVisit(Request $request, Visitor $visitor, $action)
 {
     if (!$visitor->isVisitorKnown()) {
         return false;
     }
     $totalTime = $visitor->getVisitorColumn('visit_total_time');
     // 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
     $totalTime = $totalTime + $request->getParam('idgoal');
     // +2 to offset idgoal=-1 and idgoal=0
     $totalTime = $totalTime + 2;
     return $this->cleanupVisitTotalTime($totalTime);
 }
示例#3
0
 /**
  *  Returns visitor cookie
  *
  * @return string  binary
  */
 protected function getVisitorIdcookie(Visitor $visitor)
 {
     if ($visitor->isVisitorKnown()) {
         return $this->visitorInfo['idvisitor'];
     }
     // If the visitor had a first party ID cookie, then we use this value
     if (!empty($this->visitorInfo['idvisitor']) && Tracker::LENGTH_BINARY_ID == strlen($this->visitorInfo['idvisitor'])) {
         return $this->visitorInfo['idvisitor'];
     }
     return Common::hex2bin($this->generateUniqueVisitorId());
 }
 /**
  * This event is triggered when an any custom goal is converted. In this example we would store a the id of the
  * goal in the 'example_conversion_dimension' column if the visitor is known and nothing otherwise.
  * Return boolean false if you do not want to change the value in some cases. If you do not want to perform any
  * action on an ecommerce order at all it is recommended to just remove this method.
  *
  * @param Request $request
  * @param Visitor $visitor
  * @param Action|null $action
  * @param GoalManager $goalManager
  *
  * @return mixed|false
  */
 public function onGoalConversion(Request $request, Visitor $visitor, $action, GoalManager $goalManager)
 {
     $goalId = $goalManager->getGoalColumn('idgoal');
     if ($visitor->isVisitorKnown()) {
         return $goalId;
     }
     return false;
 }
示例#5
0
 /**
  *    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()
     $ip = $this->request->getIp();
     $this->visitorInfo['location_ip'] = $ip;
     $excluded = new VisitExcluded($this->request, $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;
     $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;
         }
     } elseif ($requestIsManualGoalConversion) {
         $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) {
             throw new \Exception('Invalid goal tracking request for goal id = ' . $this->goalManager->idGoal);
         }
     } else {
         $action = Action::factory($this->request);
         $action->writeDebugInfo();
         $someGoalsConverted = $this->goalManager->detectGoalsMatchingUrl($this->request->getIdSite(), $action);
         $visitIsConverted = $someGoalsConverted;
         $action->loadIdsFromLogActionTable();
     }
     /***
      * Visitor recognition
      */
     $visitor = new Visitor($this->request, $this->getSettingsObject(), $this->visitorInfo, $this->visitorCustomVariables);
     $visitor->recognize();
     $this->visitorKnown = $visitor->isVisitorKnown();
     $this->visitorInfo = $visitor->getVisitorInfo();
     $isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit();
     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 ($this->isVisitorKnown() && $isLastActionInTheSameVisit) {
         $idReferrerActionUrl = $this->visitorInfo['visit_exit_idaction_url'];
         $idReferrerActionName = $this->visitorInfo['visit_exit_idaction_name'];
         try {
             $this->handleExistingVisit($action, $visitIsConverted);
             if (!is_null($action)) {
                 $action->record($this->visitorInfo['idvisit'], $this->visitorInfo['idvisitor'], $idReferrerActionUrl, $idReferrerActionName, $this->visitorInfo['time_spent_ref_action']);
             }
         } 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 ($requestIsManualGoalConversion || $requestIsEcommerce) {
                 $someGoalsConverted = $visitIsConverted = false;
             } 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($action, $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->request->setThirdPartyCookie($this->visitorInfo['idvisitor']);
     // record the goals if applicable
     if ($someGoalsConverted) {
         $this->goalManager->recordGoals($this->request->getIdSite(), $this->visitorInfo, $this->visitorCustomVariables, $action);
     }
     unset($this->goalManager);
     unset($action);
 }
示例#6
0
文件: Visit.php 项目: hichnik/piwik
 /**
  * Determines if the tracker if the current action should be treated as the start of a new visit or
  * an action in an existing visit.
  *
  * @param Visitor $visitor The current visit/visitor information.
  * @param Action|null $action The current action being tracked.
  * @return bool
  */
 public function isVisitNew(Visitor $visitor, Action $action = null)
 {
     if (!$visitor->isVisitorKnown()) {
         return true;
     }
     $isLastActionInTheSameVisit = $this->isLastActionInTheSameVisit($visitor);
     if (!$isLastActionInTheSameVisit) {
         Common::printDebug("Visitor detected, but last action was more than 30 minutes ago...");
         return true;
     }
     $wasLastActionYesterday = $this->wasLastActionNotToday($visitor);
     if ($wasLastActionYesterday) {
         Common::printDebug("Visitor detected, but last action was yesterday...");
         return true;
     }
     $shouldForceNewVisit = $this->triggerPredicateHookOnDimensions($this->getAllVisitDimensions(), 'shouldForceNewVisit', $visitor, $action);
     if ($shouldForceNewVisit) {
         return true;
     }
     return false;
 }