summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhass2011-02-05 20:08:20 (GMT)
committer hass2011-02-05 20:08:20 (GMT)
commit4f87d9ac3599658aacfc4e03de3f84f64462f239 (patch)
tree4141de3cca784b59f16b60649450cbdf9cdf286b
parent4add50a9175156d8596c1ce261dce6ce5e3e60a1 (diff)
#339235: Add multi/cross domain tracking
-rw-r--r--googleanalytics.admin.inc53
-rw-r--r--googleanalytics.admin.js13
-rw-r--r--googleanalytics.install2
-rw-r--r--googleanalytics.js17
-rw-r--r--googleanalytics.module23
5 files changed, 107 insertions, 1 deletions
diff --git a/googleanalytics.admin.inc b/googleanalytics.admin.inc
index d3d9f6d..741e6a8 100644
--- a/googleanalytics.admin.inc
+++ b/googleanalytics.admin.inc
@@ -178,6 +178,53 @@ function googleanalytics_admin_settings_form($form_state) {
'#default_value' => variable_get('googleanalytics_trackadsense', FALSE),
);
+ $form['tracking']['domain_tracking'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Domains'),
+ );
+
+ global $cookie_domain;
+ $multiple_sub_domains = array();
+ foreach (array('www', 'app', 'shop') as $subdomain) {
+ if (count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
+ $multiple_sub_domains[] = $subdomain . $cookie_domain;
+ }
+ // IP addresses or localhost.
+ else {
+ $multiple_sub_domains[] = $subdomain . '.example.com';
+ }
+ }
+
+ $multiple_toplevel_domains = array();
+ foreach (array('.com', '.net', '.org') as $tldomain) {
+ $host = $_SERVER['HTTP_HOST'];
+ $domain = substr($host, 0, strrpos($host, '.'));
+ if (count(explode('.', $host)) > 2 && !is_numeric(str_replace('.', '', $host))) {
+ $multiple_toplevel_domains[] = $domain . $tldomain;
+ }
+ // IP addresses or localhost
+ else {
+ $multiple_toplevel_domains[] = 'www.example' . $tldomain;
+ }
+ }
+
+ $form['tracking']['domain_tracking']['googleanalytics_domain_mode'] = array(
+ '#type' => 'radios',
+ '#title' => t('What are you tracking?'),
+ '#options' => array(
+ 0 => t('A single domain (default)') . '<div class="description">' . t('Domain: @domain', array('@domain' => $_SERVER['HTTP_HOST'])) . '</div>',
+ 1 => t('One domain with multiple subdomains') . '<div class="description">' . t('Examples: @domains', array('@domains' => implode(', ', $multiple_sub_domains))) . '</div>',
+ 2 => t('Multiple top-level domains') . '<div class="description">' . t('Examples: @domains', array('@domains' => implode(', ', $multiple_toplevel_domains))) . '</div>',
+ ),
+ '#default_value' => variable_get('googleanalytics_domain_mode', 0),
+ );
+ $form['tracking']['domain_tracking']['googleanalytics_cross_domains'] = array(
+ '#title' => t('List of top-level domains'),
+ '#type' => 'textarea',
+ '#default_value' => variable_get('googleanalytics_cross_domains', ''),
+ '#description' => t('If you selected "Multiple top-level domains" above, enter all related top-level domains. Add one domain per line. By default, the data in your reports only includes the path and name of the page, and not the domain name. For more information see section <em>Show separate domain names</em> in <a href="http://www.google.com/support/analytics/bin/answer.py?answer=175538">Tracking multiple domains</a>.'),
+ );
+
// Backward compatibility only.
// TODO: If currently not in use, hide the UI and later remove the code.
$segmentation = variable_get('googleanalytics_segmentation', array());
@@ -362,6 +409,7 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) {
// Trim some text values.
$form_state['values']['googleanalytics_account'] = trim($form_state['values']['googleanalytics_account']);
$form_state['values']['googleanalytics_pages'] = trim($form_state['values']['googleanalytics_pages']);
+ $form_state['values']['googleanalytics_cross_domains'] = trim($form_state['values']['googleanalytics_cross_domains']);
$form_state['values']['googleanalytics_codesnippet_before'] = trim($form_state['values']['googleanalytics_codesnippet_before']);
$form_state['values']['googleanalytics_codesnippet_after'] = trim($form_state['values']['googleanalytics_codesnippet_after']);
@@ -369,6 +417,11 @@ function googleanalytics_admin_settings_form_validate($form, &$form_state) {
form_set_error('googleanalytics_account', t('A valid Google Analytics Web Property ID is case sensitive and formatted like UA-xxxxxxx-yy.'));
}
+ // If multiple top-level domains has been selected, a domain names list is required.
+ if ($form_state['values']['googleanalytics_domain_mode'] == 2 && empty($form_state['values']['googleanalytics_cross_domains'])) {
+ form_set_error('googleanalytics_cross_domains', t('A list of top-level domains is required if <em>Multiple top-level domains</em> has been selected.'));
+ }
+
// Clear obsolete local cache if cache has been disabled.
if (empty($form_state['values']['googleanalytics_cache']) && $form['advanced']['googleanalytics_cache']['#default_value']) {
googleanalytics_clear_js_cache();
diff --git a/googleanalytics.admin.js b/googleanalytics.admin.js
index ec97f6a..6602768 100644
--- a/googleanalytics.admin.js
+++ b/googleanalytics.admin.js
@@ -80,6 +80,19 @@ Drupal.behaviors.trackingSettingsSummary = {
}
return Drupal.t('@items tracked', {'@items' : vals.join(', ')});
});
+
+ $('fieldset#edit-domain-tracking', context).drupalSetSummary(function (context) {
+ var $radio = $('input[name="googleanalytics_domain_mode"]:checked', context);
+ if ($radio.val() == 0) {
+ return Drupal.t('A single domain');
+ }
+ else if ($radio.val() == 1) {
+ return Drupal.t('One domain with multiple subdomains');
+ }
+ else {
+ return Drupal.t('Multiple top-level domains');
+ }
+ });
}
};
diff --git a/googleanalytics.install b/googleanalytics.install
index c8cb629..c392ac5 100644
--- a/googleanalytics.install
+++ b/googleanalytics.install
@@ -40,8 +40,10 @@ function googleanalytics_uninstall() {
variable_del('googleanalytics_cache');
variable_del('googleanalytics_codesnippet_before');
variable_del('googleanalytics_codesnippet_after');
+ variable_del('googleanalytics_cross_domains');
variable_del('googleanalytics_custom');
variable_del('googleanalytics_custom_vars');
+ variable_del('googleanalytics_domain_mode');
variable_del('googleanalytics_js_scope');
variable_del('googleanalytics_last_cache');
variable_del('googleanalytics_pages');
diff --git a/googleanalytics.js b/googleanalytics.js
index b398527..f48f3e1 100644
--- a/googleanalytics.js
+++ b/googleanalytics.js
@@ -3,6 +3,14 @@
$(document).ready(function() {
+ // Accepts a string; returns the string with regex metacharacters escaped. The returned string
+ // can safely be used at any point within a regex to match the provided literal string. Escaped
+ // characters are [ ] { } ( ) * + ? - . , \ ^ $ # and whitespace. The character | is excluded
+ // in this function as it's used to separate the domains names.
+ RegExp.escapeDomains = function(text) {
+ return text.replace(/[-[\]{}()*+?.,\\^$#\s]/g, "\\$&");
+ }
+
// Attach onclick event to document only and catch clicks on all elements.
$(document.body).click(function(event) {
// Catch only the first parent link of a clicked element.
@@ -15,6 +23,8 @@ $(document).ready(function() {
var isInternalSpecial = new RegExp("(\/go\/.*)$", "i");
// Expression to check for download links.
var isDownload = new RegExp("\\.(" + ga.trackDownloadExtensions + ")$", "i");
+ // Expression to check for the sites cross domains.
+ var isCrossDomain = new RegExp("^(https?|ftp|news|nntp|telnet|irc|ssh|sftp|webcal):\/\/.*(" + RegExp.escapeDomains(ga.trackCrossDomains) + ")", "i");
// Is the clicked URL internal?
if (isInternal.test(this.href)) {
@@ -36,7 +46,12 @@ $(document).ready(function() {
_gaq.push(["_trackEvent", "Mails", "Click", this.href.substring(7)]);
}
else if (ga.trackOutbound && this.href) {
- if (ga.trackOutboundAsPageview) {
+ if (ga.trackDomainMode == 2 && isCrossDomain.test(this.href)) {
+ // Top-level cross domain clicked.
+ _gaq.push(["_link", this.href]);
+ setTimeout('document.location = "' + this.href + '"', 100);
+ }
+ else if (ga.trackOutboundAsPageview) {
// Track all external links as page views after URL cleanup.
// Currently required, if click should be tracked as goal.
_gaq.push(["_trackPageview", '/outbound/' + this.href.replace(/^(https?|ftp|news|nntp|telnet|irc|ssh|sftp|webcal):\/\//i, '').split('/').join('--')]);
diff --git a/googleanalytics.module b/googleanalytics.module
index 332b669..5069a94 100644
--- a/googleanalytics.module
+++ b/googleanalytics.module
@@ -114,6 +114,14 @@ function googleanalytics_page_alter(&$page) {
if ($track_outbound_as_pageview = variable_get('googleanalytics_trackoutboundaspageview', 0)) {
$link_settings['trackOutboundAsPageview'] = $track_outbound_as_pageview;
}
+ if ($track_domain_mode = variable_get('googleanalytics_domain_mode', 0)) {
+ $link_settings['trackDomainMode'] = $track_domain_mode;
+ }
+ if ($track_cross_domains = variable_get('googleanalytics_cross_domains', '')) {
+ $domains = preg_split('/(\r\n?|\n)/', $track_cross_domains);
+ $link_settings['trackCrossDomains'] = implode('|', $domains);
+ }
+
if (!empty($link_settings)) {
drupal_add_js(array('googleanalytics' => $link_settings), 'setting');
drupal_add_js(drupal_get_path('module', 'googleanalytics') . '/googleanalytics.js');
@@ -213,6 +221,21 @@ function googleanalytics_page_alter(&$page) {
// a workaround until "_anonymizeIp" has been implemented/fixed.
$script .= '_gaq.push(["_gat._anonymizeIp"]);';
}
+
+ // Domain tracking type.
+ global $cookie_domain;
+ $domain_mode = variable_get('googleanalytics_domain_mode', 0);
+
+ // 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.
+ if ($domain_mode == 1 && count(explode('.', $cookie_domain)) > 2 && !is_numeric(str_replace('.', '', $cookie_domain))) {
+ $script .= '_gaq.push(["_setDomainName", ' . drupal_json_encode($cookie_domain) . ']);';
+ }
+ else if ($domain_mode == 2) {
+ $script .= '_gaq.push(["_setDomainName", "none"]);';
+ $script .= '_gaq.push(["_setAllowLinker", true]);';
+ }
+
if (!empty($segmentation)) {
$script .= $segmentation;
}