You are here

function google_analytics_counter_get_sum_per_path in Google Analytics Counter 6.2

Same name and namespace in other branches
  1. 6 google_analytics_counter.module \google_analytics_counter_get_sum_per_path()
  2. 7.3 google_analytics_counter_data.inc \google_analytics_counter_get_sum_per_path()
  3. 7 google_analytics_counter.module \google_analytics_counter_get_sum_per_path()
  4. 7.2 google_analytics_counter_data.inc \google_analytics_counter_get_sum_per_path()
2 calls to google_analytics_counter_get_sum_per_path()
google_analytics_counter_display in ./google_analytics_counter.module
google_analytics_counter_gac_get_count in ./google_analytics_counter.module

File

./google_analytics_counter.module, line 147

Code

function google_analytics_counter_get_sum_per_path($path) {
  $timenow = time();

  // Recognize special path 'all'
  if ($path == 'all') {

    // Let's use a less common path (this is for GA API)
    // Requires GA API to adopt http://drupal.org/node/949986
    $path = 'ga_api_all_paths';
  }

  // Watch out for http://code.google.com/apis/analytics/docs/gdata/gdataDeveloperGuide.html#quota

  //$cache_period = 60*60*24;
  $cache_period = round(variable_get('google_analytics_counter_api_refresh', 6) * 3600);

  //$cache_period = 90;

  // Needing to stay under the Google Analytics API quota, let's count how many API retrievals were made in the last 24 hours.
  // We should take into consideration that the quota is reset at midnight PST (while time() always returns UTC) - that could be looked into one day.
  $dayquota = variable_get('google_analytics_counter_dayquota', array(
    0,
    0,
  ));
  if ($timenow - $dayquota[0] >= 86400) {

    // If last API request was more than a day ago, set monitoring time to now.
    $dayquota[0] = $timenow;
    $dayquota[1] = 0;
    variable_set('google_analytics_counter_dayquota', array(
      $dayquota[0],
      0,
    ));
  }
  $apirequestallowed = FALSE;
  $maxdailyrequests = variable_get('google_analytics_counter_api_dayquota', 10000);

  // see http://code.google.com/apis/analytics/docs/gdata/gdataDeveloperGuide.html#quota
  if ($dayquota[1] <= $maxdailyrequests) {
    $apirequestallowed = TRUE;
  }
  $key = 'google_analytics_counter_' . $path;

  // Cache expiration logic is not governed by Drupal's cache_set. Cache life is set to much longer time than what the desired refresh time is so that in case of not receiving fresh value (for whatever reason) there is at least an approximate value available for display.
  // First let's find out when this cache entry was created.
  $cache = cache_get($key);
  $cachecreated = @$cache->created;
  $needfreshvalue = FALSE;
  if (time() - $cachecreated > $cache_period) {
    $needfreshvalue = TRUE;
  }

  // Let's say we only allow retrieval from Google Analytics API once a second. We have to watch the quotas - see http://code.google.com/apis/analytics/docs/gdata/gdataDeveloperGuide.html#quota
  $noconcurrency = FALSE;

  // $concurrencymax = 1 means that the difference of current and recorded time must be at least 1 second, which is all right. Should not need to be higher, except maybe for testing.
  $concurrencymax = variable_get('google_analytics_counter_concurrency', 1);
  if ($timenow - variable_get('google_analytics_counter_latest', $timenow - $concurrencymax) >= $concurrencymax) {

    // If the value is not yet there (first run!), use ($timenow-$concurrencymax) otherwise it will always detect concurrency!
    $noconcurrency = TRUE;
  }
  $cachedvalue = '';

  // Get from cache if not expired, if we don't need a fresh value, if there is concurrency, or if we exceeded Google's day quota.
  if ($cache = cache_get($key) and !empty($cache->data) and (!$needfreshvalue or !$noconcurrency or !$apirequestallowed)) {
    $result = $cache->data;
    $cachedvalue = t(' This value was fetched from Drupal cache.');
  }
  else {

    // Let's set a time variable indicating no other script should retrieve Google Analytics data within some period.
    variable_set('google_analytics_counter_latest', $timenow);

    // Let's increase the count of API requests in order to check for daily quota excess.
    variable_set('google_analytics_counter_dayquota', array(
      $dayquota[0],
      $dayquota[1] + 1,
    ));

    // Grab the data using http://drupal.org/project/google_analytics_reports -- see http://drupal.org/node/1144994#comment-4431586

    /*
     $request = array(
     #'#dimensions' => array('pagePath', 'date'),
     '#dimensions' => array('date'), // date would not be necessary for totals, but we also calculate stats of views per day, so we need it
     // '#metrics' => array('pageviews', 'timeOnPage', 'bounces', 'uniquePageviews'),
     '#metrics' => array('pageviews'),
     #'#sort_metric' => array('date', 'pagePath'),
     // We want to retrueve all page views for this path. The earliest valid start-date for Google Analytics is 2005-01-01.
     '#start_date' => strtotime('2005-01-01')
     );
    */
    $request = array(
      'dimensions' => array(
        'ga:date',
      ),
      // date would not be necessary for totals, but we also calculate stats of views per day, so we need it
      'metrics' => array(
        'ga:pageviews',
      ),
    );

    /*
        $request = array(
       'dimensions' => array('ga:date'), // date would not be necessary for totals, but we also calculate stats of views per day, so we need it
       'metrics' => array('ga:pageviews'),
       'start_date' => strtotime('-5 days'), // We want to retrueve all page views for this path. The earliest valid start-date for Google Analytics is 2005-01-01.
       'end_date' => strtotime('-5 days'), // We want to retrueve all page views for this path. The earliest valid start-date for Google Analytics is 2005-01-01.
        );
    */
    $rows = _google_analytics_counter_path_report($request, $path);

    //

    /**
     *
     * @param $params
     *   An associative array containing:
     *   - profile_id: required [default=variable_get('google_analytics_reports_profile_id')]
     *   - metrics: required.
     *   - dimensions: optional [default=none]
     *   - sort_metric: optional [default=none]
     *   - filters: optional [default=none]
     *   - segment: optional [default=none]
     *   - start_date: optional [default=GA release date]
     *   - end_date: optional [default=today]
     *   - start_index: optional [default=1]
     *   - max_results: optional [default=10,000]
     * @param $cache_options
     *   An optional associative array containing:
     *   - cid: optional [default=md5 hash]
     *   - expire: optional [default=CACHE_TEMPORARY]
     *   - refresh: optional [default=FALSE]
     */

    //function google_analytics_api_report_data($params = array(), $cache_options = array()) {

    /*
     $params = array(
     'metrics' => array('ga:visits'),
     'dimensions' => array('ga:date'),
     'sort_metric' => array('ga:date'),
     'start_date' => strtotime('-31 days'),
     'end_date' => strtotime('-1 day'),
     );
     $feed = google_analytics_api_report_data($params);
     if ($feed->error) {
     return FALSE;
     }
     $max_visits = 0;
     foreach ($feed->results as $row) {
     $data[] = $row['visits'];
     $max_visits = max($row['visits'], $max_visits);
     }
    */
    $sum_of_pageviews = 0;
    $countdays = 0;
    $lookingforfirsthit = TRUE;
    foreach ($rows as $date) {

      // In case some error message appears, set zero and get out.
      if (!is_numeric($date['pageviews'])) {
        $sum_of_pageviews = 0;
        break;
      }
      $sum_of_pageviews += $date['pageviews'];

      // We need to count only days since when the first hit was registered
      if ($date['pageviews'] != 0 or !$lookingforfirsthit) {
        $countdays++;
        $lookingforfirsthit = FALSE;
      }
    }

    // We need to store the count, days of counting, and also the absolute time of caching as well.
    $result = array(
      $sum_of_pageviews,
      $countdays,
      $timenow,
    );

    // Set the cache duration for much longer than the desired refresh period so as to assure approximate values are returned in case GA API limits are reached or if there are temporary problems with retrieving fresh values (that would set the displayed value to 0!)
    $safe_margin_cache_time = $cache_period * 50;
    cache_set($key, $result, 'cache', $safe_margin_cache_time);

    // All right. Now - if it's desired and if it's a node page - update Drupal's own page view counter
    if (variable_get('google_analytics_counter_update_node_counter', 0) == 1) {

      // Let's get the nid
      $nid = FALSE;
      $pathbits = explode('/', $path);
      if ($pathbits[0] == 'node' && is_numeric($pathbits[1])) {

        // Provided in format node/x
        $nid = $pathbits[1];
      }
      else {
        $pathbits = drupal_lookup_path('source', $path);
        $pathbits = explode('/', $pathbits);
        if ($pathbits[0] == 'node' && is_numeric($pathbits[1])) {

          // Provided as an alias
          $nid = $pathbits[1];
        }
      }
      if ($nid !== FALSE and $sum_of_pageviews != 0) {

        // This is a node, so update the node's counters.
        // We don't do anything with daycount here
        db_query('UPDATE {node_counter} SET daycount = 0, totalcount = %d, timestamp = %d WHERE nid = %d', $sum_of_pageviews, time(), $nid);

        // If we affected 0 rows, this is the first time viewing the node.
        if (!db_affected_rows()) {

          // We must create a new row to store counters for the new node.
          db_query('INSERT INTO {node_counter} (nid, daycount, totalcount, timestamp) VALUES (%d, 0, %d, %d)', $nid, $sum_of_pageviews, time());
        }
      }
    }
  }
  $lastfresh = $timenow - $result[2];
  $extrapolated_for_current_cache_period = 'N/A';

  // No reason to extrapolate if no data has been ever recorded (not a single date).
  if ($result[1] != 0) {
    $views_per_second = $result[0] / ($result[1] * 60 * 60 * 24);
    $extrapolated_for_current_cache_period = $lastfresh * $views_per_second;

    // If extrapolation is desired, add it to the retrieved count.
    $addextrapolated = 0;
    if (variable_get('google_analytics_counter_extrapolation', 1) == 1) {
      $addextrapolated = round($extrapolated_for_current_cache_period);
      $result[0] += $addextrapolated;
    }
  }

  // Add debug information, if requested.
  $debuggeron = GOOGLE_ANALYTICS_COUNTER_DEBUG;
  if ($debuggeron == 1) {
    $debug = '';

    //$debug .= '<span style="color:teal;">';

    //$debug .= '<br/>';
    $debug .= t('Debugging info: ');
    $debug .= $result[0] - $addextrapolated . t(' views of /') . $path . t(' over ') . $result[1] . t(' days');
    if ($result[1] != 0) {
      $debug .= t(' (about ') . round($result[0] / $result[1]) . t(' views per day since starting collecting statistics for this page on ') . date('Y-m-d', $timenow - $result[1] * 60 * 60 * 24) . ')';
    }
    $debug .= t('. Fresh data for this page has been retrieved from Google Analytics API ') . $lastfresh . t(' seconds ago (next in ') . ($cache_period - ($timenow - $result[2])) . t(' seconds).');
    $debug .= t(' With ') . $views_per_second * $cache_period . t(' views per caching period (') . $cache_period . t(' seconds), the estimated number of views for current part (') . $lastfresh . t(' seconds) of the caching period is ') . $extrapolated_for_current_cache_period . '.';
    if ($noconcurrency) {
      $debug .= t(' There is no problem with concurrency (');
      $debug .= $timenow - variable_get('google_analytics_counter_latest', $timenow) . ' seconds';
      $debug .= ' > ' . $concurrencymax . ').';
    }
    else {
      $debug .= t(' There is a concurrency problem (');
      $debug .= $timenow - variable_get('google_analytics_counter_latest', $timenow) . ' seconds';
      $debug .= ' < ' . $concurrencymax . ')!';
    }
    $debug .= t(' Sum of API requests for the past 24 hours: ') . $dayquota[1] . t('. (The maximum is set to ') . $maxdailyrequests;
    if (!$apirequestallowed) {
      $debug .= t(', so no more API requests will be allowed until the end of the 24-hour period');
    }
    $debug .= '.)';

    //$debug .= '</span>';
    $result[3] = $debug;
  }
  return $result;
}