Add hook_google_analytics for other modules

hass - March 7, 2008 - 23:14
Project:Google Analytics
Version:6.x-1.x-dev
Component:Code
Category:feature request
Priority:normal
Assigned:Unassigned
Status:active
Description

Since ga.js it looks impossible (untested) for other modules to set a custom variable in head. So it becomes impossible to add tracking data like shopping data to the ga tracking. See http://0-code.google.com.millennium.unicatt.it/apis/analytics/docs/gaJSA... for some good examples.

var pageTracker = _gat._getTracker("UA-12345-1");
   pageTracker._initData();
   pageTracker._trackPageview();
   pageTracker._addTrans(
      "1234", // order ID - required
      "Womens Apparel", // affiliation or store name
      "11.99", // total - required
      "1.29", // tax
      "15.00", // shipping
      "San Jose", // city
      "California", // state or province
      "USA" // country
    );
   pageTracker._addItem(
      "1234", // order ID - required
      "DD44", // SKU/code
      "T-Shirt", // product name
      "Olive Medium", // category or variation
      "11.99", // unit price - required
      "1" // quantity - required
   );
   pageTracker._trackTrans();

It looks like we need a hook or something else that would allow other modules to set custom variables and urls. We should do some brainstroming what the best way would be.

#1

hass - April 3, 2008 - 16:50

Marked #231451 as duplicate.

#2

jmesam - April 24, 2008 - 11:57

Nobody is interested on this?

I think it is the 'natural' next step for Analytics module. Now we have tracking and segmentation, but Analytics module has to be capable to track: subscriptions, e-commerce, registrations, newsletter or any other 'calls to action' to use all the power features from Google Analytics.

#3

hass - May 3, 2008 - 22:34
Priority:normal» minor

I thought a little bit more about this and i think there are possible workarounds. There is no real need to add this in the hook way. Someone could create a variable in the page head like

var ecommerceTracker =_addTrans(...);
ecommerceTracker =_addTrans(...);

and add something like:

if (ecommerceTracker) { pageTracker = ecommerceTracker; }

to the "Custom JavaScript code" text area... not perfect, but this should work, too.

#4

hass - June 26, 2008 - 17:39

The implementation must allow to add code *before* and *after* _trackPageview() call. See #275359: Allow adding custom javascript code before and after _trackPageview()

#5

hass - June 28, 2008 - 08:20
Title:Add hook_google_analytics for other modules» Add hook_googleanalytics for other modules

#6

hass - June 28, 2008 - 18:22
Status:active» needs review

This is a first try to implement such a hook for all other modules that likes to hook into GA module. It allows to push in every custom tracking method available in the GA API (http://code.google.com/apis/analytics/docs/gaJSApi.html).

I hope one of the google adsense, ubercart or ecommerce module maintainers could take a look if they are comfortable with this code or if they have a better idea. Feedback is very welcome!!! This patch will stay in queue until a maintainer depend on this code and approved it is working well.

Here follows a code example how this could be integrated in other modules:

<?php
function mymodule_googleanalytics(&$hook) {

  switch (
$hook) {
    case
'preprocess':
     
$value['methods'][]['_setDomainName'] = array('.example.com');
     
$value['methods'][]['_clearIgnoredOrganic'] = array();
     
$value['methods'][]['_setSampleRate'] = array('80');
      break;

    case
'process':
     
$value['methods'][]['_addTrans'] = array(
       
"1234", //order ID - required
       
"My Partner Store", //affiliation or store name
       
"84.99", //total - required
       
"7.66", //tax
       
"15.99", //shipping
       
"Boston", //city
       
"MA", //state or province
       
"USA" //country
     
);
     
$value['methods'][]['_addItem'] = array(
       
'343212',
       
'DD4444',
       
'Lava Lamp',
       
'Decor',
       
'34.99',
       
'1',
      );
     
$value['methods'][]['_addItem'] = array(
       
'46464',
       
'CC1111',
       
'Black Lamp',
       
'Decor',
       
'2.99',
       
'5',
      );
     
$value['methods'][]['_trackTrans'] = array();
      break;

  }
  return
$value;
}
?>

AttachmentSize
ga_hook_googleanalytics.patch 2.52 KB

#7

moshe weitzman - July 2, 2008 - 01:11

Strictly speaking, I don't think this is needed. Modules can use hook_preprocess_page to fiddle with the $javascript array. They can inject their own calls wherever needed. They should do so before template_preprocess_page() does the final drupal_get_js().

#8

hass - July 2, 2008 - 05:52

I'm not sure how they should insert something before the 'pageTracker._initData();'; or after 'pageTracker._trackPageview('. $url_custom .');';. If they like to do - they need to alter the $script added in footer with regexes or so and I'm not sure if template_preprocess_page() have the ability to alter this at this late stage. I've got some other troubles at this late stage in D6 that made me to move some parts to the hook_init(), but not all.

I will try to test template_preprocess_page() for altering the footer code. Aside this is only available in D6.

#9

hass - July 2, 2008 - 06:13
Status:needs review» needs work

I've dumped all $variables in module_preprocess_page() and the only place I can see the footer code is in $variables['closure']. This is completely ready HTML code. No way to alter an array of javascript code. Therefor this will become a funny regex, but could work.

Marking need work to make clear this needs some more investigation and testing.

#10

hass - July 2, 2008 - 07:07
Status:needs work» needs review

Ok, here the funny regex... the patch above will not be committed by this way. I hope this regex is correct. Maybe someone else could review this. Then we are able to add this to a readme or a handbook page to give other maintainers the ability to reuse this variant.

<?php
function mymodule_preprocess_page(&$variables) {

 
// Example code. Make sure your module runs all values through drupal_to_js() to be protected against XSS.
 
$before = 'pageTracker._setDomainName(".example.com");';

 
$after  = 'pageTracker._addTrans("1234", "My Partner Store", "84.99", "7.66", "15.99", "Boston", "MA", "USA");';
 
$after .= 'pageTracker._addItem("343212", "DD4444", "Lava Lamp", "Decor", "34.99", "1");';
 
$after .= 'pageTracker._trackTrans();';
 
 
$variables['closure'] = preg_replace('/(.*)(<script type="text\/javascript">var pageTracker = _gat._getTracker\("(UA-\d{4,}-\d+)"\);)(.*)(pageTracker._initData\(\);pageTracker._trackPageview\(\);)(.*)(<\/?script>)(.*)/i', "$2$before$5$after$7", $variables['closure']);

}
?>

The only issue we really have with this solution is - it is not working for D5 and all e-commerce packages are only available for D5 today. I also expect that many people are not able or don't like to upgrade to D6 for a good time...

We could also change the (UA-\d{4,}-\d+) to (.*) validation here to reduce complexity (untested). We don't really need to validation here.

#11

hass - July 2, 2008 - 07:11
Title:Add hook_googleanalytics for other modules» hook_preprocess_page example for other modules

#12

hass - July 2, 2008 - 16:42
Status:needs review» needs work

There are some bugs... I will update asap.

#13

hass - July 2, 2008 - 19:03
Status:needs work» needs review

Ok, new version that fixes to keep custom URL's, segmentation data and custom javascript code settings as is. Custom javascript code take recedence over module provided google api methods.

<?php
function mymodule_preprocess_page(&$variables) {

 
// Example code. Make sure your module runs all values through drupal_to_js() to be protected against XSS.
 
$before = 'pageTracker._setDomainName(".example.com");';

 
$after  = 'pageTracker._addTrans("1234", "My Partner Store", "84.99", "7.66", "15.99", "Boston", "MA", "USA");';
 
$after .= 'pageTracker._addItem("343212", "DD4444", "Lava Lamp", "Decor", "34.99", "1");';
 
$after .= 'pageTracker._trackTrans();';
 
 
$variables['closure'] = preg_replace('/(.*)(<script type="text\/javascript">var pageTracker = _gat._getTracker\("(UA-\d{4,}-\d+)"\);)(.*)(pageTracker._initData\(\);pageTracker._trackPageview\((.*)?\);)(.*)(<\/?script>)(.*)/i', "$2$before$4$5$7$after$8", $variables['closure']);

}
?>

#14

hass - July 19, 2008 - 07:06
Component:Code» Documentation
Category:feature request» task
Priority:minor» normal
Status:needs review» fixed

Book page have been added at http://drupal.org/node/284599.

#15

Anonymous (not verified) - August 2, 2008 - 07:14
Status:fixed» closed

Automatically closed -- issue fixed for two weeks with no activity.

#16

greggles - October 23, 2008 - 14:36

The original idea seems completely reasonable to me. In fact, I think we should extend the hook idea to include the ability to add multiple trackers.

Modifying this information via a preprocess hook feels quite strange and un-Drupal to me. Where else do we recommend that people do this? Does core ever recommend that people modify it via preg_replace in the theme layer?

#17

hass - October 23, 2008 - 14:42

#18

greggles - October 23, 2008 - 15:08

That should also be possible with a theme_form_id function and/or a hook_form_alter which give the data in a structured way (much like the initial hook you proposed here...).

#19

hass - October 23, 2008 - 15:17

Could you provide an example? I asked this label question very long time and found many many people doing string replacements and such crazy things...

I have thought about a template file in 2.x, but not yet sure how this theming function should looks like best. Otherwise I'm not sure how moshe would do it, but he said we don't need this hook...

#20

hass - January 9, 2009 - 16:30

#21

hass - January 9, 2009 - 16:37
Status:closed» active

@moshe: could you please enlighten us why we don't need it? Others don't like the regex stuff I've created very much... what would be the best solution?

#22

moshe weitzman - January 9, 2009 - 17:09

I'm don't have enough familiarity with javascript or pagetracker (in the example). my idea was that modules could call pagetracker methods in their javascript that fiddle with variables. then the javascript that finally sends info to google runs last.

another idea is for this module to structure its javascript injection into a few different drupal_add_js() calls. Then modules can remove/add the parts they want during MODULE_process_page(). for an example of this fiddling, see jquery_update_preprocess_age() at http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/jquery_upda...

#23

hass - January 9, 2009 - 19:26

#24

hass - January 9, 2009 - 19:29
Title:hook_preprocess_page example for other modules» Add hook_google_analytics for other modules
Component:Documentation» Code
Category:task» feature request

#25

drumm - February 26, 2009 - 02:23

Another use case is changing $url_custom from modules. The Apache Solr search module, used on Drupal.org, should set a custom URL to enable site search tracking.

#26

drumm - February 26, 2009 - 02:41

For $url_custom, it would be more simple to do something like:

<?php
drupal_add_js
(array('googleAnalyticsPageURL' => ...), 'setting');
?>

And from JS, pageTracker._trackPageview(Drupal.settings.googleAnalyticsPageURL).

#28

hass - March 8, 2009 - 12:15

@drumm: logic wise this sounds difficult as we process the most code in hook_footer and hook_footer does not have the ability to add a JS setting to head... so core is blocking here :-(

#29

jmesam - March 10, 2009 - 23:34

The preg_replace code has no try{} and catch (err) {} statement, without them the replace doesn't do anything.

#30

hass - March 11, 2009 - 07:43

Yeah, this needs an update.

#31

danithaca - April 24, 2009 - 16:10

Damien (DamZ) proposed a much cleaner way of doing it:

<?php
// use hook_preprocess_page or hook_init, etc.
function mymodule_block() {
 
$node = menu_get_object();
 
$your_ga_code = "pageTracker._trackEvent('Click', ${node->nid)";
  $GLOBALS
['conf']['googleanalytics_codesnippet_after'] .= $your_ga_code;
}
?>

The trick is that $GLOBALS['conf'] got flushed for every page request. so you can just use .= to append your GA code.

I've tested the code, and it works!! Thanks Damien!

#32

hass - April 24, 2009 - 16:18

This is the most dirty way I can think of and not a way we go here.

 
 

Drupal is a registered trademark of Dries Buytaert.