PageRenderTime 55ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/libs/PiwikTracker/PiwikTracker.php

https://github.com/quarkness/piwik
PHP | 994 lines | 525 code | 72 blank | 397 comment | 76 complexity | 98787faba628ea31c953fb9141ba8c08 MD5 | raw file
  1. <?php
  2. /**
  3. * Piwik - Open source web analytics
  4. *
  5. * Client to record visits, page views, Goals, Ecommerce activity (product views, add to carts, Ecommerce orders) in a Piwik server.
  6. * This is a PHP Version of the piwik.js standard Tracking API.
  7. * For more information, see http://piwik.org/docs/tracking-api/
  8. *
  9. * This class requires:
  10. * - json extension (json_decode, json_encode)
  11. * - CURL or STREAM extensions (to issue the http request to Piwik)
  12. *
  13. * @license released under BSD License http://www.opensource.org/licenses/bsd-license.php
  14. * @version $Id$
  15. * @link http://piwik.org/docs/tracking-api/
  16. *
  17. * @category Piwik
  18. * @package PiwikTracker
  19. */
  20. /**
  21. * @package PiwikTracker
  22. */
  23. class PiwikTracker
  24. {
  25. /**
  26. * Piwik base URL, for example http://example.org/piwik/
  27. * Must be set before using the class by calling
  28. * PiwikTracker::$URL = 'http://yourwebsite.org/piwik/';
  29. *
  30. * @var string
  31. */
  32. static public $URL = '';
  33. /**
  34. * API Version
  35. *
  36. * @ignore
  37. * @var int
  38. */
  39. const VERSION = 1;
  40. /**
  41. * @ignore
  42. */
  43. public $DEBUG_APPEND_URL = '';
  44. /**
  45. * Visitor ID length
  46. *
  47. * @ignore
  48. */
  49. const LENGTH_VISITOR_ID = 16;
  50. /**
  51. * Builds a PiwikTracker object, used to track visits, pages and Goal conversions
  52. * for a specific website, by using the Piwik Tracking API.
  53. *
  54. * @param int $idSite Id site to be tracked
  55. * @param string $apiUrl "http://example.org/piwik/" or "http://piwik.example.org/"
  56. * If set, will overwrite PiwikTracker::$URL
  57. */
  58. function __construct( $idSite, $apiUrl = false )
  59. {
  60. $this->cookieSupport = true;
  61. $this->userAgent = false;
  62. $this->localHour = false;
  63. $this->localMinute = false;
  64. $this->localSecond = false;
  65. $this->hasCookies = false;
  66. $this->plugins = false;
  67. $this->visitorCustomVar = false;
  68. $this->pageCustomVar = false;
  69. $this->customData = false;
  70. $this->forcedDatetime = false;
  71. $this->token_auth = false;
  72. $this->attributionInfo = false;
  73. $this->ecommerceLastOrderTimestamp = false;
  74. $this->ecommerceItems = array();
  75. $this->requestCookie = '';
  76. $this->idSite = $idSite;
  77. $this->urlReferrer = @$_SERVER['HTTP_REFERER'];
  78. $this->pageUrl = self::getCurrentUrl();
  79. $this->ip = @$_SERVER['REMOTE_ADDR'];
  80. $this->acceptLanguage = @$_SERVER['HTTP_ACCEPT_LANGUAGE'];
  81. $this->userAgent = @$_SERVER['HTTP_USER_AGENT'];
  82. if(!empty($apiUrl)) {
  83. self::$URL = $apiUrl;
  84. }
  85. $this->visitorId = substr(md5(uniqid(rand(), true)), 0, self::LENGTH_VISITOR_ID);
  86. }
  87. /**
  88. * Sets the current URL being tracked
  89. *
  90. * @param string Raw URL (not URL encoded)
  91. */
  92. public function setUrl( $url )
  93. {
  94. $this->pageUrl = $url;
  95. }
  96. /**
  97. * Sets the URL referrer used to track Referrers details for new visits.
  98. *
  99. * @param string Raw URL (not URL encoded)
  100. */
  101. public function setUrlReferrer( $url )
  102. {
  103. $this->urlReferrer = $url;
  104. }
  105. /**
  106. * @deprecated
  107. * @ignore
  108. */
  109. public function setUrlReferer( $url )
  110. {
  111. $this->setUrlReferrer($url);
  112. }
  113. /**
  114. * Sets the attribution information to the visit, so that subsequent Goal conversions are
  115. * properly attributed to the right Referrer URL, timestamp, Campaign Name & Keyword.
  116. *
  117. * This must be a JSON encoded string that would typically be fetched from the JS API:
  118. * piwikTracker.getAttributionInfo() and that you have JSON encoded via JSON2.stringify()
  119. *
  120. * @param string $jsonEncoded JSON encoded array containing Attribution info
  121. * @see function getAttributionInfo() in http://dev.piwik.org/trac/browser/trunk/js/piwik.js
  122. */
  123. public function setAttributionInfo( $jsonEncoded )
  124. {
  125. $decoded = json_decode($jsonEncoded, $assoc = true);
  126. if(!is_array($decoded))
  127. {
  128. throw new Exception("setAttributionInfo() is expecting a JSON encoded string, $jsonEncoded given");
  129. }
  130. $this->attributionInfo = $decoded;
  131. }
  132. /**
  133. * Sets Visit Custom Variable.
  134. * See http://piwik.org/docs/custom-variables/
  135. *
  136. * @param int Custom variable slot ID from 1-5
  137. * @param string Custom variable name
  138. * @param string Custom variable value
  139. * @param string Custom variable scope. Possible values: visit, page
  140. */
  141. public function setCustomVariable($id, $name, $value, $scope = 'visit')
  142. {
  143. if(!is_int($id))
  144. {
  145. throw new Exception("Parameter id to setCustomVariable should be an integer");
  146. }
  147. if($scope == 'page')
  148. {
  149. $this->pageCustomVar[$id] = array($name, $value);
  150. }
  151. elseif($scope == 'visit')
  152. {
  153. $this->visitorCustomVar[$id] = array($name, $value);
  154. }
  155. else
  156. {
  157. throw new Exception("Invalid 'scope' parameter value");
  158. }
  159. }
  160. /**
  161. * Returns the currently assigned Custom Variable stored in a first party cookie.
  162. *
  163. * This function will only work if the user is initiating the current request, and his cookies
  164. * can be read by PHP from the $_COOKIE array.
  165. *
  166. * @param int Custom Variable integer index to fetch from cookie. Should be a value from 1 to 5
  167. * @param string Custom variable scope. Possible values: visit, page
  168. *
  169. * @return array|false An array with this format: array( 0 => CustomVariableName, 1 => CustomVariableValue )
  170. * @see Piwik.js getCustomVariable()
  171. */
  172. public function getCustomVariable($id, $scope = 'visit')
  173. {
  174. if($scope == 'page')
  175. {
  176. return isset($this->pageCustomVar[$id]) ? $this->pageCustomVar[$id] : false;
  177. }
  178. else if($scope != 'visit')
  179. {
  180. throw new Exception("Invalid 'scope' parameter value");
  181. }
  182. if(!empty($this->visitorCustomVar[$id]))
  183. {
  184. return $this->visitorCustomVar[$id];
  185. }
  186. $customVariablesCookie = 'cvar.'.$this->idSite.'.';
  187. $cookie = $this->getCookieMatchingName($customVariablesCookie);
  188. if(!$cookie)
  189. {
  190. return false;
  191. }
  192. if(!is_int($id))
  193. {
  194. throw new Exception("Parameter to getCustomVariable should be an integer");
  195. }
  196. $cookieDecoded = json_decode($cookie, $assoc = true);
  197. if(!is_array($cookieDecoded)
  198. || !isset($cookieDecoded[$id])
  199. || !is_array($cookieDecoded[$id])
  200. || count($cookieDecoded[$id]) != 2)
  201. {
  202. return false;
  203. }
  204. return $cookieDecoded[$id];
  205. }
  206. /**
  207. * Sets the Browser language. Used to guess visitor countries when GeoIP is not enabled
  208. *
  209. * @param string For example "fr-fr"
  210. */
  211. public function setBrowserLanguage( $acceptLanguage )
  212. {
  213. $this->acceptLanguage = $acceptLanguage;
  214. }
  215. /**
  216. * Sets the user agent, used to detect OS and browser.
  217. * If this function is not called, the User Agent will default to the current user agent.
  218. *
  219. * @param string $userAgent
  220. */
  221. public function setUserAgent($userAgent)
  222. {
  223. $this->userAgent = $userAgent;
  224. }
  225. /**
  226. * Tracks a page view
  227. *
  228. * @param string $documentTitle Page title as it will appear in the Actions > Page titles report
  229. * @return string Response
  230. */
  231. public function doTrackPageView( $documentTitle )
  232. {
  233. $url = $this->getUrlTrackPageView($documentTitle);
  234. return $this->sendRequest($url);
  235. }
  236. /**
  237. * Records a Goal conversion
  238. *
  239. * @param int $idGoal Id Goal to record a conversion
  240. * @param int $revenue Revenue for this conversion
  241. * @return string Response
  242. */
  243. public function doTrackGoal($idGoal, $revenue = false)
  244. {
  245. $url = $this->getUrlTrackGoal($idGoal, $revenue);
  246. return $this->sendRequest($url);
  247. }
  248. /**
  249. * Tracks a download or outlink
  250. *
  251. * @param string $actionUrl URL of the download or outlink
  252. * @param string $actionType Type of the action: 'download' or 'link'
  253. * @return string Response
  254. */
  255. public function doTrackAction($actionUrl, $actionType)
  256. {
  257. // Referrer could be udpated to be the current URL temporarily (to mimic JS behavior)
  258. $url = $this->getUrlTrackAction($actionUrl, $actionType);
  259. return $this->sendRequest($url);
  260. }
  261. /**
  262. * Adds an item in the Ecommerce order.
  263. *
  264. * This should be called before doTrackEcommerceOrder(), or before doTrackEcommerceCartUpdate().
  265. * This function can be called for all individual products in the cart (or order).
  266. * SKU parameter is mandatory. Other parameters are optional (set to false if value not known).
  267. * Ecommerce items added via this function are automatically cleared when doTrackEcommerceOrder() or getUrlTrackEcommerceOrder() is called.
  268. *
  269. * @param string $sku (required) SKU, Product identifier
  270. * @param string $name (optional) Product name
  271. * @param string|array $category (optional) Product category, or array of product categories (up to 5 categories can be specified for a given product)
  272. * @param float|int $price (optional) Individual product price (supports integer and decimal prices)
  273. * @param int $quantity (optional) Product quantity. If not specified, will default to 1 in the Reports
  274. */
  275. public function addEcommerceItem($sku, $name = false, $category = false, $price = false, $quantity = false)
  276. {
  277. if(empty($sku))
  278. {
  279. throw new Exception("You must specify a SKU for the Ecommerce item");
  280. }
  281. $this->ecommerceItems[$sku] = array( $sku, $name, $category, $price, $quantity );
  282. }
  283. /**
  284. * Tracks a Cart Update (add item, remove item, update item).
  285. *
  286. * On every Cart update, you must call addEcommerceItem() for each item (product) in the cart,
  287. * including the items that haven't been updated since the last cart update.
  288. * Items which were in the previous cart and are not sent in later Cart updates will be deleted from the cart (in the database).
  289. *
  290. * @param float $grandTotal Cart grandTotal (typically the sum of all items' prices)
  291. */
  292. public function doTrackEcommerceCartUpdate($grandTotal)
  293. {
  294. $url = $this->getUrlTrackEcommerceCartUpdate($grandTotal);
  295. return $this->sendRequest($url);
  296. }
  297. /**
  298. * Tracks an Ecommerce order.
  299. *
  300. * If the Ecommerce order contains items (products), you must call first the addEcommerceItem() for each item in the order.
  301. * All revenues (grandTotal, subTotal, tax, shipping, discount) will be individually summed and reported in Piwik reports.
  302. * Only the parameters $orderId and $grandTotal are required.
  303. *
  304. * @param string|int $orderId (required) Unique Order ID.
  305. * This will be used to count this order only once in the event the order page is reloaded several times.
  306. * orderId must be unique for each transaction, even on different days, or the transaction will not be recorded by Piwik.
  307. * @param float $grandTotal (required) Grand Total revenue of the transaction (including tax, shipping, etc.)
  308. * @param float $subTotal (optional) Sub total amount, typically the sum of items prices for all items in this order (before Tax and Shipping costs are applied)
  309. * @param float $tax (optional) Tax amount for this order
  310. * @param float $shipping (optional) Shipping amount for this order
  311. * @param float $discount (optional) Discounted amount in this order
  312. */
  313. public function doTrackEcommerceOrder($orderId, $grandTotal, $subTotal = false, $tax = false, $shipping = false, $discount = false)
  314. {
  315. $url = $this->getUrlTrackEcommerceOrder($orderId, $grandTotal, $subTotal, $tax, $shipping, $discount);
  316. return $this->sendRequest($url);
  317. }
  318. /**
  319. * Sets the current page view as an item (product) page view, or an Ecommerce Category page view.
  320. *
  321. * This must be called before doTrackPageView() on this product/category page.
  322. * It will set 3 custom variables of scope "page" with the SKU, Name and Category for this page view.
  323. * Note: Custom Variables of scope "page" slots 3, 4 and 5 will be used.
  324. *
  325. * On a category page, you may set the parameter $category only and set the other parameters to false.
  326. *
  327. * Tracking Product/Category page views will allow Piwik to report on Product & Categories
  328. * conversion rates (Conversion rate = Ecommerce orders containing this product or category / Visits to the product or category)
  329. *
  330. * @param string $sku Product SKU being viewed
  331. * @param string $name Product Name being viewed
  332. * @param string|array $category Category being viewed. On a Product page, this is the product's category.
  333. * You can also specify an array of up to 5 categories for a given page view.
  334. * @param float $price Specify the price at which the item was displayed
  335. */
  336. public function setEcommerceView($sku = false, $name = false, $category = false, $price = false)
  337. {
  338. if(!empty($category)) {
  339. if(is_array($category)) {
  340. $category = json_encode($category);
  341. }
  342. } else {
  343. $category = "";
  344. }
  345. $this->pageCustomVar[5] = array('_pkc', $category);
  346. if(!empty($price)) {
  347. $this->pageCustomVar[2] = array('_pkp', (float)$price);
  348. }
  349. // On a category page, do not record "Product name not defined"
  350. if(empty($sku) && empty($name))
  351. {
  352. return;
  353. }
  354. if(!empty($sku)) {
  355. $this->pageCustomVar[3] = array('_pks', $sku);
  356. }
  357. if(empty($name)) {
  358. $name = "";
  359. }
  360. $this->pageCustomVar[4] = array('_pkn', $name);
  361. }
  362. /**
  363. * Returns URL used to track Ecommerce Cart updates
  364. * Calling this function will reinitializes the property ecommerceItems to empty array
  365. * so items will have to be added again via addEcommerceItem()
  366. * @ignore
  367. */
  368. public function getUrlTrackEcommerceCartUpdate($grandTotal)
  369. {
  370. $url = $this->getUrlTrackEcommerce($grandTotal);
  371. return $url;
  372. }
  373. /**
  374. * Returns URL used to track Ecommerce Orders
  375. * Calling this function will reinitializes the property ecommerceItems to empty array
  376. * so items will have to be added again via addEcommerceItem()
  377. * @ignore
  378. */
  379. public function getUrlTrackEcommerceOrder($orderId, $grandTotal, $subTotal = false, $tax = false, $shipping = false, $discount = false)
  380. {
  381. if(empty($orderId))
  382. {
  383. throw new Exception("You must specifiy an orderId for the Ecommerce order");
  384. }
  385. $url = $this->getUrlTrackEcommerce($grandTotal, $subTotal, $tax, $shipping, $discount);
  386. $url .= '&ec_id=' . urlencode($orderId);
  387. $this->ecommerceLastOrderTimestamp = $this->getTimestamp();
  388. return $url;
  389. }
  390. /**
  391. * Returns URL used to track Ecommerce orders
  392. * Calling this function will reinitializes the property ecommerceItems to empty array
  393. * so items will have to be added again via addEcommerceItem()
  394. * @ignore
  395. */
  396. protected function getUrlTrackEcommerce($grandTotal, $subTotal = false, $tax = false, $shipping = false, $discount = false)
  397. {
  398. if(!is_numeric($grandTotal))
  399. {
  400. throw new Exception("You must specifiy a grandTotal for the Ecommerce order (or Cart update)");
  401. }
  402. $url = $this->getRequest( $this->idSite );
  403. $url .= '&idgoal=0';
  404. if(!empty($grandTotal))
  405. {
  406. $url .= '&revenue='.$grandTotal;
  407. }
  408. if(!empty($subTotal))
  409. {
  410. $url .= '&ec_st='.$subTotal;
  411. }
  412. if(!empty($tax))
  413. {
  414. $url .= '&ec_tx='.$tax;
  415. }
  416. if(!empty($shipping))
  417. {
  418. $url .= '&ec_sh='.$shipping;
  419. }
  420. if(!empty($discount))
  421. {
  422. $url .= '&ec_dt='.$discount;
  423. }
  424. if(!empty($this->ecommerceItems))
  425. {
  426. // Removing the SKU index in the array before JSON encoding
  427. $items = array();
  428. foreach($this->ecommerceItems as $item)
  429. {
  430. $items[] = $item;
  431. }
  432. $url .= '&ec_items='. urlencode(json_encode($items));
  433. }
  434. $this->ecommerceItems = array();
  435. return $url;
  436. }
  437. /**
  438. * @see doTrackPageView()
  439. * @param string $documentTitle Page view name as it will appear in Piwik reports
  440. * @return string URL to piwik.php with all parameters set to track the pageview
  441. */
  442. public function getUrlTrackPageView( $documentTitle = false )
  443. {
  444. $url = $this->getRequest( $this->idSite );
  445. if(!empty($documentTitle)) {
  446. $url .= '&action_name=' . urlencode($documentTitle);
  447. }
  448. return $url;
  449. }
  450. /**
  451. * @see doTrackGoal()
  452. * @param int $idGoal Id Goal to record a conversion
  453. * @param int $revenue Revenue for this conversion
  454. * @return string URL to piwik.php with all parameters set to track the goal conversion
  455. */
  456. public function getUrlTrackGoal($idGoal, $revenue = false)
  457. {
  458. $url = $this->getRequest( $this->idSite );
  459. $url .= '&idgoal=' . $idGoal;
  460. if(!empty($revenue)) {
  461. $url .= '&revenue=' . $revenue;
  462. }
  463. return $url;
  464. }
  465. /**
  466. * @see doTrackAction()
  467. * @param string $actionUrl URL of the download or outlink
  468. * @param string $actionType Type of the action: 'download' or 'link'
  469. * @return string URL to piwik.php with all parameters set to track an action
  470. */
  471. public function getUrlTrackAction($actionUrl, $actionType)
  472. {
  473. $url = $this->getRequest( $this->idSite );
  474. $url .= '&'.$actionType.'=' . $actionUrl .
  475. '&redirect=0';
  476. return $url;
  477. }
  478. /**
  479. * Overrides server date and time for the tracking requests.
  480. * By default Piwik will track requests for the "current datetime" but this function allows you
  481. * to track visits in the past. All times are in UTC.
  482. *
  483. * Allowed only for Super User, must be used along with setTokenAuth()
  484. * Set tracking_requests_require_authentication = 0 in config.ini.php [Tracker] section
  485. * to change this security constraint.
  486. * @see setTokenAuth()
  487. * @param string Date with the format 'Y-m-d H:i:s', or a UNIX timestamp
  488. */
  489. public function setForceVisitDateTime($dateTime)
  490. {
  491. $this->forcedDatetime = $dateTime;
  492. }
  493. /**
  494. * Overrides IP address
  495. *
  496. * Allowed only for Super User, must be used along with setTokenAuth()
  497. * Set tracking_requests_require_authentication = 0 in config.ini.php [Tracker] section
  498. * to change this security constraint.
  499. * @see setTokenAuth()
  500. * @param string IP string, eg. 130.54.2.1
  501. */
  502. public function setIp($ip)
  503. {
  504. $this->ip = $ip;
  505. }
  506. /**
  507. * Forces the requests to be recorded for the specified Visitor ID
  508. * rather than using the heuristics based on IP and other attributes.
  509. *
  510. * This is typically used with the Javascript getVisitorId() function.
  511. *
  512. * Allowed only for Super User, must be used along with setTokenAuth().
  513. * Set tracking_requests_require_authentication = 0 in config.ini.php [Tracker] section
  514. * to change this security constraint.
  515. * @see setTokenAuth()
  516. * @param string $visitorId 16 hexadecimal characters visitor ID, eg. "33c31e01394bdc63"
  517. */
  518. public function setVisitorId($visitorId)
  519. {
  520. if(strlen($visitorId) != self::LENGTH_VISITOR_ID)
  521. {
  522. throw new Exception("setVisitorId() expects a ".self::LENGTH_VISITOR_ID." characters ID");
  523. }
  524. $this->forcedVisitorId = $visitorId;
  525. }
  526. /**
  527. * If the user initiating the request has the Piwik first party cookie,
  528. * this function will try and return the ID parsed from this first party cookie (found in $_COOKIE).
  529. *
  530. * If you call this function from a server, where the call is triggered by a cron or script
  531. * not initiated by the actual visitor being tracked, then it will return
  532. * the random Visitor ID that was assigned to this visit object.
  533. *
  534. * This can be used if you wish to record more visits, actions or goals for this visitor ID later on.
  535. *
  536. * @return string 16 hex chars visitor ID string
  537. */
  538. public function getVisitorId()
  539. {
  540. if(!empty($this->forcedVisitorId))
  541. {
  542. return $this->forcedVisitorId;
  543. }
  544. $idCookieName = 'id.'.$this->idSite.'.';
  545. $idCookie = $this->getCookieMatchingName($idCookieName);
  546. if($idCookie !== false)
  547. {
  548. $visitorId = substr($idCookie, 0, strpos($idCookie, '.'));
  549. if(strlen($visitorId) == self::LENGTH_VISITOR_ID)
  550. {
  551. return $visitorId;
  552. }
  553. }
  554. return $this->visitorId;
  555. }
  556. /**
  557. * Returns the currently assigned Attribution Information stored in a first party cookie.
  558. *
  559. * This function will only work if the user is initiating the current request, and his cookies
  560. * can be read by PHP from the $_COOKIE array.
  561. *
  562. * @return string JSON Encoded string containing the Referer information for Goal conversion attribution.
  563. * Will return false if the cookie could not be found
  564. * @see Piwik.js getAttributionInfo()
  565. */
  566. public function getAttributionInfo()
  567. {
  568. $attributionCookieName = 'ref.'.$this->idSite.'.';
  569. return $this->getCookieMatchingName($attributionCookieName);
  570. }
  571. /**
  572. * Some Tracking API functionnality requires express authentication, using either the
  573. * Super User token_auth, or a user with 'admin' access to the website.
  574. *
  575. * The following features require access:
  576. * - force the visitor IP
  577. * - force the date & time of the tracking requests rather than track for the current datetime
  578. * - force Piwik to track the requests to a specific VisitorId rather than use the standard visitor matching heuristic
  579. *
  580. * Set tracking_requests_require_authentication = 0 in config.ini.php [Tracker] section
  581. * to change this security constraint.
  582. * @param string token_auth 32 chars token_auth string
  583. */
  584. public function setTokenAuth($token_auth)
  585. {
  586. $this->token_auth = $token_auth;
  587. }
  588. /**
  589. * Sets local visitor time
  590. *
  591. * @param string $time HH:MM:SS format
  592. */
  593. public function setLocalTime($time)
  594. {
  595. list($hour, $minute, $second) = explode(':', $time);
  596. $this->localHour = (int)$hour;
  597. $this->localMinute = (int)$minute;
  598. $this->localSecond = (int)$second;
  599. }
  600. /**
  601. * Sets user resolution width and height.
  602. *
  603. * @param int $width
  604. * @param int $height
  605. */
  606. public function setResolution($width, $height)
  607. {
  608. $this->width = $width;
  609. $this->height = $height;
  610. }
  611. /**
  612. * Sets if the browser supports cookies
  613. * This is reported in "List of plugins" report in Piwik.
  614. *
  615. * @param bool $bool
  616. */
  617. public function setBrowserHasCookies( $bool )
  618. {
  619. $this->hasCookies = $bool ;
  620. }
  621. /**
  622. * Will append a custom string at the end of the Tracking request.
  623. * @param string $string
  624. */
  625. public function setDebugStringAppend( $string )
  626. {
  627. $this->DEBUG_APPEND_URL = $string;
  628. }
  629. /**
  630. * Sets visitor browser supported plugins
  631. *
  632. * @param bool $flash
  633. * @param bool $java
  634. * @param bool $director
  635. * @param bool $quickTime
  636. * @param bool $realPlayer
  637. * @param bool $pdf
  638. * @param bool $windowsMedia
  639. * @param bool $gears
  640. * @param bool $silverlight
  641. */
  642. public function setPlugins($flash = false, $java = false, $director = false, $quickTime = false, $realPlayer = false, $pdf = false, $windowsMedia = false, $gears = false, $silverlight = false)
  643. {
  644. $this->plugins =
  645. '&fla='.(int)$flash.
  646. '&java='.(int)$java.
  647. '&dir='.(int)$director.
  648. '&qt='.(int)$quickTime.
  649. '&realp='.(int)$realPlayer.
  650. '&pdf='.(int)$pdf.
  651. '&wma='.(int)$windowsMedia.
  652. '&gears='.(int)$gears.
  653. '&ag='.(int)$silverlight
  654. ;
  655. }
  656. /**
  657. * By default, PiwikTracker will read third party cookies
  658. * from the response and sets them in the next request.
  659. * This can be disabled by calling this function.
  660. *
  661. * @return void
  662. */
  663. public function disableCookieSupport()
  664. {
  665. $this->cookieSupport = false;
  666. }
  667. /**
  668. * @ignore
  669. */
  670. protected function sendRequest($url)
  671. {
  672. $timeout = 600; // Allow debug while blocking the request
  673. $response = '';
  674. if(!$this->cookieSupport)
  675. {
  676. $this->requestCookie = '';
  677. }
  678. if(function_exists('curl_init'))
  679. {
  680. $ch = curl_init();
  681. curl_setopt_array($ch, array(
  682. CURLOPT_URL => $url,
  683. CURLOPT_USERAGENT => $this->userAgent,
  684. CURLOPT_HEADER => true,
  685. CURLOPT_TIMEOUT => $timeout,
  686. CURLOPT_RETURNTRANSFER => true,
  687. CURLOPT_HTTPHEADER => array(
  688. 'Accept-Language: ' . $this->acceptLanguage,
  689. 'Cookie: '. $this->requestCookie,
  690. ),
  691. ));
  692. ob_start();
  693. $response = @curl_exec($ch);
  694. ob_end_clean();
  695. $header = $content = '';
  696. if(!empty($response))
  697. {
  698. list($header,$content) = explode("\r\n\r\n", $response, $limitCount = 2);
  699. }
  700. }
  701. else if(function_exists('stream_context_create'))
  702. {
  703. $stream_options = array(
  704. 'http' => array(
  705. 'user_agent' => $this->userAgent,
  706. 'header' => "Accept-Language: " . $this->acceptLanguage . "\r\n" .
  707. "Cookie: ".$this->requestCookie. "\r\n" ,
  708. 'timeout' => $timeout, // PHP 5.2.1
  709. )
  710. );
  711. $ctx = stream_context_create($stream_options);
  712. $response = file_get_contents($url, 0, $ctx);
  713. $header = implode("\r\n", $http_response_header);
  714. $content = $response;
  715. }
  716. // The cookie in the response will be set in the next request
  717. preg_match_all('/^Set-Cookie: (.*?);/m', $header, $cookie);
  718. if(!empty($cookie[1]))
  719. {
  720. // in case several cookies returned, we keep only the latest one (ie. XDEBUG puts its cookie first in the list)
  721. if(is_array($cookie[1]))
  722. {
  723. $cookie = end($cookie[1]);
  724. }
  725. else
  726. {
  727. $cookie = $cookie[1];
  728. }
  729. if(strpos($cookie, 'XDEBUG') === false)
  730. {
  731. $this->requestCookie = $cookie;
  732. }
  733. }
  734. return $content;
  735. }
  736. /**
  737. * Returns current timestamp, or forced timestamp/datetime if it was set
  738. * @return string|int
  739. */
  740. protected function getTimestamp()
  741. {
  742. return !empty($this->forcedDatetime)
  743. ? strtotime($this->forcedDatetime)
  744. : time();
  745. }
  746. /**
  747. * @ignore
  748. */
  749. protected function getRequest( $idSite )
  750. {
  751. if(empty(self::$URL))
  752. {
  753. throw new Exception('You must first set the Piwik Tracker URL by calling PiwikTracker::$URL = \'http://your-website.org/piwik/\';');
  754. }
  755. if(strpos(self::$URL, '/piwik.php') === false
  756. && strpos(self::$URL, '/proxy-piwik.php') === false)
  757. {
  758. self::$URL .= '/piwik.php';
  759. }
  760. $url = self::$URL .
  761. '?idsite=' . $idSite .
  762. '&rec=1' .
  763. '&apiv=' . self::VERSION .
  764. '&r=' . substr(strval(mt_rand()), 2, 6) .
  765. // PHP DEBUGGING: Optional since debugger can be triggered remotely
  766. (!empty($_GET['XDEBUG_SESSION_START']) ? '&XDEBUG_SESSION_START=' . @$_GET['XDEBUG_SESSION_START'] : '') .
  767. (!empty($_GET['KEY']) ? '&KEY=' . @$_GET['KEY'] : '') .
  768. // Only allowed for Super User, token_auth required,
  769. // except when tracking_requests_require_authentication = 0 in config.ini.php [Tracker] section
  770. (!empty($this->ip) ? '&cip=' . $this->ip : '') .
  771. (!empty($this->forcedVisitorId) ? '&cid=' . $this->forcedVisitorId : '&_id=' . $this->visitorId) .
  772. (!empty($this->forcedDatetime) ? '&cdt=' . urlencode($this->forcedDatetime) : '') .
  773. (!empty($this->token_auth) ? '&token_auth=' . urlencode($this->token_auth) : '') .
  774. // These parameters are set by the JS, but optional when using API
  775. (!empty($this->plugins) ? $this->plugins : '') .
  776. (($this->localHour !== false && $this->localMinute !== false && $this->localSecond !== false) ? '&h=' . $this->localHour . '&m=' . $this->localMinute . '&s=' . $this->localSecond : '' ).
  777. (!empty($this->width) && !empty($this->height) ? '&res=' . $this->width . 'x' . $this->height : '') .
  778. (!empty($this->hasCookies) ? '&cookie=' . $this->hasCookies : '') .
  779. (!empty($this->ecommerceLastOrderTimestamp) ? '&_ects=' . urlencode($this->ecommerceLastOrderTimestamp) : '') .
  780. // Various important attributes
  781. (!empty($this->customData) ? '&data=' . $this->customData : '') .
  782. (!empty($this->visitorCustomVar) ? '&_cvar=' . urlencode(json_encode($this->visitorCustomVar)) : '') .
  783. (!empty($this->pageCustomVar) ? '&cvar=' . urlencode(json_encode($this->pageCustomVar)) : '') .
  784. // URL parameters
  785. '&url=' . urlencode($this->pageUrl) .
  786. '&urlref=' . urlencode($this->urlReferrer) .
  787. // Attribution information, so that Goal conversions are attributed to the right referrer or campaign
  788. // Campaign name
  789. (!empty($this->attributionInfo[0]) ? '&_rcn=' . urlencode($this->attributionInfo[0]) : '') .
  790. // Campaign keyword
  791. (!empty($this->attributionInfo[1]) ? '&_rck=' . urlencode($this->attributionInfo[1]) : '') .
  792. // Timestamp at which the referrer was set
  793. (!empty($this->attributionInfo[2]) ? '&_refts=' . $this->attributionInfo[2] : '') .
  794. // Referrer URL
  795. (!empty($this->attributionInfo[3]) ? '&_ref=' . urlencode($this->attributionInfo[3]) : '') .
  796. // DEBUG
  797. $this->DEBUG_APPEND_URL
  798. ;
  799. // Reset page level custom variables after this page view
  800. $this->pageCustomVar = false;
  801. return $url;
  802. }
  803. /**
  804. * Returns a first party cookie which name contains $name
  805. *
  806. * @param string $name
  807. * @return string String value of cookie, or false if not found
  808. * @ignore
  809. */
  810. protected function getCookieMatchingName($name)
  811. {
  812. // Piwik cookie names use dots separators in piwik.js,
  813. // but PHP Replaces . with _ http://www.php.net/manual/en/language.variables.predefined.php#72571
  814. $name = str_replace('.', '_', $name);
  815. foreach($_COOKIE as $cookieName => $cookieValue)
  816. {
  817. if(strpos($cookieName, $name) !== false)
  818. {
  819. return $cookieValue;
  820. }
  821. }
  822. return false;
  823. }
  824. /**
  825. * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
  826. * will return "/dir1/dir2/index.php"
  827. *
  828. * @return string
  829. * @ignore
  830. */
  831. static protected function getCurrentScriptName()
  832. {
  833. $url = '';
  834. if( !empty($_SERVER['PATH_INFO']) ) {
  835. $url = $_SERVER['PATH_INFO'];
  836. }
  837. else if( !empty($_SERVER['REQUEST_URI']) ) {
  838. if( ($pos = strpos($_SERVER['REQUEST_URI'], '?')) !== false ) {
  839. $url = substr($_SERVER['REQUEST_URI'], 0, $pos);
  840. } else {
  841. $url = $_SERVER['REQUEST_URI'];
  842. }
  843. }
  844. if(empty($url)) {
  845. $url = $_SERVER['SCRIPT_NAME'];
  846. }
  847. if($url[0] !== '/') {
  848. $url = '/' . $url;
  849. }
  850. return $url;
  851. }
  852. /**
  853. * If the current URL is 'http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
  854. * will return 'http'
  855. *
  856. * @return string 'https' or 'http'
  857. * @ignore
  858. */
  859. static protected function getCurrentScheme()
  860. {
  861. if(isset($_SERVER['HTTPS'])
  862. && ($_SERVER['HTTPS'] == 'on' || $_SERVER['HTTPS'] === true))
  863. {
  864. return 'https';
  865. }
  866. return 'http';
  867. }
  868. /**
  869. * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
  870. * will return "http://example.org"
  871. *
  872. * @return string
  873. * @ignore
  874. */
  875. static protected function getCurrentHost()
  876. {
  877. if(isset($_SERVER['HTTP_HOST'])) {
  878. return $_SERVER['HTTP_HOST'];
  879. }
  880. return 'unknown';
  881. }
  882. /**
  883. * If current URL is "http://example.org/dir1/dir2/index.php?param1=value1&param2=value2"
  884. * will return "?param1=value1&param2=value2"
  885. *
  886. * @return string
  887. * @ignore
  888. */
  889. static protected function getCurrentQueryString()
  890. {
  891. $url = '';
  892. if(isset($_SERVER['QUERY_STRING'])
  893. && !empty($_SERVER['QUERY_STRING']))
  894. {
  895. $url .= '?'.$_SERVER['QUERY_STRING'];
  896. }
  897. return $url;
  898. }
  899. /**
  900. * Returns the current full URL (scheme, host, path and query string.
  901. *
  902. * @return string
  903. * @ignore
  904. */
  905. static protected function getCurrentUrl()
  906. {
  907. return self::getCurrentScheme() . '://'
  908. . self::getCurrentHost()
  909. . self::getCurrentScriptName()
  910. . self::getCurrentQueryString();
  911. }
  912. }
  913. function Piwik_getUrlTrackPageView( $idSite, $documentTitle = false )
  914. {
  915. $tracker = new PiwikTracker($idSite);
  916. return $tracker->getUrlTrackPageView($documentTitle);
  917. }
  918. function Piwik_getUrlTrackGoal($idSite, $idGoal, $revenue = false)
  919. {
  920. $tracker = new PiwikTracker($idSite);
  921. return $tracker->getUrlTrackGoal($idGoal, $revenue);
  922. }