PageRenderTime 75ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 1ms

/tests/integration/Main.test.php

https://github.com/quarkness/piwik
PHP | 825 lines | 519 code | 124 blank | 182 comment | 12 complexity | 4339cfc557c0f9a1391858960a6c51ac MD5 | raw file
  1. <?php
  2. if(!defined('PIWIK_CONFIG_TEST_INCLUDED'))
  3. {
  4. require_once dirname(__FILE__)."/../../tests/config_test.php";
  5. }
  6. require_once PIWIK_INCLUDE_PATH . '/tests/core/Database.test.php';
  7. require_once PIWIK_INCLUDE_PATH . '/tests/integration/Integration.php';
  8. /**
  9. * Runs integration / acceptance tests
  10. *
  11. * The test calls the Piwik tracker with known sets of data, expected errors,
  12. * and can _test the output of the tracker beacon, as well as calling
  13. * all API functions and compare their XML output with the 'expected output'.
  14. *
  15. * If an algorithm changes in the Tracker or in the Archiving, tests can easily be run to check that
  16. * the output changes as expected (eg. More accurate browser detection, adding a new metric in the
  17. * API results, etc.
  18. *
  19. * @see Ideas for improvements http://dev.piwik.org/trac/ticket/1465
  20. */
  21. class Test_Piwik_Integration_Main extends Test_Integration
  22. {
  23. /*
  24. * Path where expected/processed output files are stored
  25. */
  26. public function getPathToTestDirectory()
  27. {
  28. return PIWIK_INCLUDE_PATH . '/tests/integration';
  29. }
  30. function test_ecommerceOrderWithItems()
  31. {
  32. $this->setApiNotToCall(array());
  33. $dateTime = '2011-04-05 00:11:42';
  34. $idSite = $this->createWebsite($dateTime, $ecommerce=1);
  35. $idSite2 = $this->createWebsite($dateTime);
  36. $idGoal = Piwik_Goals_API::getInstance()->addGoal($idSite, 'title match, triggered ONCE', 'title', 'incredible', 'contains', $caseSensitive=false, $revenue=10, $allowMultipleConversions = true);
  37. $idGoalStandard = $idGoal;
  38. $t = $this->getTracker($idSite, $dateTime, $defaultInit = true);
  39. // VISIT NO 1
  40. $t->setUrl( 'http://example.org/index.htm' );
  41. $category = 'Electronics & Cameras';
  42. $price = 1111.11111;
  43. // VIEW product page
  44. $t->setEcommerceView('SKU2', 'PRODUCT name', $category, $price);
  45. $t->setCustomVariable(5, 'VisitorType', 'NewLoggedOut', 'visit');
  46. $this->assertTrue($t->getCustomVariable(3, 'page') == array('_pks','SKU2'));
  47. $this->assertTrue($t->getCustomVariable(4, 'page') == array('_pkn','PRODUCT name'));
  48. $this->assertTrue($t->getCustomVariable(5, 'page') == array('_pkc',$category));
  49. $this->assertTrue($t->getCustomVariable(2, 'page') == array('_pkp',$price));
  50. $this->assertTrue($t->getCustomVariable(5, 'visit') == array('VisitorType','NewLoggedOut' ));
  51. $this->checkResponse($t->doTrackPageView( 'incredible title!'));
  52. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.1)->getDatetime());
  53. $t->setEcommerceView($sku = 'SKU VERY nice indeed', $name = 'PRODUCT name' , $category, $price=666);
  54. $this->checkResponse($t->doTrackPageView( 'Another Product page'));
  55. // Note: here testing to pass a timestamp to the tracking API rather than the datetime string
  56. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.2)->getTimestampUTC());
  57. $t->setEcommerceView($sku = 'SKU VERY nice indeed', $name = 'PRODUCT name' , '');
  58. $this->checkResponse($t->doTrackPageView( 'Another Product page with no category'));
  59. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.2)->getDatetime());
  60. $t->setEcommerceView($sku = 'SKU VERY nice indeed', $name = 'PRODUCT name' , $categories = array('Multiple Category 1', '', 0, 'Multiple Category 2', 'Electronics & Cameras', 'Multiple Category 4', 'Multiple Category 5', 'SHOULD NOT BE REPORTEDSSSSSSSSSSSSSSssssssssssssssssssssssssssstttttttttttttttttttttttuuuu!'));
  61. $this->checkResponse($t->doTrackPageView( 'Another Product page with multiple categories'));
  62. // VISIT NO 2
  63. // VIEW category page
  64. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(1.6)->getDatetime());
  65. $t->setEcommerceView('','', $category);
  66. $this->checkResponse($t->doTrackPageView( 'Looking at '.$category.' page with a page level custom variable'));
  67. // VIEW category page again
  68. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(1.7)->getDatetime());
  69. $t->setEcommerceView('','', $category);
  70. $this->checkResponse($t->doTrackPageView( 'Looking at '.$category.' page again'));
  71. // VIEW product page
  72. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(1.8)->getDatetime());
  73. $t->setEcommerceView($sku = 'SKU VERY nice indeed', $name = 'PRODUCT name' , $category = 'Electronics & Cameras', $price = 666);
  74. $this->checkResponse($t->doTrackPageView( 'Looking at product page'));
  75. // ADD TO CART
  76. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(1.9)->getDatetime());
  77. $t->setCustomVariable(3, 'VisitorName', 'Great name!', 'visit');
  78. $t->addEcommerceItem($sku = 'SKU VERY nice indeed', $name = 'PRODUCT name' , $category = 'Electronics & Cameras', $price = 500, $quantity = 1);
  79. $t->addEcommerceItem($sku = 'SKU VERY nice indeed', $name = 'PRODUCT name' , $category = 'Electronics & Cameras', $price = 500, $quantity = 2);
  80. $t->addEcommerceItem($sku = 'SKU WILL BE DELETED', $name = 'BLABLA DELETED' , $category = '', $price = 5000000, $quantity = 20);
  81. $this->checkResponse($t->doTrackEcommerceCartUpdate($grandTotal = 1000));
  82. // ORDER NO 1
  83. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(2)->getDatetime());
  84. $t->addEcommerceItem($sku = 'SKU VERY nice indeed', $name = 'PRODUCT name' , $categories, $price = 500, $quantity = 2);
  85. $t->addEcommerceItem($sku = 'ANOTHER SKU HERE', $name = 'PRODUCT name BIS' , $category = '', $price = 100, $quantity = 6);
  86. $this->checkResponse($t->doTrackEcommerceOrder($orderId = '937nsjusu 3894', $grandTotal = 1111.11, $subTotal = 1000, $tax = 111, $shipping = 0.11, $discount = 666));
  87. // ORDER NO 2
  88. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(2.1)->getDatetime());
  89. $t->addEcommerceItem($sku = 'SKU2', $name = 'Canon SLR' , $category = 'Electronics & Cameras', $price = 1500, $quantity = 1);
  90. // Product bought with empty category
  91. $t->addEcommerceItem($sku = 'SKU VERY nice indeed', $name = 'PRODUCT name' , '', $price = 11.22, $quantity = 1);
  92. // test to delete all custom vars, they should be copied from visits
  93. // This is a frequent use case: ecommerce shops tracking the order from backoffice
  94. // without passing the custom variable 1st party cookie along since it's not known by back office
  95. $visitorCustomVarSave = $t->visitorCustomVar;
  96. $t->visitorCustomVar = false;
  97. $this->checkResponse($t->doTrackEcommerceOrder($orderId = '1037nsjusu4s3894', $grandTotal = 2000, $subTotal = 1500, $tax = 400, $shipping = 100, $discount = 0));
  98. $t->visitorCustomVar = $visitorCustomVarSave;
  99. // ORDER SHOULD DEDUPE
  100. // Refresh the page with the receipt for the second order, should be ignored
  101. // we test that both the order, and the products, are not updated on subsequent "Receipt" views
  102. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(2.2)->getDatetime());
  103. $t->addEcommerceItem($sku = 'SKU2', $name = 'Canon SLR NOT!' , $category = 'Electronics & Cameras NOT!', $price = 15000000000, $quantity = 10000);
  104. $this->checkResponse($t->doTrackEcommerceOrder($orderId = '1037nsjusu4s3894', $grandTotal = 20000000, $subTotal = 1500, $tax = 400, $shipping = 100, $discount = 0));
  105. // Leave with an opened cart
  106. // No category
  107. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(2.3)->getDatetime());
  108. $t->addEcommerceItem($sku = 'SKU IN ABANDONED CART ONE', $name = 'PRODUCT ONE LEFT in cart' , $category = '', $price = 500.11111112, $quantity = 2);
  109. $this->checkResponse($t->doTrackEcommerceCartUpdate($grandTotal = 1000));
  110. // Record the same visit leaving twice an abandoned cart
  111. foreach(array(0, 5, 24) as $offsetHour)
  112. {
  113. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour($offsetHour + 2.4)->getDatetime());
  114. // Also recording an order the day after
  115. if($offsetHour >= 24)
  116. {
  117. $t->addEcommerceItem($sku = 'SKU2', $name = 'Canon SLR' , $category = 'Electronics & Cameras', $price = 1500, $quantity = 1);
  118. $this->checkResponse($t->doTrackEcommerceOrder($orderId = '1037nsjusu4s3894', $grandTotal = 20000000, $subTotal = 1500, $tax = 400, $shipping = 100, $discount = 0));
  119. }
  120. // VIEW PRODUCT PAGES
  121. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour($offsetHour + 2.5)->getDatetime());
  122. $t->setEcommerceView($sku = 'SKU VERY nice indeed', $name = 'PRODUCT THREE LEFT in cart' , $category = '', $price=999);
  123. $this->checkResponse($t->doTrackPageView("View product left in cart"));
  124. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour($offsetHour + 2.55)->getDatetime());
  125. $t->setEcommerceView($sku = 'SKU VERY nice indeed', $name = 'PRODUCT THREE LEFT in cart' , $category = '', $price=333);
  126. $this->checkResponse($t->doTrackPageView("View product left in cart"));
  127. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour($offsetHour + 2.6)->getDatetime());
  128. $t->setEcommerceView($sku = 'SKU IN ABANDONED CART TWO', $name = 'PRODUCT TWO LEFT in cart' , $category = 'Category TWO LEFT in cart');
  129. $this->checkResponse($t->doTrackPageView("View product left in cart"));
  130. // ABANDONED CART
  131. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour($offsetHour + 2.7)->getDatetime());
  132. $t->addEcommerceItem($sku = 'SKU IN ABANDONED CART ONE', $name = 'PRODUCT ONE LEFT in cart' , $category = '', $price = 500.11111112, $quantity = 1);
  133. $t->addEcommerceItem($sku = 'SKU IN ABANDONED CART TWO', $name = 'PRODUCT TWO LEFT in cart' , $category = 'Category TWO LEFT in cart', $price = 1000, $quantity = 2);
  134. $t->addEcommerceItem($sku = 'SKU VERY nice indeed', $name = 'PRODUCT THREE LEFT in cart' , $category = 'Electronics & Cameras', $price = 10, $quantity = 1);
  135. $this->checkResponse($t->doTrackEcommerceCartUpdate($grandTotal = 2510.11111112));
  136. }
  137. // One more Ecommerce order to check weekly archiving works fine on orders
  138. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour( 30.7 )->getDatetime());
  139. $t->addEcommerceItem($sku = 'TRIPOD SKU', $name = 'TRIPOD - bought day after' , $category = 'Tools', $price = 100, $quantity = 2);
  140. $this->checkResponse($t->doTrackEcommerceOrder($orderId = '666', $grandTotal = 240, $subTotal = 200, $tax = 20, $shipping = 20, $discount = 20));
  141. // One more Ecommerce order, without any product in it, because we still track orders without products
  142. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour( 30.8 )->getDatetime());
  143. $this->checkResponse($t->doTrackEcommerceOrder($orderId = '777', $grandTotal = 10000));
  144. // testing the same order in a different website should record
  145. $t = $this->getTracker($idSite2, $dateTime, $defaultInit = true);
  146. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour( 30.9 )->getDatetime());
  147. $t->addEcommerceItem($sku = 'TRIPOD SKU', $name = 'TRIPOD - bought day after' , $category = 'Tools', $price = 100, $quantity = 2);
  148. $this->checkResponse($t->doTrackEcommerceOrder($orderId = '777', $grandTotal = 250));
  149. //------------------------------------- End tracking
  150. // From Piwik 1.5, we hide Goals.getConversions and other get* methods via @ignore, but we ensure that they still work
  151. // This hack allows the API proxy to let us generate example URLs for the ignored functions
  152. Piwik_API_Proxy::getInstance()->hideIgnoredFunctions = false;
  153. $this->setApiToCall( array('VisitsSummary.get', 'VisitTime', 'CustomVariables.getCustomVariables', 'Live.getLastVisitsDetails', 'UserCountry', 'API.getProcessedReport', 'Goals.get', 'Goals.getConversions', 'Goals.getItemsSku', 'Goals.getItemsName', 'Goals.getItemsCategory' ) );
  154. $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime, $periods = array('day'));
  155. $this->setApiToCall( array('Goals.get', 'Goals.getItemsSku', 'Goals.getItemsName', 'Goals.getItemsCategory' ) );
  156. $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime, $periods = array('week'));
  157. // Abandoned carts calls
  158. $abandonedCarts = 1;
  159. $this->setApiToCall( array('Goals.getItemsSku', 'Goals.getItemsName', 'Goals.getItemsCategory') );
  160. $this->callGetApiCompareOutput(__FUNCTION__ . '_AbandonedCarts', 'xml', $idSite, $dateTime, $periods = array('day', 'week'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts);
  161. // test with multiple periods
  162. $this->callGetApiCompareOutput(__FUNCTION__ . 'multipleDates', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN=true);
  163. // test with multiple periods and multiple websites
  164. $this->callGetApiCompareOutput(__FUNCTION__ . 'multipleDates_andMultipleWebsites', 'xml', $idSites = "$idSite,$idSite2", $dateTime, $periods = array('day'), $setDateLastN=true);
  165. // test metadata products
  166. $this->setApiToCall( array('API.getProcessedReport' ) );
  167. $apiModule = 'Goals';
  168. $apiAction = 'getItemsSku';
  169. $this->callGetApiCompareOutput(__FUNCTION__ . '_Metadata_ItemsSku', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal = false, $apiModule, $apiAction);
  170. $apiModule = 'Goals';
  171. $apiAction = 'getItemsCategory';
  172. $this->callGetApiCompareOutput(__FUNCTION__ . '_Metadata_ItemsCategory', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal = false, $apiModule, $apiAction);
  173. // test metadata Goals.get for Ecommerce orders & Carts
  174. $idGoal = Piwik_Archive::LABEL_ECOMMERCE_ORDER;
  175. $apiModule = 'Goals';
  176. $apiAction = 'get';
  177. $this->callGetApiCompareOutput(__FUNCTION__ . '_Metadata_Goals.Get_Order', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal, $apiModule, $apiAction);
  178. $idGoal = Piwik_Archive::LABEL_ECOMMERCE_CART;
  179. $apiModule = 'Goals';
  180. $apiAction = 'get';
  181. $this->callGetApiCompareOutput(__FUNCTION__ . '_Metadata_Goals.Get_AbandonedCart', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal, $apiModule, $apiAction);
  182. // Normal standard goal
  183. $idGoal = $idGoalStandard;
  184. $this->callGetApiCompareOutput(__FUNCTION__ . '_Metadata_Goals.Get_NormalGoal', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal, $apiModule, $apiAction);
  185. // Non existing goal id should return error
  186. $idGoal = 'FAKE IDGOAL';
  187. $this->callGetApiCompareOutput(__FUNCTION__ . '_Metadata_Goals.Get_NotExistingGoal', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal, $apiModule, $apiAction);
  188. // While we're at it, test for a standard Metadata report with zero entries
  189. $apiModule = 'VisitTime';
  190. $apiAction = 'getVisitInformationPerServerTime';
  191. $this->callGetApiCompareOutput(__FUNCTION__ . '_Metadata_VisitTime.getVisitInformationPerServerTime', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal = false, $apiModule, $apiAction);
  192. // Standard non metadata Goals.get
  193. // test Goals.get with idGoal=ecommerceOrder and ecommerceAbandonedCart
  194. $this->setApiToCall( array('Goals.get') );
  195. $idGoal = Piwik_Archive::LABEL_ECOMMERCE_CART;
  196. $this->callGetApiCompareOutput(__FUNCTION__ . '_GoalAbandonedCart', 'xml', $idSite, $dateTime, $periods = array('day', 'week'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal);
  197. $idGoal = Piwik_Archive::LABEL_ECOMMERCE_ORDER;
  198. $this->callGetApiCompareOutput(__FUNCTION__ . '_GoalOrder', 'xml', $idSite, $dateTime, $periods = array('day', 'week'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal);
  199. $idGoal = 1;
  200. $this->callGetApiCompareOutput(__FUNCTION__ . '_GoalMatchTitle', 'xml', $idSite, $dateTime, $periods = array('day', 'week'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal);
  201. $idGoal = '';
  202. $this->callGetApiCompareOutput(__FUNCTION__ . '_GoalOverall', 'xml', $idSite, $dateTime, $periods = array('day', 'week'), $setDateLastN = false, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal);
  203. $this->setApiToCall( array('VisitsSummary.get') );
  204. $segment = 'visitEcommerceStatus==none';
  205. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentNoEcommerce', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment);
  206. $segment = 'visitEcommerceStatus==ordered,visitEcommerceStatus==orderedThenAbandonedCart';
  207. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentOrderedSomething', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment);
  208. $segment = 'visitEcommerceStatus==abandonedCart,visitEcommerceStatus==orderedThenAbandonedCart';
  209. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentAbandonedCart', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment);
  210. // test segment visitConvertedGoalId
  211. $segment = 'visitConvertedGoalId=='.$idGoalStandard;
  212. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentConvertedGoalId1', 'xml', $idSite, $dateTime, $periods = array('day','week'), $setDateLastN = false, $language = false, $segment);
  213. $segment = 'visitConvertedGoalId!='.$idGoalStandard;
  214. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentDidNotConvertGoalId1', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment);
  215. // test segment visitorType
  216. $segment = 'visitorType==new';
  217. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentNewVisitors', 'xml', $idSite, $dateTime, $periods = array('week'), $setDateLastN = false, $language = false, $segment);
  218. $segment = 'visitorType==returning';
  219. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentReturningVisitors', 'xml', $idSite, $dateTime, $periods = array('week'), $setDateLastN = false, $language = false, $segment);
  220. $segment = 'visitorType==returningCustomer';
  221. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentReturningCustomers', 'xml', $idSite, $dateTime, $periods = array('week'), $setDateLastN = false, $language = false, $segment);
  222. // test segment pageTitle
  223. $segment = 'pageTitle==incredible%20title!';
  224. $this->callGetApiCompareOutput(__FUNCTION__ . '_SegmentPageTitleMatch', 'xml', $idSite, $dateTime, $periods = array('day'), $setDateLastN = false, $language = false, $segment);
  225. // test Live! output is OK also for the visit that just bought something (other visits leave an abandoned cart)
  226. $this->setApiToCall(array('Live.getLastVisitsDetails'));
  227. $this->callGetApiCompareOutput(__FUNCTION__ . '_LiveEcommerceStatusOrdered', 'xml', $idSite, Piwik_Date::factory($dateTime)->addHour( 30.65 )->getDatetime(), $periods = array('day'));
  228. // test API.get method
  229. $this->setApiToCall(array('API.get'));
  230. $this->callGetApiCompareOutput(__FUNCTION__ . '_API_get', 'xml', $idSite, $dateTime,
  231. $periods = array('day', 'week'), $setDateLastN = false, $language = false,
  232. $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal = false,
  233. $apiModule = false, $apiAction = false, $otherParams = array(
  234. 'columns' => 'nb_pageviews,nb_visits,avg_time_on_site,nb_visits_converted'));
  235. // Website2
  236. $this->setApiToCall( array('Goals.get', 'Goals.getItemsSku', 'Goals.getItemsName', 'Goals.getItemsCategory' ) );
  237. $this->callGetApiCompareOutput(__FUNCTION__ . '_Website2', 'xml', $idSite2, $dateTime, $periods = array('week'));
  238. }
  239. function test_trackGoals_allowMultipleConversionsPerVisit()
  240. {
  241. $this->setApiToCall(array(
  242. 'VisitTime.getVisitInformationPerServerTime',
  243. 'VisitsSummary.get',
  244. ));
  245. $dateTime = '2009-01-04 00:11:42';
  246. $idSite = $this->createWebsite($dateTime);
  247. // First, a goal that is only recorded once per visit
  248. $allowMultipleConversions = false;
  249. $idGoal_OneConversionPerVisit = Piwik_Goals_API::getInstance()->addGoal($idSite, 'triggered js ONCE', 'title', 'Thank you', 'contains', $caseSensitive=false, $revenue=10, $allowMultipleConversions);
  250. // Second, a goal allowing multiple conversions
  251. $allowMultipleConversions = true;
  252. $defaultRevenue = 10;
  253. $idGoal_MultipleConversionPerVisit = Piwik_Goals_API::getInstance()->addGoal($idSite, 'triggered js MULTIPLE ALLOWED', 'manually', '', '', $caseSensitive=false, $defaultRevenue, $allowMultipleConversions);
  254. $t = $this->getTracker($idSite, $dateTime, $defaultInit = true);
  255. // Record 1st goal, should only have 1 conversion
  256. $t->setUrl( 'http://example.org/index.htm' );
  257. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.3)->getDatetime());
  258. $this->checkResponse($t->doTrackPageView('Thank you mate'));
  259. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.4)->getDatetime());
  260. $this->checkResponse($t->doTrackGoal($idGoal_OneConversionPerVisit, $revenue = 10000000));
  261. // Record 2nd goal, should record both conversions
  262. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.5)->getDatetime());
  263. $this->checkResponse($t->doTrackGoal($idGoal_MultipleConversionPerVisit, $revenue = 300));
  264. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.6)->getDatetime());
  265. $this->checkResponse($t->doTrackGoal($idGoal_MultipleConversionPerVisit, $revenue = 366));
  266. // Update & set to not allow multiple
  267. $goals = Piwik_Goals_API::getInstance()->getGoals($idSite);
  268. $goal = $goals[$idGoal_OneConversionPerVisit];
  269. $this->assertTrue($goal['allow_multiple'] == 0);
  270. Piwik_Goals_API::getInstance()->updateGoal($idSite, $idGoal_OneConversionPerVisit, $goal['name'], @$goal['match_attribute'], @$goal['pattern'], @$goal['pattern_type'], @$goal['case_sensitive'], $goal['revenue'], $goal['allow_multiple'] = 1);
  271. $this->assertTrue($goal['allow_multiple'] == 1);
  272. // 1st goal should Now be tracked
  273. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.61)->getDatetime());
  274. $this->checkResponse($t->doTrackGoal($idGoal_OneConversionPerVisit, $revenue = 656));
  275. // Compare XML
  276. $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime);
  277. // test delete is working as expected
  278. $goals = Piwik_Goals_API::getInstance()->getGoals($idSite);
  279. $this->assertTrue( 2 == count($goals) );
  280. Piwik_Goals_API::getInstance()->deleteGoal($idSite, $idGoal_OneConversionPerVisit);
  281. Piwik_Goals_API::getInstance()->deleteGoal($idSite, $idGoal_MultipleConversionPerVisit);
  282. $goals = Piwik_Goals_API::getInstance()->getGoals($idSite);
  283. $this->assertTrue( empty($goals) );
  284. }
  285. /**
  286. * This tests the output of the API plugin API
  287. * It will return metadata about all API reports from all plugins
  288. * as well as the data itself, pre-processed and ready to be displayed
  289. * @return
  290. */
  291. function test_apiGetReportMetadata()
  292. {
  293. $this->setApiNotToCall(array());
  294. $this->setApiToCall( 'API' );
  295. $dateTime = '2009-01-04 00:11:42';
  296. $idSite = $this->createWebsite($dateTime, $ecommerce = 1);
  297. $idGoal = Piwik_Goals_API::getInstance()->addGoal($idSite, 'Goal 1 - Thank you', 'title', 'Thank you', 'contains', $caseSensitive=false, $revenue=10, $allowMultipleConversions = 1);
  298. $idGoal2 = Piwik_Goals_API::getInstance()->addGoal($idSite, 'Goal 2 - Hello', 'url', 'hellow', 'contains', $caseSensitive=false, $revenue=10, $allowMultipleConversions = 0);
  299. $t = $this->getTracker($idSite, $dateTime, $defaultInit = true);
  300. // Record 1st page view
  301. $t->setUrl( 'http://example.org/index.htm' );
  302. $this->checkResponse($t->doTrackPageView( 'incredible title!'));
  303. $idGoal = Piwik_Goals_API::getInstance()->addGoal($idSite, 'triggered js', 'manually', '', '');
  304. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.3)->getDatetime());
  305. $this->checkResponse($t->doTrackGoal($idGoal, $revenue = 42.256));
  306. $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime);
  307. }
  308. /**
  309. * test the Yearly metadata API response,
  310. * with no visits, with custom response language
  311. */
  312. function test_apiGetReportMetadata_year()
  313. {
  314. $this->setApiNotToCall(array());
  315. $this->setApiToCall( array('API.getProcessedReport',
  316. 'API.getReportMetadata',
  317. 'LanguagesManager.getTranslationsForLanguage',
  318. 'LanguagesManager.getAvailableLanguageNames',
  319. 'SitesManager.getJavascriptTag') );
  320. $dateTime = '2009-01-04 00:11:42';
  321. $idSite = $this->createWebsite($dateTime);
  322. $language = 'fr';
  323. $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime, 'year', $setDateLastN = false, $language);
  324. }
  325. /*
  326. * testing various wrong Tracker requests and check that they behave as expected:
  327. * not throwing errors and not recording data.
  328. *
  329. * API will archive and output empty stats.
  330. *
  331. */
  332. function test_noVisit()
  333. {
  334. $dateTime = '2009-01-04 00:11:42';
  335. $idSite = $this->createWebsite($dateTime);
  336. // Trigger invalid website
  337. $trackerInvalidWebsite = $this->getTracker($idSiteFake = 0, $dateTime, $defaultInit = true);
  338. $response = Piwik_Http::fetchRemoteFile($trackerInvalidWebsite->getUrlTrackPageView());
  339. $this->assertTrue(strpos($response, 'Invalid idSite') !== false, 'invalid website ID');
  340. // Trigger wrong website
  341. $trackerWrongWebsite = $this->getTracker($idSiteFake = 33, $dateTime, $defaultInit = true);
  342. $response = Piwik_Http::fetchRemoteFile($trackerWrongWebsite->getUrlTrackPageView());
  343. $this->assertTrue(strpos($response, 'The requested website id = 33 couldn\'t be found') !== false, 'non-existent website ID');
  344. // Trigger empty request
  345. $trackerUrl = $this->getTrackerUrl();
  346. $response = Piwik_Http::fetchRemoteFile($trackerUrl);
  347. $this->assertTrue(strpos($response, 'web analytics') !== false, 'Piwik empty request response not correct: ' . $response);
  348. $t = $this->getTracker($idSite, $dateTime, $defaultInit = true);
  349. // test GoogleBot UA visitor
  350. $t->setUserAgent('Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)');
  351. $this->checkResponse($t->doTrackPageView('bot visit, please do not record'));
  352. // test with excluded IP
  353. $t->setUserAgent('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.2.6) Gecko/20100625 Firefox/3.6.6 (.NET CLR 3.5.30729)'); // restore normal user agent
  354. $excludedIp = '154.1.12.34';
  355. Piwik_SitesManager_API::getInstance()->updateSite($idSite, 'new site name', $url=array('http://site.com'),$ecommerce = 0, $excludedIp . ',1.2.3.4');
  356. $t->setIp($excludedIp);
  357. $this->checkResponse($t->doTrackPageView('visit from IP excluded'));
  358. // test with global list of excluded IPs
  359. $excludedIpBis = '145.5.3.4';
  360. Piwik_SitesManager_API::getInstance()->setGlobalExcludedIps($excludedIpBis);
  361. $t->setIp($excludedIpBis);
  362. $this->checkResponse($t->doTrackPageView('visit from IP globally excluded'));
  363. try {
  364. @$t->setAttributionInfo(array());
  365. $this->fail();
  366. } catch(Exception $e) {}
  367. try {
  368. $t->setAttributionInfo(json_encode('test'));
  369. $this->fail();
  370. } catch(Exception $e) {}
  371. $t->setAttributionInfo(json_encode(array()));
  372. // this will output empty XML result sets as no visit was tracked
  373. $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime);
  374. $this->callGetApiCompareOutput(__FUNCTION__ . '_PeriodIsLast', 'xml', $idSite, $dateTime, $periods = array('day', 'week'), $setLastN = true);
  375. }
  376. /*
  377. * This use case covers many simple tracking features.
  378. * - Tracking Goal by manual trigger, and URL matching, with custom revenue
  379. * - Tracking the same Goal twice only records it once
  380. * - Tracks 2 page views, a click and a file download
  381. * - URLs parameters exclude is tested
  382. * - In a returning visit, tracks a Goal conversion
  383. * URL matching, with custom referer and keyword
  384. *
  385. * NO cookie support
  386. */
  387. function test_OneVisitorTwoVisits()
  388. {
  389. // tests run in UTC, the Tracker in UTC
  390. $dateTime = '2010-03-06 11:22:33';
  391. $idSite = $this->createWebsite($dateTime);
  392. $t = $this->getTracker($idSite, $dateTime, $defaultInit = true);
  393. $t->disableCookieSupport();
  394. $this->doTest_oneVisitorTwoVisits($t, $dateTime, $idSite );
  395. $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime);
  396. }
  397. /*
  398. * Same as before, but with cookie support, which incurs some slight changes
  399. * in the reporting data (more accurate unique visitor count, better referer tracking for goals, etc.)
  400. */
  401. function test_OneVisitorTwoVisits_withCookieSupport()
  402. {
  403. $this->setApiNotToCall(array());
  404. $this->setApiToCall(array('VisitTime', 'VisitsSummary', 'VisitorInterest', 'VisitFrequency', 'UserSettings', 'UserCountry', 'Referers', 'Provider', 'Goals', 'CustomVariables', 'CoreAdminHome', 'Actions', 'Live.getLastVisitsDetails'));
  405. // tests run in UTC, the Tracker in UTC
  406. $dateTime = '2010-03-06 11:22:33';
  407. $idSite = $this->createWebsite($dateTime);
  408. $t = $this->getTracker($idSite, $dateTime, $defaultInit = true, $useThirdPartyCookie = 1);
  409. $t->DEBUG_APPEND_URL = '&forceUseThirdPartyCookie=1';
  410. $this->doTest_oneVisitorTwoVisits($t, $dateTime, $idSite );
  411. $this->callGetApiCompareOutput(__FUNCTION__, 'xml', $idSite, $dateTime);
  412. }
  413. private function doTest_oneVisitorTwoVisits($t, $dateTime, $idSite )
  414. {
  415. $t->setUrlReferrer( 'http://referer.com/page.htm?param=valuewith some spaces');
  416. // testing URL excluded parameters
  417. $parameterToExclude = 'excluded_parameter';
  418. Piwik_SitesManager_API::getInstance()->updateSite($idSite, 'new name', $url=array('http://site.com'),$ecommerce = 0, $excludedIps = null, $parameterToExclude . ',anotherParameter');
  419. // Record 1st page view
  420. $urlPage1 = 'http://example.org/index.htm?excluded_Parameter=SHOULD_NOT_DISPLAY&parameter=Should display';
  421. $t->setUrl( $urlPage1 );
  422. $this->checkResponse($t->doTrackPageView( 'incredible title!'));
  423. // testing that / and index.htm above record with different URLs
  424. // Recording the 2nd page after 3 minutes
  425. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.05)->getDatetime());
  426. $urlPage2 = 'http://example.org/' ;
  427. $t->setUrl( $urlPage2 );
  428. // $t->setUrlReferrer($urlPage1);
  429. $this->checkResponse($t->doTrackPageView( 'Second page view - should be registered as URL /'));
  430. // $t->setUrlReferrer($urlPage2);
  431. // Click on external link after 6 minutes (3rd action)
  432. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.1)->getDatetime());
  433. $this->checkResponse($t->doTrackAction( 'http://dev.piwik.org/svn', 'link' ));
  434. // Click on file download after 12 minutes (4th action)
  435. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.2)->getDatetime());
  436. $this->checkResponse($t->doTrackAction( 'http://piwik.org/path/again/latest.zip', 'download' ));
  437. // Create Goal 1: Triggered by JS, after 18 minutes
  438. $idGoal = Piwik_Goals_API::getInstance()->addGoal($idSite, 'triggered js', 'manually', '', '');
  439. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.3)->getDatetime());
  440. $this->checkResponse($t->doTrackGoal($idGoal, $revenue = 42));
  441. // Track same Goal twice (after 24 minutes), should only be tracked once
  442. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.4)->getDatetime());
  443. $this->checkResponse($t->doTrackGoal($idGoal, $revenue = 42));
  444. // Final page view (after 27 min)
  445. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.45)->getDatetime());
  446. $t->setUrl( 'http://example.org/index.htm' );
  447. $this->checkResponse($t->doTrackPageView( 'Looking at homepage (again)...'));
  448. // -
  449. // End of first visit: 24min
  450. // Create Goal 2: Matching on URL
  451. Piwik_Goals_API::getInstance()->addGoal($idSite, 'matching purchase.htm', 'url', '(.*)store\/purchase\.(.*)', 'regex', false, $revenue = 1);
  452. // -
  453. // Start of returning visit, 1 hour after first page view
  454. $t->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(1)->getDatetime());
  455. $t->setUrl( 'http://example.org/store/purchase.htm' );
  456. $t->setUrlReferrer( 'http://search.yahoo.com/search?p=purchase');
  457. // Temporary, until we implement 1st party cookies in PiwikTracker
  458. $t->DEBUG_APPEND_URL = '&_idvc=2';
  459. // Goal Tracking URL matching, testing custom referer including keyword
  460. $this->checkResponse($t->doTrackPageView( 'Checkout/Purchasing...'));
  461. // -
  462. // End of second visit
  463. }
  464. /*
  465. * tests Tracker several websites, different days.
  466. * tests API for period=day/week/month/year, requesting data for both websites,
  467. * and requesting data for last N periods.
  468. * Also tests a visit that spans over 2 days.
  469. * And testing empty URL and empty Page name request
  470. * Also testing a click on a mailto counted as outlink
  471. * Also testing metadata API for multiple periods
  472. */
  473. function test_TwoVisitors_twoWebsites_differentDays()
  474. {
  475. $apiToCall = array('VisitFrequency.get',
  476. 'VisitsSummary.get',
  477. 'Referers.getWebsites',
  478. 'Actions.getPageUrls',
  479. 'Actions.getPageTitles',
  480. 'Actions.getOutlinks',
  481. 'Actions.getPageTitle',
  482. 'Actions.getPageUrl',
  483. 'VisitorInterest.getNumberOfVisitsByDaysSinceLast'
  484. );
  485. $this->doTest_TwoVisitors_twoWebsites_differentDays(__FUNCTION__, $apiToCall);
  486. }
  487. public function test_TwoVisitors_twoWebsites_differentDays_Conversions()
  488. {
  489. $apiToCall = array('Goals.getDaysToConversion');
  490. $this->doTest_TwoVisitors_twoWebsites_differentDays(__FUNCTION__, $apiToCall, true, false);
  491. }
  492. private function doTest_TwoVisitors_twoWebsites_differentDays(
  493. $function, $apiToCall, $allowConversions = false, $testGetProcessedReport = true)
  494. {
  495. $dateTime = '2010-01-03 11:22:33';
  496. $idSites = $this->setup_TwoVisitors_twoWebsites_differentDays($dateTime, $allowConversions);
  497. $this->setApiToCall($apiToCall);
  498. $periods = array('day', 'week', 'month', 'year');
  499. // Request data for the last 6 periods and idSite=all
  500. $this->callGetApiCompareOutput($function, 'xml', $allSites = 'all', $dateTime, $periods, $setDateLastN = true);
  501. // Request data for the last 6 periods and idSite=1
  502. $this->callGetApiCompareOutput($function.'_idSiteOne_', 'xml', $idSites[0], $dateTime, array('day','week','month','year'), $setDateLastN = true);
  503. // We also test a single period to check that this use case (Reports per idSite in the response) works
  504. $this->setApiToCall(array('VisitsSummary.get', 'Goals.get'));
  505. $this->callGetApiCompareOutput($function . '_NotLastNPeriods', 'xml', $allSites = 'all', $dateTime, array('day', 'month'), $setDateLastN = false);
  506. // testing metadata API for multiple periods
  507. $this->setApiNotToCall(array());
  508. if ($testGetProcessedReport)
  509. {
  510. $this->setApiToCall( array('API.getProcessedReport' ) );
  511. }
  512. $apiToCall = array_diff($apiToCall, array('Actions.getPageTitle', 'Actions.getPageUrl'));
  513. foreach($apiToCall as $api)
  514. {
  515. list($apiModule, $apiAction) = explode(".", $api);
  516. $this->callGetApiCompareOutput($function . '_'.$api.'_firstSite_lastN', 'xml', $idSites[0], $dateTime, $periods = array('day'), $setDateLastN = true, $language = false, $segment = false, $visitorId = false, $abandonedCarts = false, $idGoal = false, $apiModule, $apiAction);
  517. }
  518. }
  519. private function setup_TwoVisitors_twoWebsites_differentDays($dateTime, $allowConversions = false)
  520. {
  521. // tests run in UTC, the Tracker in UTC
  522. $idSite = $this->createWebsite($dateTime);
  523. $idSite2 = $this->createWebsite($dateTime);
  524. if ($allowConversions)
  525. {
  526. Piwik_Goals_API::getInstance()->addGoal($idSite, 'all', 'url', 'http', 'contains');
  527. Piwik_Goals_API::getInstance()->addGoal($idSite2, 'all', 'url', 'http', 'contains');
  528. }
  529. // -
  530. // First visitor on Idsite 1: two page views
  531. $datetimeSpanOverTwoDays = '2010-01-03 23:55:00';
  532. $visitorA = $this->getTracker($idSite, $datetimeSpanOverTwoDays, $defaultInit = true);
  533. $visitorA->setUrlReferrer( 'http://referer.com/page.htm?param=valuewith some spaces');
  534. $visitorA->setUrl('http://example.org/index.htm');
  535. $visitorA->DEBUG_APPEND_URL = '&_idts='.Piwik_Date::factory($datetimeSpanOverTwoDays)->getTimestamp();
  536. $this->checkResponse($visitorA->doTrackPageView('first page view'));
  537. $visitorA->setForceVisitDateTime(Piwik_Date::factory($datetimeSpanOverTwoDays)->addHour(0.1)->getDatetime());
  538. // testing with empty URL and empty page title
  539. $visitorA->setUrl(' ');
  540. $this->checkResponse($visitorA->doTrackPageView(' '));
  541. // -
  542. // Second new visitor on Idsite 1: one page view
  543. $visitorB = $this->getTracker($idSite, $dateTime, $defaultInit = true);
  544. $visitorB->setIp('100.52.156.83');
  545. $visitorB->setResolution(800, 300);
  546. $visitorB->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(1)->getDatetime());
  547. $visitorB->setUrlReferrer( '' );
  548. $visitorB->setUserAgent('Opera/9.63 (Windows NT 5.1; U; en) Presto/2.1.1');
  549. $visitorB->setUrl('http://example.org/products');
  550. $visitorB->DEBUG_APPEND_URL = '&_idts='.Piwik_Date::factory($dateTime)->addHour(1)->getTimestamp();
  551. $this->checkResponse($visitorB->doTrackPageView('first page view'));
  552. // -
  553. // Second visitor again on Idsite 1: 2 page views 2 days later, 2010-01-05
  554. $visitorB->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(48)->getDatetime());
  555. // visitor_returning is set to 1 only when visit count more than 1
  556. // Temporary, until we implement 1st party cookies in PiwikTracker
  557. $visitorB->DEBUG_APPEND_URL .= '&_idvc=2&_viewts='.Piwik_Date::factory($dateTime)->getTimestamp();
  558. $visitorB->setUrlReferrer( 'http://referer.com/Other_Page.htm' );
  559. $visitorB->setUrl('http://example.org/index.htm');
  560. $this->checkResponse($visitorB->doTrackPageView('second visitor/two days later/a new visit'));
  561. // Second page view 6 minutes later
  562. $visitorB->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(48)->addHour(0.1)->getDatetime());
  563. $visitorB->setUrl('http://example.org/thankyou');
  564. $this->checkResponse($visitorB->doTrackPageView('second visitor/two days later/second page view'));
  565. // testing a strange combination causing an error in r3767
  566. $visitorB->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(48)->addHour(0.2)->getDatetime());
  567. $this->checkResponse($visitorB->doTrackAction('mailto:test@example.org', 'link'));
  568. $visitorB->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(48)->addHour(0.25)->getDatetime());
  569. $this->checkResponse($visitorB->doTrackAction('mailto:test@example.org/strangelink', 'link'));
  570. // Actions.getPageTitle tested with this title
  571. $visitorB->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(48)->addHour(0.25)->getDatetime());
  572. $this->checkResponse($visitorB->doTrackPageView('Checkout / Purchasing...'));
  573. // -
  574. // First visitor on Idsite 2: one page view, with Website referer
  575. $visitorAsite2 = $this->getTracker($idSite2, Piwik_Date::factory($dateTime)->addHour(24)->getDatetime(), $defaultInit = true);
  576. $visitorAsite2->setUserAgent('Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0;)');
  577. $visitorAsite2->setUrlReferrer('http://only-homepage-referer.com/');
  578. $visitorAsite2->setUrl('http://example2.com/home');
  579. $visitorAsite2->DEBUG_APPEND_URL = '&_idts='.Piwik_Date::factory($dateTime)->addHour(24)->getTimestamp();
  580. $this->checkResponse($visitorAsite2->doTrackPageView('Website 2 page view'));
  581. // test with invalid URL
  582. $visitorAsite2->setUrl('this is invalid url');
  583. // and an empty title
  584. $this->checkResponse($visitorAsite2->doTrackPageView(''));
  585. // Returning visitor on Idsite 2 1 day later, one page view, with chinese referer
  586. // $t2->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(48 + 10)->getDatetime());
  587. // $t2->setUrlReferrer('http://www.baidu.com/s?wd=%D0%C2+%CE%C5&n=2');
  588. // $t2->setUrl('http://example2.com/home');
  589. // $this->checkResponse($t2->doTrackPageView('I\'m a returning visitor...'));
  590. return array($idSite, $idSite2);
  591. }
  592. public function test_TwoVisitors_twoWebsites_differentDays_ArchivingDisabled()
  593. {
  594. $apiToCall = array('VisitsSummary.get');
  595. $dateTime = '2010-01-03 11:22:33';
  596. $periods = array('day', 'week', 'month', 'year');
  597. $idSites = $this->setup_TwoVisitors_twoWebsites_differentDays($dateTime, false);
  598. $this->setApiToCall($apiToCall);
  599. // disable archiving & check that there is no archive data
  600. Piwik_ArchiveProcessing::$forceDisableArchiving = true;
  601. $this->callGetApiCompareOutput(__FUNCTION__ . '_disabledBefore', 'xml', $allSites = 'all', $dateTime, $periods);
  602. // re-enable archiving & check the output
  603. Piwik_ArchiveProcessing::$forceDisableArchiving = false;
  604. $this->callGetApiCompareOutput(__FUNCTION__ . '_enabled', 'xml', $allSites = 'all', $dateTime, $periods);
  605. // disable archiving again & check the output
  606. Piwik_ArchiveProcessing::$forceDisableArchiving = true;
  607. $this->callGetApiCompareOutput(__FUNCTION__ . '_disabledAfter', 'xml', $allSites = 'all', $dateTime, $periods);
  608. // re-enable archiving
  609. Piwik_ArchiveProcessing::$forceDisableArchiving = false;
  610. }
  611. private function doTest_twoVisitsWithCustomVariables($dateTime, $width=1111, $height=222)
  612. {
  613. // tests run in UTC, the Tracker in UTC
  614. $idSite = $this->createWebsite($dateTime);
  615. $this->setApiToCall(array( 'VisitsSummary.get',
  616. 'CustomVariables.getCustomVariables'
  617. ));
  618. ob_start();
  619. $idGoal = Piwik_Goals_API::getInstance()->addGoal($idSite, 'triggered js', 'manually', '', '');
  620. $idGoal2 = Piwik_Goals_API::getInstance()->addGoal($idSite, 'second goal', 'manually', '', '');
  621. $visitorA = $this->getTracker($idSite, $dateTime, $defaultInit = true);
  622. // Used to test actual referer + keyword position in Live!
  623. $visitorA->setUrlReferrer(urldecode('http://www.google.com/url?sa=t&source=web&cd=1&ved=0CB4QFjAA&url=http%3A%2F%2Fpiwik.org%2F&rct=j&q=this%20keyword%20should%20be%20ranked&ei=V8WfTePkKKLfiALrpZWGAw&usg=AFQjCNF_MGJRqKPvaKuUokHtZ3VvNG9ALw&sig2=BvKAdCtNixsmfNWXjsNyMw'));
  624. // no campaign, but a search engine to attribute the goal conversion to
  625. $attribution = array(
  626. '',
  627. '',
  628. 1302306504,
  629. 'http://www.google.com/search?q=piwik&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-GB:official&client=firefox-a'
  630. );
  631. $visitorA->setAttributionInfo(json_encode($attribution));
  632. $visitorA->setResolution($width, $height);
  633. // At first, visitor custom var is set to LoggedOut
  634. $visitorA->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.1)->getDatetime());
  635. $visitorA->setUrl('http://example.org/homepage');
  636. $visitorA->setCustomVariable($id = 1, $name = 'VisitorType', $value = 'LoggedOut');
  637. $this->checkResponse($visitorA->doTrackPageView('Homepage'));
  638. $this->checkResponse($visitorA->doTrackGoal($idGoal2));
  639. // After login, set to LoggedIn, should overwrite previous value
  640. $visitorA->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(0.2)->getDatetime());
  641. $visitorA->setUrl('http://example.org/user/profile');
  642. $visitorA->setCustomVariable($id = 1, $name = 'VisitorType', $value = 'LoggedIn');
  643. $visitorA->setCustomVariable($id = 4, $name = 'Status user', $value = 'Loggedin', $scope = 'page');
  644. $visitorA->setCustomVariable($id = 5, $name = 'Status user', $value = 'looking at profile page', $scope = 'page');
  645. $this->checkResponse($visitorA->doTrackPageView('Profile page'));
  646. $visitorA->setCustomVariable($id = 2, $name = 'SET WITH EMPTY VALUE', $value = '');
  647. $visitorA->setCustomVariable($id = 1, $name = 'Language', $value = 'FR', $scope = 'page');
  648. $visitorA->setCustomVariable($id = 2, $name = 'SET WITH EMPTY VALUE PAGE SCOPE', $value = '', $scope = 'page');
  649. $visitorA->setCustomVariable($id = 4, $name = 'Status user', $value = 'looking at profile page', $scope = 'page');
  650. $visitorA->setCustomVariable($id = 3, $name = 'Value will be VERY long and truncated', $value = 'abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----abcdefghijklmnopqrstuvwxyz----');
  651. $this->checkResponse($visitorA->doTrackPageView('Profile page'));
  652. $this->checkResponse($visitorA->doTrackGoal($idGoal));
  653. // -
  654. // Second new visitor on Idsite 1: one page view
  655. $visitorB = $this->getTracker($idSite, $dateTime, $defaultInit = true);
  656. $visitorB->setUrlReferrer('');
  657. $attribution = array(
  658. ' CAMPAIGN NAME -%20YEAH! ',
  659. ' CAMPAIGN%20KEYWORD - RIGHT... ',
  660. 1302306504,
  661. 'http://www.example.org/test/really?q=yes'
  662. );
  663. $visitorB->setAttributionInfo(json_encode($attribution));
  664. $visitorB->setResolution($width, $height);
  665. $visitorB->setUserAgent('Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.9.0.6) Gecko/2009011913 Firefox/3.0.6');
  666. $visitorB->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(1)->getDatetime());
  667. $visitorB->setCustomVariable($id = 1, $name = 'VisitorType', $value = 'LoggedOut');
  668. $visitorB->setCustomVariable($id = 2, $name = 'Othercustom value which should be truncated abcdefghijklmnopqrstuvwxyz', $value = 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz');
  669. $visitorB->setCustomVariable($id = -2, $name = 'not tracked', $value = 'not tracked');
  670. $visitorB->setCustomVariable($id = 6, $name = 'not tracked', $value = 'not tracked');
  671. $visitorB->setCustomVariable($id = 6, $name = array('not tracked'), $value = 'not tracked');
  672. $visitorB->setUrl('http://example.org/homepage');
  673. $this->checkResponse($visitorB->doTrackGoal($idGoal, 1000));
  674. // DIFFERENT test -
  675. // testing that starting the visit with an outlink works (doesn't trigger errors)
  676. $visitorB->setForceVisitDateTime(Piwik_Date::factory($dateTime)->addHour(2)->getDatetime());
  677. $this->checkResponse($visitorB->doTrackAction('http://test.com', 'link'));
  678. // hack
  679. $this->visitorId = $visitorB->getVisitorId();
  680. return $idSite;
  681. }
  682. function test_twoVisitsWithCustomVariables()
  683. {
  684. $dateTime = '2010-01-03 11:22:33';
  685. $this->doTest_twoVisitsWithCustomVariables($dateTime);
  686. $this->callGetApiCompareOutput(__FUNCTION__, 'xml',
  687. $idSite = 'all',
  688. $dateTime,
  689. $periods = array('day', 'week'),
  690. $setDateLastN = true);
  691. }
  692. function test_twoVisitsWithCustomVariables_segmentMatchVisitorType()
  693. {
  694. $dateTime = '2010-01-03 11:22:33';
  695. $this->doTest_twoVisitsWithCustomVariables($dateTime);
  696. // Segment matching some
  697. $segments = array(
  698. 'customVariableName1==VisitorType;customVariableValue1==LoggedIn',
  699. 'customVariableName1==VisitorType;customVariableValue1=@LoggedI',
  700. );
  701. // We run it twice just to check that running archiving twice for same input parameters doesn't cre