You are here

yandex_metrics_reports.module in Yandex.Metrics 7.3

The main code of Yandex.Metrics Reports module.

File

yandex_metrics_reports/yandex_metrics_reports.module
View source
<?php

/**
 * @file
 * The main code of Yandex.Metrics Reports module.
 */

// Include report callbacks.
module_load_include('inc', 'yandex_metrics_reports', 'yandex_metrics_reports.reports');

/**
 * Quantity of popular search phrases.
 */
define('YANDEX_METRICS_REPORTS_SEARCH_PHRASES_QUANTITY', 12);

/**
 * Quantity of popular content lines.
 */
define('YANDEX_METRICS_REPORTS_POPULAR_CONTENT_COUNT', 30);

/**
 * Implements hook_permission().
 */
function yandex_metrics_reports_permission() {
  return array(
    'access Yandex.Metrics report' => array(
      'title' => t('Access Yandex.Metrics report'),
    ),
  );
}

/**
 * Implements hook_menu().
 */
function yandex_metrics_reports_menu() {

  // Display fake Authorization tab in case if
  // we have yandex_services_auth module installed.
  if (module_exists('yandex_services_auth')) {
    $items['admin/config/system/yandex_metrics/authorization'] = array(
      // The yandex_services_auth module requires
      // 'administer site configuration' permission.
      'access arguments' => array(
        'administer Yandex.Metrics settings',
      ),
      'page callback' => 'drupal_goto',
      'page arguments' => array(
        'admin/config/system/yandex_services_auth',
      ),
      'title' => 'Authorization',
      'type' => MENU_LOCAL_TASK,
      'weight' => 2,
    );
  }
  $items['admin/config/system/yandex_metrics/reports'] = array(
    'access arguments' => array(
      'administer Yandex.Metrics settings',
    ),
    'page callback' => 'drupal_get_form',
    'page arguments' => array(
      'yandex_metrics_reports_reports',
    ),
    'title' => 'Reports',
    'type' => MENU_LOCAL_TASK,
    'weight' => 3,
  );
  $items['admin/reports/yandex_metrics_summary'] = array(
    'access arguments' => array(
      'access Yandex.Metrics report',
    ),
    'page callback' => 'yandex_metrics_reports_report',
    'title' => 'Yandex.Metrics Summary Report',
    'type' => MENU_NORMAL_ITEM,
  );
  $items['admin/reports/yandex_metrics_summary/%'] = array(
    'access arguments' => array(
      'access Yandex.Metrics report',
    ),
    'page callback' => 'yandex_metrics_reports_report',
    'page arguments' => array(
      3,
    ),
    'title' => 'Yandex.Metrics Summary Report',
    'title callback' => 'yandex_metrics_reports_summary_page_title_callback',
    'title arguments' => array(
      3,
    ),
    'load arguments' => array(
      3,
    ),
    'type' => MENU_CALLBACK,
  );
  return $items;
}

/**
 * Implements hook_init().
 */
function yandex_metrics_reports_init() {

  // Redirect from old authorization callback url to the new one.
  // It's necessary because old Yandex applications have old urls in their settings.
  if (arg(0) == 'yandex_metrics' && arg(1) == 'oauth' && module_exists('yandex_services_auth')) {
    drupal_goto('yandex_services_auth/oauth', array(
      'query' => drupal_get_query_parameters(),
    ));
  }
}

/**
 * Implements hook_theme().
 */
function yandex_metrics_reports_theme() {
  return array(
    'yandex_metrics_reports_reports' => array(
      'render element' => 'form',
    ),
  );
}

/**
 * It is quick filter form for report page.
 */
function yandex_metrics_reports_filter_form() {
  $form = array();
  $current_filter = arg(3) ? arg(3) : 'week';
  $options = array(
    'day' => t('Today'),
    'yesterday' => t('Yesterday'),
    'week' => t('Week'),
    'month' => t('Month'),
  );
  $form['filter'] = array(
    '#type' => 'select',
    '#title' => t('Quick filter'),
    '#default_value' => $current_filter,
    '#options' => $options,
    '#attributes' => array(
      'onchange' => 'this.form.submit();',
    ),
  );
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
    '#attributes' => array(
      'style' => 'display:none;',
    ),
  );
  return $form;
}

/**
 * Form submit handler for yandex_metrics_reports_time_interval_form form.
 */
function yandex_metrics_reports_filter_form_submit($form, &$form_state) {
  $filter = $form_state['values']['filter'];
  if (!empty($filter)) {
    drupal_goto('admin/reports/yandex_metrics_summary/' . $filter);
  }
}

/**
 * Converts filter value to date range array.
 *
 * @param string $filter
 *    Date range filter: (day, yesterday, week, month).
 *
 * @return array
 *    Format: array(
 *      'start_date' => 'YYYYMMDD',
 *      'end_date' => 'YYYYMMDD',
 *      'group' => 'week' // [optional]
 *   );
 */
function yandex_metrics_reports_filter_to_date_range($filter) {
  switch ($filter) {
    case 'day':
      return array(
        'start_date' => date('Ymd'),
        'end_date' => date('Ymd'),
      );
    case 'yesterday':
      return array(
        'start_date' => date('Ymd', time() - 60 * 60 * 24),
        'end_date' => date('Ymd', time() - 60 * 60 * 24),
      );
    case 'week':
    default:
      return array(
        'start_date' => date('Ymd', time() - 60 * 60 * 24 * 6),
        'end_date' => date('Ymd'),
      );
    case 'month':
      return array(
        'start_date' => date('Ymd', time() - 60 * 60 * 24 * 31),
        'end_date' => date('Ymd'),
        'group' => 'week',
      );
  }
}

/**
 * Menu callback; displays a Summary page containing reports and charts.
 */
function yandex_metrics_reports_report($filter = 'week') {
  $counter_id = yandex_metrics_reports_get_counter_for_current_site();
  if (empty($counter_id)) {
    drupal_set_message(t("Couldn't get information about the counter from Yandex.Metrica. See more details in log.") . '<br/>' . t('Also, make sure that you created the counter and authorized your site at Yandex.'), 'error');
    return '';
  }
  $counter_code = variable_get('yandex_metrics_counter_code', '');
  if (empty($counter_code)) {
    drupal_set_message(t('Perhaps you have not yet placed Yandex.Metrica counter code on the site. You can do this !link.', array(
      '!link' => l(t('here'), 'admin/config/system/yandex_metrics'),
    )), 'notice');
  }
  $authorisation_token = yandex_services_auth_info('token');
  if (empty($authorisation_token)) {
    drupal_set_message(t('Please make sure that your application is authorized !link.', array(
      '!link' => l(t('here'), 'admin/config/system/yandex_services_auth'),
    )), 'error');
    return '';
  }
  drupal_add_css(drupal_get_path('module', 'yandex_metrics_reports') . '/css/yandex_metrics_reports.css');
  $output = '';
  $form = drupal_get_form('yandex_metrics_reports_filter_form');
  $output .= drupal_render($form);
  $reports = yandex_metrics_reports_get_active_list();
  $output .= '<input type="hidden" id="yandex_metrics_reports_counter_id" value="' . $counter_id . '" />';
  $output .= '<input type="hidden" id="yandex_metrics_reports_filter" value="' . $filter . '" />';
  foreach ($reports as $report_name => $report_data) {
    $type = 'yandex_metrics_reports_' . $report_name;
    $report_content = yandex_metrics_reports_render_report($counter_id, $filter, $report_name);
    $output .= "<div class=\"yandex_metrics_reports-report\" id=\"{$type}\">";
    $output .= $report_content . '</div>';
  }
  return $output;
}

/**
 * Retrieves analytic information from Yandex.Metrica.
 *
 * @param string $service_uri
 *    Short uri of service.
 * @param array $parameters
 *    Associative array with parameters.
 * @param string $result_type
 *    Result type (json, xml).
 */
function yandex_metrics_reports_retreive_data($service_uri, $parameters = array(), $result_type = 'json') {
  $parameters['oauth_token'] = yandex_services_auth_info('token');
  $query_parts = array();
  foreach ($parameters as $key => $value) {
    $query_parts[] = $key . '=' . $value;
  }
  $parameter_string = implode('&', $query_parts);
  $full_service_url = "http://api-metrika.yandex.ru" . $service_uri . "." . $result_type . "?" . $parameter_string;
  return drupal_http_request($full_service_url);
}

/**
 * Gets counter ID for the current site from Yandex.Metrica.
 */
function yandex_metrics_reports_get_counter_for_current_site() {
  $counter_id = variable_get('yandex_metrics_reports_counter_id', '');
  if (!empty($counter_id)) {
    return $counter_id;
  }
  $result = yandex_metrics_reports_retreive_data('/counters', array(
    'field' => 'mirrors',
  ));
  if (isset($result->error)) {
    watchdog('yandex_metrics_reports', 'Counters request seems to be fail, due to "%error".', array(
      '%error' => $result->code . ' ' . $result->error,
    ), WATCHDOG_WARNING);
    return FALSE;
  }
  $counters = json_decode($result->data);
  $current_host = $_SERVER['HTTP_HOST'];

  // Try to decode national domain.
  $decoded_domain = _yandex_metrics_reports_idna_decode($current_host);
  if ($decoded_domain != FALSE && $decoded_domain != $current_host) {
    $current_host = $decoded_domain;
  }

  // Collect all registered domains and their mirrors for all counters.
  $registered_hosts = array();
  foreach ($counters->counters as $counter) {

    // If current host is the main counter host.
    if ($counter->site == $current_host) {
      variable_set('yandex_metrics_reports_counter_id', $counter->id);
      return $counter->id;
    }

    // If current host is in site mirrors.
    if (isset($counter->mirrors) && in_array($current_host, $counter->mirrors)) {
      variable_set('yandex_metrics_reports_counter_id', $counter->id);
      return $counter->id;
    }

    // Include counter host and mirrors to the $registered_hosts array
    // in case current host doesn't belong to the counter.
    $registered_hosts[] = $counter->site;
    $registered_hosts = array_merge($registered_hosts, $counter->mirrors);
  }
  watchdog('yandex_metrics_reports', 'The site host does not belong to any Yandex.Metrika counter of the account. Current host: "%host". Known hosts: "%registered_hosts".', array(
    '%host' => $current_host,
    "%registered_hosts" => implode('", "', $registered_hosts),
  ), WATCHDOG_WARNING);
  drupal_set_message(t('The site host does not belong to any Yandex.Metrika counter of the account. Check your counter host and mirrors. Pay special attention to the www. prefix.'), 'error');
  return FALSE;
}

/**
 * Callback that prints content of one of the 4 reports.
 *
 * It is intended for AJAX calls.
 */
function yandex_metrics_reports_render_report($counter_id, $filter, $type) {
  $output = '';
  $reports = yandex_metrics_reports_get_list();
  if (isset($reports[$type]) && isset($reports[$type]['callback']) && function_exists($reports[$type]['callback'])) {
    $output = call_user_func($reports[$type]['callback'], $counter_id, $filter);
  }
  return $output;
}

/**
 * Menu callback. Reports setting form.
 */
function yandex_metrics_reports_reports() {
  $form = array();
  $reports = yandex_metrics_reports_get_list();
  foreach ($reports as $report_name => $report_data) {
    $form['reports'][$report_name]['yandex_metrics_reports_' . $report_name . '_visible'] = array(
      '#type' => 'checkbox',
      '#title' => check_plain($report_data['title']),
      '#default_value' => isset($report_data['visible']) && !$report_data['visible'] ? FALSE : TRUE,
    );
    $form['reports'][$report_name]['yandex_metrics_reports_' . $report_name . '_weight'] = array(
      '#type' => 'weight',
      '#delta' => 100,
      '#default_value' => (int) $report_data['weight'],
      '#attributes' => array(
        'class' => array(
          'yandex-metrics-reports-report-weight',
        ),
      ),
    );
  }
  $form['save'] = array(
    '#type' => 'submit',
    '#value' => t('Save configuration'),
  );
  $form['reset'] = array(
    '#type' => 'submit',
    '#value' => t('Reset to default'),
  );
  return $form;
}

/**
 * Submit handler for yandex_metrics_reports_reports form.
 */
function yandex_metrics_reports_reports_submit($form, &$form_state) {
  $values = $form_state['values'];
  if ($values['op'] == t('Reset to default')) {
    yandex_metrics_reports_get_list(TRUE);
    return;
  }
  $reports = yandex_metrics_reports_get_list();
  foreach ($reports as $report_name => $report_data) {
    $reports[$report_name]['visible'] = $values['yandex_metrics_reports_' . $report_name . '_visible'];
    $reports[$report_name]['weight'] = $values['yandex_metrics_reports_' . $report_name . '_weight'];
  }
  yandex_metrics_reports_sort_and_save($reports);
}

/**
 * Sort and save reports array to the variable.
 */
function yandex_metrics_reports_sort_and_save($reports) {

  // Sort by weight.
  usort($reports, '_yandex_metrics_reports_sort_reports_by_weight');
  variable_set('yandex_metrics_reports_list', $reports);
}

/**
 * Theme function for the Report setting table.
 */
function theme_yandex_metrics_reports_reports($vars) {
  $form = $vars['form'];
  $header = array(
    array(
      'data' => t('Report visibility settings'),
      'colspan' => 2,
    ),
  );
  $rows = array();
  foreach (element_children($form['reports']) as $report_name) {
    $row = array(
      drupal_render($form['reports'][$report_name]['yandex_metrics_reports_' . $report_name . '_visible']),
      drupal_render($form['reports'][$report_name]['yandex_metrics_reports_' . $report_name . '_weight']),
    );
    $rows[] = array(
      'data' => $row,
      'class' => array(
        'draggable',
      ),
    );
  }
  $output = theme('table', array(
    'header' => $header,
    'rows' => $rows,
    'attributes' => array(
      'id' => 'yandex-metrics-reports-reports-table',
    ),
  ));
  drupal_add_tabledrag('yandex-metrics-reports-reports-table', 'order', 'sibling', 'yandex-metrics-reports-report-weight');
  $output .= drupal_render_children($form);
  return $output;
}

/**
 * Returns path of idna_convert class.
 */
function _yandex_metrics_reports_get_idna_library_path() {
  $file = 'idna_convert.class.php';
  $library = 'idna_convert';
  if (module_exists('libraries') && file_exists(libraries_get_path($library) . "/{$file}")) {
    return libraries_get_path($library) . "/{$file}";
  }
  else {
    $paths = array(
      drupal_get_path('module', 'yandex_metrics'),
      drupal_get_path('module', 'yandex_metrics') . "/libraries",
      drupal_get_path('module', 'yandex_metrics_reports'),
      drupal_get_path('module', 'yandex_metrics_reports') . "/libraries",
      'profiles/' . variable_get('install_profile', 'default') . '/libraries',
      'profiles/' . variable_get('install_profile', 'default') . '/libraries/' . $library,
      'sites/all/libraries',
      'sites/all/libraries/' . $library,
    );
    foreach ($paths as $library_path) {
      $path = $library_path . "/{$file}";
      if (file_exists($path)) {
        return $path;
      }
    }
  }
  return FALSE;
}

/**
 * Decode ASCII 'xn--*' domain name to Unicode national domain name.
 *
 * Used idna_convert module if it's installed
 * or idna_convert class created by Matthias Sommerfeld <mso@phlylabs.de>
 * and licensed under LGPL.
 *
 * @see http://www.phpclasses.org/package/1509-PHP-Convert-from-and-to-IDNA-Punycode-domain-names.html
 */
function _yandex_metrics_reports_idna_decode($domain) {

  // Use idna_convert module function if it's available.
  if (function_exists('idna_convert_decode')) {
    return idna_convert_decode($domain);
  }
  $idna_library_path = _yandex_metrics_reports_get_idna_library_path();

  // Library has not been found.
  if ($idna_library_path == FALSE) {
    return $domain;
  }
  require_once $idna_library_path;
  $idn = new idna_convert();
  return $idn
    ->decode($domain);
}

/**
 * Implements hook_help().
 */
function yandex_metrics_reports_help($path, $arg) {
  $output = '';
  switch ($path) {
    case 'admin/help#yandex_metrics_reports':
      $output = '';
      $output .= '<h3>' . t('About the module') . '</h3>';
      $output .= '<p>' . t('The <a href="@yandex_metrika" target="_blank">Yandex.Metrica</a> service is European alternative of Google Analytics. This is a free tool that helps you to increase the conversion rate of your site.', array(
        '@yandex_metrika' => 'http://metrika.yandex.ru/',
      )) . '</p>';
      $output .= '<p>' . t('The Yandex.Metrics Reports module allows to view basic reports by key effectiveness indicators.') . '</p>';
      $output .= '<h3>' . t('Usage') . '</h3>';
      $output .= '<dl>';
      $output .= '<dt>' . t('Authorizing site') . '</dt>';
      $output .= '<dd>' . t('Register Yandex application and authorize your site following <a href="!yandex_services_oauth">the documentation of Yandex Services Authorization API module</a>.', array(
        '!yandex_services_oauth' => url('admin/help/yandex_services_auth'),
      )) . '</dd>';
      $output .= '<dt>' . t('Configuring reports') . '</dt>';
      $output .= '<dd>' . t('You can choose necessary reports <a href="@report-setting-page">here</a> to display on <a href="@summary-report-page">Yandex.Metrics Summary Report</a> page.', array(
        '@summary-report-page' => url('admin/reports/yandex_metrics_summary'),
        '@report-setting-page' => url('admin/config/system/yandex_metrics/reports'),
      )) . '</dd>';
      $output .= '<dt>' . t('Reports API') . '</dt>';
      $output .= '<dd>' . t('The module has API for developers which allows you to implement new reports in own modules. Please read module README.txt file for more information.') . '</dd>';
      $output .= '</dl>';
      break;
    case 'admin/config/system/yandex_metrics/reports':
      $output = '<p>' . t('You can choose necessary reports to display on <a href="@summary-report-page">Yandex.Metrics Summary Report</a> page.', array(
        '@summary-report-page' => url('admin/reports/yandex_metrics_summary'),
      )) . '</p>';
      break;
  }
  return $output;
}

/**
 * Implements hook_yandex_metrics_reports_list().
 */
function yandex_metrics_reports_yandex_metrics_reports_list() {
  $reports = array();
  $reports['visits_chart'] = array(
    'title' => t('Page Views, Visitors, New Visitors'),
    'callback' => 'yandex_metrics_reports_visits_chart',
    'weight' => 10,
  );
  $reports['sources_chart'] = array(
    'title' => t('Traffic Sources'),
    'callback' => 'yandex_metrics_reports_sources_chart',
    'weight' => 20,
  );
  $reports['search_phrases'] = array(
    'title' => t('Popular Search Phrases'),
    'callback' => 'yandex_metrics_reports_search_phrases',
    'weight' => 30,
  );
  $reports['popular_content'] = array(
    'title' => t('Popular Content'),
    'callback' => 'yandex_metrics_reports_popular_content',
    'weight' => 40,
  );
  $reports['geo_chart'] = array(
    'title' => t('Geography of Visits'),
    'callback' => 'yandex_metrics_reports_geo_chart',
    'weight' => 50,
  );
  $reports['hourly_chart'] = array(
    'title' => t('Hourly Traffic'),
    'callback' => 'yandex_metrics_reports_traffic_hourly_chart',
    'weight' => 60,
  );
  $reports['gender_chart'] = array(
    'title' => t('Demography of Visits'),
    'callback' => 'yandex_metrics_reports_gender_chart',
    'weight' => 70,
  );
  return $reports;
}

/**
 * Sort callback that helps to sort reports by weight.
 */
function _yandex_metrics_reports_sort_reports_by_weight($a, $b) {
  if (!isset($a['weight'])) {
    $a['weight'] = 0;
  }
  if (!isset($b['weight'])) {
    $b['weight'] = 0;
  }
  return $a['weight'] - $b['weight'];
}

/**
 * Returns list of all reports.
 */
function yandex_metrics_reports_get_list($reset = FALSE) {
  $reports =& drupal_static(__FUNCTION__);
  if (!isset($reports) || $reset) {

    // Permanent cache.
    $cache = variable_get('yandex_metrics_reports_list');
    if ($cache === NULL || $reset) {
      $reports = array();
      foreach (module_implements('yandex_metrics_reports_list') as $module) {
        $module_report_list = module_invoke($module, 'yandex_metrics_reports_list');
        if (isset($module_report_list) && is_array($module_report_list)) {
          $reports = array_merge($reports, $module_report_list);
        }
      }

      // Allow other modules to alter reports list before caching.
      drupal_alter('yandex_metrics_reports_list', $reports);
      yandex_metrics_reports_sort_and_save($reports);
    }
    else {
      $reports = $cache;
    }
  }
  return $reports;
}

/**
 * Returns list of available and enabled reports only.
 */
function yandex_metrics_reports_get_active_list() {
  $reports = yandex_metrics_reports_get_list();
  foreach ($reports as $report_name => $report_data) {
    if (isset($report_data['visible']) && !$report_data['visible'] || !function_exists($report_data['callback'])) {
      unset($reports[$report_name]);
    }
  }
  return $reports;
}

/**
 * Returns string with human-readable filter's name.
 */
function yandex_metrics_reports_get_filter_name($filter) {
  $filters = yandex_metrics_reports_get_filters();
  return isset($filters[$filter]) ? $filters[$filter] : FALSE;
}

/**
 * Returns array with list of all available filters.
 */
function yandex_metrics_reports_get_filters() {
  return array(
    'day' => t('Today'),
    'yesterday' => t('Yesterday'),
    'week' => t('Week'),
    'month' => t('Month'),
  );
}

/**
 * Callback for title on summary page, which is modified depending on time period.
 *
 * @param $filter
 * @return string
 */
function yandex_metrics_reports_summary_page_title_callback($filter) {
  $title = t('Yandex.Metrics Summary Report') . ': ' . yandex_metrics_reports_get_filter_name($filter);
  return $title;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Add submit handler for Yandex Services Authorization.
 */
function yandex_metrics_reports_form_yandex_services_auth_admin_settings_alter(&$form, &$form_state, $form_id) {
  array_unshift($form['#submit'], 'yandex_metrics_reports_reset_counter_id');
}

/**
 * Reset counter ID on authorization via Yandex Services Authorization.
 */
function yandex_metrics_reports_reset_counter_id($form, &$form_state) {
  variable_set('yandex_metrics_reports_counter_id', '');
}

Functions

Namesort descending Description
theme_yandex_metrics_reports_reports Theme function for the Report setting table.
yandex_metrics_reports_filter_form It is quick filter form for report page.
yandex_metrics_reports_filter_form_submit Form submit handler for yandex_metrics_reports_time_interval_form form.
yandex_metrics_reports_filter_to_date_range Converts filter value to date range array.
yandex_metrics_reports_form_yandex_services_auth_admin_settings_alter Implements hook_form_FORM_ID_alter().
yandex_metrics_reports_get_active_list Returns list of available and enabled reports only.
yandex_metrics_reports_get_counter_for_current_site Gets counter ID for the current site from Yandex.Metrica.
yandex_metrics_reports_get_filters Returns array with list of all available filters.
yandex_metrics_reports_get_filter_name Returns string with human-readable filter's name.
yandex_metrics_reports_get_list Returns list of all reports.
yandex_metrics_reports_help Implements hook_help().
yandex_metrics_reports_init Implements hook_init().
yandex_metrics_reports_menu Implements hook_menu().
yandex_metrics_reports_permission Implements hook_permission().
yandex_metrics_reports_render_report Callback that prints content of one of the 4 reports.
yandex_metrics_reports_report Menu callback; displays a Summary page containing reports and charts.
yandex_metrics_reports_reports Menu callback. Reports setting form.
yandex_metrics_reports_reports_submit Submit handler for yandex_metrics_reports_reports form.
yandex_metrics_reports_reset_counter_id Reset counter ID on authorization via Yandex Services Authorization.
yandex_metrics_reports_retreive_data Retrieves analytic information from Yandex.Metrica.
yandex_metrics_reports_sort_and_save Sort and save reports array to the variable.
yandex_metrics_reports_summary_page_title_callback Callback for title on summary page, which is modified depending on time period.
yandex_metrics_reports_theme Implements hook_theme().
yandex_metrics_reports_yandex_metrics_reports_list Implements hook_yandex_metrics_reports_list().
_yandex_metrics_reports_get_idna_library_path Returns path of idna_convert class.
_yandex_metrics_reports_idna_decode Decode ASCII 'xn--*' domain name to Unicode national domain name.
_yandex_metrics_reports_sort_reports_by_weight Sort callback that helps to sort reports by weight.

Constants

Namesort descending Description
YANDEX_METRICS_REPORTS_POPULAR_CONTENT_COUNT Quantity of popular content lines.
YANDEX_METRICS_REPORTS_SEARCH_PHRASES_QUANTITY Quantity of popular search phrases.