Commit 3e677343 authored by Riccardo Padovani's avatar Riccardo Padovani

Updated module google_analytics to 7.x-2.1

parent adf988be
......@@ -184,7 +184,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'checkbox',
'#title' => t('Track User ID'),
'#default_value' => variable_get('googleanalytics_trackuserid', 0),
'#description' => t('User ID enables the analysis of groups of sessions, across devices, using a unique, persistent, and non-personally identifiable ID string representing a user. <a href="@url">Learn more about the benfits of using User ID</a>.', array('@url' => 'https://support.google.com/analytics/answer/3123663')),
'#description' => t('User ID enables the analysis of groups of sessions, across devices, using a unique, persistent, and non-personally identifiable ID string representing a user. <a href="@url">Learn more about the benefits of using User ID</a>.', array('@url' => 'https://support.google.com/analytics/answer/3123663')),
);
// Link specific configurations.
......@@ -213,7 +213,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'textfield',
'#default_value' => variable_get('googleanalytics_trackfiles_extensions', GOOGLEANALYTICS_TRACKFILES_EXTENSIONS),
'#description' => t('A file extension list separated by the | character that will be tracked as download when clicked. Regular expressions are supported. For example: !extensions', array('!extensions' => GOOGLEANALYTICS_TRACKFILES_EXTENSIONS)),
'#maxlength' => 255,
'#maxlength' => 500,
'#states' => array(
'enabled' => array(
':input[name="googleanalytics_trackfiles"]' => array('checked' => TRUE),
......@@ -254,8 +254,6 @@ function googleanalytics_admin_settings_form($form_state) {
),
);
// Google already have many translations, if not - they display a note to change the language.
global $language;
$form['tracking']['search_and_advertising'] = array(
'#type' => 'fieldset',
'#title' => t('Search and Advertising'),
......@@ -307,7 +305,7 @@ function googleanalytics_admin_settings_form($form_state) {
$form['googleanalytics_custom_dimension'] = array(
'#collapsed' => TRUE,
'#collapsible' => TRUE,
'#description' => t('You can set values for Google Analytics <a href="@custom_var_documentation">Custom Dimensions</a> here. You must have already configured your custom dimensions in the <a href="@setup_documentation">Google Analytics Management Interface</a>. You may use tokens. Global and user tokens are always available; on node pages, node tokens are also available.', array('@custom_var_documentation' => 'https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets', '@setup_documentation' => 'https://support.google.com/analytics/answer/2709829')),
'#description' => t('You can set values for Google Analytics <a href="@custom_var_documentation">Custom Dimensions</a> here. You must have already configured your custom dimensions in the <a href="@setup_documentation">Google Analytics Management Interface</a>. You may use tokens. Global and user tokens are always available; on node pages, node tokens are also available. A dimension <em>value</em> is allowed to have a maximum lenght of 150 bytes. Expect longer values to get trimmed.', array('@custom_var_documentation' => 'https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets', '@setup_documentation' => 'https://support.google.com/analytics/answer/2709829')),
'#theme' => 'googleanalytics_admin_custom_var_table',
'#title' => t('Custom dimensions'),
'#tree' => TRUE,
......@@ -328,7 +326,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'textfield',
);
$form['googleanalytics_custom_dimension']['indexes'][$i]['value'] = array(
'#default_value' => !empty($googleanalytics_custom_dimension['indexes'][$i]['value']) ? $googleanalytics_custom_dimension['indexes'][$i]['value'] : '',
'#default_value' => isset($googleanalytics_custom_dimension[$i]['value']) ? $googleanalytics_custom_dimension[$i]['value'] : '',
'#description' => t('The custom dimension value.'),
'#maxlength' => 255,
'#title' => t('Custom dimension value #@index', array('@index' => $i)),
......@@ -346,11 +344,13 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'item',
'#description' => t('You can supplement Google Analytics\' basic IP address tracking of visitors by segmenting users based on custom dimensions. Section 7 of the <a href="@ga_tos">Google Analytics terms of service</a> requires that You will not (and will not allow any third party to) use the Service to track, collect or upload any data that personally identifies an individual (such as a name, userid, email address or billing information), or other data which can be reasonably linked to such information by Google. You will have and abide by an appropriate Privacy Policy and will comply with all applicable laws and regulations relating to the collection of information from Visitors. You must post a Privacy Policy and that Privacy Policy must provide notice of Your use of cookies that are used to collect traffic data, and You must not circumvent any privacy features (e.g., an opt-out) that are part of the Service.', array('@ga_tos' => 'http://www.google.com/analytics/terms/gb.html')),
);
if (module_exists('token')) {
$form['googleanalytics_custom_dimension']['googleanalytics_token_tree'] = array(
'#theme' => 'token_tree',
'#token_types' => array('node'),
'#dialog' => TRUE,
);
}
// Custom Metrics.
$form['googleanalytics_custom_metric'] = array(
......@@ -377,7 +377,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'textfield',
);
$form['googleanalytics_custom_metric']['indexes'][$i]['value'] = array(
'#default_value' => !empty($googleanalytics_custom_metric['indexes'][$i]['value']) ? $googleanalytics_custom_metric['indexes'][$i]['value'] : '',
'#default_value' => isset($googleanalytics_custom_metric[$i]['value']) ? $googleanalytics_custom_metric[$i]['value'] : '',
'#description' => t('The custom metric value.'),
'#maxlength' => 255,
'#title' => t('Custom metric value #@index', array('@index' => $i)),
......@@ -395,11 +395,13 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'item',
'#description' => t('You can supplement Google Analytics\' basic IP address tracking of visitors by segmenting users based on custom metrics. Section 7 of the <a href="@ga_tos">Google Analytics terms of service</a> requires that You will not (and will not allow any third party to) use the Service to track, collect or upload any data that personally identifies an individual (such as a name, userid, email address or billing information), or other data which can be reasonably linked to such information by Google. You will have and abide by an appropriate Privacy Policy and will comply with all applicable laws and regulations relating to the collection of information from Visitors. You must post a Privacy Policy and that Privacy Policy must provide notice of Your use of cookies that are used to collect traffic data, and You must not circumvent any privacy features (e.g., an opt-out) that are part of the Service.', array('@ga_tos' => 'http://www.google.com/analytics/terms/gb.html')),
);
if (module_exists('token')) {
$form['googleanalytics_custom_metric']['googleanalytics_token_tree'] = array(
'#theme' => 'token_tree',
'#token_types' => array('node'),
'#dialog' => TRUE,
);
}
// Advanced feature configurations.
$form['advanced'] = array(
......@@ -473,10 +475,21 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) {
// Trim custom dimensions and metrics.
foreach ($form_state['values']['googleanalytics_custom_dimension']['indexes'] as $dimension) {
$form_state['values']['googleanalytics_custom_dimension']['indexes'][$dimension['index']]['value'] = trim($dimension['value']);
// Remove empty values from the array.
if (!drupal_strlen($form_state['values']['googleanalytics_custom_dimension']['indexes'][$dimension['index']]['value'])) {
unset($form_state['values']['googleanalytics_custom_dimension']['indexes'][$dimension['index']]);
}
}
$form_state['values']['googleanalytics_custom_dimension'] = $form_state['values']['googleanalytics_custom_dimension']['indexes'];
foreach ($form_state['values']['googleanalytics_custom_metric']['indexes'] as $metric) {
$form_state['values']['googleanalytics_custom_metric']['indexes'][$metric['index']]['value'] = trim($metric['value']);
// Remove empty values from the array.
if (!drupal_strlen($form_state['values']['googleanalytics_custom_metric']['indexes'][$metric['index']]['value'])) {
unset($form_state['values']['googleanalytics_custom_metric']['indexes'][$metric['index']]);
}
}
$form_state['values']['googleanalytics_custom_metric'] = $form_state['values']['googleanalytics_custom_metric']['indexes'];
// Trim some text values.
$form_state['values']['googleanalytics_account'] = trim($form_state['values']['googleanalytics_account']);
......@@ -497,6 +510,11 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) {
if ($form_state['values']['googleanalytics_domain_mode'] == 2 && empty($form_state['values']['googleanalytics_cross_domains'])) {
form_set_error('googleanalytics_cross_domains', t('A list of top-level domains is required if <em>Multiple top-level domains</em> has been selected.'));
}
// Clear the domain list if cross domains are disabled.
if ($form_state['values']['googleanalytics_domain_mode'] != 2) {
$form_state['values']['googleanalytics_cross_domains'] = '';
}
// Disallow empty list of download file extensions.
if ($form_state['values']['googleanalytics_trackfiles'] && empty($form_state['values']['googleanalytics_trackfiles_extensions'])) {
form_set_error('googleanalytics_trackfiles_extensions', t('List of download file extensions cannot empty.'));
......@@ -544,7 +562,9 @@ function theme_googleanalytics_admin_custom_var_table($variables) {
$output = theme('table', array('header' => $header, 'rows' => $rows));
$output .= drupal_render($form['googleanalytics_description']);
if (isset($form['googleanalytics_token_tree'])) {
$output .= drupal_render($form['googleanalytics_token_tree']);
}
return $output;
}
......@@ -735,7 +755,6 @@ function _googleanalytics_validate_create_field_name($name) {
// List of supported field names:
// https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#create
$create_only_fields = array(
'name',
'clientId',
'userId',
'sampleRate',
......@@ -748,8 +767,14 @@ function _googleanalytics_validate_create_field_name($name) {
'legacyCookieDomain',
);
if ($name == 'name') {
return t('Create only field name %name is a disallowed field name. Changing the <em>Tracker Name</em> is currently not supported.', array('%name' => $name));
}
if ($name == 'allowLinker') {
return t('Create only field name %name is a disallowed field name. Please select <em>Multiple top-level domains</em> under <em>What are you tracking</em> to enable cross domain tracking.', array('%name' => $name));
}
if (!in_array($name, $create_only_fields)) {
return t('Field name %name is an unknown field name. Please see <a href="@url">create only fields</a> documentation for supported field names.', array('%name' => $name, '@url' => 'https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#create'));
return t('Create only field name %name is an unknown field name. Field names are case sensitive. Please see <a href="@url">create only fields</a> documentation for supported field names.', array('%name' => $name, '@url' => 'https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#create'));
}
}
......@@ -763,11 +788,11 @@ function _googleanalytics_validate_create_field_name($name) {
* The error message if the specified value is invalid, NULL otherwise.
*/
function _googleanalytics_validate_create_field_value($value) {
if (!is_bool($value) && empty($value)) {
return t('A value is required.');
if (!is_bool($value) && !drupal_strlen($value)) {
return t('A create only field requires a value.');
}
if (drupal_strlen($value) > 255) {
return t('Each value must be a string at most 255 characters long.');
return t('The value of a create only field must be a string at most 255 characters long.');
}
}
......
......@@ -30,7 +30,7 @@ $(document).ready(function() {
else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
// Keep the internal URL for Google Analytics website overlay intact.
console.info("Click on internal special link '%s' has been tracked.", Drupal.googleanalytics.getPageUrl(this.href));
ga("send", "pageview", { page: Drupal.googleanalytics.getPageUrl(this.href) });
ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(this.href) });
}
else {
// e.g. anchor in same page or other internal page link
......@@ -44,7 +44,7 @@ $(document).ready(function() {
ga("send", "event", "Mails", "Click", this.href.substring(7));
}
else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) {
if (Drupal.settings.googleanalytics.trackDomainMode != 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains)) {
if (Drupal.settings.googleanalytics.trackDomainMode != 2 || (Drupal.settings.googleanalytics.trackDomainMode == 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
// External link clicked / No top-level cross domain clicked.
console.info("Outbound link '%s' has been tracked.", this.href);
ga("send", "event", "Outbound links", "Click", this.href);
......@@ -73,7 +73,7 @@ $(document).ready(function() {
var href = $.colorbox.element().attr("href");
if (href) {
console.info("Colorbox transition to url '%s' has been tracked.", Drupal.googleanalytics.getPageUrl(href));
ga("send", "pageview", { page: Drupal.googleanalytics.getPageUrl(href) });
ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(href) });
}
});
......@@ -103,7 +103,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
else {
return $.inArray(hostname, crossDomains) > -1 ? true : false;
}
}
};
/**
* Check whether this is a download URL or not.
......@@ -116,7 +116,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
Drupal.googleanalytics.isDownload = function (url) {
var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
return isDownload.test(url);
}
};
/**
* Check whether this is an absolute internal URL or not.
......@@ -129,7 +129,7 @@ Drupal.googleanalytics.isDownload = function (url) {
Drupal.googleanalytics.isInternal = function (url) {
var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i");
return isInternal.test(url);
}
};
/**
* Check whether this is a special URL or not.
......@@ -145,7 +145,7 @@ Drupal.googleanalytics.isInternal = function (url) {
Drupal.googleanalytics.isInternalSpecial = function (url) {
var isInternalSpecial = new RegExp("(\/go\/.*)$", "i");
return isInternalSpecial.test(url);
}
};
/**
* Extract the relative internal URL from an absolute internal URL.
......@@ -163,7 +163,7 @@ Drupal.googleanalytics.isInternalSpecial = function (url) {
Drupal.googleanalytics.getPageUrl = function (url) {
var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i");
return url.replace(extractInternalUrl, '');
}
};
/**
* Extract the download file extension from the URL.
......@@ -178,6 +178,6 @@ Drupal.googleanalytics.getDownloadExtension = function (url) {
var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
var extension = extractDownloadextension.exec(url);
return (extension === null) ? '' : extension[1];
}
};
})(jQuery);
......@@ -5,9 +5,9 @@ package = Statistics
configure = admin/config/system/googleanalytics
files[] = googleanalytics.test
test_dependencies[] = token
; Information added by Drupal.org packaging script on 2014-07-01
version = "7.x-2.0"
; Information added by Drupal.org packaging script on 2014-11-29
version = "7.x-2.1"
core = "7.x"
project = "google_analytics"
datestamp = "1404257628"
datestamp = "1417276982"
......@@ -41,11 +41,8 @@ function googleanalytics_uninstall() {
variable_del('googleanalytics_privacy_donottrack');
// Remove backup variables if exist. Remove this code in D8.
variable_del('googleanalytics_codesnippet_after_backup_6300');
variable_del('googleanalytics_codesnippet_before_backup_6300');
variable_del('googleanalytics_codesnippet_after_backup_7200');
variable_del('googleanalytics_codesnippet_before_backup_7200');
variable_del('googleanalytics_segmentation');
}
/**
......@@ -74,7 +71,7 @@ function googleanalytics_requirements($phase) {
'value' => $t('Not configured'),
);
}
}
// Raise warning if debugging is enabled.
if (variable_get('googleanalytics_debug', 0)) {
$requirements['google_analytics_debugging'] = array(
......@@ -84,6 +81,7 @@ function googleanalytics_requirements($phase) {
'value' => $t('Debugging enabled'),
);
}
}
return $requirements;
}
......@@ -445,7 +443,7 @@ function googleanalytics_update_7200() {
// ga.js code will cause the tracker to break. Remove custom code snippets.
$googleanalytics_codesnippet_before = variable_get('googleanalytics_codesnippet_before', '');
if (!empty($googleanalytics_codesnippet_before)) {
if (!empty($googleanalytics_codesnippet_before) && stristr($googleanalytics_codesnippet_before, '_gaq.push(')) {
variable_set('googleanalytics_codesnippet_before_backup_7200', $googleanalytics_codesnippet_before);
variable_del('googleanalytics_codesnippet_before');
drupal_set_message(Database::getConnection()->prefixTables("A backup of your previous Google Analytics code snippet has been saved in database table '{variable}' as 'googleanalytics_codesnippet_before_backup_7200'. You need to manually upgrade the custom 'before' code snippet."), 'warning');
......@@ -453,7 +451,7 @@ function googleanalytics_update_7200() {
}
$googleanalytics_codesnippet_after = variable_get('googleanalytics_codesnippet_after', '');
if (!empty($googleanalytics_codesnippet_after)) {
if (!empty($googleanalytics_codesnippet_after) && stristr($googleanalytics_codesnippet_after, '_gaq.push(')) {
variable_set('googleanalytics_codesnippet_after_backup_7200', $googleanalytics_codesnippet_after);
variable_del('googleanalytics_codesnippet_after');
drupal_set_message(Database::getConnection()->prefixTables("A backup of your previous Google Analytics code snippet has been saved in database table '{variable}' as 'googleanalytics_codesnippet_before_backup_7200'. You need to manually upgrade the custom 'before' code snippet."), 'warning');
......@@ -481,3 +479,59 @@ function googleanalytics_update_7202() {
return t('Removed obsolete JavaScript scope variable.');
}
/**
* Flatten the metrics and dimensions arrays.
*/
function googleanalytics_update_7203() {
$googleanalytics_custom_dimension = variable_get('googleanalytics_custom_dimension', array());
if (isset($googleanalytics_custom_dimension['indexes'])) {
foreach ($googleanalytics_custom_dimension['indexes'] as $dimension) {
$googleanalytics_custom_dimension['indexes'][$dimension['index']]['value'] = trim($dimension['value']);
// Remove empty values from the array.
if (!drupal_strlen($googleanalytics_custom_dimension['indexes'][$dimension['index']]['value'])) {
unset($googleanalytics_custom_dimension['indexes'][$dimension['index']]);
}
}
variable_set('googleanalytics_custom_dimension', $googleanalytics_custom_dimension['indexes']);
}
$googleanalytics_custom_metric = variable_get('googleanalytics_custom_metric', array());
if (isset($googleanalytics_custom_metric['indexes'])) {
foreach ($googleanalytics_custom_metric['indexes'] as $dimension) {
$googleanalytics_custom_metric['indexes'][$dimension['index']]['value'] = trim($dimension['value']);
// Remove empty values from the array.
if (!drupal_strlen($googleanalytics_custom_metric['indexes'][$dimension['index']]['value'])) {
unset($googleanalytics_custom_metric['indexes'][$dimension['index']]);
}
}
variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric['indexes']);
}
return t('Saved custom dimensions and metrics.');
}
/**
* Remove obsolete backup variables.
*/
function googleanalytics_update_7204() {
variable_del('googleanalytics_segmentation');
variable_del('googleanalytics_codesnippet_after_backup_6300');
variable_del('googleanalytics_codesnippet_before_backup_6300');
variable_del('googleanalytics_codesnippet_after_backup_6400');
variable_del('googleanalytics_codesnippet_before_backup_6400');
return t('Removed obsolete backup variables.');
}
/**
* Update list of default file extensions.
*/
function googleanalytics_update_7205() {
if (variable_get('googleanalytics_trackfiles_extensions', '') == '7z|aac|arc|arj|asf|asx|avi|bin|csv|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt|qtm?|ra(m|r)?|sea|sit|tar|tgz|torrent|txt|wav|wma|wmv|wpd|xls|xml|z|zip') {
variable_set('googleanalytics_trackfiles_extensions', '7z|aac|arc|arj|asf|asx|avi|bin|csv|doc(x|m)?|dot(x|m)?|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt(x|m)?|pot(x|m)?|pps(x|m)?|ppam|sld(x|m)?|thmx|qtm?|ra(m|r)?|sea|sit|tar|tgz|torrent|txt|wav|wma|wmv|wpd|xls(x|m|b)?|xlt(x|m)|xlam|xml|z|zip');
return t('The default extensions for download tracking have been updated.');
}
else {
return t('Custom extensions for download tracking setting found. Update skipped!');
}
}
......@@ -25,7 +25,7 @@ $(document).ready(function() {
}
else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
// Keep the internal URL for Google Analytics website overlay intact.
ga("send", "pageview", { page: Drupal.googleanalytics.getPageUrl(this.href) });
ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(this.href) });
}
}
else {
......@@ -34,7 +34,7 @@ $(document).ready(function() {
ga("send", "event", "Mails", "Click", this.href.substring(7));
}
else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) {
if (Drupal.settings.googleanalytics.trackDomainMode != 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains)) {
if (Drupal.settings.googleanalytics.trackDomainMode != 2 || (Drupal.settings.googleanalytics.trackDomainMode == 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
// External link clicked / No top-level cross domain clicked.
ga("send", "event", "Outbound links", "Click", this.href);
}
......@@ -55,7 +55,7 @@ $(document).ready(function() {
$(document).bind("cbox_complete", function () {
var href = $.colorbox.element().attr("href");
if (href) {
ga("send", "pageview", { page: Drupal.googleanalytics.getPageUrl(href) });
ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(href) });
}
});
......@@ -85,7 +85,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
else {
return $.inArray(hostname, crossDomains) > -1 ? true : false;
}
}
};
/**
* Check whether this is a download URL or not.
......@@ -98,7 +98,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
Drupal.googleanalytics.isDownload = function (url) {
var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
return isDownload.test(url);
}
};
/**
* Check whether this is an absolute internal URL or not.
......@@ -111,7 +111,7 @@ Drupal.googleanalytics.isDownload = function (url) {
Drupal.googleanalytics.isInternal = function (url) {
var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i");
return isInternal.test(url);
}
};
/**
* Check whether this is a special URL or not.
......@@ -127,7 +127,7 @@ Drupal.googleanalytics.isInternal = function (url) {
Drupal.googleanalytics.isInternalSpecial = function (url) {
var isInternalSpecial = new RegExp("(\/go\/.*)$", "i");
return isInternalSpecial.test(url);
}
};
/**
* Extract the relative internal URL from an absolute internal URL.
......@@ -145,7 +145,7 @@ Drupal.googleanalytics.isInternalSpecial = function (url) {
Drupal.googleanalytics.getPageUrl = function (url) {
var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i");
return url.replace(extractInternalUrl, '');
}
};
/**
* Extract the download file extension from the URL.
......@@ -160,6 +160,6 @@ Drupal.googleanalytics.getDownloadExtension = function (url) {
var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
var extension = extractDownloadextension.exec(url);
return (extension === null) ? '' : extension[1];
}
};
})(jQuery);
......@@ -13,7 +13,7 @@
/**
* Define the default file extension list that should be tracked as download.
*/
define('GOOGLEANALYTICS_TRACKFILES_EXTENSIONS', '7z|aac|arc|arj|asf|asx|avi|bin|csv|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt|qtm?|ra(m|r)?|sea|sit|tar|tgz|torrent|txt|wav|wma|wmv|wpd|xls|xml|z|zip');
define('GOOGLEANALYTICS_TRACKFILES_EXTENSIONS', '7z|aac|arc|arj|asf|asx|avi|bin|csv|doc(x|m)?|dot(x|m)?|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|msi|msp|pdf|phps|png|ppt(x|m)?|pot(x|m)?|pps(x|m)?|ppam|sld(x|m)?|thmx|qtm?|ra(m|r)?|sea|sit|tar|tgz|torrent|txt|wav|wma|wmv|wpd|xls(x|m|b)?|xlt(x|m)|xlam|xml|z|zip');
/**
* Define default path exclusion list to remove tracking from admin pages,
......@@ -204,25 +204,38 @@ function googleanalytics_page_alter(&$page) {
$custom_var = '';
foreach (array('dimension', 'metric') as $googleanalytics_custom_type) {
$googleanalytics_custom_vars = variable_get('googleanalytics_custom_' . $googleanalytics_custom_type, array());
for ($i = 1; $i <= 20; $i++) {
$custom_var_value = !empty($googleanalytics_custom_vars['indexes'][$i]['value']) ? $googleanalytics_custom_vars['indexes'][$i]['value'] : '';
if (!empty($custom_var_value)) {
// Are there dimensions or metrics configured?
if (!empty($googleanalytics_custom_vars)) {
// Add all the configured variables to the content.
foreach ($googleanalytics_custom_vars as $googleanalytics_custom_var) {
// Replace tokens in values.
$types = array();
$node = menu_get_object();
if (is_object($node)) {
$types += array('node' => $node);
}
$custom_var_value = token_replace($custom_var_value, $types, array('clear' => TRUE));
// Suppress empty custom names and/or variables.
if (!drupal_strlen(trim($custom_var_value))) {
$googleanalytics_custom_var['value'] = token_replace($googleanalytics_custom_var['value'], $types, array('clear' => TRUE));
// Suppress empty values.
if (!drupal_strlen(trim($googleanalytics_custom_var['value']))) {
continue;
}
// Per documentation the max length of a dimension is 150 bytes.
// A metric has no length limitation. It's not documented if this
// limit means 150 bytes after url encoding or before.
// See https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#customs
if ($googleanalytics_custom_type == 'dimension' && drupal_strlen($googleanalytics_custom_var['value']) > 150) {
$googleanalytics_custom_var['value'] = substr($googleanalytics_custom_var['value'], 0, 150);
}
// Cast metric values for json_encode to data type numeric.
if ($googleanalytics_custom_type == 'metric') {
settype($custom_var_value, 'float');
settype($googleanalytics_custom_var['value'], 'float');
};
$custom_var .= 'ga("set", ' . drupal_json_encode($googleanalytics_custom_type . $i) . ', ' . drupal_json_encode($custom_var_value) . ');';
// Add variables to tracker.
$custom_var .= 'ga("set", ' . drupal_json_encode($googleanalytics_custom_type . $googleanalytics_custom_var['index']) . ', ' . drupal_json_encode($googleanalytics_custom_var['value']) . ');';
}
}
}
......@@ -259,7 +272,7 @@ function googleanalytics_page_alter(&$page) {
$codesnippet_after = variable_get('googleanalytics_codesnippet_after', '');
// Build the create only fields list.
$create_only_fields = array();
$create_only_fields = array('cookieDomain' => 'auto');
$create_only_fields = array_merge($create_only_fields, $codesnippet_create);
// Domain tracking type.
......@@ -279,16 +292,15 @@ function googleanalytics_page_alter(&$page) {
$googleanalytics_adsense_script .= 'window.google_analytics_domain_name = "none";';
}
// Track logged in users accross all devices.
// Track logged in users across all devices.
if (variable_get('googleanalytics_trackuserid', 0) && user_is_logged_in()) {
// The USER_ID value should be a unique, persistent, and non-personally
// identifiable string identifier that represents a user or signed-in
// account across devices.
$create_only_fields['userId'] = drupal_base64_encode(drupal_get_hash_salt() . $user->uid);
$create_only_fields['userId'] = drupal_hmac_base64($user->uid, drupal_get_private_key() . drupal_get_hash_salt());
}
// Create a tracker.
$create_only_fields = empty($create_only_fields) ? 'auto' : $create_only_fields;
$script .= 'ga("create", ' . drupal_json_encode($id) . ', ' . drupal_json_encode($create_only_fields) .');';
// Prepare Adsense tracking.
......@@ -439,11 +451,13 @@ function googleanalytics_cron() {
* Collects and adds the number of search results to the head.
*/
function googleanalytics_preprocess_search_results(&$variables) {
if (variable_get('googleanalytics_site_search', FALSE)) {
// There is no search result $variable available that hold the number of items
// found. But the pager item mumber can tell the number of search results.
global $pager_total_items;
drupal_add_js('window.googleanalytics_search_results = ' . intval($pager_total_items[0]) . ';', array('type' => 'inline', 'group' => JS_LIBRARY-1));
}
}
/**
......
......@@ -30,10 +30,10 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
}
function testGoogleAnalyticsConfiguration() {
// Check if Configure link is available on 'Extend' page.
// Check if Configure link is available on 'Modules' page.
// Requires 'administer modules' permission.
$this->drupalGet('admin/modules');
$this->assertRaw('admin/config/system/googleanalytics', '[testGoogleAnalyticsConfiguration]: Configure link from Extend page to Google Analytics Settings page exists.');
$this->assertRaw('admin/config/system/googleanalytics', '[testGoogleAnalyticsConfiguration]: Configure link from Modules page to Google Analytics Settings page exists.');
// Check if Configure link is available on 'Status Reports' page. NOTE: Link is only shown without UA code configured.
// Requires 'administer site configuration' permission.
......@@ -61,7 +61,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
// Show tracking on "every page except the listed pages".
variable_set('googleanalytics_visibility_pages', 0);
// Disable tracking one "admin*" pages only.
// Disable tracking on "admin*" pages only.
variable_set('googleanalytics_pages', "admin\nadmin/*");
// Enable tracking only for authenticated users only.
variable_set('googleanalytics_roles', array(DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID));
......@@ -174,12 +174,12 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
// Test if tracking of User ID is enabled.
variable_set('googleanalytics_trackuserid', 1);
$this->drupalGet('');
$this->assertRaw(', {"userId":"', '[testGoogleAnalyticsTrackingCode]: Tracking code for User ID is enabled.');
$this->assertRaw(', {"cookieDomain":"auto","userId":"', '[testGoogleAnalyticsTrackingCode]: Tracking code for User ID is enabled.');
// Test if tracking of User ID is disabled.
variable_set('googleanalytics_trackuserid', 0);
$this->drupalGet('');
$this->assertNoRaw(', {"userId":"', '[testGoogleAnalyticsTrackingCode]: Tracking code for User ID is disabled.');
$this->assertNoRaw(', {"cookieDomain":"auto","userId":"', '[testGoogleAnalyticsTrackingCode]: Tracking code for User ID is disabled.');
// Test if tracking of url fragments is enabled.
variable_set('googleanalytics_trackurlfragments', 1);
......@@ -203,7 +203,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
// Test whether single domain tracking is active.
$this->drupalGet('');
$this->assertNoRaw('{"cookieDomain":"', '[testGoogleAnalyticsTrackingCode]: Single domain tracking is active.');
$this->assertRaw('{"cookieDomain":"auto"}', '[testGoogleAnalyticsTrackingCode]: Single domain tracking is active.');
// Enable "One domain with multiple subdomains".
variable_set('googleanalytics_domain_mode', 1);
......@@ -224,7 +224,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
variable_set('googleanalytics_domain_mode', 2);
variable_set('googleanalytics_cross_domains', "www.example.com\nwww.example.net");
$this->drupalGet('');
$this->assertRaw('ga("create", "' . $ua_code . '", {"allowLinker":true', '[testGoogleAnalyticsTrackingCode]: "allowLinker" has been found. Cross domain tracking is active.');
$this->assertRaw('ga("create", "' . $ua_code . '", {"cookieDomain":"auto","allowLinker":true', '[testGoogleAnalyticsTrackingCode]: "allowLinker" has been found. Cross domain tracking is active.');
$this->assertRaw('ga("require", "linker");', '[testGoogleAnalyticsTrackingCode]: Require linker has been found. Cross domain tracking is active.');
$this->assertRaw('ga("linker:autoLink", ["www.example.com","www.example.net"]);', '[testGoogleAnalyticsTrackingCode]: "linker:autoLink" has been found. Cross domain tracking is active.');
$this->assertRaw('"trackCrossDomains":["www.example.com","www.example.net"]', '[testGoogleAnalyticsTrackingCode]: Cross domain tracking with www.example.com and www.example.net is active.');
......@@ -255,11 +255,11 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
);
variable_set('googleanalytics_codesnippet_create', $codesnippet_create);
variable_set('googleanalytics_codesnippet_before', 'ga("set", "forceSSL", true);');
variable_set('googleanalytics_codesnippet_after', 'ga("create", "UA-123456-3", {name: "newTracker"});ga("newTracker.send", "pageview");');
variable_set('googleanalytics_codesnippet_after', 'ga("create", "UA-123456-3", {"name": "newTracker"});ga("newTracker.send", "pageview");');
$this->drupalGet('');
$this->assertRaw('ga("create", "' . $ua_code . '", {"cookieDomain":"foo.example.com","cookieName":"myNewName","cookieExpires":20000,"allowAnchor":true,"sampleRate":4.3});', '[testGoogleAnalyticsTrackingCode]: Create only fields have been found.');
$this->assertRaw('ga("set", "forceSSL", true);', '[testGoogleAnalyticsTrackingCode]: Before codesnippet will force http pages to also send all beacons using https.');
$this->assertRaw('ga("create", "UA-123456-3", {name: "newTracker"});', '[testGoogleAnalyticsTrackingCode]: After codesnippet with "newTracker" tracker has been found.');
$this->assertRaw('ga("create", "UA-123456-3", {"name": "newTracker"});', '[testGoogleAnalyticsTrackingCode]: After codesnippet with "newTracker" tracker has been found.');
}
}
......@@ -292,7 +292,6 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
// Basic test if the feature works.
$googleanalytics_custom_dimension = array(
'indexes' => array(
1 => array(
'index' => 1,
'value' => 'Bar 1',
......@@ -313,12 +312,11 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
'index' => 5,
'value' => 'Bar 5',
),
)
);
variable_set('googleanalytics_custom_dimension', $googleanalytics_custom_dimension);
$this->drupalGet('');
foreach ($googleanalytics_custom_dimension['indexes'] as $dimension) {
foreach ($googleanalytics_custom_dimension as $dimension) {
$this->assertRaw('ga("set", ' . drupal_json_encode('dimension' . $dimension['index']) . ', ' . drupal_json_encode($dimension['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Dimension #' . $dimension['index'] . ' is shown.');
}
......@@ -327,7 +325,6 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
variable_set('site_slogan', $site_slogan);
$googleanalytics_custom_dimension = array(
'indexes' => array(
1 => array(
'index' => 1,
'value' => 'Value: [site:slogan]',
......@@ -340,15 +337,20 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
'index' => 3,
'value' => '',
),
)
// #2300701: Custom dimensions and custom metrics not outputed on zero value.
4 => array(
'index' => 4,
'value' => '0',
),
);
variable_set('googleanalytics_custom_dimension', $googleanalytics_custom_dimension);
$this->verbose('<pre>' . print_r($googleanalytics_custom_dimension, TRUE) . '</pre>');
$this->drupalGet('');
$this->assertRaw('ga("set", ' . drupal_json_encode('dimension1') . ', ' . drupal_json_encode("Value: $site_slogan") . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Tokens have been replaced in dimension value.');
$this->assertRaw('ga("set", ' . drupal_json_encode('dimension2') . ', ' . drupal_json_encode($googleanalytics_custom_dimension['indexes']['2']['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Random value is shown.');
$this->assertRaw('ga("set", ' . drupal_json_encode('dimension2') . ', ' . drupal_json_encode($googleanalytics_custom_dimension['2']['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Random value is shown.');
$this->assertNoRaw('ga("set", ' . drupal_json_encode('dimension3') . ', ' . drupal_json_encode('') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Empty value is not shown.');
$this->assertRaw('ga("set", ' . drupal_json_encode('dimension4') . ', ' . drupal_json_encode('0') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Value 0 is shown.');
}
function testGoogleAnalyticsCustomMetrics() {
......@@ -357,7 +359,6 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
// Basic test if the feature works.
$googleanalytics_custom_metric = array(
'indexes' => array(
1 => array(
'index' => 1,
'value' => '6',
......@@ -383,18 +384,16 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
'value' => '5,67',
'value_expected' => 5,
),
)
);
variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric);
$this->drupalGet('');
foreach ($googleanalytics_custom_metric['indexes'] as $metric) {
foreach ($googleanalytics_custom_metric as $metric) {
$this->assertRaw('ga("set", ' . drupal_json_encode('metric' . $metric['index']) . ', ' . drupal_json_encode($metric['value_expected']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Metric #' . $metric['index'] . ' is shown.');
}
// Test whether tokens are replaced in custom metric values.
$googleanalytics_custom_metric = array(
'indexes' => array(
1 => array(
'index' => 1,
'value' => '[current-user:roles:count]',
......@@ -407,15 +406,20 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
'index' => 3,
'value' => '',
),
)
// #2300701: Custom dimensions and custom metrics not outputed on zero value.
4 => array(
'index' => 4,
'value' => '0',
),
);
variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric);
$this->verbose('<pre>' . print_r($googleanalytics_custom_metric, TRUE) . '</pre>');
$this->drupalGet('');
$this->assertRaw('ga("set", ' . drupal_json_encode('metric1') . ', ', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Tokens have been replaced in metric value.');
$this->assertRaw('ga("set", ' . drupal_json_encode('metric2') . ', ' . drupal_json_encode($googleanalytics_custom_metric['indexes']['2']['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Random value is shown.');
$this->assertRaw('ga("set", ' . drupal_json_encode('metric2') . ', ' . drupal_json_encode($googleanalytics_custom_metric['2']['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Random value is shown.');
$this->assertNoRaw('ga("set", ' . drupal_json_encode('metric3') . ', ' . drupal_json_encode('') . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Empty value is not shown.');
$this->assertRaw('ga("set", ' . drupal_json_encode('metric4') . ', ' . drupal_json_encode(0) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Value 0 is shown.');
}
}
......@@ -572,6 +576,8 @@ class GoogleAnalyticsSearchTest extends DrupalWebTestCase {
'access administration pages',
'administer google analytics',
'search content',
'create page content',
'edit own page content',
);
// User to set up google_analytics.
......@@ -590,16 +596,44 @@ class GoogleAnalyticsSearchTest extends DrupalWebTestCase {
$this->drupalGet('search/node');
$this->assertNoRaw('ga("set", "page",', '[testGoogleAnalyticsSearch]: Custom url not set.');
// Enable site search support.
variable_set('googleanalytics_site_search', 1);
// Search for random string.
$search = array();
$search['keys'] = $this->randomName(8);
// Create a node to search for.
$langcode = LANGUAGE_NONE;
$edit = array();
$edit['keys'] = $this->randomName(32);
$edit['title'] = 'This is a test title';
$edit["body[$langcode][0][value]"] = 'This test content contains ' . $search['keys'] . ' string.';
variable_set('googleanalytics_site_search', 1);
$this->drupalPost('search/node', $edit, t('Search'));
// Fire a search, it's expected to get 0 results.
$this->drupalPost('search/node', $search, t('Search'));
$this->assertRaw('ga("set", "page", (window.googleanalytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
$this->assertRaw('window.googleanalytics_search_results = 0;', '[testGoogleAnalyticsSearch]: Search yielded no results.');
// Save the node.
$this->drupalPost('node/add/page', $edit, t('Save'));
$this->assertText(t('@type @title has been created.', array('@type' => 'Basic page', '@title' => $edit['title'])), 'Node was created.');
// Index the node or it cannot found.
$this->cronRun();
$this->drupalPost('search/node', $search, t('Search'));
$this->assertRaw('ga("set", "page", (window.googleanalytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
$this->assertRaw('window.googleanalytics_search_results = 1;', '[testGoogleAnalyticsSearch]: One search result found.');
$this->drupalPost('node/add/page', $edit, t('Save'));
$this->assertText(t('@type @title has been created.', array('@type' => 'Basic page', '@title' => $edit['title'])), 'Node was created.');
// Test search results counter.
$this->assertRaw('window.googleanalytics_search_results = ', '[testGoogleAnalyticsSearch]: Search results counter is displayed.');
// Index the node or it cannot found.
$this->cronRun();
$this->drupalPost('search/node', $search, t('Search'));
$this->assertRaw('ga("set", "page", (window.googleanalytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.');
$this->assertRaw('window.googleanalytics_search_results = 2;', '[testGoogleAnalyticsSearch]: Two search results found.');
}
}
......
......@@ -21,7 +21,7 @@ Drupal.googleanalytics.test.assertSame = function (value1, value2, message) {
else {
console.error(message);
}
}
};
Drupal.googleanalytics.test.assertNotSame = function (value1, value2, message) {
if (value1 !== value2) {
......@@ -30,7 +30,7 @@ Drupal.googleanalytics.test.assertNotSame = function (value1, value2, message) {
else {
console.error(message);
}
}
};
Drupal.googleanalytics.test.assertTrue = function (value1, message) {
if (value1 === true) {
......@@ -39,7 +39,7 @@ Drupal.googleanalytics.test.assertTrue = function (value1, message) {
else {
console.error(message);
}
}
};
Drupal.googleanalytics.test.assertFalse = function (value1, message) {
if (value1 === false) {
......@@ -48,7 +48,7 @@ Drupal.googleanalytics.test.assertFalse = function (value1, message) {
else {
console.error(message);
}
}
};
// Run after the documented is ready or Drupal.settings is undefined.
$(document).ready(function() {
......@@ -86,8 +86,8 @@ $(document).ready(function() {
console.groupEnd();
console.group("Test 'getPageUrl':");
Drupal.googleanalytics.test.assertSame(base_path + 'node/1', Drupal.googleanalytics.getPageUrl(base_url + Drupal.settings.basePath + 'node/1'), "Absolute internal URL '" + Drupal.settings.basePath + "node/1' has been extracted from full qualified url '" + base_url + base_path + "node/1'.");
Drupal.googleanalytics.test.assertSame(base_path + 'node/1', Drupal.googleanalytics.getPageUrl(Drupal.settings.basePath + 'node/1'), "Absolute internal URL '" + Drupal.settings.basePath + "node/1' has been extracted from absolute url '" + base_path + "node/1'.");
Drupal.googleanalytics.test.assertSame(base_path, Drupal.googleanalytics.getPageUrl(base_url + Drupal.settings.basePath + 'node/1'), "Absolute internal URL '" + Drupal.settings.basePath + "node/1' has been extracted from full qualified url '" + base_url + base_path + "'.");
Drupal.googleanalytics.test.assertSame(base_path, Drupal.googleanalytics.getPageUrl(Drupal.settings.basePath + 'node/1'), "Absolute internal URL '" + Drupal.settings.basePath + "node/1' has been extracted from absolute url '" + base_path + "'.");
Drupal.googleanalytics.test.assertSame('http://example.com/node/2', Drupal.googleanalytics.getPageUrl('http://example.com/node/2'), "Full qualified external url 'http://example.com/node/2' has been extracted.");
Drupal.googleanalytics.test.assertSame('//example.com/node/2', Drupal.googleanalytics.getPageUrl('//example.com/node/2'), "Full qualified external url '//example.com/node/2' has been extracted.");
console.groupEnd();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment