Index: googleanalytics.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/google_analytics/googleanalytics.admin.inc,v
retrieving revision 1.21
diff -u -p -r1.21 googleanalytics.admin.inc
--- googleanalytics.admin.inc	15 Aug 2010 16:55:50 -0000	1.21
+++ googleanalytics.admin.inc	29 Sep 2010 19:39:47 -0000
@@ -250,6 +250,44 @@ function googleanalytics_admin_settings_
     '#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."),
   );
 
+  $form['advanced']['custom_var'] = array(
+    '#type' => 'fieldset',
+    '#title' => t('Custom Variables'),
+    '#collapsible' => TRUE,
+    '#collapsed' => TRUE,
+    '#description' => '<p>' . t('You can add Google Analytics <a href="!custom_var_url">Custom Variables</a> here. These will be added to every page that Google Analytics appears on.', array('!custom_var_url' => 'http://code.google.com/intl/zh-TW/apis/analytics/docs/tracking/gaTrackingCustomVariables.html')) . '</p>' .
+                      '<p>' . t('Google Analytics will only accept custom variables where the name and value combined are less than 64 bytes when URL encoded. Translation: keep them short, and expect long values to get trimmed.') . '</p>' .
+                      '<p>' . t('You may use tokens in custom variable values. Global and user tokens are always available; on node pages, node tokens are also available.') . '</p>',
+  );
+
+  for ($i = 1; $i < 6; $i++) {
+    $form['advanced']['custom_var']['googleanalytics_custom_var_'. $i] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Variable %index', array('%index' => $i)),
+    );
+    $form['advanced']['custom_var']['googleanalytics_custom_var_'. $i]['googleanalytics_custom_var_'. $i .'_name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Name'),
+      '#default_value' => variable_get('googleanalytics_custom_var_'. $i .'_name', ''),
+    );
+    $form['advanced']['custom_var']['googleanalytics_custom_var_'. $i]['googleanalytics_custom_var_'. $i .'_value'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Value'),
+      '#default_value' => variable_get('googleanalytics_custom_var_'. $i .'_value', ''),
+      '#description' => (module_exists('token') ? t('You may use tokens in this field.') : ''),
+    );
+    $form['advanced']['custom_var']['googleanalytics_custom_var_'. $i]['googleanalytics_custom_var_'. $i .'_scope'] = array(
+      '#type' => 'select',
+      '#title' => t('Scope'),
+      '#default_value' => variable_get('googleanalytics_custom_var_'. $i .'_scope', 3),
+      '#options' => array(
+         3 => 'page', 
+         2 => 'session',
+         1 => 'visitor',
+      ),
+    );
+  }
+
   $form['advanced']['googleanalytics_js_scope'] = array(
     '#type' => 'select',
     '#title' => t('JavaScript scope'),
Index: googleanalytics.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/google_analytics/googleanalytics.install,v
retrieving revision 1.18
diff -u -p -r1.18 googleanalytics.install
--- googleanalytics.install	28 Aug 2010 18:15:28 -0000	1.18
+++ googleanalytics.install	29 Sep 2010 19:39:47 -0000
@@ -50,6 +50,12 @@ function googleanalytics_uninstall() {
   variable_del('googleanalytics_tracker_anonymizeip');
   variable_del('googleanalytics_translation_set');
 
+  for ($i = 1; $i < 6; $i++) {
+    variable_del('googleanalytics_custom_var_'. $i .'_name');
+    variable_del('googleanalytics_custom_var_'. $i .'_value');
+    variable_del('googleanalytics_custom_var_'. $i .'_scope');
+  }
+
   // Remove backup variables if exits. Remove this code in D8.
   variable_del('googleanalytics_codesnippet_before_backup_6300');
   variable_del('googleanalytics_codesnippet_after_backup_6300');
Index: googleanalytics.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/google_analytics/googleanalytics.module,v
retrieving revision 1.48
diff -u -p -r1.48 googleanalytics.module
--- googleanalytics.module	28 Aug 2010 15:30:53 -0000	1.48
+++ googleanalytics.module	29 Sep 2010 19:39:47 -0000
@@ -155,6 +155,37 @@ function googleanalytics_page_alter(&$pa
     $codesnippet_before = variable_get('googleanalytics_codesnippet_before', '');
     $codesnippet_after = variable_get('googleanalytics_codesnippet_after', '');
 
+    // Add custom variables.
+    $custom_var = '';
+    for ($i = 1; $i < 6; $i++) {
+      $custom_var_name = variable_get('googleanalytics_custom_var_'. $i .'_name', '');
+      if ($custom_var_name) {
+        $custom_var_value = variable_get('googleanalytics_custom_var_'. $i .'_value', '');
+        $custom_var_scope = variable_get('googleanalytics_custom_var_'. $i .'_scope', '');
+
+        if (module_exists('token')) {
+          $node = menu_get_object();
+          $custom_var_value = token_replace($custom_var_value, array('global' => NULL, 'user' => $user, 'node' => $node), array('clear' => TRUE));
+        }
+
+        if (!is_numeric($custom_var_value) && !$custom_var_value) { continue; }
+
+        // The custom variable name + value must not be more than 64 bytes after url encoding
+        $name_length = strlen(rawurlencode($custom_var_name));
+        $tmp_value = rawurlencode($custom_var_value);
+        $value_length = strlen($tmp_value);
+        if ($name_length + $value_length > 64) {
+          // Trim value and remove fragments of url encoding.
+          $tmp_value = rtrim(substr($tmp_value, 0, 63 - $name_length),'%0..9A..F');
+          $custom_var_value = urldecode($tmp_value);
+        }
+
+        $custom_var_name = drupal_json_encode($custom_var_name);
+        $custom_var_value = drupal_json_encode($custom_var_value);
+        $custom_var .= "_gaq.push(['_setCustomVar', $i, $custom_var_name, $custom_var_value, $custom_var_scope]);";
+      }
+    }
+
     // Build tracker code.
     $script = 'var _gaq = _gaq || [];';
     $script .= '_gaq.push(["_setAccount", ' . drupal_json_encode($id) . ']);';
@@ -169,6 +200,9 @@ function googleanalytics_page_alter(&$pa
     if (!empty($codesnippet_before)) {
       $script .= $codesnippet_before;
     }
+    if (!empty($custom_var)) {
+      $script .= $custom_var;
+    }
     if (empty($url_custom)) {
       $script .= '_gaq.push(["_trackPageview"]);';
     }
