From d903c1f0be860bae5e48031baa6d0512a917dcbb Mon Sep 17 00:00:00 2001 From: mattab <matthieu.aubry@gmail.com> Date: Mon, 1 Sep 2014 15:33:07 +0200 Subject: [PATCH] Refs #3490 User ID Tracker is now working: - new user_id field to contain the raw user id value - new &uid= tracker api parameter - add userId to Live API output - added integration test --- core/Db/Schema/Mysql.php | 1 + core/Tracker/Request.php | 48 +++++- core/Tracker/Visit.php | 6 + core/Tracker/Visitor.php | 6 + core/Updates/2.7.0-b2.php | 35 +++++ core/Version.php | 2 +- libs/PiwikTracker/PiwikTracker.php | 36 ++++- plugins/Live/Visitor.php | 9 ++ .../Fixtures/FewVisitsWithSetVisitorId.php | 95 ------------ .../FewVisitsWithSetVisitorIdAndUserId.php | 145 ++++++++++++++++++ tests/PHPUnit/Impl/ApiTestConfig.php | 10 +- tests/PHPUnit/Impl/TestRequestResponse.php | 23 ++- .../TrackingAPISetVisitorIdTest.php | 15 +- ...sitorId__Live.getLastVisitsDetails_day.xml | 97 ++++++++++++ ...PI_SetVisitorId__VisitsSummary.get_day.xml | 12 +- 15 files changed, 422 insertions(+), 118 deletions(-) create mode 100644 core/Updates/2.7.0-b2.php delete mode 100644 tests/PHPUnit/Fixtures/FewVisitsWithSetVisitorId.php create mode 100644 tests/PHPUnit/Fixtures/FewVisitsWithSetVisitorIdAndUserId.php create mode 100644 tests/PHPUnit/Integration/expected/test_TrackingAPI_SetVisitorId__Live.getLastVisitsDetails_day.xml diff --git a/core/Db/Schema/Mysql.php b/core/Db/Schema/Mysql.php index 43a42f167d..1130c1b6bf 100644 --- a/core/Db/Schema/Mysql.php +++ b/core/Db/Schema/Mysql.php @@ -149,6 +149,7 @@ class Mysql implements SchemaInterface idvisitor BINARY(8) NOT NULL, visit_last_action_time DATETIME NOT NULL, config_id BINARY(8) NOT NULL, + user_id varchar(200) NULL, location_ip VARBINARY(16) NOT NULL, PRIMARY KEY(idvisit), INDEX index_idsite_config_datetime (idsite, config_id, visit_last_action_time), diff --git a/core/Tracker/Request.php b/core/Tracker/Request.php index 98057f6ccc..3ddd52951b 100644 --- a/core/Tracker/Request.php +++ b/core/Tracker/Request.php @@ -277,6 +277,7 @@ class Request 'cip' => array(false, 'string'), 'cdt' => array(false, 'string'), 'cid' => array(false, 'string'), + 'uid' => array(false, 'string'), // Actions / pages 'cs' => array(false, 'string'), @@ -436,21 +437,37 @@ class Request } /** - * Is the request for a known VisitorId, based on 1st party, 3rd party (optional) cookies or Tracking API forced Visitor ID + * 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? + * * @throws Exception */ public function getVisitorId() { $found = false; + // If User ID is set it takes precedence + $userId = $this->getForcedUserId(); + if(strlen($userId) > 0) { + $idVisitor = md5($userId); + $idVisitor = $this->truncateIdAsVisitorId($idVisitor); + Common::printDebug("Request will be recorded for this user_id = " . $userId . " (idvisitor = $idVisitor)"); + $found = true; + } + // Was a Visitor ID "forced" (@see Tracking API setVisitorId()) for this request? - $idVisitor = $this->getForcedVisitorId(); - if (!empty($idVisitor)) { - if (strlen($idVisitor) != Tracker::LENGTH_HEX_ID_STRING) { - throw new Exception("Visitor ID (cid) $idVisitor must be " . Tracker::LENGTH_HEX_ID_STRING . " characters long"); + if (!$found) { + $idVisitor = $this->getForcedVisitorId(); + if (!empty($idVisitor)) { + if (strlen($idVisitor) != Tracker::LENGTH_HEX_ID_STRING) { + throw new Exception("Visitor ID (cid) $idVisitor must be " . Tracker::LENGTH_HEX_ID_STRING . " characters long"); + } + Common::printDebug("Request will be recorded for this idvisitor = " . $idVisitor); + $found = true; } - Common::printDebug("Request will be recorded for this idvisitor = " . $idVisitor); - $found = true; } // - If set to use 3rd party cookies for Visit ID, read the cookie @@ -467,6 +484,7 @@ class Request } } } + // If a third party cookie was not found, we default to the first party cookie if (!$found) { $idVisitor = Common::getRequestVar('_id', '', 'string', $this->params); @@ -474,7 +492,7 @@ class Request } if ($found) { - $truncated = substr($idVisitor, 0, Tracker::LENGTH_HEX_ID_STRING); + $truncated = $this->truncateIdAsVisitorId($idVisitor); $binVisitorId = @Common::hex2bin($truncated); if (!empty($binVisitorId)) { return $binVisitorId; @@ -523,6 +541,11 @@ class Request return $this->forcedVisitorId; } + public function getForcedUserId() + { + return $this->getParam('uid'); + } + public function getPlugins() { static $pluginsInOrder = array('fla', 'java', 'dir', 'qt', 'realp', 'pdf', 'wma', 'gears', 'ag', 'cookie'); @@ -550,4 +573,13 @@ class Request } return false; } + + /** + * @param $idVisitor + * @return string + */ + private function truncateIdAsVisitorId($idVisitor) + { + return substr($idVisitor, 0, Tracker::LENGTH_HEX_ID_STRING); + } } diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php index 90b58a88b0..793cfefb1c 100644 --- a/core/Tracker/Visit.php +++ b/core/Tracker/Visit.php @@ -497,6 +497,7 @@ class Visit implements VisitInterface 'idvisitor' => $this->getVisitorIdcookie($visitor), 'config_id' => $this->getSettingsObject()->getConfigId(), 'location_ip' => $this->getVisitorIp(), + 'user_id' => $this->request->getForcedUserId(), ); } @@ -518,6 +519,11 @@ class Visit implements VisitInterface $visitor->setVisitorColumn('idvisitor', $this->visitorInfo['idvisitor']); } + if (strlen($this->request->getForcedUserId()) > 0) { + $valuesToUpdate['user_id'] = $this->request->getForcedUserId(); + $visitor->setVisitorColumn('user_id', $valuesToUpdate['user_id']); + } + $dimensions = $this->getAllVisitDimensions(); $valuesToUpdate = $this->triggerHookOnDimensions($dimensions, 'onExistingVisit', $visitor, $action, $valuesToUpdate); diff --git a/core/Tracker/Visitor.php b/core/Tracker/Visitor.php index 70fb165f9b..3cc2275853 100644 --- a/core/Tracker/Visitor.php +++ b/core/Tracker/Visitor.php @@ -236,8 +236,12 @@ class Visitor // If a &cid= was set, we force to select this visitor (or create a new one) $isForcedVisitorIdMustMatch = ($this->request->getForcedVisitorId() != null); + // if &iud was set, we force to select this visitor (or create new one) + $isForcedUserIdMustMatch = ($this->request->getForcedUserId() != null); + $shouldMatchOneFieldOnly = (($isVisitorIdToLookup && $trustCookiesOnly) || $isForcedVisitorIdMustMatch + || $isForcedUserIdMustMatch || !$isVisitorIdToLookup); return $shouldMatchOneFieldOnly; } @@ -250,6 +254,8 @@ class Visitor $fields = array( 'idvisitor', 'idvisit', + 'user_id', + 'visit_exit_idaction_url', 'visit_exit_idaction_name', 'visitor_returning', diff --git a/core/Updates/2.7.0-b2.php b/core/Updates/2.7.0-b2.php new file mode 100644 index 0000000000..914d2ab65e --- /dev/null +++ b/core/Updates/2.7.0-b2.php @@ -0,0 +1,35 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + * + */ + +namespace Piwik\Updates; + +use Piwik\Common; +use Piwik\Updater; +use Piwik\Updates; + +/** + */ +class Updates_2_7_0_b2 extends Updates +{ + static function getSql() + { + return array( + 'ALTER TABLE `' . Common::prefixTable('log_visit') . '` + ADD `user_id` varchar(200) NULL AFTER `config_id` + ' => array(1060), + ); + } + + static function update() + { + // Run the SQL + Updater::updateDatabase(__FILE__, self::getSql()); + } +} + diff --git a/core/Version.php b/core/Version.php index 843a22004b..b91bb28685 100644 --- a/core/Version.php +++ b/core/Version.php @@ -21,5 +21,5 @@ final class Version * The current Piwik version. * @var string */ - const VERSION = '2.6.0-b1'; + const VERSION = '2.7.0-b2'; } diff --git a/libs/PiwikTracker/PiwikTracker.php b/libs/PiwikTracker/PiwikTracker.php index 3afc2db93a..02788cf224 100644 --- a/libs/PiwikTracker/PiwikTracker.php +++ b/libs/PiwikTracker/PiwikTracker.php @@ -196,6 +196,7 @@ class PiwikTracker $this->configReferralCookieTimeout = 15768000; // 6 months // Visitor Ids in order + $this->userId = false; $this->forcedVisitorId = false; $this->cookieVisitorId = false; $this->randomVisitorId = false; @@ -380,6 +381,7 @@ class PiwikTracker public function setNewVisitorId() { $this->randomVisitorId = substr(md5(uniqid(rand(), true)), 0, self::LENGTH_VISITOR_ID); + $this->userId = false; $this->forcedVisitorId = false; $this->cookieVisitorId = false; } @@ -975,6 +977,25 @@ class PiwikTracker $this->forcedVisitorId = $visitorId; } + + /** + * + * @param string $userId Any user ID string (eg. email address, ID, username). Must be non empty. Set to false to de-assign a user id previously set. + * @throws Exception + */ + public function setUserId($userId) + { + if($userId === '') { + throw new Exception("User ID cannot be empty."); + } + $this->userId = $userId; + } + + static public function getIdHashed($id) + { + return substr(md5( $id ), 0, 16); + } + /** * If the user initiating the request has the Piwik first party cookie, * this function will try and return the ID parsed from this first party cookie (found in $_COOKIE). @@ -989,13 +1010,21 @@ class PiwikTracker */ public function getVisitorId() { + if (!empty($this->userId)) { + return $this->getIdHashed($this->userId); + } if (!empty($this->forcedVisitorId)) { return $this->forcedVisitorId; - } else if ($this->loadVisitorIdCookie()) { + } + if ($this->loadVisitorIdCookie()) { return $this->cookieVisitorId; - } else { - return $this->randomVisitorId; } + return $this->randomVisitorId; + } + + public function getUserId() + { + return $this->userId; } /** @@ -1308,6 +1337,7 @@ class PiwikTracker // Only allowed for Super User, token_auth required, (!empty($this->ip) ? '&cip=' . $this->ip : '') . + (!empty($this->userId) ? '&uid=' . $this->userId : '') . (!empty($this->forcedVisitorId) ? '&cid=' . $this->forcedVisitorId : '&_id=' . $this->getVisitorId()) . (!empty($this->forcedDatetime) ? '&cdt=' . urlencode($this->forcedDatetime) : '') . (!empty($this->forcedNewVisit) ? '&new_visit=1' : '') . diff --git a/plugins/Live/Visitor.php b/plugins/Live/Visitor.php index b03d37e650..b9153a374d 100644 --- a/plugins/Live/Visitor.php +++ b/plugins/Live/Visitor.php @@ -39,6 +39,7 @@ class Visitor implements VisitorInterface 'idSite' => $this->getIdSite(), 'idVisit' => $this->getIdVisit(), 'visitIp' => $this->getIp(), + 'userId' => $this->getUserId(), 'visitorId' => $this->getVisitorId(), // => false are placeholders to be filled in API later @@ -84,6 +85,14 @@ class Visitor implements VisitorInterface return false; } + function getUserId() + { + if (!is_null($this->details['user_id'])) { + return $this->details['user_id']; + } + return false; + } + function getVisitServerHour() { return date('G', strtotime($this->details['visit_last_action_time'])); diff --git a/tests/PHPUnit/Fixtures/FewVisitsWithSetVisitorId.php b/tests/PHPUnit/Fixtures/FewVisitsWithSetVisitorId.php deleted file mode 100644 index 8d895228b4..0000000000 --- a/tests/PHPUnit/Fixtures/FewVisitsWithSetVisitorId.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php -/** - * Piwik - free/libre analytics platform - * - * @link http://piwik.org - * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later - */ -namespace Piwik\Tests\Fixtures; - -use Piwik\Date; -use Piwik\Tracker\Visit; -use Piwik\Tests\Fixture; -use PiwikTracker; -use Exception; - -/** - * Adds one site and tracks a couple visits using a custom visitor ID. - */ -class FewVisitsWithSetVisitorId extends Fixture -{ - public $idSite = 1; - public $dateTime = '2010-03-06 11:22:33'; - - public function setUp() - { - $this->setUpWebsitesAndGoals(); - $this->trackVisits(); - } - - public function tearDown() - { - // empty - } - - private function setUpWebsitesAndGoals() - { - // tests run in UTC, the Tracker in UTC - if (!self::siteCreated($idSite = 1)) { - self::createWebsite($this->dateTime); - } - } - - private function trackVisits() - { - $dateTime = $this->dateTime; - $idSite = $this->idSite; - - $t = self::getTracker($idSite, $dateTime, $defaultInit = true); - - // First, some basic tests - self::settingInvalidVisitorIdShouldThrow($t); - - // We create VISITOR A - $t->setUrl('http://example.org/index.htm'); - $t->setVisitorId(Visit::generateUniqueVisitorId()); - self::checkResponse($t->doTrackPageView('incredible title!')); - - // VISITOR B: few minutes later, we trigger the same tracker but with a custom visitor ID, - // => this will create a new visit B - $t->setForceVisitDateTime(Date::factory($dateTime)->addHour(0.05)->getDatetime()); - $t->setUrl('http://example.org/index2.htm'); - $t->setVisitorId(Visit::generateUniqueVisitorId()); - self::checkResponse($t->doTrackPageView('incredible title!')); - - // This new visit B will have 2 page views - $t->setForceVisitDateTime(Date::factory($dateTime)->addHour(0.1)->getDatetime()); - $t->setUrl('http://example.org/index3.htm'); - self::checkResponse($t->doTrackPageView('incredible title!')); - - // total = 2 visitors, 3 page views - - } - - private static function settingInvalidVisitorIdShouldThrow(PiwikTracker $t) - { - try { - $t->setVisitorId('test'); - $this->fail('should throw'); - } catch (Exception $e) { - //OK - } - try { - $t->setVisitorId('61e8'); - $this->fail('should throw'); - } catch (Exception $e) { - //OK - } - try { - $t->setVisitorId('61e8cc2d51fea26dabcabcabc'); - $this->fail('should throw'); - } catch (Exception $e) { - //OK - } - } -} \ No newline at end of file diff --git a/tests/PHPUnit/Fixtures/FewVisitsWithSetVisitorIdAndUserId.php b/tests/PHPUnit/Fixtures/FewVisitsWithSetVisitorIdAndUserId.php new file mode 100644 index 0000000000..5fd4260539 --- /dev/null +++ b/tests/PHPUnit/Fixtures/FewVisitsWithSetVisitorIdAndUserId.php @@ -0,0 +1,145 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +namespace Piwik\Tests\Fixtures; + +use Piwik\Date; +use Piwik\Tracker\Visit; +use Piwik\Tests\Fixture; +use PiwikTracker; +use Exception; + +/** + * Adds one site and tracks a couple visits using a custom visitor ID. + */ +class FewVisitsWithSetVisitorId extends Fixture +{ + public $idSite = 1; + public $dateTime = '2010-03-06 11:22:33'; + + public function setUp() + { + $this->setUpWebsitesAndGoals(); + $this->trackVisits_setVisitorId(); + $this->trackVisits_setUserId(); + } + + public function tearDown() + { + // empty + } + + private function setUpWebsitesAndGoals() + { + // tests run in UTC, the Tracker in UTC + if (!self::siteCreated($idSite = 1)) { + self::createWebsite($this->dateTime); + } + } + + private function trackVisits_setVisitorId() + { + // total = 2 visitors, 3 page views + $t = self::getTracker($this->idSite, $this->dateTime, $defaultInit = true); + + // First, some basic tests + self::settingInvalidVisitorIdShouldThrow($t); + + // We create VISITOR A + $t->setUrl('http://example.org/index.htm'); + $t->setVisitorId('a13b7c5a62f72dea'); + self::checkResponse($t->doTrackPageView('incredible title!')); + + // VISITOR B: few minutes later, we trigger the same tracker but with a custom visitor ID, + // => this will create a new visit B + $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.05)->getDatetime()); + $t->setUrl('http://example.org/index2.htm'); + $t->setVisitorId('f66bc315f2a01a79'); + self::checkResponse($t->doTrackPageView('incredible title!')); + + // This new visit B will have 2 page views + $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(0.1)->getDatetime()); + $t->setUrl('http://example.org/index3.htm'); + self::checkResponse($t->doTrackPageView('incredible title!')); + + } + + private function trackVisits_setUserId() + { + // total = 2 visitors, 3 page views + $t = self::getTracker($this->idSite, $this->dateTime, $defaultInit = true); + + // First, some basic tests + self::settingInvalidUserIdShouldThrow($t); + + // A NEW VISIT + // Setting both Visitor ID and User ID + // -> User ID takes precedence + $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(2)->getDatetime()); + $t->setUrl('http://example.org/index.htm'); + + // Set Visitor ID first. + $generatedVisitorId = '6ccebef4faef4969'; + $t->setVisitorId($generatedVisitorId); + $this->assertEquals($generatedVisitorId, $t->getVisitorId()); + + // Set User ID + $userId = 'email@example.com'; + $t->setUserId($userId); + $this->assertEquals($userId, $t->getUserId()); + + // User ID takes precedence over any previously set Visitor ID + $hashUserId = $t->getIdHashed($userId); + $this->assertEquals($hashUserId, $t->getVisitorId()); + + // Track a pageview with this user id + self::checkResponse($t->doTrackPageView('incredible title!')); + + // Track another pageview + $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(2.1)->getDatetime()); + self::checkResponse($t->doTrackPageView('second page')); + + + // A NEW VISIT + // Change User ID -> This will create a new visit + $t->setForceVisitDateTime(Date::factory($this->dateTime)->addHour(2.2)->getDatetime()); + $t->setUserId('new-email@example.com'); + self::checkResponse($t->doTrackPageView('a new user id was set -> new visit')); + } + + private static function settingInvalidVisitorIdShouldThrow(PiwikTracker $t) + { + try { + $t->setVisitorId('test'); + $this->fail('should throw'); + } catch (Exception $e) { + //OK + } + try { + $t->setVisitorId('61e8'); + $this->fail('should throw'); + } catch (Exception $e) { + //OK + } + try { + $t->setVisitorId('61e8cc2d51fea26dabcabcabc'); + $this->fail('should throw'); + } catch (Exception $e) { + //OK + } + } + + private static function settingInvalidUserIdShouldThrow(PiwikTracker $t) + { + try { + $t->setUserId(''); + $this->fail('should throw'); + } catch (Exception $e) { + //OK + } + } +} \ No newline at end of file diff --git a/tests/PHPUnit/Impl/ApiTestConfig.php b/tests/PHPUnit/Impl/ApiTestConfig.php index ecb778f536..a2dfab24d4 100644 --- a/tests/PHPUnit/Impl/ApiTestConfig.php +++ b/tests/PHPUnit/Impl/ApiTestConfig.php @@ -176,13 +176,21 @@ class ApiTestConfig public $xmlFieldsToRemove = false; /** - * If true, XML fields that change on each request for Live API methods are retained. + * If true, Date times XML fields that change on each request for Live API methods are retained. * Normally, they are removed before comparing the API response w/ expected. * * @param bool */ public $keepLiveDates = false; + /** + * If true, ID visitors/User ID/other IDs that change on each request for Live API methods are retained. + * Normally, they are removed before comparing the API response w/ expected. + * + * @param bool + */ + public $keepLiveIds = false; + /** * Constructor. Sets class properties using an associative array mapping property names w/ values. * diff --git a/tests/PHPUnit/Impl/TestRequestResponse.php b/tests/PHPUnit/Impl/TestRequestResponse.php index 9ce1a3da76..923e53088e 100644 --- a/tests/PHPUnit/Impl/TestRequestResponse.php +++ b/tests/PHPUnit/Impl/TestRequestResponse.php @@ -81,6 +81,10 @@ class TestRequestResponse private function normalizeApiResponse($apiResponse) { + if ($this->shouldDeleteLiveIds()) { + $this->removeAllIdsFromXml($apiResponse); + } + if ($this->shouldDeleteLiveDates()) { $apiResponse = $this->removeAllLiveDatesFromXml($apiResponse); } else if ($this->requestHasNonDeterministicDate()) { @@ -123,6 +127,17 @@ class TestRequestResponse return preg_replace("/idSubtable=[0-9]+/", 'idSubtable=', $apiResponse); } + private function removeAllIdsFromXml($apiResponse) + { + $toRemove = array( + 'visitorId', + 'nextVisitorId', + 'previousVisitorId', + ); + + return $this->removeXmlFields($apiResponse, $toRemove); + } + private function removeAllLiveDatesFromXml($apiResponse) { $toRemove = array( @@ -137,9 +152,6 @@ class TestRequestResponse 'serverTimePrettyFirstAction', 'goalTimePretty', 'serverTimePretty', - 'visitorId', - 'nextVisitorId', - 'previousVisitorId', 'visitServerHour', 'date', 'prettyDate', @@ -211,6 +223,11 @@ class TestRequestResponse || strpos($dateTime, 'now') !== false; } + private function shouldDeleteLiveIds() + { + return empty($this->params['keepLiveDates']); + } + private function shouldDeleteLiveDates() { return empty($this->params['keepLiveDates']) diff --git a/tests/PHPUnit/Integration/TrackingAPISetVisitorIdTest.php b/tests/PHPUnit/Integration/TrackingAPISetVisitorIdTest.php index 86885f513d..45c6fd038b 100644 --- a/tests/PHPUnit/Integration/TrackingAPISetVisitorIdTest.php +++ b/tests/PHPUnit/Integration/TrackingAPISetVisitorIdTest.php @@ -51,7 +51,20 @@ class TrackingAPISetVisitorIdTest extends IntegrationTestCase 'date' => self::$fixture->dateTime, 'periods' => 'day', 'testSuffix' => '', - )) + )), + + array('Live.getLastVisitsDetails', array('idSite' => self::$fixture->idSite, + 'date' => self::$fixture->dateTime, + 'periods' => 'day', + 'keepLiveIds' => true, + 'keepLiveDates' => true, + 'otherRequestParameters' => array( + 'showColumns' => 'idVisit,visitorId,userId,lastActionDateTime,actions,actionDetails', + 'filter_sort_column' => 'idVisit', + 'filter_sort_order' => 'asc', + ) + )), + ); } } diff --git a/tests/PHPUnit/Integration/expected/test_TrackingAPI_SetVisitorId__Live.getLastVisitsDetails_day.xml b/tests/PHPUnit/Integration/expected/test_TrackingAPI_SetVisitorId__Live.getLastVisitsDetails_day.xml new file mode 100644 index 0000000000..c5b8d05443 --- /dev/null +++ b/tests/PHPUnit/Integration/expected/test_TrackingAPI_SetVisitorId__Live.getLastVisitsDetails_day.xml @@ -0,0 +1,97 @@ +<?xml version="1.0" encoding="utf-8" ?> +<result> + <row> + <idVisit>1</idVisit> + <userId /> + <visitorId>a13b7c5a62f72dea</visitorId> + <actionDetails> + <row> + <type>action</type> + <url>http://example.org/index.htm</url> + <pageTitle>incredible title!</pageTitle> + <pageIdAction>2</pageIdAction> + <serverTimePretty>Sat 6 Mar 11:22:33</serverTimePretty> + <pageId>1</pageId> + <icon /> + </row> + </actionDetails> + <lastActionDateTime>2010-03-06 11:22:33</lastActionDateTime> + <actions>1</actions> + </row> + <row> + <idVisit>2</idVisit> + <userId /> + <visitorId>f66bc315f2a01a79</visitorId> + <actionDetails> + <row> + <type>action</type> + <url>http://example.org/index2.htm</url> + <pageTitle>incredible title!</pageTitle> + <pageIdAction>3</pageIdAction> + <serverTimePretty>Sat 6 Mar 11:25:33</serverTimePretty> + <pageId>2</pageId> + <timeSpent>180</timeSpent> + <timeSpentPretty>3 min 0s</timeSpentPretty> + <icon /> + </row> + <row> + <type>action</type> + <url>http://example.org/index3.htm</url> + <pageTitle>incredible title!</pageTitle> + <pageIdAction>4</pageIdAction> + <serverTimePretty>Sat 6 Mar 11:28:33</serverTimePretty> + <pageId>3</pageId> + <icon /> + </row> + </actionDetails> + <lastActionDateTime>2010-03-06 11:28:33</lastActionDateTime> + <actions>2</actions> + </row> + <row> + <idVisit>3</idVisit> + <userId>email@example.com</userId> + <visitorId>5658ffccee7f0ebf</visitorId> + <actionDetails> + <row> + <type>action</type> + <url>http://example.org/index.htm</url> + <pageTitle>incredible title!</pageTitle> + <pageIdAction>2</pageIdAction> + <serverTimePretty>Sat 6 Mar 13:22:33</serverTimePretty> + <pageId>4</pageId> + <timeSpent>360</timeSpent> + <timeSpentPretty>6 min 0s</timeSpentPretty> + <icon /> + </row> + <row> + <type>action</type> + <url>http://example.org/index.htm</url> + <pageTitle>second page</pageTitle> + <pageIdAction>2</pageIdAction> + <serverTimePretty>Sat 6 Mar 13:28:33</serverTimePretty> + <pageId>5</pageId> + <icon /> + </row> + </actionDetails> + <lastActionDateTime>2010-03-06 13:28:33</lastActionDateTime> + <actions>2</actions> + </row> + <row> + <idVisit>4</idVisit> + <userId>new-email@example.com</userId> + <visitorId>4b60563d119613fb</visitorId> + <actionDetails> + <row> + <type>action</type> + <url>http://example.org/index.htm</url> + <pageTitle>a new user id was set -> new visit</pageTitle> + <pageIdAction>2</pageIdAction> + <serverTimePretty>Sat 6 Mar 13:34:33</serverTimePretty> + <pageId>6</pageId> + <icon /> + </row> + </actionDetails> + <lastActionDateTime>2010-03-06 13:34:33</lastActionDateTime> + <actions>1</actions> + </row> +</result> \ No newline at end of file diff --git a/tests/PHPUnit/Integration/expected/test_TrackingAPI_SetVisitorId__VisitsSummary.get_day.xml b/tests/PHPUnit/Integration/expected/test_TrackingAPI_SetVisitorId__VisitsSummary.get_day.xml index 1076ef51ea..db02e17f0a 100644 --- a/tests/PHPUnit/Integration/expected/test_TrackingAPI_SetVisitorId__VisitsSummary.get_day.xml +++ b/tests/PHPUnit/Integration/expected/test_TrackingAPI_SetVisitorId__VisitsSummary.get_day.xml @@ -1,13 +1,13 @@ <?xml version="1.0" encoding="utf-8" ?> <result> - <nb_uniq_visitors>2</nb_uniq_visitors> - <nb_visits>2</nb_visits> - <nb_actions>3</nb_actions> + <nb_uniq_visitors>4</nb_uniq_visitors> + <nb_visits>4</nb_visits> + <nb_actions>6</nb_actions> <nb_visits_converted>0</nb_visits_converted> - <bounce_count>1</bounce_count> - <sum_visit_length>181</sum_visit_length> + <bounce_count>2</bounce_count> + <sum_visit_length>542</sum_visit_length> <max_actions>2</max_actions> <bounce_rate>50%</bounce_rate> <nb_actions_per_visit>1.5</nb_actions_per_visit> - <avg_time_on_site>91</avg_time_on_site> + <avg_time_on_site>136</avg_time_on_site> </result> \ No newline at end of file -- GitLab