Commit a33c820b authored by hass's avatar hass
Browse files

#1833596: Add basic support for Analytics.js (port is incomplete, lack

of API docs and features, see @todo's)
parent 70096c48
...@@ -72,5 +72,5 @@ code textarea. These can be found on the official Google Analytics pages ...@@ -72,5 +72,5 @@ code textarea. These can be found on the official Google Analytics pages
and a few examples at http://drupal.org/node/248699. Support is not and a few examples at http://drupal.org/node/248699. Support is not
provided for any customisations you include. provided for any customisations you include.
To speed up page loading you may also cache the Analytics ga.js To speed up page loading you may also cache the Google Analytics "analytics.js"
file locally. file locally.
...@@ -237,6 +237,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -237,6 +237,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#default_value' => variable_get('googleanalytics_site_search', FALSE), '#default_value' => variable_get('googleanalytics_site_search', FALSE),
'#disabled' => (module_exists('search') ? FALSE : TRUE), '#disabled' => (module_exists('search') ? FALSE : TRUE),
); );
/* @todo: not supported, https://support.google.com/analytics/bin/answer.py?hl=en&hlrm=de&answer=2795983
$form['tracking']['search_and_advertising']['googleanalytics_trackadsense'] = array( $form['tracking']['search_and_advertising']['googleanalytics_trackadsense'] = array(
'#type' => 'checkbox', '#type' => 'checkbox',
'#title' => t('Track AdSense ads'), '#title' => t('Track AdSense ads'),
...@@ -248,7 +249,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -248,7 +249,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#title' => t('Track DoubleClick data'), '#title' => t('Track DoubleClick data'),
'#description' => t('If checked, the alternative Google <a href="@doubleclick">DoubleClick data tracking</a> is used to enable AdWords remarketing features. If you choose this option you will need to <a href="@privacy">update your privacy policy</a>.', array('@doubleclick' => url('http://support.google.com/analytics/bin/answer.py', array('query' => array('answer' => '2444872'))), '@privacy' => url('http://support.google.com/analytics/bin/answer.py', array('query' => array('answer' => '2636405'))))), '#description' => t('If checked, the alternative Google <a href="@doubleclick">DoubleClick data tracking</a> is used to enable AdWords remarketing features. If you choose this option you will need to <a href="@privacy">update your privacy policy</a>.', array('@doubleclick' => url('http://support.google.com/analytics/bin/answer.py', array('query' => array('answer' => '2444872'))), '@privacy' => url('http://support.google.com/analytics/bin/answer.py', array('query' => array('answer' => '2636405'))))),
'#default_value' => variable_get('googleanalytics_trackdoubleclick', FALSE), '#default_value' => variable_get('googleanalytics_trackdoubleclick', FALSE),
); ); */
// Privacy specific configurations. // Privacy specific configurations.
$form['tracking']['privacy'] = array( $form['tracking']['privacy'] = array(
...@@ -269,6 +270,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -269,6 +270,7 @@ function googleanalytics_admin_settings_form($form_state) {
); );
// Custom variables. // Custom variables.
/* @todo: Update to custom dimensions.
$form['googleanalytics_custom_var'] = array( $form['googleanalytics_custom_var'] = array(
'#collapsed' => TRUE, '#collapsed' => TRUE,
'#collapsible' => TRUE, '#collapsible' => TRUE,
...@@ -339,7 +341,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -339,7 +341,7 @@ function googleanalytics_admin_settings_form($form_state) {
'#theme' => 'token_tree', '#theme' => 'token_tree',
'#token_types' => array('node'), '#token_types' => array('node'),
'#dialog' => TRUE, '#dialog' => TRUE,
); ); */
// Advanced feature configurations. // Advanced feature configurations.
...@@ -367,6 +369,7 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -367,6 +369,7 @@ function googleanalytics_admin_settings_form($form_state) {
); );
} }
// @todo: Update urls once they are available.
$form['advanced']['codesnippet'] = array( $form['advanced']['codesnippet'] = array(
'#type' => 'fieldset', '#type' => 'fieldset',
'#title' => t('Custom JavaScript code'), '#title' => t('Custom JavaScript code'),
...@@ -379,14 +382,14 @@ function googleanalytics_admin_settings_form($form_state) { ...@@ -379,14 +382,14 @@ function googleanalytics_admin_settings_form($form_state) {
'#title' => t('Code snippet (before)'), '#title' => t('Code snippet (before)'),
'#default_value' => variable_get('googleanalytics_codesnippet_before', ''), '#default_value' => variable_get('googleanalytics_codesnippet_before', ''),
'#rows' => 5, '#rows' => 5,
'#description' => t("Code in this textarea will be added <strong>before</strong> _gaq.push(['_trackPageview'])."), '#description' => t("Code in this textarea will be added <strong>before</strong> <code>ga('send', 'pageview');</code>."),
); );
$form['advanced']['codesnippet']['googleanalytics_codesnippet_after'] = array( $form['advanced']['codesnippet']['googleanalytics_codesnippet_after'] = array(
'#type' => 'textarea', '#type' => 'textarea',
'#title' => t('Code snippet (after)'), '#title' => t('Code snippet (after)'),
'#default_value' => variable_get('googleanalytics_codesnippet_after', ''), '#default_value' => variable_get('googleanalytics_codesnippet_after', ''),
'#rows' => 5, '#rows' => 5,
'#description' => t("Code in this textarea will be added <strong>after</strong> _gaq.push(['_trackPageview']). This is useful if you'd like to track a site in two accounts."), '#description' => t("Code in this textarea will be added <strong>after</strong> <code>ga('send', 'pageview');</code>. This is useful if you'd like to track a site in two accounts."),
); );
$form['advanced']['googleanalytics_js_scope'] = array( $form['advanced']['googleanalytics_js_scope'] = array(
...@@ -446,10 +449,10 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) { ...@@ -446,10 +449,10 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) {
} }
// This is for the Newbie's who cannot read a text area description. // This is for the Newbie's who cannot read a text area description.
if (stristr($form_state['values']['googleanalytics_codesnippet_before'], 'google-analytics.com/ga.js')) { if (stristr($form_state['values']['googleanalytics_codesnippet_before'], 'google-analytics.com/analytics.js')) {
form_set_error('googleanalytics_codesnippet_before', t('Do not add the tracker code provided by Google into the javascript code snippets! This module already builds the tracker code based on your Google Analytics account number and settings.')); form_set_error('googleanalytics_codesnippet_before', t('Do not add the tracker code provided by Google into the javascript code snippets! This module already builds the tracker code based on your Google Analytics account number and settings.'));
} }
if (stristr($form_state['values']['googleanalytics_codesnippet_after'], 'google-analytics.com/ga.js')) { if (stristr($form_state['values']['googleanalytics_codesnippet_after'], 'google-analytics.com/analytics.js')) {
form_set_error('googleanalytics_codesnippet_after', t('Do not add the tracker code provided by Google into the javascript code snippets! This module already builds the tracker code based on your Google Analytics account number and settings.')); form_set_error('googleanalytics_codesnippet_after', t('Do not add the tracker code provided by Google into the javascript code snippets! This module already builds the tracker code based on your Google Analytics account number and settings.'));
} }
if (preg_match('/(.*)<\/?script(.*)>(.*)/i', $form_state['values']['googleanalytics_codesnippet_before'])) { if (preg_match('/(.*)<\/?script(.*)>(.*)/i', $form_state['values']['googleanalytics_codesnippet_before'])) {
......
...@@ -87,12 +87,13 @@ Drupal.behaviors.trackingSettingsSummary = { ...@@ -87,12 +87,13 @@ Drupal.behaviors.trackingSettingsSummary = {
if ($('input#edit-googleanalytics-site-search', context).is(':checked')) { if ($('input#edit-googleanalytics-site-search', context).is(':checked')) {
vals.push(Drupal.t('Site search')); vals.push(Drupal.t('Site search'));
} }
/* @todo: Features not yet supported by analytics.js
if ($('input#edit-googleanalytics-trackadsense', context).is(':checked')) { if ($('input#edit-googleanalytics-trackadsense', context).is(':checked')) {
vals.push(Drupal.t('AdSense ads')); vals.push(Drupal.t('AdSense ads'));
} }
if ($('input#edit-googleanalytics-trackdoubleclick', context).is(':checked')) { if ($('input#edit-googleanalytics-trackdoubleclick', context).is(':checked')) {
vals.push(Drupal.t('DoubleClick data')); vals.push(Drupal.t('DoubleClick data'));
} } */
if (!vals.length) { if (!vals.length) {
return Drupal.t('Not tracked'); return Drupal.t('Not tracked');
} }
......
...@@ -36,8 +36,8 @@ function googleanalytics_uninstall() { ...@@ -36,8 +36,8 @@ function googleanalytics_uninstall() {
variable_del('googleanalytics_pages'); variable_del('googleanalytics_pages');
variable_del('googleanalytics_roles'); variable_del('googleanalytics_roles');
variable_del('googleanalytics_site_search'); variable_del('googleanalytics_site_search');
variable_del('googleanalytics_trackadsense'); variable_del('googleanalytics_trackadsense'); // @todo
variable_del('googleanalytics_trackdoubleclick'); variable_del('googleanalytics_trackdoubleclick'); // @todo
variable_del('googleanalytics_tracker_anonymizeip'); variable_del('googleanalytics_tracker_anonymizeip');
variable_del('googleanalytics_trackfiles'); variable_del('googleanalytics_trackfiles');
variable_del('googleanalytics_trackfiles_extensions'); variable_del('googleanalytics_trackfiles_extensions');
...@@ -50,7 +50,7 @@ function googleanalytics_uninstall() { ...@@ -50,7 +50,7 @@ function googleanalytics_uninstall() {
// 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_after_backup_6300');
variable_del('googleanalytics_codesnippet_before_backup_6300'); variable_del('googleanalytics_codesnippet_before_backup_6300');
variable_del('googleanalytics_segmentation'); variable_del('googleanalytics_segmentation');
} }
/** /**
......
...@@ -26,27 +26,29 @@ $(document).ready(function() { ...@@ -26,27 +26,29 @@ $(document).ready(function() {
else if (ga.trackDownload && isDownload.test(this.href)) { else if (ga.trackDownload && isDownload.test(this.href)) {
// Download link clicked. // Download link clicked.
var extension = isDownload.exec(this.href); var extension = isDownload.exec(this.href);
_gaq.push(["_trackEvent", "Downloads", extension[1].toUpperCase(), this.href.replace(isInternal, '')]); ga("send", "event", "Downloads", extension[1].toUpperCase(), this.href.replace(isInternal, ''));
} }
else if (isInternalSpecial.test(this.href)) { else if (isInternalSpecial.test(this.href)) {
// Keep the internal URL for Google Analytics website overlay intact. // Keep the internal URL for Google Analytics website overlay intact.
_gaq.push(["_trackPageview", this.href.replace(isInternal, '')]); ga("send", "pageview", { page: this.href.replace(isInternal, '')});
} }
} }
else { else {
if (ga.trackMailto && $(this).is("a[href^='mailto:'],area[href^='mailto:']")) { if (ga.trackMailto && $(this).is("a[href^='mailto:'],area[href^='mailto:']")) {
// Mailto link clicked. // Mailto link clicked.
_gaq.push(["_trackEvent", "Mails", "Click", this.href.substring(7)]); ga("send", "event", "Mails", "Click", this.href.substring(7));
} }
else if (ga.trackOutbound && this.href.match(/^\w+:\/\//i)) { else if (ga.trackOutbound && this.href.match(/^\w+:\/\//i)) {
if (ga.trackDomainMode == 2 && isCrossDomain($(this).attr('hostname'), ga.trackCrossDomains)) { if (ga.trackDomainMode == 2 && isCrossDomain($(this).attr('hostname'), ga.trackCrossDomains)) {
// Top-level cross domain clicked. document.location is handled by _link internally. // Top-level cross domain clicked. document.location is handled by _link internally.
event.preventDefault(); event.preventDefault();
_gaq.push(["_link", this.href]); // @todo: unknown upgrade path
//_gaq.push(["_link", this.href]);
//ga("link", this.href); ???
} }
else { else {
// External link clicked. // External link clicked.
_gaq.push(["_trackEvent", "Outbound links", "Click", this.href]); ga("send", "event", "Outbound links", "Click", this.href);
} }
} }
} }
...@@ -58,7 +60,7 @@ $(document).ready(function() { ...@@ -58,7 +60,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) {
_gaq.push(["_trackPageview", href.replace(isInternal, '')]); ga("send", "pageview", { page: href.replace(isInternal, '') });
} }
}); });
......
...@@ -95,12 +95,14 @@ function googleanalytics_page_alter(&$page) { ...@@ -95,12 +95,14 @@ function googleanalytics_page_alter(&$page) {
if (!empty($id) && (_googleanalytics_visibility_pages() || in_array($status, $trackable_status_codes)) && _googleanalytics_visibility_user($user)) { if (!empty($id) && (_googleanalytics_visibility_pages() || in_array($status, $trackable_status_codes)) && _googleanalytics_visibility_user($user)) {
// We allow different scopes. Default to 'header' but allow user to override if they really need to. // We allow different scopes. Default to 'header' but allow user to override if they really need to.
// @todo: footer may no longer suppored
$scope = variable_get('googleanalytics_js_scope', 'header'); $scope = variable_get('googleanalytics_js_scope', 'header');
/* @todo: not supported, https://support.google.com/analytics/bin/answer.py?hl=en&hlrm=de&answer=2795983
if (variable_get('googleanalytics_trackadsense', FALSE)) { if (variable_get('googleanalytics_trackadsense', FALSE)) {
// Custom tracking. Prepend before all other JavaScript. // Custom tracking. Prepend before all other JavaScript.
drupal_add_js('window.google_analytics_uacct = ' . drupal_json_encode($id) . ';', array('type' => 'inline', 'group' => JS_LIBRARY-1)); //drupal_add_js('window.google_analytics_uacct = ' . drupal_json_encode($id) . ';', array('type' => 'inline', 'group' => JS_LIBRARY-1));
} } */
// Add link tracking. // Add link tracking.
$link_settings = array(); $link_settings = array();
...@@ -140,7 +142,8 @@ function googleanalytics_page_alter(&$page) { ...@@ -140,7 +142,8 @@ function googleanalytics_page_alter(&$page) {
// Track only the selected message types. // Track only the selected message types.
if (in_array($type, $message_types)) { if (in_array($type, $message_types)) {
foreach ($messages as $message) { foreach ($messages as $message) {
$message_events .= '_gaq.push(["_trackEvent", ' . drupal_json_encode(t('Messages')) . ', ' . drupal_json_encode($status_heading[$type]) . ', ' . drupal_json_encode(strip_tags($message)) . ']);'; // @todo: Track as exceptions?
$message_events .= 'ga("send", "event", ' . drupal_json_encode(t('Messages')) . ', ' . drupal_json_encode($status_heading[$type]) . ', ' . drupal_json_encode(strip_tags($message)) . ');';
} }
} }
} }
...@@ -149,8 +152,8 @@ function googleanalytics_page_alter(&$page) { ...@@ -149,8 +152,8 @@ function googleanalytics_page_alter(&$page) {
// Site search tracking support. // Site search tracking support.
$url_custom = ''; $url_custom = '';
if (module_exists('search') && variable_get('googleanalytics_site_search', FALSE) && arg(0) == 'search' && $keys = googleanalytics_search_get_keys()) { if (module_exists('search') && variable_get('googleanalytics_site_search', FALSE) && arg(0) == 'search' && $keys = googleanalytics_search_get_keys()) {
// hook_preprocess_search_results() is not executed if search result is // hook_preprocess_search_results() is not executed if search result is
// empty. Make sure the counter is set to 0 if there are no results. // empty. Make sure the counter is set to 0 if there are no results.
$url_custom = '(window.googleanalytics_search_results) ? ' . drupal_json_encode(url('search/' . arg(1), array('query' => array('search' => $keys)))) . ' : ' . drupal_json_encode(url('search/' . arg(1), array('query' => array('search' => 'no-results:' . $keys, 'cat' => 'no-results')))); $url_custom = '(window.googleanalytics_search_results) ? ' . drupal_json_encode(url('search/' . arg(1), array('query' => array('search' => $keys)))) . ' : ' . drupal_json_encode(url('search/' . arg(1), array('query' => array('search' => 'no-results:' . $keys, 'cat' => 'no-results'))));
} }
...@@ -181,6 +184,7 @@ function googleanalytics_page_alter(&$page) { ...@@ -181,6 +184,7 @@ function googleanalytics_page_alter(&$page) {
$codesnippet_after = variable_get('googleanalytics_codesnippet_after', ''); $codesnippet_after = variable_get('googleanalytics_codesnippet_after', '');
// Add custom variables. // Add custom variables.
/* @todo: Needs upgrade to custom dimensions
$googleanalytics_custom_vars = variable_get('googleanalytics_custom_var', array()); $googleanalytics_custom_vars = variable_get('googleanalytics_custom_var', array());
$custom_var = ''; $custom_var = '';
for ($i = 1; $i < 6; $i++) { for ($i = 1; $i < 6; $i++) {
...@@ -215,17 +219,47 @@ function googleanalytics_page_alter(&$page) { ...@@ -215,17 +219,47 @@ function googleanalytics_page_alter(&$page) {
$custom_var_name = drupal_json_encode($custom_var_name); $custom_var_name = drupal_json_encode($custom_var_name);
$custom_var_value = drupal_json_encode($custom_var_value); $custom_var_value = drupal_json_encode($custom_var_value);
$custom_var .= "_gaq.push(['_setCustomVar', $i, $custom_var_name, $custom_var_value, $custom_var_scope]);";
$custom_var .= "ga('set', 'dimension" . $i . "', $custom_var_name);"; // Max 150 bytes
$custom_var .= "ga('set', 'metric" . $i . "', $custom_var_value);";
} }
} } */
// Build tracker code. // Build tracker code.
$script = 'var _gaq = _gaq || [];'; $script = '(function(q,u,i,c,k){';
$script .= '_gaq.push(["_setAccount", ' . drupal_json_encode($id) . ']);'; $script .= 'window["GoogleAnalyticsObject"]=q;';
$script .= 'window[q]=window[q]||function(){';
$script .= '(window[q].q=window[q].q||[]).push(arguments)},';
$script .= 'window[q].l=1*new Date();c=i.createElement(u),k=i.getElementsByTagName(u)[0];';
$script .= 'c.async=true;';
// Which version of the tracking library should be used?
$library_tracker_url = '//www.google-analytics.com/analytics.js';
$library_cache_url = 'http:' . $library_tracker_url;
// Should a local cached copy of analytics.js be used?
if (variable_get('googleanalytics_cache', 0) && $url = _googleanalytics_cache($library_cache_url)) {
// A dummy query-string is added to filenames, to gain control over
// browser-caching. The string changes on every update or full cache
// flush, forcing browsers to load a new copy of the files, as the
// URL changed.
$query_string = '?' . variable_get('css_js_query_string', '0');
$script .= 'c.src="' . $url . $query_string . '";';
}
else {
$script .= 'c.src="' . $library_tracker_url . '";';
}
$script .= 'k.parentNode.insertBefore(c,k)})("ga","script",document);';
// Create a tracker.
$script .= 'ga("create", ' . drupal_json_encode($id) . ');';
if (variable_get('googleanalytics_tracker_anonymizeip', 0)) { if (variable_get('googleanalytics_tracker_anonymizeip', 0)) {
// @todo: unknown
// FIXME: The Google API is currently broken and "_gat._anonymizeIp" is only // FIXME: The Google API is currently broken and "_gat._anonymizeIp" is only
// a workaround until "_anonymizeIp" has been implemented/fixed. // a workaround until "_anonymizeIp" has been implemented/fixed.
$script .= '_gaq.push(["_gat._anonymizeIp"]);'; $script .= 'ga("set", "anonymizeIp", true);';
} }
// Domain tracking type. // Domain tracking type.
...@@ -235,11 +269,12 @@ function googleanalytics_page_alter(&$page) { ...@@ -235,11 +269,12 @@ function googleanalytics_page_alter(&$page) {
// Per RFC 2109, cookie domains must contain at least one dot other than the // Per RFC 2109, cookie domains must contain at least one dot other than the
// first. For hosts such as 'localhost' or IP Addresses we don't set a cookie domain. // first. For hosts such as 'localhost' or IP Addresses we don't set a cookie domain.
if ($domain_mode == 1 && count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) { if ($domain_mode == 1 && count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
$script .= '_gaq.push(["_setDomainName", ' . drupal_json_encode($cookie_domain) . ']);'; $script .= 'ga("set", "cookieDomain", ' . drupal_json_encode($cookie_domain) . ');';
} }
elseif ($domain_mode == 2) { elseif ($domain_mode == 2) {
$script .= '_gaq.push(["_setDomainName", "none"]);'; // @todo: unclear, cookieDomain = "none" is not documented.
$script .= '_gaq.push(["_setAllowLinker", true]);'; $script .= 'ga("set", "cookieDomain", "none");';
$script .= 'ga("set", "allowLinker", true);';
} }
if (!empty($custom_var)) { if (!empty($custom_var)) {
...@@ -248,12 +283,11 @@ function googleanalytics_page_alter(&$page) { ...@@ -248,12 +283,11 @@ function googleanalytics_page_alter(&$page) {
if (!empty($codesnippet_before)) { if (!empty($codesnippet_before)) {
$script .= $codesnippet_before; $script .= $codesnippet_before;
} }
if (empty($url_custom)) { if (!empty($url_custom)) {
$script .= '_gaq.push(["_trackPageview"]);'; $script .= 'ga("set", "page", ' . $url_custom . ');';
}
else {
$script .= '_gaq.push(["_trackPageview", ' . $url_custom . ']);';
} }
$script .= 'ga("send", "pageview");';
if (!empty($message_events)) { if (!empty($message_events)) {
$script .= $message_events; $script .= $message_events;
} }
...@@ -261,44 +295,6 @@ function googleanalytics_page_alter(&$page) { ...@@ -261,44 +295,6 @@ function googleanalytics_page_alter(&$page) {
$script .= $codesnippet_after; $script .= $codesnippet_after;
} }
$script .= '(function() {';
$script .= 'var ga = document.createElement("script");';
$script .= 'ga.type = "text/javascript";';
$script .= 'ga.async = true;';
// Which version of the tracking library should be used?
if ($trackdoubleclick = variable_get('googleanalytics_trackdoubleclick', FALSE)) {
$library_tracker_url = 'stats.g.doubleclick.net/dc.js';
$library_cache_url = 'http://' . $library_tracker_url;
}
else {
$library_tracker_url = '.google-analytics.com/ga.js';
$library_cache_url = 'http://www' . $library_tracker_url;
}
// Should a local cached copy of ga.js be used?
if (variable_get('googleanalytics_cache', 0) && $url = _googleanalytics_cache($library_cache_url)) {
// A dummy query-string is added to filenames, to gain control over
// browser-caching. The string changes on every update or full cache
// flush, forcing browsers to load a new copy of the files, as the
// URL changed.
$query_string = '?' . variable_get('css_js_query_string', '0');
$script .= 'ga.src = "' . $url . $query_string . '";';
}
else {
// Library paths do not follow the same naming convention.
if ($trackdoubleclick) {
$script .= 'ga.src = ("https:" == document.location.protocol ? "https://" : "http://") + "' . $library_tracker_url . '";';
}
else {
$script .= 'ga.src = ("https:" == document.location.protocol ? "https://ssl" : "http://www") + "' . $library_tracker_url . '";';
}
}
$script .= 'var s = document.getElementsByTagName("script")[0];';
$script .= 's.parentNode.insertBefore(ga, s);';
$script .= '})();';
drupal_add_js($script, array('scope' => $scope, 'type' => 'inline')); drupal_add_js($script, array('scope' => $scope, 'type' => 'inline'));
} }
} }
...@@ -384,13 +380,7 @@ function googleanalytics_user_presave(&$edit, $account, $category) { ...@@ -384,13 +380,7 @@ function googleanalytics_user_presave(&$edit, $account, $category) {
function googleanalytics_cron() { function googleanalytics_cron() {
// Regenerate the tracking code file every day. // Regenerate the tracking code file every day.
if (REQUEST_TIME - variable_get('googleanalytics_last_cache', 0) >= 86400 && variable_get('googleanalytics_cache', 0)) { if (REQUEST_TIME - variable_get('googleanalytics_last_cache', 0) >= 86400 && variable_get('googleanalytics_cache', 0)) {
// Which version of the tracking library should be used? _googleanalytics_cache('http://www.google-analytics.com/analytics.js', TRUE);
if (variable_get('googleanalytics_trackdoubleclick', FALSE)) {
_googleanalytics_cache('http://stats.g.doubleclick.net/dc.js', TRUE);
}
else {
_googleanalytics_cache('http://www.google-analytics.com/ga.js', TRUE);
}
variable_set('googleanalytics_last_cache', REQUEST_TIME); variable_set('googleanalytics_last_cache', REQUEST_TIME);
} }
} }
......
...@@ -58,7 +58,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -58,7 +58,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
$this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed on admin page.'); $this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed on admin page.');
$this->drupalGet('admin/config/system/googleanalytics'); $this->drupalGet('admin/config/system/googleanalytics');
// Checking for tracking code URI here, as $ua_code is displayed in the form. // Checking for tracking code URI here, as $ua_code is displayed in the form.
$this->assertNoRaw('google-analytics.com/ga.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed on admin subpage.'); $this->assertNoRaw('google-analytics.com/analytics.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is not displayed on admin subpage.');
// Test whether tracking code display is properly flipped. // Test whether tracking code display is properly flipped.
variable_set('googleanalytics_visibility_pages', 1); variable_set('googleanalytics_visibility_pages', 1);
...@@ -66,7 +66,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -66,7 +66,7 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
$this->assertRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed on admin page.'); $this->assertRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed on admin page.');
$this->drupalGet('admin/config/system/googleanalytics'); $this->drupalGet('admin/config/system/googleanalytics');
// Checking for tracking code URI here, as $ua_code is displayed in the form. // Checking for tracking code URI here, as $ua_code is displayed in the form.
$this->assertRaw('google-analytics.com/ga.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed on admin subpage.'); $this->assertRaw('google-analytics.com/analytics.js', '[testGoogleAnalyticsPageVisibility]: Tracking code is displayed on admin subpage.');
$this->drupalGet(''); $this->drupalGet('');
$this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is NOT displayed on front page.'); $this->assertNoRaw($ua_code, '[testGoogleAnalyticsPageVisibility]: Tracking code is NOT displayed on front page.');
...@@ -93,18 +93,18 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -93,18 +93,18 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
variable_set('cache', 1); variable_set('cache', 1);
// Test whether DNT headers will fail to disable embedding of tracking code. // Test whether DNT headers will fail to disable embedding of tracking code.
$this->drupalGet('', array(), array('DNT: 1')); $this->drupalGet('', array(), array('DNT: 1'));
$this->assertRaw('_gaq.push(["_trackPageview"]);', '[testGoogleAnalyticsDNTVisibility]: DNT header send from client, but page caching is enabled and tracker cannot removed.'); $this->assertRaw('ga("send", "pageview");', '[testGoogleAnalyticsDNTVisibility]: DNT header send from client, but page caching is enabled and tracker cannot removed.');
// DNT works only with caching of pages for anonymous users disabled. // DNT works only with caching of pages for anonymous users disabled.
variable_set('cache', 0); variable_set('cache', 0);
$this->drupalGet(''); $this->drupalGet('');
$this->assertRaw('_gaq.push(["_trackPageview"]);', '[testGoogleAnalyticsDNTVisibility]: Tracking is enabled without DNT header.'); $this->assertRaw('ga("send", "pageview");', '[testGoogleAnalyticsDNTVisibility]: Tracking is enabled without DNT header.');
// Test whether DNT header is able to remove the tracking code. // Test whether DNT header is able to remove the tracking code.
$this->drupalGet('', array(), array('DNT: 1')); $this->drupalGet('', array(), array('DNT: 1'));
$this->assertNoRaw('_gaq.push(["_trackPageview"]);', '[testGoogleAnalyticsDNTVisibility]: DNT header received from client. Tracking has been disabled by browser.'); $this->assertNoRaw('ga("send", "pageview");', '[testGoogleAnalyticsDNTVisibility]: DNT header received from client. Tracking has been disabled by browser.');
// Disable DNT feature and see if tracker is still embedded. // Disable DNT feature and see if tracker is still embedded.
variable_set('googleanalytics_privacy_donottrack', 0); variable_set('googleanalytics_privacy_donottrack', 0);
$this->drupalGet('', array(), array('DNT: 1')); $this->drupalGet('', array(), array('DNT: 1'));
$this->assertRaw('_gaq.push(["_trackPageview"]);', '[testGoogleAnalyticsDNTVisibility]: DNT feature is disabled, DNT header from browser has been ignored.'); $this->assertRaw('ga("send", "pageview");', '[testGoogleAnalyticsDNTVisibility]: DNT feature is disabled, DNT header from browser has been ignored.');
} }
function testGoogleAnalyticsTrackingCode() { function testGoogleAnalyticsTrackingCode() {
...@@ -118,40 +118,34 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -118,40 +118,34 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
/* Sample JS code as added to page: /* Sample JS code as added to page:
<script type="text/javascript" src="/sites/all/modules/google_analytics/googleanalytics.js?w"></script> <script type="text/javascript" src="/sites/all/modules/google_analytics/googleanalytics.js?w"></script>
<script type="text/javascript"> <script>
var _gaq = _gaq || []; (function(q,u,i,c,k){window['GoogleAnalyticsObject']=q;
_gaq.push(['_setAccount', 'UA-123456-7']); window[q]=window[q]||function(){(window[q].q=window[q].q||[]).push(arguments)},
_gaq.push(['_trackPageview']); window[q].l=1*new Date();c=i.createElement(u),k=i.getElementsByTagName(u)[0];
c.async=true;c.src='//www.google-analytics.com/analytics.js';
(function() { k.parentNode.insertBefore(c,k)})('ga','script',document);
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga('create', 'UA-123456-7');
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; ga('send', 'pageview');
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script> </script>
<!-- End Google Analytics -->
*/ */
// Test whether tracking code uses latest JS. // Test whether tracking code uses latest JS.
variable_set('googleanalytics_cache', 0); variable_set('googleanalytics_cache', 0);
$this->drupalGet(''); $this->drupalGet('');
$this->assertRaw('google-analytics.com/ga.js', '[testGoogleAnalyticsTrackingCode]: Latest tracking code used.'); $this->assertRaw('google-analytics.com/analytics.js', '[testGoogleAnalyticsTrackingCode]: Latest tracking code used.');
// Test whether the alternate doubleclick library is used
variable_set('googleanalytics_trackdoubleclick', 1);
$this->drupalGet('');
$this->assertRaw('stats.g.doubleclick.net/dc.js', '[testGoogleAnalyticsTrackingCode]: Doubleclick tracking code used.');
// Test whether anonymize visitors IP address feature has been enabled. // Test whether anonymize visitors IP address feature has been enabled.
$this->drupalGet(''); $this->drupalGet('');
$this->assertNoRaw('_gaq.push(["_gat._anonymizeIp"]);', '[testGoogleAnalyticsTrackingCode]: Anonymize visitors IP address not found on frontpage.'); $this->assertNoRaw('ga("set", "anonymizeIp", true);', '[testGoogleAnalyticsTrackingCode]: Anonymize visitors IP address not found on frontpage.');
// Enable anonymizing of IP addresses. // Enable anonymizing of IP addresses.
variable_set('googleanalytics_tracker_anonymizeip', 1); variable_set('googleanalytics_tracker_anonymizeip', 1);
$this->drupalGet(''); $this->drupalGet('');
$this->assertRaw('_gaq.push(["_gat._anonymizeIp"]);', '[testGoogleAnalyticsTrackingCode]: Anonymize visitors IP address found on frontpage.'); $this->assertRaw('ga("set", "anonymizeIp", true);', '[testGoogleAnalyticsTrackingCode]: Anonymize visitors IP address found on frontpage.');
// Test whether single domain tracking is active. // Test whether single domain tracking is active.
$this->drupalGet(''); $this->drupalGet('');
$this->assertNoRaw('_gaq.push(["_setDomainName"', '[testGoogleAnalyticsTrackingCode]: Single domain tracking is active.'); $this->assertNoRaw('ga("set", "cookieDomain",', '[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);
...@@ -161,30 +155,32 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase { ...@@ -161,30 +155,32 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
// TODO: Workaround to run tests successfully. This feature cannot tested reliable. // TODO: Workaround to run tests successfully. This feature cannot tested reliable.