security updates of unpatched modules
This commit is contained in:
@@ -12,12 +12,20 @@ Requirements
|
||||
|
||||
* Google Analytics user account
|
||||
|
||||
|
||||
Installation
|
||||
============
|
||||
Copy the 'googleanalytics' module directory in to your Drupal
|
||||
sites/all/modules directory as usual.
|
||||
|
||||
Upgrading from 6.x-3.x and 7.x-1.x
|
||||
==================================
|
||||
If you upgrade from 6.x-3.x and 7.x-1.x (ga.js) to 7.x-2.x (analytics.js) you
|
||||
should verify if you used custom variables. Write down your settings or make a
|
||||
screenshot. You need to re-configure the settings to use custom dimensions or
|
||||
metrics. There is no automatic upgrade path for custom variables feature. All
|
||||
other module settings are upgraded automatically.
|
||||
|
||||
See https://support.google.com/analytics/answer/2795983?hl=en for more details.
|
||||
|
||||
Usage
|
||||
=====
|
||||
@@ -27,12 +35,8 @@ All pages will now have the required JavaScript added to the
|
||||
HTML footer can confirm this by viewing the page source from
|
||||
your browser.
|
||||
|
||||
New approach to page tracking in 5.x-1.5 and 6.x-1.1
|
||||
====================================================
|
||||
With 5.x-1.5 and 6.x-1.1 there are new settings on the settings page at
|
||||
admin/config/system/googleanalytics. The "Page specific tracking" area now
|
||||
comes with an interface that copies Drupal's block visibility settings.
|
||||
|
||||
Page specific tracking
|
||||
======================
|
||||
The default is set to "Add to every page except the listed pages". By
|
||||
default the following pages are listed for exclusion:
|
||||
|
||||
@@ -44,23 +48,24 @@ node/*/*
|
||||
user/*/*
|
||||
|
||||
These defaults are changeable by the website administrator or any other
|
||||
user with 'administer google analytics' permission.
|
||||
user with 'Administer Google Analytics' permission.
|
||||
|
||||
Like the blocks visibility settings in Drupal core, there is now a
|
||||
choice for "Add if the following PHP code returns TRUE." Sample PHP snippets
|
||||
that can be used in this textarea can be found on the handbook page
|
||||
"Overview-approach to block visibility" at http://drupal.org/node/64135.
|
||||
Like the blocks visibility settings in Drupal core, there is a choice for
|
||||
"Add if the following PHP code returns TRUE." Sample PHP snippets that can be
|
||||
used in this textarea can be found on the handbook page "Overview-approach to
|
||||
block visibility" at http://drupal.org/node/64135.
|
||||
|
||||
Custom dimensions and metrics
|
||||
=============================
|
||||
One example for custom dimensions tracking is the "User roles" tracking.
|
||||
|
||||
1. In the Google Analytics Management Interface you need to setup Dimension #1
|
||||
with name e.g. "User roles". This step is required. Do not miss it, please.
|
||||
1. In the Google Analytics Management Interface (http://www.google.com/analytics/)
|
||||
you need to setup Dimension #1 with name e.g. "User roles". This step is
|
||||
required. Do not miss it, please.
|
||||
|
||||
2. Enter the below configuration data into the custom dimensions settings form
|
||||
under admin/config/system/googleanalytics. You can also choose another index,
|
||||
but keep it always in sync with the index used in step #1.
|
||||
2. Enter the below configuration data into the Drupal custom dimensions settings
|
||||
form under admin/config/system/googleanalytics. You can also choose another
|
||||
index, but keep it always in sync with the index used in step #1.
|
||||
|
||||
Index: 1
|
||||
Value: [current-user:role-names]
|
||||
@@ -77,3 +82,23 @@ provided for any customisations you include.
|
||||
|
||||
To speed up page loading you may also cache the Google Analytics "analytics.js"
|
||||
file locally.
|
||||
|
||||
Manual JS debugging
|
||||
===================
|
||||
For manual debugging of the JS code you are able to create a test node. This
|
||||
is the example HTML code for this test node. You need to enable debugging mode
|
||||
in your Drupal configuration of Google Analytics settings to see verbose
|
||||
messages in your browsers JS console.
|
||||
|
||||
Title: Google Analytics test page
|
||||
|
||||
Body:
|
||||
<ul>
|
||||
<li><a href="mailto:foo@example.com">Mailto</a></li>
|
||||
<li><a href="/files/test.txt">Download file</a></li>
|
||||
<li><a class="colorbox" href="#">Open colorbox</a></li>
|
||||
<li><a href="http://example.com/">External link</a></li>
|
||||
<li><a href="/go/test">Go link</a></li>
|
||||
</ul>
|
||||
|
||||
Text format: Full HTML
|
||||
|
@@ -224,6 +224,18 @@ function googleanalytics_admin_settings_form($form_state) {
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$colorbox_dependencies = '<div class="admin-requirements">';
|
||||
$colorbox_dependencies .= t('Requires: !module-list', array('!module-list' => (module_exists('colorbox') ? t('@module (<span class="admin-enabled">enabled</span>)', array('@module' => 'Colorbox')) : t('@module (<span class="admin-disabled">disabled</span>)', array('@module' => 'Colorbox')))));
|
||||
$colorbox_dependencies .= '</div>';
|
||||
|
||||
$form['tracking']['linktracking']['googleanalytics_trackcolorbox'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Track content in colorbox modal dialogs'),
|
||||
'#default_value' => variable_get('googleanalytics_trackcolorbox', 1),
|
||||
'#description' => t('Enable to track the content shown in colorbox modal windows.') . $colorbox_dependencies,
|
||||
'#disabled' => (module_exists('colorbox') ? FALSE : TRUE),
|
||||
);
|
||||
$form['tracking']['linktracking']['googleanalytics_tracklinkid'] = array(
|
||||
'#type' => 'checkbox',
|
||||
'#title' => t('Track enhanced link attribution'),
|
||||
@@ -246,7 +258,7 @@ function googleanalytics_admin_settings_form($form_state) {
|
||||
'#type' => 'checkboxes',
|
||||
'#title' => t('Track messages of type'),
|
||||
'#default_value' => variable_get('googleanalytics_trackmessages', array()),
|
||||
'#description' => t('This will track the selected message types shown to users. Tracking of form validation errors may help you identifying usability issues in your site. For each visit (user session), a maximum of approximately 500 combined GATC requests (both events and page views) can be tracked. Every message is tracked as one individual event. Note that - as the number of events in a session approaches the limit - additional events might not be tracked. Messages from excluded pages cannot tracked.'),
|
||||
'#description' => t('This will track the selected message types shown to users. Tracking of form validation errors may help you identifying usability issues in your site. For each visit (user session), a maximum of approximately 500 combined GATC requests (both events and page views) can be tracked. Every message is tracked as one individual event. Note that - as the number of events in a session approaches the limit - additional events might not be tracked. Messages from excluded pages cannot be tracked.'),
|
||||
'#options' => array(
|
||||
'status' => t('Status message'),
|
||||
'warning' => t('Warning message'),
|
||||
@@ -305,7 +317,7 @@ function googleanalytics_admin_settings_form($form_state) {
|
||||
$form['googleanalytics_custom_dimension'] = array(
|
||||
'#collapsed' => TRUE,
|
||||
'#collapsible' => TRUE,
|
||||
'#description' => t('You can set values for Google Analytics <a href="@custom_var_documentation">Custom Dimensions</a> here. You must have already configured your custom dimensions in the <a href="@setup_documentation">Google Analytics Management Interface</a>. You may use tokens. Global and user tokens are always available; on node pages, node tokens are also available. 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')),
|
||||
'#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 length of 150 bytes. Expect longer values to get trimmed.', array('@custom_var_documentation' => 'https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets', '@setup_documentation' => 'https://support.google.com/analytics/answer/2709829')),
|
||||
'#theme' => 'googleanalytics_admin_custom_var_table',
|
||||
'#title' => t('Custom dimensions'),
|
||||
'#tree' => TRUE,
|
||||
@@ -428,6 +440,8 @@ function googleanalytics_admin_settings_form($form_state) {
|
||||
);
|
||||
}
|
||||
|
||||
$user_access_add_js_snippets = !user_access('add JS snippets for google analytics');
|
||||
$user_access_add_js_snippets_permission_warning = $user_access_add_js_snippets ? ' <em>' . t('This field has been disabled because you do not have sufficient permissions to edit it.') . '</em>' : '';
|
||||
$form['advanced']['codesnippet'] = array(
|
||||
'#type' => 'fieldset',
|
||||
'#title' => t('Custom JavaScript code'),
|
||||
@@ -447,15 +461,17 @@ function googleanalytics_admin_settings_form($form_state) {
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Code snippet (before)'),
|
||||
'#default_value' => variable_get('googleanalytics_codesnippet_before', ''),
|
||||
'#disabled' => $user_access_add_js_snippets,
|
||||
'#rows' => 5,
|
||||
'#description' => t('Code in this textarea will be added <strong>before</strong> <code>ga("send", "pageview");</code>.'),
|
||||
'#description' => t('Code in this textarea will be added <strong>before</strong> <code>ga("send", "pageview");</code>.') . $user_access_add_js_snippets_permission_warning,
|
||||
);
|
||||
$form['advanced']['codesnippet']['googleanalytics_codesnippet_after'] = array(
|
||||
'#type' => 'textarea',
|
||||
'#title' => t('Code snippet (after)'),
|
||||
'#default_value' => variable_get('googleanalytics_codesnippet_after', ''),
|
||||
'#disabled' => $user_access_add_js_snippets,
|
||||
'#rows' => 5,
|
||||
'#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.'),
|
||||
'#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.') . $user_access_add_js_snippets_permission_warning,
|
||||
);
|
||||
|
||||
$form['advanced']['googleanalytics_debug'] = array(
|
||||
@@ -541,6 +557,12 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) {
|
||||
|
||||
/**
|
||||
* Layout for the custom variables table in the admin settings form.
|
||||
*
|
||||
* @param array $variables
|
||||
* An array contains the form elements.
|
||||
*
|
||||
* @return string
|
||||
* The rendered output.
|
||||
*/
|
||||
function theme_googleanalytics_admin_custom_var_table($variables) {
|
||||
$form = $variables['form'];
|
||||
@@ -551,7 +573,7 @@ function theme_googleanalytics_admin_custom_var_table($variables) {
|
||||
);
|
||||
|
||||
$rows = array();
|
||||
foreach (element_children($form['indexes']) as $key => $id) {
|
||||
foreach (element_children($form['indexes']) as $id) {
|
||||
$rows[] = array(
|
||||
'data' => array(
|
||||
drupal_render($form['indexes'][$id]['index']),
|
||||
@@ -600,11 +622,18 @@ function googleanalytics_token_element_validate(&$element, &$form_state) {
|
||||
return $element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $value
|
||||
* An array of token values.
|
||||
*
|
||||
* @return array
|
||||
* A unique array of invalid tokens.
|
||||
*/
|
||||
function _googleanalytics_get_forbidden_tokens($value) {
|
||||
$invalid_tokens = array();
|
||||
$value_tokens = is_string($value) ? token_scan($value) : $value;
|
||||
|
||||
foreach ($value_tokens as $type => $tokens) {
|
||||
foreach ($value_tokens as $tokens) {
|
||||
if (array_filter($tokens, '_googleanalytics_contains_forbidden_token')) {
|
||||
$invalid_tokens = array_merge($invalid_tokens, array_values($tokens));
|
||||
}
|
||||
@@ -617,8 +646,9 @@ function _googleanalytics_get_forbidden_tokens($value) {
|
||||
/**
|
||||
* Validate if a string contains forbidden tokens not allowed by privacy rules.
|
||||
*
|
||||
* @param $token_string
|
||||
* @param string $token_string
|
||||
* A string with one or more tokens to be validated.
|
||||
*
|
||||
* @return boolean
|
||||
* TRUE if blacklisted token has been found, otherwise FALSE.
|
||||
*/
|
||||
@@ -724,7 +754,7 @@ function _googleanalytics_extract_create_field_values($string) {
|
||||
$list = array_map('trim', $list);
|
||||
$list = array_filter($list, 'strlen');
|
||||
|
||||
foreach ($list as $position => $text) {
|
||||
foreach ($list as $text) {
|
||||
// Check for an explicit key.
|
||||
$matches = array();
|
||||
if (preg_match('/(.*)\|(.*)/', $text, $matches)) {
|
||||
|
@@ -65,6 +65,15 @@ Drupal.behaviors.trackingSettingsSummary = {
|
||||
if ($('input#edit-googleanalytics-trackfiles', context).is(':checked')) {
|
||||
vals.push(Drupal.t('Downloads'));
|
||||
}
|
||||
if ($('input#edit-googleanalytics-trackcolorbox', context).is(':checked')) {
|
||||
vals.push(Drupal.t('Colorbox'));
|
||||
}
|
||||
if ($('input#edit-googleanalytics-tracklinkid', context).is(':checked')) {
|
||||
vals.push(Drupal.t('Link attribution'));
|
||||
}
|
||||
if ($('input#edit-googleanalytics-trackurlfragments', context).is(':checked')) {
|
||||
vals.push(Drupal.t('URL fragments'));
|
||||
}
|
||||
if (!vals.length) {
|
||||
return Drupal.t('Not tracked');
|
||||
}
|
||||
|
@@ -8,16 +8,16 @@ $(document).ready(function() {
|
||||
// clicks on all elements.
|
||||
$(document.body).bind("mousedown keyup touchstart", function(event) {
|
||||
console.group("Running Google Analytics for Drupal.");
|
||||
console.info(event);
|
||||
console.info("Event '%s' has been detected.", event.type);
|
||||
|
||||
// Catch the closest surrounding link of a clicked element.
|
||||
$(event.target).closest("a,area").each(function() {
|
||||
console.info("Element '%o' has been detected. Link '%s' found.", this, this.href);
|
||||
console.info("Closest element '%o' has been found. URL '%s' extracted.", this, this.href);
|
||||
|
||||
// Is the clicked URL internal?
|
||||
if (Drupal.googleanalytics.isInternal(this.href)) {
|
||||
// Skip 'click' tracking, if custom tracking events are bound.
|
||||
if ($(this).is('.colorbox')) {
|
||||
if ($(this).is('.colorbox') && (Drupal.settings.googleanalytics.trackColorbox)) {
|
||||
// Do nothing here. The custom event will handle all tracking.
|
||||
console.info("Click on .colorbox item has been detected.");
|
||||
}
|
||||
@@ -25,12 +25,22 @@ $(document).ready(function() {
|
||||
else if (Drupal.settings.googleanalytics.trackDownload && Drupal.googleanalytics.isDownload(this.href)) {
|
||||
// Download link clicked.
|
||||
console.info("Download url '%s' has been found. Tracked download as extension '%s'.", Drupal.googleanalytics.getPageUrl(this.href), Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase());
|
||||
ga("send", "event", "Downloads", Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase(), Drupal.googleanalytics.getPageUrl(this.href));
|
||||
ga("send", {
|
||||
"hitType": "event",
|
||||
"eventCategory": "Downloads",
|
||||
"eventAction": Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase(),
|
||||
"eventLabel": Drupal.googleanalytics.getPageUrl(this.href),
|
||||
"transport": "beacon"
|
||||
});
|
||||
}
|
||||
else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
|
||||
// Keep the internal URL for Google Analytics website overlay intact.
|
||||
console.info("Click on internal special link '%s' has been tracked.", Drupal.googleanalytics.getPageUrl(this.href));
|
||||
ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(this.href) });
|
||||
ga("send", {
|
||||
"hitType": "pageview",
|
||||
"page": Drupal.googleanalytics.getPageUrl(this.href),
|
||||
"transport": "beacon"
|
||||
});
|
||||
}
|
||||
else {
|
||||
// e.g. anchor in same page or other internal page link
|
||||
@@ -41,13 +51,25 @@ $(document).ready(function() {
|
||||
if (Drupal.settings.googleanalytics.trackMailto && $(this).is("a[href^='mailto:'],area[href^='mailto:']")) {
|
||||
// Mailto link clicked.
|
||||
console.info("Click on e-mail '%s' has been tracked.", this.href.substring(7));
|
||||
ga("send", "event", "Mails", "Click", this.href.substring(7));
|
||||
ga("send", {
|
||||
"hitType": "event",
|
||||
"eventCategory": "Mails",
|
||||
"eventAction": "Click",
|
||||
"eventLabel": this.href.substring(7),
|
||||
"transport": "beacon"
|
||||
});
|
||||
}
|
||||
else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) {
|
||||
if (Drupal.settings.googleanalytics.trackDomainMode != 2 || (Drupal.settings.googleanalytics.trackDomainMode == 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
|
||||
if (Drupal.settings.googleanalytics.trackDomainMode !== 2 || (Drupal.settings.googleanalytics.trackDomainMode === 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
|
||||
// External link clicked / No top-level cross domain clicked.
|
||||
console.info("Outbound link '%s' has been tracked.", this.href);
|
||||
ga("send", "event", "Outbound links", "Click", this.href);
|
||||
ga("send", {
|
||||
"hitType": "event",
|
||||
"eventCategory": "Outbound links",
|
||||
"eventAction": "Click",
|
||||
"eventLabel": this.href,
|
||||
"transport": "beacon"
|
||||
});
|
||||
}
|
||||
else {
|
||||
console.info("Internal link '%s' clicked, not tracked.", this.href);
|
||||
@@ -63,19 +85,27 @@ $(document).ready(function() {
|
||||
if (Drupal.settings.googleanalytics.trackUrlFragments) {
|
||||
window.onhashchange = function() {
|
||||
console.info("Track URL '%s' as pageview. Hash '%s' has changed.", location.pathname + location.search + location.hash, location.hash);
|
||||
ga('send', 'pageview', location.pathname + location.search + location.hash);
|
||||
}
|
||||
ga("send", {
|
||||
"hitType": "pageview",
|
||||
"page": location.pathname + location.search + location.hash
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Colorbox: This event triggers when the transition has completed and the
|
||||
// newly loaded content has been revealed.
|
||||
$(document).bind("cbox_complete", function () {
|
||||
var href = $.colorbox.element().attr("href");
|
||||
if (href) {
|
||||
console.info("Colorbox transition to url '%s' has been tracked.", Drupal.googleanalytics.getPageUrl(href));
|
||||
ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(href) });
|
||||
}
|
||||
});
|
||||
if (Drupal.settings.googleanalytics.trackColorbox) {
|
||||
$(document).bind("cbox_complete", function () {
|
||||
var href = $.colorbox.element().attr("href");
|
||||
if (href) {
|
||||
console.info("Colorbox transition to url '%s' has been tracked.", Drupal.googleanalytics.getPageUrl(href));
|
||||
ga("send", {
|
||||
"hitType": "pageview",
|
||||
"page": Drupal.googleanalytics.getPageUrl(href)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
@@ -5,9 +5,9 @@ package = Statistics
|
||||
configure = admin/config/system/googleanalytics
|
||||
files[] = googleanalytics.test
|
||||
test_dependencies[] = token
|
||||
; Information added by Drupal.org packaging script on 2014-11-29
|
||||
version = "7.x-2.1"
|
||||
; Information added by Drupal.org packaging script on 2016-08-09
|
||||
version = "7.x-2.3"
|
||||
core = "7.x"
|
||||
project = "google_analytics"
|
||||
datestamp = "1417276982"
|
||||
datestamp = "1470779953"
|
||||
|
||||
|
@@ -25,6 +25,7 @@ function googleanalytics_uninstall() {
|
||||
variable_del('googleanalytics_roles');
|
||||
variable_del('googleanalytics_site_search');
|
||||
variable_del('googleanalytics_trackadsense');
|
||||
variable_del('googleanalytics_trackcolorbox');
|
||||
variable_del('googleanalytics_trackdoubleclick');
|
||||
variable_del('googleanalytics_tracker_anonymizeip');
|
||||
variable_del('googleanalytics_trackfiles');
|
||||
@@ -446,16 +447,16 @@ function googleanalytics_update_7200() {
|
||||
if (!empty($googleanalytics_codesnippet_before) && stristr($googleanalytics_codesnippet_before, '_gaq.push(')) {
|
||||
variable_set('googleanalytics_codesnippet_before_backup_7200', $googleanalytics_codesnippet_before);
|
||||
variable_del('googleanalytics_codesnippet_before');
|
||||
drupal_set_message(Database::getConnection()->prefixTables("A backup of your previous Google Analytics code snippet has been saved in database table '{variable}' as 'googleanalytics_codesnippet_before_backup_7200'. You need to manually upgrade the custom 'before' code snippet."), 'warning');
|
||||
$messages[] = t('Manual upgrade of custom "before" code snippet is required.');
|
||||
drupal_set_message(Database::getConnection()->prefixTables("A backup of your previous Google Analytics code snippet (ga.js) has been saved in database table '{variable}' as 'googleanalytics_codesnippet_before_backup_7200'. You need to manually upgrade the custom 'before' code snippet to analytics.js API."), 'warning');
|
||||
$messages[] = t('Manual upgrade of custom "before" code snippet from ja.js to analytics.js API is required.');
|
||||
}
|
||||
|
||||
$googleanalytics_codesnippet_after = variable_get('googleanalytics_codesnippet_after', '');
|
||||
if (!empty($googleanalytics_codesnippet_after) && stristr($googleanalytics_codesnippet_after, '_gaq.push(')) {
|
||||
variable_set('googleanalytics_codesnippet_after_backup_7200', $googleanalytics_codesnippet_after);
|
||||
variable_del('googleanalytics_codesnippet_after');
|
||||
drupal_set_message(Database::getConnection()->prefixTables("A backup of your previous Google Analytics code snippet has been saved in database table '{variable}' as 'googleanalytics_codesnippet_before_backup_7200'. You need to manually upgrade the custom 'before' code snippet."), 'warning');
|
||||
$messages[] = t('Manual upgrade of custom "after" code snippet is required.');
|
||||
drupal_set_message(Database::getConnection()->prefixTables("A backup of your previous Google Analytics code snippet (ga.js) has been saved in database table '{variable}' as 'googleanalytics_codesnippet_after_backup_7200'. You need to manually upgrade the custom 'after' code snippet to analytics.js API."), 'warning');
|
||||
$messages[] = t('Manual upgrade of custom "after" code snippet from ja.js to analytics.js API is required.');
|
||||
}
|
||||
|
||||
return empty($messages) ? t('No custom code snipped found. Nothing to do.') : implode(' ', $messages);
|
||||
|
@@ -14,29 +14,51 @@ $(document).ready(function() {
|
||||
// Is the clicked URL internal?
|
||||
if (Drupal.googleanalytics.isInternal(this.href)) {
|
||||
// Skip 'click' tracking, if custom tracking events are bound.
|
||||
if ($(this).is('.colorbox')) {
|
||||
if ($(this).is('.colorbox') && (Drupal.settings.googleanalytics.trackColorbox)) {
|
||||
// Do nothing here. The custom event will handle all tracking.
|
||||
//console.info("Click on .colorbox item has been detected.");
|
||||
}
|
||||
// Is download tracking activated and the file extension configured for download tracking?
|
||||
else if (Drupal.settings.googleanalytics.trackDownload && Drupal.googleanalytics.isDownload(this.href)) {
|
||||
// Download link clicked.
|
||||
ga("send", "event", "Downloads", Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase(), Drupal.googleanalytics.getPageUrl(this.href));
|
||||
ga("send", {
|
||||
"hitType": "event",
|
||||
"eventCategory": "Downloads",
|
||||
"eventAction": Drupal.googleanalytics.getDownloadExtension(this.href).toUpperCase(),
|
||||
"eventLabel": Drupal.googleanalytics.getPageUrl(this.href),
|
||||
"transport": "beacon"
|
||||
});
|
||||
}
|
||||
else if (Drupal.googleanalytics.isInternalSpecial(this.href)) {
|
||||
// Keep the internal URL for Google Analytics website overlay intact.
|
||||
ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(this.href) });
|
||||
ga("send", {
|
||||
"hitType": "pageview",
|
||||
"page": Drupal.googleanalytics.getPageUrl(this.href),
|
||||
"transport": "beacon"
|
||||
});
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (Drupal.settings.googleanalytics.trackMailto && $(this).is("a[href^='mailto:'],area[href^='mailto:']")) {
|
||||
// Mailto link clicked.
|
||||
ga("send", "event", "Mails", "Click", this.href.substring(7));
|
||||
ga("send", {
|
||||
"hitType": "event",
|
||||
"eventCategory": "Mails",
|
||||
"eventAction": "Click",
|
||||
"eventLabel": this.href.substring(7),
|
||||
"transport": "beacon"
|
||||
});
|
||||
}
|
||||
else if (Drupal.settings.googleanalytics.trackOutbound && this.href.match(/^\w+:\/\//i)) {
|
||||
if (Drupal.settings.googleanalytics.trackDomainMode != 2 || (Drupal.settings.googleanalytics.trackDomainMode == 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
|
||||
if (Drupal.settings.googleanalytics.trackDomainMode !== 2 || (Drupal.settings.googleanalytics.trackDomainMode === 2 && !Drupal.googleanalytics.isCrossDomain(this.hostname, Drupal.settings.googleanalytics.trackCrossDomains))) {
|
||||
// External link clicked / No top-level cross domain clicked.
|
||||
ga("send", "event", "Outbound links", "Click", this.href);
|
||||
ga("send", {
|
||||
"hitType": "event",
|
||||
"eventCategory": "Outbound links",
|
||||
"eventAction": "Click",
|
||||
"eventLabel": this.href,
|
||||
"transport": "beacon"
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,18 +68,26 @@ $(document).ready(function() {
|
||||
// Track hash changes as unique pageviews, if this option has been enabled.
|
||||
if (Drupal.settings.googleanalytics.trackUrlFragments) {
|
||||
window.onhashchange = function() {
|
||||
ga('send', 'pageview', location.pathname + location.search + location.hash);
|
||||
}
|
||||
ga("send", {
|
||||
"hitType": "pageview",
|
||||
"page": location.pathname + location.search + location.hash
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Colorbox: This event triggers when the transition has completed and the
|
||||
// newly loaded content has been revealed.
|
||||
$(document).bind("cbox_complete", function () {
|
||||
var href = $.colorbox.element().attr("href");
|
||||
if (href) {
|
||||
ga("send", "pageview", { "page": Drupal.googleanalytics.getPageUrl(href) });
|
||||
}
|
||||
});
|
||||
if (Drupal.settings.googleanalytics.trackColorbox) {
|
||||
$(document).bind("cbox_complete", function () {
|
||||
var href = $.colorbox.element().attr("href");
|
||||
if (href) {
|
||||
ga("send", {
|
||||
"hitType": "pageview",
|
||||
"page": Drupal.googleanalytics.getPageUrl(href)
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
@@ -69,6 +69,11 @@ function googleanalytics_permission() {
|
||||
'description' => t('Enter PHP code in the field for tracking visibility settings.'),
|
||||
'restrict access' => TRUE,
|
||||
),
|
||||
'add JS snippets for google analytics' => array(
|
||||
'title' => t('Add JavaScript snippets'),
|
||||
'description' => 'Enter JavaScript code snippets for advanced Google Analytics functionality.',
|
||||
'restrict access' => TRUE,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -125,6 +130,9 @@ function googleanalytics_page_alter(&$page) {
|
||||
$link_settings['trackDownload'] = $track_download;
|
||||
$link_settings['trackDownloadExtensions'] = $trackfiles_extensions;
|
||||
}
|
||||
if (module_exists('colorbox') && ($track_colorbox = variable_get('googleanalytics_trackcolorbox', 1))) {
|
||||
$link_settings['trackColorbox'] = $track_colorbox;
|
||||
}
|
||||
if ($track_domain_mode = variable_get('googleanalytics_domain_mode', 0)) {
|
||||
$link_settings['trackDomainMode'] = $track_domain_mode;
|
||||
}
|
||||
@@ -294,10 +302,7 @@ function googleanalytics_page_alter(&$page) {
|
||||
|
||||
// Track logged in users across all devices.
|
||||
if (variable_get('googleanalytics_trackuserid', 0) && user_is_logged_in()) {
|
||||
// The USER_ID value should be a unique, persistent, and non-personally
|
||||
// identifiable string identifier that represents a user or signed-in
|
||||
// account across devices.
|
||||
$create_only_fields['userId'] = drupal_hmac_base64($user->uid, drupal_get_private_key() . drupal_get_hash_salt());
|
||||
$create_only_fields['userId'] = google_analytics_user_id_hash($user->uid);
|
||||
}
|
||||
|
||||
// Create a tracker.
|
||||
@@ -352,13 +357,30 @@ function googleanalytics_page_alter(&$page) {
|
||||
// Custom tracking. Prepend before all other JavaScript.
|
||||
// @TODO: https://support.google.com/adsense/answer/98142
|
||||
// sounds like it could be appended to $script.
|
||||
drupal_add_js($googleanalytics_adsense_script, array('type' => 'inline', 'group' => JS_LIBRARY-1));
|
||||
drupal_add_js($googleanalytics_adsense_script, array('type' => 'inline', 'group' => JS_LIBRARY-1, 'requires_jquery' => FALSE));
|
||||
}
|
||||
|
||||
drupal_add_js($script, array('scope' => 'header', 'type' => 'inline'));
|
||||
drupal_add_js($script, array('scope' => 'header', 'type' => 'inline', 'requires_jquery' => FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate user id hash to implement USER_ID.
|
||||
*
|
||||
* The USER_ID value should be a unique, persistent, and non-personally
|
||||
* identifiable string identifier that represents a user or signed-in
|
||||
* account across devices.
|
||||
*
|
||||
* @param int $uid
|
||||
* User id.
|
||||
*
|
||||
* @return string
|
||||
* User id hash.
|
||||
*/
|
||||
function google_analytics_user_id_hash($uid) {
|
||||
return drupal_hmac_base64($uid, drupal_get_private_key() . drupal_get_hash_salt());
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_extra_fields().
|
||||
*/
|
||||
@@ -456,7 +478,7 @@ function googleanalytics_preprocess_search_results(&$variables) {
|
||||
// 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, 'requires_jquery' => FALSE));
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,13 @@
|
||||
*/
|
||||
class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
|
||||
|
||||
/**
|
||||
* User without permissions to edit snippets.
|
||||
*
|
||||
* @var \StdClass
|
||||
*/
|
||||
protected $noSnippetUser;
|
||||
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Google Analytics basic tests',
|
||||
@@ -25,6 +32,8 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
|
||||
);
|
||||
|
||||
// User to set up google_analytics.
|
||||
$this->noSnippetUser = $this->drupalCreateUser($permissions);
|
||||
$permissions[] = 'add JS snippets for google analytics';
|
||||
$this->admin_user = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
@@ -48,6 +57,26 @@ class GoogleAnalyticsBasicTest extends DrupalWebTestCase {
|
||||
$edit['googleanalytics_account'] = $this->randomName(2);
|
||||
$this->drupalPost('admin/config/system/googleanalytics', $edit, t('Save configuration'));
|
||||
$this->assertRaw(t('A valid Google Analytics Web Property ID is case sensitive and formatted like UA-xxxxxxx-yy.'), '[testGoogleAnalyticsConfiguration]: Invalid Web Property ID number validated.');
|
||||
|
||||
// User should have access to code snippets.
|
||||
$this->assertFieldByName('googleanalytics_codesnippet_create');
|
||||
$this->assertFieldByName('googleanalytics_codesnippet_before');
|
||||
$this->assertFieldByName('googleanalytics_codesnippet_after');
|
||||
$this->assertNoFieldByXPath("//textarea[@name='googleanalytics_codesnippet_create' and @disabled='disabled']", NULL, '"Create only fields" is enabled.');
|
||||
$this->assertNoFieldByXPath("//textarea[@name='googleanalytics_codesnippet_before' and @disabled='disabled']", NULL, '"Code snippet (before)" is enabled.');
|
||||
$this->assertNoFieldByXPath("//textarea[@name='googleanalytics_codesnippet_after' and @disabled='disabled']", NULL, '"Code snippet (after)" is enabled.');
|
||||
|
||||
// Login as user without JS permissions.
|
||||
$this->drupalLogin($this->noSnippetUser);
|
||||
$this->drupalGet('admin/config/system/googleanalytics');
|
||||
|
||||
// User should *not* have access to snippets, but create fields.
|
||||
$this->assertFieldByName('googleanalytics_codesnippet_create');
|
||||
$this->assertFieldByName('googleanalytics_codesnippet_before');
|
||||
$this->assertFieldByName('googleanalytics_codesnippet_after');
|
||||
$this->assertNoFieldByXPath("//textarea[@name='googleanalytics_codesnippet_create' and @disabled='disabled']", NULL, '"Create only fields" is enabled.');
|
||||
$this->assertFieldByXPath("//textarea[@name='googleanalytics_codesnippet_before' and @disabled='disabled']", NULL, '"Code snippet (before)" is disabled.');
|
||||
$this->assertFieldByXPath("//textarea[@name='googleanalytics_codesnippet_after' and @disabled='disabled']", NULL, '"Code snippet (after)" is disabled.');
|
||||
}
|
||||
|
||||
function testGoogleAnalyticsPageVisibility() {
|
||||
@@ -284,6 +313,7 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
|
||||
|
||||
// User to set up google_analytics.
|
||||
$this->admin_user = $this->drupalCreateUser($permissions);
|
||||
$this->drupalLogin($this->admin_user);
|
||||
}
|
||||
|
||||
function testGoogleAnalyticsCustomDimensions() {
|
||||
@@ -362,34 +392,30 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
|
||||
1 => array(
|
||||
'index' => 1,
|
||||
'value' => '6',
|
||||
'value_expected' => 6,
|
||||
),
|
||||
2 => array(
|
||||
'index' => 2,
|
||||
'value' => '8000',
|
||||
'value_expected' => 8000,
|
||||
),
|
||||
3 => array(
|
||||
'index' => 3,
|
||||
'value' => '7.8654',
|
||||
'value_expected' => 7.8654,
|
||||
),
|
||||
4 => array(
|
||||
'index' => 4,
|
||||
'value' => '1123.4',
|
||||
'value_expected' => 1123.4,
|
||||
),
|
||||
5 => array(
|
||||
'index' => 5,
|
||||
'value' => '5,67',
|
||||
'value_expected' => 5,
|
||||
),
|
||||
);
|
||||
|
||||
variable_set('googleanalytics_custom_metric', $googleanalytics_custom_metric);
|
||||
$this->drupalGet('');
|
||||
|
||||
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((float) $metric['value']) . ');', '[testGoogleAnalyticsCustomDimensionsAndMetrics]: Metric #' . $metric['index'] . ' is shown.');
|
||||
}
|
||||
|
||||
// Test whether tokens are replaced in custom metric values.
|
||||
@@ -421,6 +447,30 @@ class GoogleAnalyticsCustomDimensionsAndMetricsTest extends DrupalWebTestCase {
|
||||
$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.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if Custom Dimensions token form validation works.
|
||||
*/
|
||||
public function testGoogleAnalyticsCustomDimensionsTokenFormValidation() {
|
||||
$ua_code = 'UA-123456-1';
|
||||
|
||||
// Check form validation.
|
||||
$edit['googleanalytics_account'] = $ua_code;
|
||||
$edit['googleanalytics_custom_dimension[indexes][1][value]'] = '[current-user:name]';
|
||||
$edit['googleanalytics_custom_dimension[indexes][2][value]'] = '[current-user:edit-url]';
|
||||
$edit['googleanalytics_custom_dimension[indexes][3][value]'] = '[user:name]';
|
||||
$edit['googleanalytics_custom_dimension[indexes][4][value]'] = '[term:name]';
|
||||
$edit['googleanalytics_custom_dimension[indexes][5][value]'] = '[term:tid]';
|
||||
|
||||
$this->drupalPost('admin/config/system/googleanalytics', $edit, t('Save configuration'));
|
||||
|
||||
$this->assertRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', array('%element-title' => t('Custom dimension value #@index', array('@index' => 1)), '@invalid-tokens' => implode(', ', array('[current-user:name]')))));
|
||||
$this->assertRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', array('%element-title' => t('Custom dimension value #@index', array('@index' => 2)), '@invalid-tokens' => implode(', ', array('[current-user:edit-url]')))));
|
||||
$this->assertRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', array('%element-title' => t('Custom dimension value #@index', array('@index' => 3)), '@invalid-tokens' => implode(', ', array('[user:name]')))));
|
||||
// BUG #2037595
|
||||
//$this->assertNoRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', array('%element-title' => t('Custom dimension value #@index', array('@index' => 4)), '@invalid-tokens' => implode(', ', array('[term:name]')))));
|
||||
//$this->assertNoRaw(t('The %element-title is using the following forbidden tokens with personal identifying information: @invalid-tokens.', array('%element-title' => t('Custom dimension value #@index', array('@index' => 5)), '@invalid-tokens' => implode(', ', array('[term:tid]')))));
|
||||
}
|
||||
}
|
||||
|
||||
class GoogleAnalyticsStatusMessagesTest extends DrupalWebTestCase {
|
||||
|
@@ -40,6 +40,10 @@ function googleanalytics_variable_group_info() {
|
||||
|
||||
/**
|
||||
* Validate Web Property ID variable.
|
||||
*
|
||||
* @param array $variable
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function googleanalytics_validate_googleanalytics_account($variable) {
|
||||
// Replace all type of dashes (n-dash, m-dash, minus) with the normal dashes.
|
||||
|
Reference in New Issue
Block a user