I'm a typical use case. I'd like to add some Google Analytics goal tracking to my Drupal site, but I'm lazy. Adding them manually to end points is quite time consuming. There would also be problems with making sure these end points don't get triggered twice for the same action.

Solution: Integrate Google Analytic module with Rules.

Rules gives us a lot of wonderful "Events" which are useful for Google Analytics Goal tracking. The best thing about doing it this way, is you'll be able to integrate Google Analytics goals very easily in the future for any module which integrates it's workflow with Rules.

Here are some events which could be used (there are tonnes more)

  • Ubercart - Customer Completes Checkout
  • Comments - After Saving a new comment
  • Node - After saving new content
  • User - After saving a new user account
  • User - User has logged in

For me at least, I'd personally want all these tracked in Google Analytics as goals. I think it would be a very useful benchmark of how my site (and changes) are doing.

As for implementation, I would assume Google Analytics module after these rules are triggered, could simply inject some goal javascript into the next page request and make sure it only happens once per event.

We would also need to make sure this works with Anonymous page caching.

So developers. Is this feasible?

Please +1 to show your support for this.

Additional Bikeshed (not to be accomplished on first iteration, but version #2): What about adding Goal funnels for tracking abandon rate. Can we do this currently with Rules, or will we have to create some expanded rules to make this happen. Something to think about.

Here's some reading on Google Analytics Event Tracking with Goals:
http://analytics.blogspot.com/2011/04/new-google-analytics-events-goals....

Comments

j0rd’s picture

Status: Postponed » Active

I've got this working with my Drupal 7 install with Rules.

Event -> new user is saved

Action -> PHP Code

// Comment out, violates google analytics TOS
//$_SESSION['ga_push'][] = array('_trackEvent', 'user', 'register', 'UserID', $account->uid);

// This is fine
$_SESSION['ga_push'][] = array('_trackEvent', 'user', 'register');

Then I added some code in a theme hook

function theopen_preprocess_html(&$variables) {
  $variables['ga_push'] = '';
  if(!empty($_SESSION['ga_push'])) {
    $values = $_SESSION['ga_push'];  
    foreach($values as $i => $value) {   
      foreach($value as $k => $ga_item) {
        $values[$i][$k] = "'" . $ga_item. "'";
      }
    $variables['ga_push'] .= '_gaq.push([' . implode(',', $values[$i]) . ']); ';
    }
    $variables['ga_push'] = '<script type="text/javascript">' . $variables['ga_push'] . '</script>';
    unset($_SESSION['ga_push']);
  }
}

Then I added this into my html.tpl.php just above </body>

print $ga_push;

Ideally this would be abstracted a little better and a nice UI done with Rules....but it appears to be working as I want.

Would be very simple to add, and you should/could include some default rules as examples. User Register & New Content Posted are good ones. Then users could edit them, or create others. I'm sure after some time, please would create some wonderful ones, which would greatly add value to the Google Analytics module.

Ankabout’s picture

This is a pretty good idea, would be nice if someone could implement it.

EvanDonovan’s picture

Looks like a good solution. Where does the new variable go in relation to the existing analytics code generated by the module?

j0rd’s picture

Ideally someone would make a Rules "action" for GA _trackEvent which would let you fill out the variables for it's arguments. Then you could just add this "action" to existing "events" and then you'd have some event tracking in your GA.

I've enabled this for one of my sites. I've re-worked my code from what I've posted as I don't think I was using the arguments right. Hopefully this site will launch in beta very soon and I'll start collecting some stats and refine how it should all work...but that's the general idea.

It would help a tonne of site administrators gather a lot of wonderful information about abandon rates if this idea was expanded on. This in turn could provide a huge amount to of UX statistics in analysis of Drupal as a whole, as it would be easy enough for everyone to enable and start gathering data. This is also one of the reasons I would recommend implementing these rules by default. In turn modules would see what's going on over here and hook into the GA module and providing reasonable entry points where this type of information could/should be collected...which could then easily be enabled by everyone.

I'm personally very excited about this and I think it could be quite useful and important.

hass’s picture

Status: Active » Postponed

jOrd: you are NOT allowed to track user identifyable data (userid) with google analytics!!! I suggest you to read the google rules again. Code above have critical security issues. Don't use this code snippets.

#231451: Add hook to alter data before sending it to browser need to be done first.

j0rd’s picture

Status: Active » Postponed
Issue tags: +#d7ux

Code above has privacy issues, but not security issues. Here's the snippet from GA TOS . Let's factor that in while creating a solution.

7. PRIVACY . You will not (and will not allow any third party to) use the Service to track or collect personally identifiable information of Internet users, nor will You (or will You allow any third party to) associate any data gathered from Your website(s) (or such third parties' website(s)) with any personally identifying information from any source as part of Your use (or such third parties' use) of the Service. You will have and abide by an appropriate privacy policy and will comply with all applicable laws relating to the collection of information from visitors to Your websites. You must post a privacy policy and that policy must provide notice of your use of a cookie that collects anonymous traffic data.

More importantly as I previously mentioned, my code is wrong and tracking the value of the UserID in the value of the label, is the wrong way to do it. I was mostly interested in tracking how many signups, so I've changed my "event" code to this.

$_SESSION['ga_push'][] = array('_trackEvent', 'user', 'register');

Either way, my idea still stands and I feel is more useful than a simple hook. Also implementing both would cause fragmentation in how people implement integration. Additionally that hook_google_analytics feature request is 3 years old and according to you won't get implemented because of "design flaws".

The downfall of this suggested solution, is that it requires the rules and requires a 3rd party module to integrate with rules before it could use analytics goal tracking. This is a higher burden of entry than a simple hook.

The good thing about it, is that it auto-magically integrates with any module already using rules (like much of core and all current eCommerce platforms on Drupal). It would have the added by-product of making other modules integrate with rules so they can accept Google Analytics tracking.

@hass with that said what would you need to see to get this implemented an eventTracking feature in to Google Analytics module? I'm willing to do the work, but I'm not willing to do it if you're not going to integrate it. So let me know what you need to consider something like this (with hooks or rules or both) and I'll do the work.

hass’s picture

Code injection is possible. There is a security issue.

j0rd’s picture

@hass please elaborate on the vunerability so i can resolve it.

Additionally please tell me what work would need to get done to add eventTracking in to the Google Analytics module.

hass’s picture

Look into the api docs for drupal_to_js, drupal_json and drupal_add_js and as i know there is an api for session variables. Security issue is at $ga_item and implode. The linked issue should be fixed first and than we can look forward about the best way to get this stuff in.

udipl’s picture

subscribe

hass’s picture

j0rd’s picture

Status: Postponed » Closed (duplicate)

Its a dupe of which issue? So i can follow along.

castelar’s picture

@j0rd how did you end up accomplishing goal tracking? I imagine there are about 50,000 others that would benefit from this feature request, or a how to. Thanks!

j0rd’s picture

@castelar . I haven't implemented it yet, other than the way which @hass said is a security problem.

This is still a feature I think a lot of people could benefit from as well, and I'd still like to do it. I have a project coming up which integrates with Rules pretty deeply and I might be able to get them to pay me to do it. If that's the case I'll make sure it's robust and useful for others.

Either way, competing implementation could helps everyone come up with the best / ideal solution, so if you want this feature please implement it as well and we can see who does it best.

mrfelton’s picture

Status: Closed (duplicate) » Active

This is not a duplicate of #231451: Add hook to alter data before sending it to browser, which is about adding a new hook. This is about adding Rules integration - completely different. Mark it as won't fix if you like, but dont mark it as a duplicate as it clearly isn't.

hass’s picture

Yes, but the integration of an external module that uses rules to enhance the tracker code need the hook, isn't it? :-) Therefore was my idea to push getting the hook in to allow other modules to enhance the tracker. I'm not sure what you may plan to track based on rules, but I'm open minded to new ideas and *patches* for the ga module.

mrfelton’s picture

I have since found GA Push which adds the ability to trigger custom GA Events to be fired based on Rules. It works very well and was exactly what I was looking for. Over and above triggering Events with Rules, I'm not what else it would be useful to have Rules do. But the fact that GA Push now provides this feature, I'd say this issue could possibly just be closed now.

j0rd’s picture

@mrfelton

The idea behind integrating Rules & GA is that out of the box (at least in D6), Rules gives you these events. Almost every single one would be handy to have tracked in GA.

Additionally other modules integrate with Rules (Drupal Commerce as an example) and will then provide additional entry points where you can easily add new tracking.

Curious if this is possible with GA Push, and how much work is it to implement. Is it something a non-technical user could figure out?

Comment
After deleting a comment
After publishing a comment
After saving a new comment
After saving an updated comment
After unpublishing a comment
Comment is being viewed

Node
After deleting content
After saving new content
After updating existing content
Content is going to be saved
Content is going to be viewed

System
Cron maintenance tasks are performed
User is going to view a page

Taxonomy
After saving a new term
After updating a term

User
User account details have been updated
User account has been created
User has been deleted
User has logged in
User has logged out
User page has been viewed

hass’s picture

There are unique urls. Login/logout are well known. Some others, too. Additionally many (most?) logged in users are not tracked if they are in admin sections.

mrfelton’s picture

GA Push is very simple. It provides a new Rules Action that is able to trigger a GA Event to be registered. So, you can hook as mank of these as you want into as many Rules Events as you like. Essentially, gives you all the power of Rules Actions and Conditions to trigger GA Events.

hass’s picture

I hope these developer also blocks the use of personal data tokens.

I will review this module and may take over all this stuff.

hass’s picture

Issue summary: View changes

Added link to google goal docs

kenyob’s picture

subscribe

nvahalik’s picture

Here's a patch for the 7.x-1.x branch which provides a rule to create custom events and push them into Google Analytics. As mrfelton noted above, it is very simple.

nvahalik’s picture

Status: Active » Needs review

Updating to needs review.

hass’s picture

Version: 7.x-1.2 » 7.x-1.x-dev
Status: Needs review » Needs work

Thanks for the patch. That looks really easy.

However this one circumvent path exceptions, roles, DNT, maybe token placeholders with personal data and maybe other rules. And it's possible that there is no tracker and ga.js is missing on the page, but your events exits. This may cause JS errors. Never abbreviate names (e.g. "ga"), please. Running it in hook_init looks too early to me. I'm not sure if line 660 will not break as every value need double quotes and this may allow code injection. Line 669 and 670 has minor code style issues. Not sure, but is it correct that rules labels must not have strings in t()?

We also need 8.x-2.x and 7.x-2.x patches, too.

nvahalik’s picture

No problem. So we can easily fix the path exceptions, roles, and DNT by simply moving the hook_init code into googleanalytics_page_alter(). That's easy enough and it will fit better into the flow of things. Replacing json_encode with drupal_json_encode ought to take care of any security concerns. I checked on the hook_rules_action_info() page and t() appears to be used in the sample code on labels and groups.

I've implemented (to the best of my Rules knowledge) a form alter and validation that run the rules action form through the validation function in the admin inc file for each of the elements.

nvahalik’s picture

Status: Needs work » Needs review

[duplicate comment]

hass’s picture

  1. +++ b/googleanalytics.module
    @@ -148,6 +148,22 @@ function googleanalytics_page_alter(&$page) {
    +        $events[] = drupal_json_encode(array('_trackEvent', $event['action'], $event['label'], $event['value']));
    

    I believe this is not secure and allow code injection. I believe every single param need to be encoded by it's own. Not tested. Try to write some values with double and single quotes...

  2. +++ b/googleanalytics.module
    @@ -630,3 +649,64 @@ function _googleanalytics_visibility_header($account) {
    +/**
    + * implements hook_form_alter()
    + *
    + * @param $form ¶
    + * @param $form_state ¶
    + * @param string $form_id ¶
    + */
    +function googleanalytics_form_alter(&$form, &$form_state, $form_id) {
    +  // If this form is adding or editing a rules element that matches our rule plugin ¶
    +  // name, add a validator that checks for PII.
    +  if (($form_id == 'rules_ui_edit_element' || $form_id == 'rules_ui_add_element') ¶
    +    && $form_state['rules_element']->getPluginName() == "action googleanalytics_send_event") {
    +    array_unshift($form['#validate'], 'googleanalytics_validate_rules_pii');
    +  }
    +}
    +
    +/**
    + * Validate the form to ensure that no elements are being used that include personally
    + * identifiable information.
    + *
    + * @param $form ¶
    + * @param $form_state ¶
    + */
    +function googleanalytics_validate_rules_pii($form, &$form_state) {
    +  module_load_include('inc', 'googleanalytics', 'googleanalytics.admin');
    +
    +  foreach (element_children($form['parameter']) as $key => $param) {
    +    $data = &$form['parameter'][$param];
    +
    +    // Grab the actual element.
    +    $is_select = !empty($data['settings'][$param . ':select']);
    +    $element = $is_select ? $data['settings'][$param . ':select'] : $data['settings'][$param];
    +    $element['#old_value'] = $element['#value'];
    +
    +    if ($is_select) {
    +      // If it is a select, we "tokenize" it.
    +      $element['#value'] = '[' . $element['#value'] . ']';
    +    }
    +    // Do the heavy lifting.
    +    googleanalytics_token_element_validate($element, $form_state);
    +
    +    // Undo anything we did.
    +    $element['#value'] = $element['#old_value'];
    +  }
    +}
    

    Huh? Are you not able to reuse the custom variables element validation?

  3. +++ b/googleanalytics.module
    @@ -630,3 +649,64 @@ function _googleanalytics_visibility_header($account) {
    + * @param $form ¶
    

    There are trailing spaces in this and many other lines.

nvahalik’s picture

  1. Read the docs. drupal_json_encode is safe as it encodes '<', '>', "'", and '"' (even in arrays). You can run this drush command to verify: drush php-eval "echo drupal_json_encode(array('a', \"b\", 3, '\"4\"', \"'5'\"));"
  2. No. If you are editing the rule using a token "data selector" which allows you to select a token using auto-complete, the token value is submitted without its enclosing brackets []. Therefore, we have to add those brackets before doing the actual validation since that's what the existing function looks for.
  3. I ran the code formatter on the entire module but it introduced many other changes aside from my code. You might want to run it on the entire module.
hass’s picture

1. where are you sourounding every value with quotes that are not json encoded? I do not see this and they are required as I know.
3. i'm not aware of any code style bugs in the module. I guess your code formater does something wrong. Coder has a lot of bugs.

nvahalik’s picture

  1. All of the values that are user-entered are passing through drupal_json_encode (inside of the array), which is going to protect from any sort of injection. Can you give me an example or be a little bit about what exactly your issue is with the implementation?
  2. Trailing white-spaces from the patch have been removed.
nvahalik’s picture

Fixed a problem with some errors when creating certain kinds of rule elements.

j0rd’s picture

As far as injection goes. Make sure you set up the variables in a PHP array, then json_encode() that array and pass that javascript array into gaq.push();

That should be fine and avoid injection.

j0rd’s picture

Issue summary: View changes

Spam removed

zmove’s picture

Is there any news about that patch, I would love to see google analytics providing some helpful rules actions to manage goals.

gagarine’s picture

Status: Needs review » Fixed

As already mentioned https://www.drupal.org/project/ga_push as the requested features. I think we can therefor close this issue.

hass’s picture

Status: Fixed » Needs review

Well, but I'd like to integrate this feature.

hass’s picture

Status: Needs review » Closed (duplicate)
Parent issue: » #2121093: Support custom events via Rules

I will stop maintenance of 1.x soon and there is also a duplicate for 2.x. Please join there.

hass’s picture

Has someone in here and idea how to enable Rules module? See #2306551: Module completly broken, cannot enable.