SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Helpers/SessionStats.php

  1. <?php
  2. /*
  3.  * Copyright (C) 2017 Karmabunny Pty Ltd.
  4.  *
  5.  * This file is a part of SproutCMS.
  6.  *
  7.  * SproutCMS is free software: you can redistribute it and/or modify it under the terms
  8.  * of the GNU General Public License as published by the Free Software Foundation, either
  9.  * version 2 of the License, or (at your option) any later version.
  10.  *
  11.  * For more information, visit <http://getsproutcms.com>.
  12.  */
  13.  
  14. namespace Sprout\Helpers;
  15.  
  16. use DateInterval;
  17. use DateTime;
  18.  
  19.  
  20. class SessionStats
  21. {
  22.  
  23. /**
  24.   * Should tracking be done? Determined at request start time
  25.   */
  26. private static $do_tracking = false;
  27.  
  28.  
  29. /**
  30.   * Prefixes of URLs to ignore
  31.   */
  32. private static $untracked = [
  33. 'admin',
  34. 'dbtools',
  35. 'email_share',
  36. 'embed_video',
  37. 'file',
  38. 'page',
  39. 'result',
  40. 'robots.txt',
  41. 'search',
  42. 'seo/xmlSitemap',
  43. 'tinymce4',
  44. ];
  45.  
  46.  
  47. /**
  48.   * Check whether this content should be tracked, and enable tracking in this case
  49.   */
  50. public static function init()
  51. {
  52. if (PHP_SAPI == 'cli') return false;
  53.  
  54. // Only track non-ajax GET requests
  55. if (Request::isAjax()) return false;
  56. if (Request::method() != 'get') return false;
  57.  
  58. // Prefixes of URLs to ignore
  59. foreach (self::$untracked as $prefix) {
  60. if (strpos(Url::current(), $prefix) === 0) return false;
  61. }
  62.  
  63. Session::instance();
  64.  
  65. self::trackSession();
  66. self::$do_tracking = true;
  67. }
  68.  
  69.  
  70. /**
  71.   * Session level tracking - utm tags, referrer, etc
  72.   */
  73. protected static function trackSession()
  74. {
  75. if (empty($_SESSION['stats'])) {
  76. $_SESSION['stats'] = [
  77. 'start' => new DateTime(),
  78. 'pageviews' => [],
  79. ];
  80.  
  81. // Set referrer, but only if it's not the current host
  82. $referrer = Request::referrer();
  83. if (!empty($referrer)) {
  84. $host = parse_url($referrer, PHP_URL_HOST);
  85. if ($_SERVER['HTTP_HOST'] !== $host) {
  86. $_SESSION['stats']['referrer'] = $referrer;
  87. }
  88. }
  89. }
  90.  
  91. // Store any provided UTM parameters
  92. $utm_params = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];
  93. foreach ($utm_params as $param) {
  94. if (isset($_GET[$param])) {
  95. $_SESSION['stats'][$param] = $_GET[$param];
  96. }
  97. }
  98.  
  99. // Attempt to auto-generate utm parameters if they're not set
  100. if (empty($_SESSION['stats']['utm_source']) and empty($_SESSION['stats']['utm_medium'])) {
  101. list($source, $medium) = self::autoDetectSourceMedium(@$_SESSION['stats']['referrer']);
  102. if (!empty($source)) {
  103. $_SESSION['stats']['utm_source'] = $source;
  104. }
  105. if (!empty($medium)) {
  106. $_SESSION['stats']['utm_medium'] = $medium;
  107. }
  108. }
  109. }
  110.  
  111.  
  112. /**
  113.   * Track a page view in the session
  114.   */
  115. public static function trackPageView()
  116. {
  117. if (!self::$do_tracking) return;
  118.  
  119. $url = Url::current(false);
  120. if (empty($_SESSION['stats']['pageviews'][$url])) {
  121. $_SESSION['stats']['pageviews'][$url] = 1;
  122. } else {
  123. $_SESSION['stats']['pageviews'][$url] += 1;
  124. }
  125. }
  126.  
  127.  
  128. /**
  129.   * Auto-generate UTM params based on the initial request referrer
  130.   *
  131.   * @param string $referrer Full URL, e.g. 'https://facebook.com/post/987654321
  132.   * @return array Two strings or NULL if not known; 0 => source, 1 => medium
  133.   */
  134. private static function autoDetectSourceMedium($referrer)
  135. {
  136. if (empty($referrer)) {
  137. return [null, 'direct'];
  138. }
  139.  
  140. $host = parse_url($referrer, PHP_URL_HOST);
  141. $host = preg_replace('/^(www|m)\./', '', $host);
  142.  
  143. switch ($host) {
  144. case 'facebook.com': return ['Facebook', 'social'];
  145. case 'twitter.com': return ['Twitter', 'social'];
  146. case 'youtube.com': return ['YouTube', 'social'];
  147. }
  148.  
  149. return [$host, 'referral'];
  150. }
  151.  
  152.  
  153. /**
  154.   * Return the total number of page views
  155.   *
  156.   * @return int Num page views
  157.   */
  158. public static function totalPageviews()
  159. {
  160. if (!empty($_SESSION['stats'])) {
  161. return array_sum($_SESSION['stats']['pageviews']);
  162. } else {
  163. return 0;
  164. }
  165. }
  166.  
  167.  
  168. /**
  169.   * Return the total number of unique page views
  170.   *
  171.   * @return int Num page views
  172.   */
  173. public static function uniquePageviews()
  174. {
  175. if (!empty($_SESSION['stats'])) {
  176. return count($_SESSION['stats']['pageviews']);
  177. } else {
  178. return 0;
  179. }
  180. }
  181.  
  182.  
  183. /**
  184.   * Return the number of page views for a given url
  185.   *
  186.   * @param int $url URL to return stats for; query strings are stripped
  187.   * @return int Num page views
  188.   */
  189. public static function numPageviews($url)
  190. {
  191. // Strip query string
  192. $url = preg_replace('!\?.+!', '', $url);
  193.  
  194. if (!empty($_SESSION['stats']['pageviews'][$url])) {
  195. return $_SESSION['stats']['pageviews'][$url];
  196. } else {
  197. return 0;
  198. }
  199. }
  200.  
  201.  
  202. /**
  203.   * Time the session started
  204.   *
  205.   * @return DateTime
  206.   */
  207. public static function timeStart()
  208. {
  209. if (!empty($_SESSION['stats'])) {
  210. return $_SESSION['stats']['start'];
  211. } else {
  212. return new DateTime();
  213. }
  214. }
  215.  
  216.  
  217. /**
  218.   * How long the user has been on the site
  219.   *
  220.   * @return DateInterval
  221.   */
  222. public static function timeOnSite()
  223. {
  224. if (!empty($_SESSION['stats'])) {
  225. $start = self::timeStart();
  226. return $start->diff(new DateTime());
  227. } else {
  228. return new DateInterval('PT0S');
  229. }
  230. }
  231.  
  232.  
  233. /**
  234.   * The initial HTTP referrer when the session was first started
  235.   *
  236.   * @return string URL
  237.   */
  238. public static function referrer()
  239. {
  240. return @$_SESSION['stats']['referrer'];
  241. }
  242.  
  243.  
  244. /**
  245.   * Value of the 'utm_source' query string parameter
  246.   * from the most recent request which contained this parameter
  247.   *
  248.   * @return string UTM request source, e.g. 'google', 'bing', 'facebook', etc
  249.   */
  250. public static function utmSource()
  251. {
  252. return @$_SESSION['stats']['utm_source'];
  253. }
  254.  
  255.  
  256. /**
  257.   * Value of the 'utm_medium' query string parameter
  258.   * from the most recent request which contained this parameter
  259.   *
  260.   * @return string UTM request medium, e.g. 'cpc', 'organic', 'social', 'email', etc
  261.   */
  262. public static function utmMedium()
  263. {
  264. return @$_SESSION['stats']['utm_medium'];
  265. }
  266.  
  267.  
  268. /**
  269.   * Value of the 'utm_campaign' query string parameter
  270.   * from the most recent request which contained this parameter
  271.   *
  272.   * @return string UTM request campaign, e.g. 'spring_sale'
  273.   */
  274. public static function utmCampaign()
  275. {
  276. return @$_SESSION['stats']['utm_campaign'];
  277. }
  278.  
  279.  
  280. /**
  281.   * Value of the 'utm_term' query string parameter
  282.   * from the most recent request which contained this parameter
  283.   *
  284.   * @return string UTM request term, e.g. 'running shoes'
  285.   */
  286. public static function utmTerm()
  287. {
  288. return @$_SESSION['stats']['utm_term'];
  289. }
  290.  
  291.  
  292. /**
  293.   * Value of the 'utm_content' query string parameter
  294.   * from the most recent request which contained this parameter
  295.   *
  296.   * @return string UTM request term, e.g. 'logolink' or 'textlink'
  297.   */
  298. public static function utmContent()
  299. {
  300. return @$_SESSION['stats']['utm_content'];
  301. }
  302.  
  303. }
  304.