/**
  * @param Request $request
  * @param Visitor $visitor
  * @param Action|null $action
  * @return int|bool
  */
 public function onExistingVisit(Request $request, Visitor $visitor, $action)
 {
     if (empty($action)) {
         return false;
     }
     return $action->getIdActionNameForEntryAndExitIds();
 }
Exemple #2
0
 private static function getPriority(Action $actionType)
 {
     $key = array_search($actionType->getActionType(), self::$factoryPriority);
     if (false === $key) {
         return -1;
     }
     return $key;
 }
 /**
  * @param Request $request
  * @param Visitor $visitor
  * @param Action|null $action
  * @return mixed
  */
 public function onNewVisit(Request $request, Visitor $visitor, $action)
 {
     $idActionName = false;
     if (!empty($action)) {
         $idActionName = $action->getIdActionNameForEntryAndExitIds();
     }
     return (int) $idActionName;
 }
Exemple #4
0
 /**
  * Detect whether action is an outlink given host aliases
  *
  * @param Action $action
  * @return bool true if the outlink the visitor clicked on points to one of the known hosts for this website
  */
 protected function detectActionIsOutlinkOnAliasHost(Action $action, $idSite)
 {
     $decodedActionUrl = $action->getActionUrl();
     $actionUrlParsed = @parse_url($decodedActionUrl);
     if (!isset($actionUrlParsed['host'])) {
         return false;
     }
     return Visit::isHostKnownAliasHost($actionUrlParsed['host'], $idSite);
 }
Exemple #5
0
 /**
  * @param Request $request
  * @param Visitor $visitor
  * @param Action|null $action
  * @return mixed
  */
 public function onNewVisit(Request $request, Visitor $visitor, $action)
 {
     $idActionUrl = false;
     if (!empty($action)) {
         $idActionUrl = $action->getIdActionUrlForEntryAndExitIds();
     }
     if ($idActionUrl === false) {
         return false;
     }
     return (int) $idActionUrl;
 }
 /**
  * @param Request $request
  * @param Visitor $visitor
  * @param Action|null $action
  * @return int
  */
 public function onExistingVisit(Request $request, Visitor $visitor, $action)
 {
     if (empty($action)) {
         return false;
     }
     $id = $action->getIdActionUrlForEntryAndExitIds();
     if (!empty($id)) {
         $id = (int) $id;
     }
     return $id;
 }
Exemple #7
0
 /**
  * Detect whether action is an outlink given host aliases
  *
  * @param Action $action
  * @return bool true if the outlink the visitor clicked on points to one of the known hosts for this website
  */
 public static function detectActionIsOutlinkOnAliasHost(Action $action, $idSite)
 {
     if ($action->getActionType() != Action::TYPE_OUTLINK) {
         return false;
     }
     $decodedActionUrl = $action->getActionUrl();
     $actionUrlParsed = @parse_url($decodedActionUrl);
     if (!isset($actionUrlParsed['host'])) {
         return false;
     }
     return Visit::isHostKnownAliasHost($actionUrlParsed['host'], $idSite);
 }
 /**
  * @param Action|null $action
  * @return bool
  */
 public static function shouldCountInteraction($action)
 {
     if (empty($action)) {
         return false;
     }
     $idActionUrl = $action->getIdActionUrlForEntryAndExitIds();
     if ($idActionUrl !== false) {
         return true;
     }
     $actionType = $action->getActionType();
     $types = array(Action::TYPE_SITE_SEARCH);
     if (in_array($actionType, $types)) {
         return true;
     }
     return false;
 }
 /**
  * @param Request $request
  * @param Visitor $visitor
  * @param Action|null $action
  * @return int
  */
 public function onExistingVisit(Request $request, Visitor $visitor, $action)
 {
     if (!$action) {
         return false;
     }
     $increment = 'visit_total_actions + 1';
     $idActionUrl = $action->getIdActionUrlForEntryAndExitIds();
     if ($idActionUrl !== false) {
         return $increment;
     }
     $actionType = $action->getActionType();
     if (in_array($actionType, array(Action::TYPE_SITE_SEARCH, Action::TYPE_EVENT))) {
         return $increment;
     }
     return false;
 }
Exemple #10
0
 public function writeDebugInfo()
 {
     $write = parent::writeDebugInfo();
     if ($write) {
         Common::printDebug("Event Value = " . $this->getCustomFloatValue());
     }
     return $write;
 }
Exemple #11
0
 public function writeDebugInfo()
 {
     $write = parent::writeDebugInfo();
     if ($write) {
         Common::printDebug("Event Category = " . $this->eventCategory . ",\n                Event Action = " . $this->eventAction . ",\n                Event Name =  " . $this->eventName . ",\n                Event Value = " . $this->getCustomFloatValue());
     }
     return $write;
 }
 function __construct($url, Request $request)
 {
     parent::__construct(Action::TYPE_PAGE_URL, $request);
     $this->setActionUrl($url);
     $actionName = $request->getParam('action_name');
     $actionName = $this->cleanupActionName($actionName);
     $this->setActionName($actionName);
     $this->timeGeneration = $this->request->getPageGenerationTime();
 }
 public function processRequestParams(VisitProperties $visitProperties, Request $request)
 {
     // normal page view, potentially triggering a URL matching goal
     $action = Action::factory($request);
     $action->writeDebugInfo();
     $request->setMetadata('Actions', 'action', $action);
     // save the exit actions of the last action in this visit as the referrer actions for the action being tracked.
     // when the visit is updated, these columns will be changed, so we have to do this before recordLogs
     $request->setMetadata('Actions', 'idReferrerActionUrl', $visitProperties->getProperty('visit_exit_idaction_url'));
     $request->setMetadata('Actions', 'idReferrerActionName', $visitProperties->getProperty('visit_exit_idaction_name'));
 }
 private static function insertNewIdsAction($actionsNameAndType, $fieldNamesToInsert)
 {
     // Then, we insert all new actions in the lookup table
     $inserted = array();
     foreach ($fieldNamesToInsert as $fieldName) {
         list($name, $type, $urlPrefix) = $actionsNameAndType[$fieldName];
         $actionId = self::getModel()->createNewIdAction($name, $type, $urlPrefix);
         Common::printDebug("Recorded a new action (" . Action::getTypeAsString($type) . ") in the lookup table: " . $name . " (idaction = " . $actionId . ")");
         $inserted[$fieldName] = $actionId;
     }
     return $inserted;
 }
 public function getCustomVariables()
 {
     $customVariables = parent::getCustomVariables();
     // Enrich Site Search actions with Custom Variables, overwriting existing values
     if (!empty($this->searchCategory)) {
         if (!empty($customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_CATEGORY])) {
             Common::printDebug("WARNING: Overwriting existing Custom Variable  in slot " . self::CVAR_INDEX_SEARCH_CATEGORY . " for this page view");
         }
         $customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_CATEGORY] = self::CVAR_KEY_SEARCH_CATEGORY;
         $customVariables['custom_var_v' . self::CVAR_INDEX_SEARCH_CATEGORY] = Request::truncateCustomVariable($this->searchCategory);
     }
     if ($this->searchCount !== false) {
         if (!empty($customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_COUNT])) {
             Common::printDebug("WARNING: Overwriting existing Custom Variable  in slot " . self::CVAR_INDEX_SEARCH_COUNT . " for this page view");
         }
         $customVariables['custom_var_k' . self::CVAR_INDEX_SEARCH_COUNT] = self::CVAR_KEY_SEARCH_COUNT;
         $customVariables['custom_var_v' . self::CVAR_INDEX_SEARCH_COUNT] = (int) $this->searchCount;
     }
     return $customVariables;
 }
Exemple #16
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()
     $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 __construct(Request $request)
 {
     parent::__construct(self::TYPE_DOWNLOAD, $request);
     $this->setActionUrlWithoutExcludingParameters($request->getParam('download'));
 }
Exemple #18
0
 public function __construct(Request $request)
 {
     parent::__construct(Action::TYPE_CONTENT, $request);
     $url = $request->getParam('url');
     $this->setActionUrl($url);
 }
Exemple #19
0
 /**
  * Look at the URL or Page Title and sees if it matches any existing Goal definition
  *
  * @param int $idSite
  * @param Action $action
  * @throws Exception
  * @return int Number of goals matched
  */
 function detectGoalsMatchingUrl($idSite, $action)
 {
     if (!Common::isGoalPluginEnabled()) {
         return false;
     }
     $decodedActionUrl = $action->getActionUrl();
     $actionType = $action->getActionType();
     $goals = $this->getGoalDefinitions($idSite);
     foreach ($goals as $goal) {
         $attribute = $goal['match_attribute'];
         // if the attribute to match is not the type of the current action
         if (($attribute == 'url' || $attribute == 'title') && $actionType != Action::TYPE_PAGE_URL || $attribute == 'file' && $actionType != Action::TYPE_DOWNLOAD || $attribute == 'external_website' && $actionType != Action::TYPE_OUTLINK || $attribute == 'manually') {
             continue;
         }
         $url = $decodedActionUrl;
         // Matching on Page Title
         if ($attribute == 'title') {
             $url = $action->getActionName();
         }
         $pattern_type = $goal['pattern_type'];
         $match = $this->isUrlMatchingGoal($goal, $pattern_type, $url);
         if ($match) {
             $goal['url'] = $decodedActionUrl;
             $this->convertedGoals[] = $goal;
         }
     }
     return count($this->convertedGoals) > 0;
 }
 /**
  * Look at the URL or Page Title and sees if it matches any existing Goal definition
  *
  * @param int $idSite
  * @param Action $action
  * @throws Exception
  * @return int Number of goals matched
  */
 function detectGoalsMatchingUrl($idSite, $action)
 {
     if (!Common::isGoalPluginEnabled()) {
         return false;
     }
     $decodedActionUrl = $action->getActionUrl();
     $actionType = $action->getActionType();
     $goals = $this->getGoalDefinitions($idSite);
     foreach ($goals as $goal) {
         $attribute = $goal['match_attribute'];
         // if the attribute to match is not the type of the current action
         if ($actionType == Action::TYPE_PAGE_URL && $attribute != 'url' && $attribute != 'title' || $actionType == Action::TYPE_DOWNLOAD && $attribute != 'file' || $actionType == Action::TYPE_OUTLINK && $attribute != 'external_website' || $attribute == 'manually') {
             continue;
         }
         $url = $decodedActionUrl;
         // Matching on Page Title
         if ($attribute == 'title') {
             $url = $action->getActionName();
         }
         $pattern_type = $goal['pattern_type'];
         switch ($pattern_type) {
             case 'regex':
                 $pattern = $goal['pattern'];
                 if (strpos($pattern, '/') !== false && strpos($pattern, '\\/') === false) {
                     $pattern = str_replace('/', '\\/', $pattern);
                 }
                 $pattern = '/' . $pattern . '/';
                 if (!$goal['case_sensitive']) {
                     $pattern .= 'i';
                 }
                 $match = @preg_match($pattern, $url) == 1;
                 break;
             case 'contains':
                 if ($goal['case_sensitive']) {
                     $matched = strpos($url, $goal['pattern']);
                 } else {
                     $matched = stripos($url, $goal['pattern']);
                 }
                 $match = $matched !== false;
                 break;
             case 'exact':
                 if ($goal['case_sensitive']) {
                     $matched = strcmp($goal['pattern'], $url);
                 } else {
                     $matched = strcasecmp($goal['pattern'], $url);
                 }
                 $match = $matched == 0;
                 break;
             default:
                 throw new Exception(Piwik::translate('General_ExceptionInvalidGoalPattern', array($pattern_type)));
                 break;
         }
         if ($match) {
             $goal['url'] = $decodedActionUrl;
             $this->convertedGoals[] = $goal;
         }
     }
     return count($this->convertedGoals) > 0;
 }
Exemple #21
0
 /**
  * Look at the URL or Page Title and sees if it matches any existing Goal definition
  *
  * @param int $idSite
  * @param Action $action
  * @throws Exception
  * @return int Number of goals matched
  */
 public function detectGoalsMatchingUrl($idSite, $action)
 {
     if (!Common::isGoalPluginEnabled()) {
         return false;
     }
     $actionType = $action->getActionType();
     $goals = $this->getGoalDefinitions($idSite);
     foreach ($goals as $goal) {
         $attribute = $goal['match_attribute'];
         // if the attribute to match is not the type of the current action
         if (($attribute == 'url' || $attribute == 'title') && $actionType != Action::TYPE_PAGE_URL || $attribute == 'file' && $actionType != Action::TYPE_DOWNLOAD || $attribute == 'external_website' && $actionType != Action::TYPE_OUTLINK || $attribute == 'manually' || in_array($attribute, array('event_action', 'event_name', 'event_category')) && $actionType != Action::TYPE_EVENT) {
             continue;
         }
         switch ($attribute) {
             case 'title':
                 // Matching on Page Title
                 $url = $action->getActionName();
                 break;
             case 'event_action':
                 $url = $action->getEventAction();
                 break;
             case 'event_name':
                 $url = $action->getEventName();
                 break;
             case 'event_category':
                 $url = $action->getEventCategory();
                 break;
                 // url, external_website, file, manually...
             // url, external_website, file, manually...
             default:
                 $url = $action->getActionUrlRaw();
                 break;
         }
         $pattern_type = $goal['pattern_type'];
         $match = $this->isUrlMatchingGoal($goal, $pattern_type, $url);
         if ($match) {
             $goal['url'] = $action->getActionUrl();
             $this->convertedGoals[] = $goal;
         }
     }
     return count($this->convertedGoals) > 0;
 }
Exemple #22
0
 /**
  * @param Action|null $action
  * @return bool
  */
 private function isEventAction($action)
 {
     return $action && $action->getActionType() == Action::TYPE_EVENT;
 }
 private static function insertNewIdsAction($actionsNameAndType, $fieldNamesToInsert)
 {
     $sql = "INSERT INTO " . Common::prefixTable('log_action') . "( name, hash, type, url_prefix ) VALUES (?,CRC32(?),?,?)";
     // Then, we insert all new actions in the lookup table
     $inserted = array();
     foreach ($fieldNamesToInsert as $fieldName) {
         list($name, $type, $urlPrefix) = $actionsNameAndType[$fieldName];
         Tracker::getDatabase()->query($sql, array($name, $name, $type, $urlPrefix));
         $actionId = Tracker::getDatabase()->lastInsertId();
         $inserted[$fieldName] = $actionId;
         Common::printDebug("Recorded a new action (" . Action::getTypeAsString($type) . ") in the lookup table: " . $name . " (idaction = " . $actionId . ")");
     }
     return $inserted;
 }
 /**
  * @param Action|null $action
  * @return bool
  */
 private function isSiteSearchAction($action)
 {
     return $action && $action->getActionType() == Action::TYPE_SITE_SEARCH;
 }
Exemple #25
0
 /**
  * Detects if an Action matches a given goal. If it does, the URL that triggered the goal
  * is returned. Otherwise null is returned.
  *
  * @param array $goal
  * @param Action $action
  * @return string|null
  */
 public function detectGoalMatch($goal, Action $action)
 {
     $actionType = $action->getActionType();
     $attribute = $goal['match_attribute'];
     // if the attribute to match is not the type of the current action
     if (($attribute == 'url' || $attribute == 'title') && $actionType != Action::TYPE_PAGE_URL || $attribute == 'file' && $actionType != Action::TYPE_DOWNLOAD || $attribute == 'external_website' && $actionType != Action::TYPE_OUTLINK || $attribute == 'manually' || in_array($attribute, array('event_action', 'event_name', 'event_category')) && $actionType != Action::TYPE_EVENT) {
         return null;
     }
     switch ($attribute) {
         case 'title':
             // Matching on Page Title
             $url = $action->getActionName();
             break;
         case 'event_action':
             $url = $action->getEventAction();
             break;
         case 'event_name':
             $url = $action->getEventName();
             break;
         case 'event_category':
             $url = $action->getEventCategory();
             break;
             // url, external_website, file, manually...
         // url, external_website, file, manually...
         default:
             $url = $action->getActionUrlRaw();
             break;
     }
     $pattern_type = $goal['pattern_type'];
     $match = $this->isUrlMatchingGoal($goal, $pattern_type, $url);
     if (!$match) {
         return null;
     }
     return $action->getActionUrl();
 }
Exemple #26
0
 /**
  * @dataProvider getExtractUrlData
  * @group Core
  */
 public function testExtractUrlAndActionNameFromRequest($request, $expected)
 {
     PluginManager::getInstance()->loadPlugins(array('Actions', 'SitesManager'));
     $this->setUpRootAccess();
     $idSite = API::getInstance()->addSite("site1", array('http://example.org'));
     $request['idsite'] = $idSite;
     $request = new Request($request);
     $action = Action::factory($request);
     $processed = array('name' => $action->getActionName(), 'url' => $action->getActionUrl(), 'type' => $action->getActionType());
     $this->assertEquals($processed, $expected);
 }