public function visitorMap($fetch = false, $segmentOverride = false) { $this->checkUserCountryPluginEnabled(); $idSite = Common::getRequestVar('idSite', 1, 'int'); Piwik::checkUserHasViewAccess($idSite); $period = Common::getRequestVar('period'); $date = Common::getRequestVar('date'); $segment = $segmentOverride ?: Request::getRawSegmentFromRequest() ?: ''; $token_auth = Piwik::getCurrentUserTokenAuth(); $view = new View('@UserCountryMap/visitorMap'); // request visits summary $request = new Request('method=VisitsSummary.get&format=PHP' . '&idSite=' . $idSite . '&period=' . $period . '&date=' . $date . '&segment=' . $segment . '&token_auth=' . $token_auth . '&filter_limit=-1'); $config = array(); $config['visitsSummary'] = unserialize($request->process()); $config['countryDataUrl'] = $this->_report('UserCountry', 'getCountry', $idSite, $period, $date, $token_auth, false, $segment); $config['regionDataUrl'] = $this->_report('UserCountry', 'getRegion', $idSite, $period, $date, $token_auth, true, $segment); $config['cityDataUrl'] = $this->_report('UserCountry', 'getCity', $idSite, $period, $date, $token_auth, true, $segment); $config['countrySummaryUrl'] = $this->getApiRequestUrl('VisitsSummary', 'get', $idSite, $period, $date, $token_auth, true, $segment); $view->defaultMetric = 'nb_visits'; // some translations $view->localeJSON = json_encode(array('nb_visits' => $this->translator->translate('General_NVisits'), 'one_visit' => $this->translator->translate('General_OneVisit'), 'no_visit' => $this->translator->translate('UserCountryMap_NoVisit'), 'nb_actions' => $this->translator->translate('VisitsSummary_NbActionsDescription'), 'nb_actions_per_visit' => $this->translator->translate('VisitsSummary_NbActionsPerVisit'), 'bounce_rate' => $this->translator->translate('VisitsSummary_NbVisitsBounced'), 'avg_time_on_site' => $this->translator->translate('VisitsSummary_AverageVisitDuration'), 'and_n_others' => $this->translator->translate('UserCountryMap_AndNOthers'), 'no_data' => $this->translator->translate('CoreHome_ThereIsNoDataForThisReport'), 'nb_uniq_visitors' => $this->translator->translate('VisitsSummary_NbUniqueVisitors'), 'nb_users' => $this->translator->translate('VisitsSummary_NbUsers'))); $view->reqParamsJSON = $this->getEnrichedRequest($params = array('period' => $period, 'idSite' => $idSite, 'date' => $date, 'segment' => $segment, 'token_auth' => $token_auth, 'enable_filter_excludelowpop' => 1, 'filter_excludelowpop_value' => -1)); $view->metrics = $config['metrics'] = $this->getMetrics($idSite, $period, $date, $token_auth); $config['svgBasePath'] = 'plugins/UserCountryMap/svg/'; $config['mapCssPath'] = 'plugins/UserCountryMap/stylesheets/map.css'; $view->config = json_encode($config); $view->noData = empty($config['visitsSummary']['nb_visits']); $view->continents = array('AF' => \Piwik\Plugins\UserCountry\continentTranslate('afr'), 'AS' => \Piwik\Plugins\UserCountry\continentTranslate('asi'), 'EU' => \Piwik\Plugins\UserCountry\continentTranslate('eur'), 'NA' => \Piwik\Plugins\UserCountry\continentTranslate('amn'), 'OC' => \Piwik\Plugins\UserCountry\continentTranslate('oce'), 'SA' => \Piwik\Plugins\UserCountry\continentTranslate('ams')); return $view->render(); }
function getContinent() { return \Piwik\Plugins\UserCountry\continentTranslate($this->getContinentCode()); }
/** * Returns an array describing a visitor using her last visits (uses a maximum of 100). * * @param int $idSite Site ID * @param bool|false|string $visitorId The ID of the visitor whose profile to retrieve. * @param bool|false|string $segment * @param bool $checkForLatLong If true, hasLatLong will appear in the output and be true if * one of the first 100 visits has a latitude/longitude. * @return array */ public function getVisitorProfile($idSite, $visitorId = false, $segment = false, $checkForLatLong = false) { Piwik::checkUserHasViewAccess($idSite); if ($visitorId === false) { $visitorId = $this->getMostRecentVisitorId($idSite, $segment); } $newSegment = ($segment === false ? '' : $segment . ';') . 'visitorId==' . $visitorId; $visits = $this->loadLastVisitorDetailsFromDatabase($idSite, $period = false, $date = false, $newSegment, $numVisitorsToFetch = self::VISITOR_PROFILE_MAX_VISITS_TO_AGGREGATE, $overrideVisitorId = false, $minTimestamp = false); $this->addFilterToCleanVisitors($visits, $idSite, $flat = false, $doNotFetchActions = false, $filterNow = true); if ($visits->getRowsCount() == 0) { return array(); } $isEcommerceEnabled = Site::isEcommerceEnabledFor($idSite); $result = array(); $result['totalVisits'] = 0; $result['totalVisitDuration'] = 0; $result['totalActions'] = 0; $result['totalSearches'] = 0; $result['totalPageViews'] = 0; $result['totalGoalConversions'] = 0; $result['totalConversionsByGoal'] = array(); if ($isEcommerceEnabled) { $result['totalEcommerceConversions'] = 0; $result['totalEcommerceRevenue'] = 0; $result['totalEcommerceItems'] = 0; $result['totalAbandonedCarts'] = 0; $result['totalAbandonedCartsRevenue'] = 0; $result['totalAbandonedCartsItems'] = 0; } $countries = array(); $continents = array(); $cities = array(); $siteSearchKeywords = array(); $pageGenerationTimeTotal = 0; // aggregate all requested visits info for total_* info foreach ($visits->getRows() as $visit) { ++$result['totalVisits']; $result['totalVisitDuration'] += $visit->getColumn('visitDuration'); $result['totalActions'] += $visit->getColumn('actions'); $result['totalGoalConversions'] += $visit->getColumn('goalConversions'); // individual goal conversions are stored in action details foreach ($visit->getColumn('actionDetails') as $action) { if ($action['type'] == 'goal') { // handle goal conversion $idGoal = $action['goalId']; $idGoalKey = 'idgoal=' . $idGoal; if (!isset($result['totalConversionsByGoal'][$idGoalKey])) { $result['totalConversionsByGoal'][$idGoalKey] = 0; } ++$result['totalConversionsByGoal'][$idGoalKey]; if (!empty($action['revenue'])) { if (!isset($result['totalRevenueByGoal'][$idGoalKey])) { $result['totalRevenueByGoal'][$idGoalKey] = 0; } $result['totalRevenueByGoal'][$idGoalKey] += $action['revenue']; } } else { if ($action['type'] == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_ORDER && $isEcommerceEnabled) { ++$result['totalEcommerceConversions']; $result['totalEcommerceRevenue'] += $action['revenue']; $result['totalEcommerceItems'] += $action['items']; } else { if ($action['type'] == Piwik::LABEL_ID_GOAL_IS_ECOMMERCE_CART && $isEcommerceEnabled) { ++$result['totalAbandonedCarts']; $result['totalAbandonedCartsRevenue'] += $action['revenue']; $result['totalAbandonedCartsItems'] += $action['items']; } } } if (isset($action['siteSearchKeyword'])) { $keyword = $action['siteSearchKeyword']; if (!isset($siteSearchKeywords[$keyword])) { $siteSearchKeywords[$keyword] = 0; ++$result['totalSearches']; } ++$siteSearchKeywords[$keyword]; } if (isset($action['generationTime'])) { $pageGenerationTimeTotal += $action['generationTime']; ++$result['totalPageViews']; } } $countryCode = $visit->getColumn('countryCode'); if (!isset($countries[$countryCode])) { $countries[$countryCode] = 0; } ++$countries[$countryCode]; $continentCode = $visit->getColumn('continentCode'); if (!isset($continents[$continentCode])) { $continents[$continentCode] = 0; } ++$continents[$continentCode]; if ($countryCode && !array_key_exists($countryCode, $cities)) { $cities[$countryCode] = array(); } $city = $visit->getColumn('city'); if (!empty($city)) { $cities[$countryCode][] = $city; } } // sort countries/continents/search keywords by visit/action asort($countries); asort($continents); arsort($siteSearchKeywords); // transform country/continents/search keywords into something that will look good in XML $result['countries'] = $result['continents'] = $result['searches'] = array(); foreach ($countries as $countryCode => $nbVisits) { $countryInfo = array('country' => $countryCode, 'nb_visits' => $nbVisits, 'flag' => \Piwik\Plugins\UserCountry\getFlagFromCode($countryCode), 'prettyName' => \Piwik\Plugins\UserCountry\countryTranslate($countryCode)); if (!empty($cities[$countryCode])) { $countryInfo['cities'] = array_unique($cities[$countryCode]); } $result['countries'][] = $countryInfo; } foreach ($continents as $continentCode => $nbVisits) { $result['continents'][] = array('continent' => $continentCode, 'nb_visits' => $nbVisits, 'prettyName' => \Piwik\Plugins\UserCountry\continentTranslate($continentCode)); } foreach ($siteSearchKeywords as $keyword => $searchCount) { $result['searches'][] = array('keyword' => $keyword, 'searches' => $searchCount); } if ($result['totalPageViews']) { $result['averagePageGenerationTime'] = round($pageGenerationTimeTotal / $result['totalPageViews'], $precision = 2); } $result['totalVisitDurationPretty'] = MetricsFormatter::getPrettyTimeFromSeconds($result['totalVisitDuration']); // use requested visits for first/last visit info $rows = $visits->getRows(); $result['firstVisit'] = $this->getVisitorProfileVisitSummary(end($rows)); $result['lastVisit'] = $this->getVisitorProfileVisitSummary(reset($rows)); // check if requested visits have lat/long if ($checkForLatLong) { $result['hasLatLong'] = false; foreach ($rows as $visit) { if ($visit->getColumn('latitude') !== false) { // realtime map only checks for latitude $result['hasLatLong'] = true; break; } } } // save count of visits we queries $result['visitsAggregated'] = count($rows); // use N most recent visits for last_visits $visits->deleteRowsOffset(self::VISITOR_PROFILE_MAX_VISITS_TO_SHOW); $result['lastVisits'] = $visits; // use the right date format for the pretty server date $timezone = Site::getTimezoneFor($idSite); foreach ($result['lastVisits']->getRows() as $visit) { $dateTimeVisitFirstAction = Date::factory($visit->getColumn('firstActionTimestamp'), $timezone); $datePretty = $dateTimeVisitFirstAction->getLocalized(self::VISITOR_PROFILE_DATE_FORMAT); $visit->setColumn('serverDatePrettyFirstAction', $datePretty); $dateTimePretty = $datePretty . ' ' . $visit->getColumn('serverTimePrettyFirstAction'); $visit->setColumn('serverDateTimePrettyFirstAction', $dateTimePretty); } $result['userId'] = $visit->getColumn('userId'); // get visitor IDs that are adjacent to this one in log_visit // TODO: make sure order of visitor ids is not changed if a returning visitor visits while the user is // looking at the popup. $latestVisitTime = reset($rows)->getColumn('lastActionDateTime'); $result['nextVisitorId'] = $this->getAdjacentVisitorId($idSite, $visitorId, $latestVisitTime, $segment, $getNext = true); $result['previousVisitorId'] = $this->getAdjacentVisitorId($idSite, $visitorId, $latestVisitTime, $segment, $getNext = false); /** * Triggered in the Live.getVisitorProfile API method. Plugins can use this event * to discover and add extra data to visitor profiles. * * For example, if an email address is found in a custom variable, a plugin could load the * gravatar for the email and add it to the visitor profile, causing it to display in the * visitor profile popup. * * The following visitor profile elements can be set to augment the visitor profile popup: * * - **visitorAvatar**: A URL to an image to display in the top left corner of the popup. * - **visitorDescription**: Text to be used as the tooltip of the avatar image. * * @param array &$visitorProfile The unaugmented visitor profile info. */ Piwik::postEvent('Live.getExtraVisitorDetails', array(&$result)); return $result; }
private function handleGeoLocationContinents() { // sort by visit/action asort($this->continents); foreach ($this->continents as $continentCode => $nbVisits) { $this->profile['continents'][] = array('continent' => $continentCode, 'nb_visits' => $nbVisits, 'prettyName' => \Piwik\Plugins\UserCountry\continentTranslate($continentCode)); } }