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) { ...@@ -184,7 +184,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => t('Track User ID'), '#title' => t('Track User ID'),
'#default_value' => variable_get('googleanalytics_trackuserid', 0), '#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. // Link specific configurations.
...@@ -213,7 +213,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -213,7 +213,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'textfield', '#type' => 'textfield',
'#default_value' => variable_get('googleanalytics_trackfiles_extensions', GOOGLEANALYTICS_TRACKFILES_EXTENSIONS), '#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)), '#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( '#states' => array(
'enabled' => array( 'enabled' => array(
':input[name="googleanalytics_trackfiles"]' => array('checked' => TRUE), ':input[name="googleanalytics_trackfiles"]' => array('checked' => TRUE),
...@@ -254,8 +254,6 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -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( $form['tracking']['search_and_advertising'] = array(
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => t('Search and Advertising'), '#title' => t('Search and Advertising'),
...@@ -307,7 +305,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -307,7 +305,7 @@ function googleanalytics_admin_settings_form($form_state) {
$form['googleanalytics_custom_dimension'] = array( $form['googleanalytics_custom_dimension'] = array(
'#collapsed' => TRUE, '#collapsed' => TRUE,
'#collapsible' => 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', '#theme' => 'googleanalytics_admin_custom_var_table',
'#title' => t('Custom dimensions'), '#title' => t('Custom dimensions'),
'#tree' => TRUE, '#tree' => TRUE,
...@@ -328,7 +326,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -328,7 +326,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'textfield', '#type' => 'textfield',
); );
$form['googleanalytics_custom_dimension']['indexes'][$i]['value'] = array( $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.'), '#description' => t('The custom dimension value.'),
'#maxlength' => 255, '#maxlength' => 255,
'#title' => t('Custom dimension value #@index', array('@index' => $i)), '#title' => t('Custom dimension value #@index', array('@index' => $i)),
...@@ -346,11 +344,13 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -346,11 +344,13 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'item', '#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')), '#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')),
); );
$form['googleanalytics_custom_dimension']['googleanalytics_token_tree'] = array( if (module_exists('token')) {
'#theme' => 'token_tree', $form['googleanalytics_custom_dimension']['googleanalytics_token_tree'] = array(
'#token_types' => array('node'), '#theme' => 'token_tree',
'#dialog' => TRUE, '#token_types' => array('node'),
); '#dialog' => TRUE,
);
}
// Custom Metrics. // Custom Metrics.
$form['googleanalytics_custom_metric'] = array( $form['googleanalytics_custom_metric'] = array(
...@@ -377,7 +377,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -377,7 +377,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'textfield', '#type' => 'textfield',
); );
$form['googleanalytics_custom_metric']['indexes'][$i]['value'] = array( $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.'), '#description' => t('The custom metric value.'),
'#maxlength' => 255, '#maxlength' => 255,
'#title' => t('Custom metric value #@index', array('@index' => $i)), '#title' => t('Custom metric value #@index', array('@index' => $i)),
...@@ -395,11 +395,13 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -395,11 +395,13 @@ function googleanalytics_admin_settings_form($form_state) {
'#type' => 'item', '#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')), '#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')),
); );
$form['googleanalytics_custom_metric']['googleanalytics_token_tree'] = array( if (module_exists('token')) {
'#theme' => 'token_tree', $form['googleanalytics_custom_metric']['googleanalytics_token_tree'] = array(
'#token_types' => array('node'), '#theme' => 'token_tree',
'#dialog' => TRUE, '#token_types' => array('node'),
); '#dialog' => TRUE,
);
}
// Advanced feature configurations. // Advanced feature configurations.
$form['advanced'] = array( $form['advanced'] = array(
...@@ -473,10 +475,21 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) { ...@@ -473,10 +475,21 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) {
// Trim custom dimensions and metrics. // Trim custom dimensions and metrics.
foreach ($form_state['values']['googleanalytics_custom_dimension']['indexes'] as $dimension) { foreach ($form_state['values']['googleanalytics_custom_dimension']['indexes'] as $dimension) {
$form_state['values']['googleanalytics_custom_dimension']['indexes'][$dimension['index']]['value'] = trim($dimension['value']); $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) { foreach ($form_state['values']['googleanalytics_custom_metric']['indexes'] as $metric) {
$form_state['values']['googleanalytics_custom_metric']['indexes'][$metric['index']]['value'] = trim($metric['value']); $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. // Trim some text values.
$form_state['values']['googleanalytics_account'] = trim($form_state['values']['googleanalytics_account']); $form_state['values']['googleanalytics_account'] = trim($form_state['values']['googleanalytics_account']);
...@@ -497,6 +510,11 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) { ...@@ -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'])) { 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.')); 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. // Disallow empty list of download file extensions.
if ($form_state['values']['googleanalytics_trackfiles'] && empty($form_state['values']['googleanalytics_trackfiles_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.')); 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) { ...@@ -544,7 +562,9 @@ function theme_googleanalytics_admin_custom_var_table($variables) {
$output = theme('table', array('header' => $header, 'rows' => $rows)); $output = theme('table', array('header' => $header, 'rows' => $rows));
$output .= drupal_render($form['googleanalytics_description']); $output .= drupal_render($form['googleanalytics_description']);
$output .= drupal_render($form['googleanalytics_token_tree']); if (isset($form['googleanalytics_token_tree'])) {
$output .= drupal_render($form['googleanalytics_token_tree']);
}
return $output; return $output;
} }
...@@ -735,7 +755,6 @@ function _googleanalytics_validate_create_field_name($name) { ...@@ -735,7 +755,6 @@ function _googleanalytics_validate_create_field_name($name) {
// List of supported field names: // List of supported field names:
// https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#create // https://developers.google.com/analytics/devguides/collection/analyticsjs/field-reference#create
$create_only_fields = array( $create_only_fields = array(
'name',
'clientId', 'clientId',
'userId', 'userId',
'sampleRate', 'sampleRate',
...@@ -748,8 +767,14 @@ function _googleanalytics_validate_create_field_name($name) { ...@@ -748,8 +767,14 @@ function _googleanalytics_validate_create_field_name($name) {
'legacyCookieDomain', '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)) { 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) { ...@@ -763,11 +788,11 @@ function _googleanalytics_validate_create_field_name($name) {
* The error message if the specified value is invalid, NULL otherwise. * The error message if the specified value is invalid, NULL otherwise.
*/ */
function _googleanalytics_validate_create_field_value($value) { function _googleanalytics_validate_create_field_value($value) {
if (!is_bool($value) && empty($value)) { if (!is_bool($value) && !drupal_strlen($value)) {
return t('A value is required.'); return t('A create only field requires a value.');
} }
if (drupal_strlen($value) > 255) { 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() { ...@@ -30,7 +30,7 @@ $(document).ready(function() {
else if (Drupal.googleanalytics.isInternalSpecial(this.href)) { else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
// Keep the internal URL for Google Analytics website overlay intact. // 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)); 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 { else {
// e.g. anchor in same page or other internal page link // e.g. anchor in same page or other internal page link
...@@ -44,7 +44,7 @@ $(document).ready(function() { ...@@ -44,7 +44,7 @@ $(document).ready(function() {
ga("send", "event", "Mails", "Click", this.href.substring(7)); ga("send", "event", "Mails", "Click", this.href.substring(7));
} }
else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) { 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. // External link clicked / No top-level cross domain clicked.
console.info("Outbound link '%s' has been tracked.", this.href); console.info("Outbound link '%s' has been tracked.", this.href);
ga("send", "event", "Outbound links", "Click", this.href); ga("send", "event", "Outbound links", "Click", this.href);
...@@ -73,7 +73,7 @@ $(document).ready(function() { ...@@ -73,7 +73,7 @@ $(document).ready(function() {
var href = $.colorbox.element().attr("href"); var href = $.colorbox.element().attr("href");
if (href) { if (href) {
console.info("Colorbox transition to url '%s' has been tracked.", Drupal.googleanalytics.getPageUrl(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) { ...@@ -103,7 +103,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
else { else {
return $.inArray(hostname, crossDomains) > -1 ? true : false; return $.inArray(hostname, crossDomains) > -1 ? true : false;
} }
} };
/** /**
* Check whether this is a download URL or not. * Check whether this is a download URL or not.
...@@ -116,7 +116,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) { ...@@ -116,7 +116,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
Drupal.googleanalytics.isDownload = function (url) { Drupal.googleanalytics.isDownload = function (url) {
var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i"); var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
return isDownload.test(url); return isDownload.test(url);
} };
/** /**
* Check whether this is an absolute internal URL or not. * Check whether this is an absolute internal URL or not.
...@@ -129,7 +129,7 @@ Drupal.googleanalytics.isDownload = function (url) { ...@@ -129,7 +129,7 @@ Drupal.googleanalytics.isDownload = function (url) {
Drupal.googleanalytics.isInternal = function (url) { Drupal.googleanalytics.isInternal = function (url) {
var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i"); var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i");
return isInternal.test(url); return isInternal.test(url);
} };
/** /**
* Check whether this is a special URL or not. * Check whether this is a special URL or not.
...@@ -145,7 +145,7 @@ Drupal.googleanalytics.isInternal = function (url) { ...@@ -145,7 +145,7 @@ Drupal.googleanalytics.isInternal = function (url) {
Drupal.googleanalytics.isInternalSpecial = function (url) { Drupal.googleanalytics.isInternalSpecial = function (url) {
var isInternalSpecial = new RegExp("(\/go\/.*)$", "i"); var isInternalSpecial = new RegExp("(\/go\/.*)$", "i");
return isInternalSpecial.test(url); return isInternalSpecial.test(url);
} };
/** /**
* Extract the relative internal URL from an absolute internal URL. * Extract the relative internal URL from an absolute internal URL.
...@@ -163,7 +163,7 @@ Drupal.googleanalytics.isInternalSpecial = function (url) { ...@@ -163,7 +163,7 @@ Drupal.googleanalytics.isInternalSpecial = function (url) {
Drupal.googleanalytics.getPageUrl = function (url) { Drupal.googleanalytics.getPageUrl = function (url) {
var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i"); var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i");
return url.replace(extractInternalUrl, ''); return url.replace(extractInternalUrl, '');
} };
/** /**
* Extract the download file extension from the URL. * Extract the download file extension from the URL.
...@@ -178,6 +178,6 @@ Drupal.googleanalytics.getDownloadExtension = function (url) { ...@@ -178,6 +178,6 @@ Drupal.googleanalytics.getDownloadExtension = function (url) {
var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i"); var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
var extension = extractDownloadextension.exec(url); var extension = extractDownloadextension.exec(url);
return (extension === null) ? '' : extension[1]; return (extension === null) ? '' : extension[1];
} };
})(jQuery); })(jQuery);
...@@ -5,9 +5,9 @@ package = Statistics ...@@ -5,9 +5,9 @@ package = Statistics
configure = admin/config/system/googleanalytics configure = admin/config/system/googleanalytics
files[] = googleanalytics.test files[] = googleanalytics.test
test_dependencies[] = token test_dependencies[] = token
; Information added by Drupal.org packaging script on 2014-07-01 ; Information added by Drupal.org packaging script on 2014-11-29
version = "7.x-2.0" version = "7.x-2.1"
core = "7.x" core = "7.x"
project = "google_analytics" project = "google_analytics"
datestamp = "1404257628" datestamp = "1417276982"
...@@ -41,11 +41,8 @@ function googleanalytics_uninstall() { ...@@ -41,11 +41,8 @@ function googleanalytics_uninstall() {
variable_del('googleanalytics_privacy_donottrack'); variable_del('googleanalytics_privacy_donottrack');
// Remove backup variables if exist. Remove this code in D8. // 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_after_backup_7200');
variable_del('googleanalytics_codesnippet_before_backup_7200'); variable_del('googleanalytics_codesnippet_before_backup_7200');
variable_del('googleanalytics_segmentation');
} }
/** /**
...@@ -74,15 +71,16 @@ function googleanalytics_requirements($phase) { ...@@ -74,15 +71,16 @@ function googleanalytics_requirements($phase) {
'value' => $t('Not configured'), 'value' => $t('Not configured'),
); );
} }
}
// Raise warning if debugging is enabled. // Raise warning if debugging is enabled.
if (variable_get('googleanalytics_debug', 0)) { if (variable_get('googleanalytics_debug', 0)) {
$requirements['google_analytics_debugging'] = array( $requirements['google_analytics_debugging'] = array(
'title' => $t('Google Analytics module'), 'title' => $t('Google Analytics module'),
'description' => $t('Google Analytics module has debugging enabled. Please disable debugging setting in production sites from the <a href="@url">Google Analytics settings page</a>.', array('@url' => url('admin/config/system/googleanalytics'))), 'description' => $t('Google Analytics module has debugging enabled. Please disable debugging setting in production sites from the <a href="@url">Google Analytics settings page</a>.', array('@url' => url('admin/config/system/googleanalytics'))),
'severity' => REQUIREMENT_WARNING, 'severity' => REQUIREMENT_WARNING,
'value' => $t('Debugging enabled'), 'value' => $t('Debugging enabled'),
); );
}
} }
return $requirements; return $requirements;
...@@ -445,7 +443,7 @@ function googleanalytics_update_7200() { ...@@ -445,7 +443,7 @@ function googleanalytics_update_7200() {
// ga.js code will cause the tracker to break. Remove custom code snippets. // ga.js code will cause the tracker to break. Remove custom code snippets.
$googleanalytics_codesnippet_before = variable_get('googleanalytics_codesnippet_before', ''); $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_set('googleanalytics_codesnippet_before_backup_7200', $googleanalytics_codesnippet_before);
variable_del('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'); 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() { ...@@ -453,7 +451,7 @@ function googleanalytics_update_7200() {
} }
$googleanalytics_codesnippet_after = variable_get('googleanalytics_codesnippet_after', ''); $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_set('googleanalytics_codesnippet_after_backup_7200', $googleanalytics_codesnippet_after);
variable_del('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'); 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() { ...@@ -481,3 +479,59 @@ function googleanalytics_update_7202() {
return t('Removed obsolete JavaScript scope variable.'); 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() { ...@@ -25,7 +25,7 @@ $(document).ready(function() {
} }
else if (Drupal.googleanalytics.isInternalSpecial(this.href)) { else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
// Keep the internal URL for Google Analytics website overlay intact. // 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 { else {
...@@ -34,7 +34,7 @@ $(document).ready(function() { ...@@ -34,7 +34,7 @@ $(document).ready(function() {
ga("send", "event", "Mails", "Click", this.href.substring(7)); ga("send", "event", "Mails", "Click", this.href.substring(7));
} }
else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) { 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. // External link clicked / No top-level cross domain clicked.
ga("send", "event", "Outbound links", "Click", this.href); ga("send", "event", "Outbound links", "Click", this.href);
} }
...@@ -55,7 +55,7 @@ $(document).ready(function() { ...@@ -55,7 +55,7 @@ $(document).ready(function() {
$(document).bind("cbox_complete", function () { $(document).bind("cbox_complete", function () {
var href = $.colorbox.element().attr("href"); var href = $.colorbox.element().attr("href");
if (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) { ...@@ -85,7 +85,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
else { else {
return $.inArray(hostname, crossDomains) > -1 ? true : false; return $.inArray(hostname, crossDomains) > -1 ? true : false;
} }
} };
/** /**
* Check whether this is a download URL or not. * Check whether this is a download URL or not.
...@@ -98,7 +98,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) { ...@@ -98,7 +98,7 @@ Drupal.googleanalytics.isCrossDomain = function (hostname, crossDomains) {
Drupal.googleanalytics.isDownload = function (url) { Drupal.googleanalytics.isDownload = function (url) {
var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i"); var isDownload = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
return isDownload.test(url); return isDownload.test(url);
} };
/** /**
* Check whether this is an absolute internal URL or not. * Check whether this is an absolute internal URL or not.
...@@ -111,7 +111,7 @@ Drupal.googleanalytics.isDownload = function (url) { ...@@ -111,7 +111,7 @@ Drupal.googleanalytics.isDownload = function (url) {
Drupal.googleanalytics.isInternal = function (url) { Drupal.googleanalytics.isInternal = function (url) {
var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i"); var isInternal = new RegExp("^(https?):\/\/" + window.location.host, "i");
return isInternal.test(url); return isInternal.test(url);
} };
/** /**
* Check whether this is a special URL or not. * Check whether this is a special URL or not.
...@@ -127,7 +127,7 @@ Drupal.googleanalytics.isInternal = function (url) { ...@@ -127,7 +127,7 @@ Drupal.googleanalytics.isInternal = function (url) {
Drupal.googleanalytics.isInternalSpecial = function (url) { Drupal.googleanalytics.isInternalSpecial = function (url) {
var isInternalSpecial = new RegExp("(\/go\/.*)$", "i"); var isInternalSpecial = new RegExp("(\/go\/.*)$", "i");
return isInternalSpecial.test(url); return isInternalSpecial.test(url);
} };
/** /**
* Extract the relative internal URL from an absolute internal URL. * Extract the relative internal URL from an absolute internal URL.
...@@ -145,7 +145,7 @@ Drupal.googleanalytics.isInternalSpecial = function (url) { ...@@ -145,7 +145,7 @@ Drupal.googleanalytics.isInternalSpecial = function (url) {
Drupal.googleanalytics.getPageUrl = function (url) { Drupal.googleanalytics.getPageUrl = function (url) {
var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i"); var extractInternalUrl = new RegExp("^(https?):\/\/" + window.location.host, "i");
return url.replace(extractInternalUrl, ''); return url.replace(extractInternalUrl, '');
} };
/** /**
* Extract the download file extension from the URL. * Extract the download file extension from the URL.
...@@ -160,6 +160,6 @@ Drupal.googleanalytics.getDownloadExtension = function (url) { ...@@ -160,6 +160,6 @@ Drupal.googleanalytics.getDownloadExtension = function (url) {
var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i"); var extractDownloadextension = new RegExp("\\.(" + Drupal.settings.googleanalytics.trackDownloadExtensions + ")([\?#].*)?$", "i");
var extension = extractDownloadextension.exec(url); var extension = extractDownloadextension.exec(url);
return (extension === null) ? '' : extension[1]; return (extension === null) ? '' : extension[1];
} };
})(jQuery); })(jQuery);
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
/** /**
* Define the default file extension list that should be tracked as download. * 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, * Define default path exclusion list to remove tracking from admin pages,
...@@ -204,25 +204,38 @@ function googleanalytics_page_alter(&$page) { ...@@ -204,25 +204,38 @@ function googleanalytics_page_alter(&$page) {
$custom_var = ''; $custom_var = '';
foreach (array('dimension', 'metric') as $googleanalytics_custom_type) { foreach (array('dimension', 'metric') as $googleanalytics_custom_type) {
$googleanalytics_custom_vars = variable_get('googleanalytics_custom_' . $googleanalytics_custom_type, array()); $googleanalytics_custom_vars = variable_get('googleanalytics_custom_' . $googleanalytics_custom_type, array());
for ($i = 1; $i <= 20; $i++) { // Are there dimensions or metrics configured?
$custom_var_value = !empty($googleanalytics_custom_vars['indexes'][$i]['value']) ? $googleanalytics_custom_vars['indexes'][$i]['value'] : ''; if (!empty($googleanalytics_custom_vars)) {
if (!empty($custom_var_value)) { // Add all the configured variables to the content.
foreach ($googleanalytics_custom_vars as $googleanalytics_custom_var) {
// Replace tokens in values.
$types = array(); $types = array();
$node = menu_get_object(); $node = menu_get_object();
if (is_object($node)) { if (is_object($node)) {
$types += array('node' => $node); $types += array('node' => $node);
} }
$custom_var_value = token_replace($custom_var_value, $types, array('clear' => TRUE)); $googleanalytics_custom_var['value'] = token_replace($googleanalytics_custom_var['value'], $types, array('clear' => TRUE));
// Suppress empty custom names and/or variables.
if (!drupal_strlen(trim($custom_var_value))) { // Suppress empty values.
if (!drupal_strlen(trim($googleanalytics_custom_var['value']))) {
continue; 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. // Cast metric values for json_encode to data type numeric.
if ($googleanalytics_custom_type == 'metric') { 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) { ...@@ -259,7 +272,7 @@ function googleanalytics_page_alter(&$page) {
$codesnippet_after = variable_get('googleanalytics_codesnippet_after', ''); $codesnippet_after = variable_get('googleanalytics_codesnippet_after', '');
// Build the create only fields list. // 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); $create_only_fields = array_merge($create_only_fields, $codesnippet_create);
// Domain tracking type. // Domain tracking type.
...@@ -279,16 +292,15 @@ function googleanalytics_page_alter(&$page) { ...@@ -279,16 +292,15 @@ function googleanalytics_page_alter(&$page) {
$googleanalytics_adsense_script .= 'window.google_analytics_domain_name = "none";'; $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()) { if (variable_get('googleanalytics_trackuserid', 0) && user_is_logged_in()) {
// The USER_ID value should be a unique, persistent, and non-personally // The USER_ID value should be a unique, persistent, and non-personally
// identifiable string identifier that represents a user or signed-in // identifiable string identifier that represents a user or signed-in
// account across devices. // 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 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) .');'; $script .= 'ga("create", ' . drupal_json_encode($id) . ', ' . drupal_json_encode($create_only_fields) .');';
// Prepare Adsense tracking. // Prepare Adsense tracking.
...@@ -439,11 +451,13 @@ function googleanalytics_cron() { ...@@ -439,11 +451,13 @@ function googleanalytics_cron() {
* Collects and adds the number of search results to the head. * Collects and adds the number of search results to the head.
*/ */
function googleanalytics_preprocess_search_results(&$variables) { function googleanalytics_preprocess_search_results(&$variables) {
// There is no search result $variable available that hold the number of items if (variable_get('googleanalytics_site_search', FALSE)) {
// found. But the pager item mumber can tell the number of search results. // There is no search result $variable available that hold the number of items
global $pager_total_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)); 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 { ...@@ -30,10 +30,10 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
} }
function testGoogleAnalyticsConfiguration() { function testGoogleAnalyticsConfiguration() {
// Check if Configure link is available on 'Extend' page. // Check if Configure link is available on 'Modules' page.
// Requires 'administer modules' permission. // Requires 'administer modules' permission.
$this->drupalGet('admin/modules'); $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. // Check if Configure link is available on 'Status Reports' page. NOTE: Link is only shown without UA code configured.
// Requires 'administer site configuration' permission. // Requires 'administer site configuration' permission.
...@@ -61,7 +61,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -61,7 +61,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
// Show tracking on "every page except the listed pages". // Show tracking on "every page except the listed pages".
variable_set('googleanalytics_visibility_pages', 0); variable_set('googleanalytics_visibility_pages', 0);
// Disable tracking one "admin*" pages only. // Disable tracking on "admin*" pages only.
variable_set('googleanalytics_pages', "admin\nadmin/*"); variable_set('googleanalytics_pages', "admin\nadmin/*");
// Enable tracking only for authenticated users only. // Enable tracking only for authenticated users only.
variable_set('googleanalytics_roles', array(DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID)); variable_set('googleanalytics_roles', array(DRUPAL_AUTHENTICATED_RID => DRUPAL_AUTHENTICATED_RID));
...@@ -174,12 +174,12 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -174,12 +174,12 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
// Test if tracking of User ID is enabled. // Test if tracking of User ID is enabled.
variable_set('googleanalytics_trackuserid', 1); variable_set('googleanalytics_trackuserid', 1);
$this->drupalGet(''); $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. // Test if tracking of User ID is disabled.
variable_set('googleanalytics_trackuserid', 0); variable_set('googleanalytics_trackuserid', 0);
$this->drupalGet(''); $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. // Test if tracking of url fragments is enabled.
variable_set('googleanalytics_trackurlfragments', 1); variable_set('googleanalytics_trackurlfragments', 1);
...@@ -203,7 +203,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -203,7 +203,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
// Test whether single domain tracking is active. // Test whether single domain tracking is active.
$this->drupalGet(''); $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". // Enable "One domain with multiple subdomains".
variable_set('googleanalytics_domain_mode', 1); variable_set('googleanalytics_domain_mode', 1);
...@@ -224,7 +224,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -224,7 +224,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
variable_set('googleanalytics_domain_mode', 2); variable_set('googleanalytics_domain_mode', 2);
variable_set('googleanalytics_cross_domains', "www.example.com\nwww.example.net"); variable_set('googleanalytics_cross_domains', "www.example.com\nwww.example.net");
$this->drupalGet(''); $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("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('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.'); $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 { ...@@ -255,11 +255,11 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
); );
variable_set('googleanalytics_codesnippet_create', $codesnippet_create); variable_set('googleanalytics_codesnippet_create', $codesnippet_create);
variable_set('googleanalytics_codesnippet_before', 'ga("set", "forceSSL", true);'); 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->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("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("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,33 +292,31 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase { ...@@ -292,33 +292,31 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
// Basic test if the feature works. // Basic test if the feature works.
$googleanalytics_custom_dimension = array( $googleanalytics_custom_dimension = array(
'indexes' => array( 1 => array(
1 => array( 'index' => 1,
'index' => 1, 'value' => 'Bar 1',
'value' => 'Bar 1', ),
), 2 => array(
2 => array( 'index' => 2,
'index' => 2, 'value' => 'Bar 2',
'value' => 'Bar 2', ),
), 3 => array(
3 => array( 'index' => 3,
'index' => 3, 'value' => 'Bar 3',
'value' => 'Bar 3', ),
), 4 => array(
4 => array( 'index' => 4,
'index' => 4, 'value' => 'Bar 4',
'value' => 'Bar 4', ),
), 5 => array(
5 => array( 'index' => 5,
'index' => 5, 'value' => 'Bar 5',
'value' => 'Bar 5', ),
),
)
); );
variable_set('googleanalytics_custom_dimension', $googleanalytics_custom_dimension); variable_set('googleanalytics_custom_dimension', $googleanalytics_custom_dimension);
$this->drupalGet(''); $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.'); $this->assertRaw('ga("set", ' . drupal_json_encode('dimension' . $dimension['index']) . ', ' . drupal_json_encode($dimension['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Dimension #' . $dimension['index'] . ' is shown.');
} }
...@@ -327,28 +325,32 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase { ...@@ -327,28 +325,32 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
variable_set('site_slogan', $site_slogan); variable_set('site_slogan', $site_slogan);
$googleanalytics_custom_dimension = array( $googleanalytics_custom_dimension = array(
'indexes' => array( 1 => array(
1 => array( 'index' => 1,
'index' => 1, 'value' => 'Value: [site:slogan]',
'value' => 'Value: [site:slogan]', ),
), 2 => array(
2 => array( 'index' => 2,
'index' => 2, 'value' => $this->randomName(16),
'value' => $this->randomName(16), ),
), 3 => array(
3 => array( 'index' => 3,
'index' => 3, 'value' => '',
'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); variable_set('googleanalytics_custom_dimension', $googleanalytics_custom_dimension);
$this->verbose('<pre>' . print_r($googleanalytics_custom_dimension, TRUE) . '</pre>'); $this->verbose('<pre>' . print_r($googleanalytics_custom_dimension, TRUE) . '</pre>');
$this->drupalGet(''); $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('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->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() { function testGoogleAnalyticsCustomMetrics() {
...@@ -357,65 +359,67 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase { ...@@ -357,65 +359,67 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
// Basic test if the feature works. // Basic test if the feature works.
$googleanalytics_custom_metric = array( $googleanalytics_custom_metric = array(
'indexes' => array( 1 => array(
1 => array( 'index' => 1,
'index' => 1, 'value' => '6',
'value' => '6', 'value_expected' => 6,
'value_expected' => 6, ),
), 2 => array(
2 => array( 'index' => 2,
'index' => 2, 'value' => '8000',
'value' => '8000', 'value_expected' => 8000,
'value_expected' => 8000, ),
), 3 => array(
3 => array( 'index' => 3,
'index' => 3, 'value' => '7.8654',
'value' => '7.8654', 'value_expected' => 7.8654,
'value_expected' => 7.8654, ),
), 4 => array(
4 => array( 'index' => 4,
'index' => 4, 'value' => '1123.4',
'value' => '1123.4', 'value_expected' => 1123.4,
'value_expected' => 1123.4, ),
), 5 => array(
5 => array( 'index' => 5,
'index' => 5, 'value' => '5,67',
'value' => '5,67', 'value_expected' => 5,
'value_expected' => 5, ),
),
)
); );
variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric); variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric);
$this->drupalGet(''); $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.'); $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. // Test whether tokens are replaced in custom metric values.
$googleanalytics_custom_metric = array( $googleanalytics_custom_metric = array(
'indexes' => array( 1 => array(
1 => array( 'index' => 1,
'index' => 1, 'value' => '[current-user:roles:count]',
'value' => '[current-user:roles:count]', ),
), 2 => array(
2 => array( 'index' => 2,
'index' => 2, 'value' => mt_rand(),
'value' => mt_rand(), ),
), 3 => array(
3 => array( 'index' => 3,
'index' => 3, 'value' => '',
'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); variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric);
$this->verbose('<pre>' . print_r($googleanalytics_custom_metric, TRUE) . '</pre>'); $this->verbose('<pre>' . print_r($googleanalytics_custom_metric, TRUE) . '</pre>');
$this->drupalGet(''); $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('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->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 { ...@@ -572,6 +576,8 @@ class GoogleAnalyticsSearchTest extends DrupalWebTestCase {
'access administration pages', 'access administration pages',
'administer google analytics', 'administer google analytics',
'search content', 'search content',
'create page content',
'edit own page content',
); );
// User to set up google_analytics. // User to set up google_analytics.
...@@ -590,16 +596,44 @@ class GoogleAnalyticsSearchTest extends DrupalWebTestCase { ...@@ -590,16 +596,44 @@ class GoogleAnalyticsSearchTest extends DrupalWebTestCase {
$this->drupalGet('search/node'); $this->drupalGet('search/node');
$this->assertNoRaw('ga("set", "page",', '[testGoogleAnalyticsSearch]: Custom url not set.'); $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 for random string.
$search = array();
$search['keys'] = $this->randomName(8);
// Create a node to search for.
$langcode = LANGUAGE_NONE;
$edit = array(); $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); // Fire a search, it's expected to get 0 results.
$this->drupalPost('search/node', $edit, t('Search')); $this->drupalPost('search/node', $search, t('Search'));
$this->assertRaw('ga("set", "page", (window.googleanalytics_search_results) ?', '[testGoogleAnalyticsSearch]: Search results tracker is displayed.'); $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();
// Test search results counter. $this->drupalPost('search/node', $search, t('Search'));
$this->assertRaw('window.googleanalytics_search_results = ', '[testGoogleAnalyticsSearch]: Search results counter is displayed.'); $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.');
// 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) { ...@@ -21,7 +21,7 @@ Drupal.googleanalytics.test.assertSame = function (value1, value2, message) {
else { else {
console.error(message); console.error(message);
} }
} };
Drupal.googleanalytics.test.assertNotSame = function (value1, value2, message) { Drupal.googleanalytics.test.assertNotSame = function (value1, value2, message) {
if (value1 !== value2) { if (value1 !== value2) {
...@@ -30,7 +30,7 @@ Drupal.googleanalytics.test.assertNotSame = function (value1, value2, message) { ...@@ -30,7 +30,7 @@ Drupal.googleanalytics.test.assertNotSame = function (value1, value2, message) {
else { else {
console.error(message); console.error(message);
} }
} };
Drupal.googleanalytics.test.assertTrue = function (value1, message) { Drupal.googleanalytics.test.assertTrue = function (value1, message) {
if (value1 === true) { if (value1 === true) {
...@@ -39,7 +39,7 @@ Drupal.googleanalytics.test.assertTrue = function (value1, message) { ...@@ -39,7 +39,7 @@ Drupal.googleanalytics.test.assertTrue = function (value1, message) {
else { else {
console.error(message); console.error(message);
} }
} };
Drupal.googleanalytics.test.assertFalse = function (value1, message) { Drupal.googleanalytics.test.assertFalse = function (value1, message) {
if (value1 === false) { if (value1 === false) {
...@@ -48,7 +48,7 @@ Drupal.googleanalytics.test.assertFalse = function (value1, message) { ...@@ -48,7 +48,7 @@ Drupal.googleanalytics.test.assertFalse = function (value1, message) {
else { else {
console.error(message); console.error(message);
} }
} };
// Run after the documented is ready or Drupal.settings is undefined. // Run after the documented is ready or Drupal.settings is undefined.
$(document).ready(function() { $(document).ready(function() {
...@@ -86,8 +86,8 @@ $(document).ready(function() { ...@@ -86,8 +86,8 @@ $(document).ready(function() {
console.groupEnd(); console.groupEnd();
console.group("Test 'getPageUrl':"); 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, 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 + '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(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('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."); 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(); 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