type:
integration
supports-foxycart-version-from:
0.7.0
system:
Google Analytics (Asynchronous)
name:
Ecommerce Tracking for Google Analytics (Asynchronous)
description:
Tutorial to set up ecommerce tracking for Google Analytics and FoxyCart
tag:
analytics, tutorial, tracking
date:
2010-10-19
developer:
http://www.foxycart.com/

Google Analytics Ecommerce Tracking

Read This First:

Assumptions

  1. The instructions and code below is current as of FoxyCart v0.7.0 and Google Analytics as of 2010-10-19. If you notice things that should be changed please let us know on our forum.
  2. If you've applied any advanced filters to rewrite your request URIs you'll need to take that into account when setting your goal and funnel. If you don't know what that means, you probably don't have to worry about it, but rewriting the request URI can be useful when you're tracking multiple subdomains in one profile.

Requirements

  • Your products should use the SKU parameter in Google Analytics, which is the code parameter in FoxyCart. If your products do not include a code value (as passed to FoxyCart) FoxyCart will attempt to generate one from the name attribute, but FoxyCart will not take into account duplicate product names, which can clobber your data. If you are not using the code parameter for your products, this Google Analytics tracking may not work correctly.
  • All your add-to-cart links and forms must point to https://your_foxycart_domain and not http://your_foxycart_domain.
  • You must be using either foxycart.colorbox.js (the default behavior) or foxycart.js in your website template (do not include this in your cart, checkout, or receipt template). If you don't know what you're using, you're probably using foxycart.colorbox.js and don't have to worry, but you can view your template source to confirm. The code below assumes that fcc has been declared as a new FC.client, so if you're using foxycart.raw.js you'll need to create fcc or modify the FC.ga object accordingly.

Other important Google Analytics stuff

  • We strongly recommend setting up a separate Google Analytics profile to test with. This setup can be tricky, it can't be confirmed immediately because Google Analytics has a delay on reporting, and if you use your primary profile it may dirty up your data (which you cannot undo).
  • Tracking your banner ads and email marketing links. Very cool, and you should definitely do it if you're going to do anything described below.
  • This is all for ga.js and not urchin.js. If you need to use urchin.js it should be similar to this, but the urchin.js Google Analytics code is deprecated at this point so you'll have to adapt these instructions as necessary.

Known Issues and Limitations

  • This code may not work correctly if you're doing direct-to-checkout (cart=checkout) links originating from outside the site being tracked by Google Analytics. For instance, if you have cart=checkout links in an email, the referrer or campaign may not be maintained. If this is an issue for you please let us know.

Changes To This Page

  • 2011-08-08: Critical change to the include code. Details on our forum. The important pieces are:
    On the cart, change this line:
      window.location.hash = fc_json.custom_fields['ga'];
    to this:
      window.location.hash = fc_json.custom_fields['ga'].replace( /\&/g, '&' );
    
    And this line:
      var href_link = $(this).attr('href') + fc_json.custom_fields['ga'];
    to this:
      var href_link = $(this).attr('href') + fc_json.custom_fields['ga'].replace( /\&/g, '&' );
    
    On the checkout, change this line:
      window.location.hash = fc_json.custom_fields['ga'];
    to this:
      window.location.hash = fc_json.custom_fields['ga'].replace( /\&/g, '&' );
    
    On the receipt, change this:
      window.location.hash = fc_json.custom_fields['ga'];
    to:
      window.location.hash = fc_json.custom_fields['ga'].replace( /\&/g, '&' );

    This has been changed in all the examples below.

Setting Up Google Analytics

Getting the Tracking Code

  1. From your “Overview” page, click the “Edit” link for the profile your want to add tracking to. (You may want to create a new profile to test with, so as not to dirty up your real account with test data.)
  2. In the “Tracking Code” section (click the “Check Status” link to get there with an existing account)…
    • If your cart and checkout are at something like example.foxycart.com, select the “Multiple top-level domains” radio button, as shown on the screenshot to the right.
    • If your cart and checkout are at a custom subdomain, something like secure.example.com, select the “One domain with multiple subdomains” radio button.
  3. Complete the setup as Google Analytics instructs: “Copy the following code, then paste it onto every page you want to track immediately before the closing </head> tag.” Do not put this code on your FoxyCart cart, checkout, or receipt templates.
  4. We'll refer back to this block of code as the main Google Analytics code block, so make a mental note that this is what we're talking about.
  5. Proceed to the next section.

Configuring Your Profile Settings

  1. Edit your Profile Settings in your Google Analytics Settings section. (You can get here by clicking the “Edit” link to the right of the profile name from your analytics dashboard, then click the “Edit” link to the right of the “Main Website Profile Information” heading.)
  2. Add fcsid to the “Exclude URL Query Parameters” in your analytics settings. Details here.
  3. Set it to “Yes, an E-Commerce Site” and set your currency as desired.
  4. Set your timezone as necessary.
  5. You may want to set your “Default Page” to index.html or index.php or etc. But make sure you understand what this means, as it affects stuff like yourdomain.com/ as well as yourdomain.com/dir/sub/. More info here and here.
  6. Proceed to the next section.

Creating Your Goals

  1. Go back to your Profile Settings and click “Add goal” on one of your four goal sets. It doesn't matter which, but Goal #1 will show up by default in most of your GA reports, so if this is your only (or your primary) goal, you probably want to set it up as Goal #1 in set #1.
  2. Enter a “Goal Name” that makes sense to you, like “E-commerce Sale” or “Transaction” or etc.
  3. Make sure it's set to “Active” up top.
  4. Set the “Goal Type” to “URL Destination”.
  5. Switch the Match Type to “Exact Match” or “Equals To” depending on the options you see.
  6. Enter for your Goal URL: /receipt
  7. Create a funnel for this Goal:
    1. Step 1: use /cart for the URL and “Cart” for the Name. (You won't have this step if you are using “direct to checkout” with the parameter “cart=checkout”). Do not check the “required step” checkbox, as there are situations where the cart can be skipped.
    2. Step 2: /checkout for the URL and “Checkout” for the Name.
  8. Hit the “Save Changes” button down at the bottom. (The receipt page is the goal, so you don't need to add it in the steps.)

If you're using PayPal Express Checkout, you can create two additional goals. We'll call them “Sale (PayPal as Checkout)” and “Sale (PayPal as Payment Method)”. Create them the same as above, but for “Sale (PayPal as Checkout)” set the funnel like this:

  1. /cart, Cart
  2. /paypal_checkout, PayPal (Checkout)
  3. /checkout, Checkout (Confirmation)

And for “Sale (PayPal as Payment Method)” set the funnel like this:

  1. /cart, Cart
  2. /checkout, Checkout
  3. /paypal_payment, PayPal (Payment Method)

Proceed to the next section.

Setting Up Your Site

  1. On your own site, add the following below your GA script tags:
    <script type="text/javascript" charset="utf-8">
    	fcc.events.cart.preprocess.add(function(e, arr) {
    		if (arr['cart'] == 'checkout' || arr['cart'] == 'updateinfo' || arr['output'] == 'json') {
    			return true;
    		}
    		if (arr['cart'] == 'checkout_paypal_express') {
    			_gaq.push(['_trackPageview', '/paypal_checkout']);
    			return true;
    		}
    		_gaq.push(['_trackPageview', '/cart']);
    		return true;
    	});
    	fcc.events.cart.process.add_pre(function(e, arr) {
    		var pageTracker = _gat._getTrackerByName();
    		jQuery.getJSON('https://' + storedomain + '/cart?' + fcc.session_get() + '&h:ga=' + escape(pageTracker._getLinkerUrl('', true)) + '&output=json&callback=?', function(data){});
    		return true;
    	});
    </script>
    • In case you're wondering… The key is that we want to keep the FoxyCart session up to date with the GA session data. The code above basically tells Google Analytics to track a “pageview” for ”/cart” when a cart request is made. It also pushes the Google Analytics cookies into the FoxyCart session so the GA session can be maintained between your own site's domain and your site's FoxyCart domain.
    • Also note that this line replaces the need to set up crosslinks/forms as Google describes in this article on tracking multiple domains. The JSONP code that we'll use throughout the cart-checkout-receipt process ensures that the Foxycart session has the correct GA session values.
  2. Do not put this code in your cart, checkout, or receipt templates.
  3. Proceed to the next section.

Setting Up Your FoxyCart Templates, The Easy Way

This section includes “the easy way” for getting Google Analytics going. It doesn't include the full “why”, but if you just want to copy and paste, follow the steps below. Copy the code, paste it into the appropriate template (either in FoxyCart's admin directly, or on your system that FoxyCart is template-caching), and change the XXXXXXXX-X. NOTE: YOU MUST CHANGE THE XXXXXXXX-X IN ALL LOCATIONS TO YOUR UA CODE!

The Cart Template

<script type="text/javascript" charset="utf-8">
	if (window.location.hash.search(/utma/) == -1 && typeof(fc_json.custom_fields['ga']) != "undefined") {
		if (fc_json.custom_fields['ga'].length > 0) {
			window.location.hash = fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
		}
	}
	if (typeof(fc_json.custom_fields['ga']) != "undefined") {
		$('a.fc_link_nav').each(function(){
			var href_link = $(this).attr('href') + fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
			$(this).attr('href', href_link);
		});
	}
</script>
 
<script type="text/javascript">
 
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
  _gaq.push(['_setDomainName', 'none']);
  _gaq.push(['_setAllowLinker', true]);
 
  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
 
</script>
 
<script type="text/javascript" charset="utf-8">
	jQuery(function($){
		$('a.fc_cart_checkout_paypal').click(function(e){
			// e.preventDefault(); // TODO
			_gaq.push(['_trackPageview', '/paypal_checkout']);
			// setTimeout('document.location = "' + this.href + '";', 200); // TODO
		});
	});
</script>

The Checkout Template

<script type="text/javascript" charset="utf-8">
	if (window.location.hash.search(/utma/) == -1 && typeof(fc_json.custom_fields['ga']) != "undefined") {
		if (fc_json.custom_fields['ga'].length > 0) {
			window.location.hash = fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
		}
	}
</script>
 
<script type="text/javascript">
 
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
  _gaq.push(['_setDomainName', 'none']);
  _gaq.push(['_setAllowLinker', true]);
  _gaq.push(['_setAllowAnchor', true]);
  _gaq.push(['_trackPageview', '/checkout']);
 
  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
 
</script>
 
<script type="text/javascript" charset="utf-8">
	function ga_tracker() {
		if (typeof(fc_json.custom_fields['ga']) != "undefined" && jQuery('#fc_payment_method_paypal').is(":checked") == true) {
			_gaq.push(['_trackPageview', '/paypal_payment']);
			// setTimeout('return true;', 250); // TODO
		}
	}
	FC.checkout.overload('validateAndSubmit', 'ga_tracker', null);
</script>

The Receipt Code

<script type="text/javascript" charset="utf-8">
	if (window.location.hash.search(/utma/) == -1 && typeof(fc_json.custom_fields['ga']) != "undefined") {
		if (fc_json.custom_fields['ga'].length > 0) {
			window.location.hash = fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
		}
	}
</script>
 
<script type="text/javascript">
 
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', 'UA-XXXXXXXX-X']);
  _gaq.push(['_setDomainName', 'none']);
  _gaq.push(['_setAllowLinker', true]);
  _gaq.push(['_setAllowAnchor', true]);
  _gaq.push(['_trackPageview', '/receipt']);
 
  (function() {
    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
  })();
 
</script>
 
^^receipt_only_begin^^
^^analytics_google_ga_async^^
^^receipt_only_end^^

Test

Once you've replaced all the XXXXXXXX-X in the copy/paste code above and got it successfully saved as your FoxyCart templates, proceed to test things out.

Setting Up Your FoxyCart Templates, The Full Details

This section includes the details that “the easy way” above skips over. If you've already done the above “easy way” section you can safely skip down to the testing section.

The Cart Template

  1. Copy the main Google Analytics tracking code used from above and paste it above the closing </body> tag in your cart template. This can be directly in your FoxyCart admin or (preferably) in your cart template on your server that you will load into FoxyCart via FoxyCart's template caching functionality.
  2. Remove or comment out the _gaq.push(['_trackPageview']); line. We're tracking it manually already. (It's not very reliable when called inside an iframe loaded from a separate domain, in case you're wondering.)
  3. Add the following code above the Google Analytics <script> tag you just added on your cart template:
    <script type="text/javascript" charset="utf-8">
    	if (window.location.hash.search(/utma/) == -1 && typeof(fc_json.custom_fields['ga']) != "undefined") {
    		if (fc_json.custom_fields['ga'].length > 0) {
    			window.location.hash = fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
    		}
    	}
    	if (typeof(fc_json.custom_fields['ga']) != "undefined") {
    		$('a.fc_link_nav').each(function(){
    			var href_link = $(this).attr('href') + fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
    			$(this).attr('href', href_link);
    		});
    	}
    </script>
  4. Add the following below the Google Analytics closing </script> tag on your cart template.
    <script type="text/javascript" charset="utf-8">
    	jQuery(function($){
    		$('a.fc_cart_checkout_paypal').click(function(e){
    			// e.preventDefault(); // TODO
    			_gaq.push(['_trackPageview', '/paypal_checkout']);
    			// setTimeout('document.location = "' + this.href + '";', 200); // TODO
    		});
    	});
    </script>
  5. Proceed to the next section.

The Checkout Template

  1. Copy the main Google Analytics tracking code used from above and paste it above the closing </body> tag in your checkout template. This can be directly in your FoxyCart admin or (preferably) in your checkout template on your server that you will load into FoxyCart via FoxyCart's template caching functionality.
  2. Find this line:
    _gaq.push(['_trackPageview']);

    and change it to this:

      _gaq.push(['_setAllowAnchor', true]);
      _gaq.push(['_trackPageview', '/checkout']);

    Notice that we added a line there. That's very important.

  3. Add the following code above the Google Analytics <script> tag you just added on your cart template:
    <script type="text/javascript" charset="utf-8">
    	if (window.location.hash.search(/utma/) == -1 && typeof(fc_json.custom_fields['ga']) != "undefined") {
    		if (fc_json.custom_fields['ga'].length > 0) {
    			window.location.hash = fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
    		}
    	}
    </script>
  4. Add the following below the Google Analytics closing </script> tag on your cart template.
    <script type="text/javascript" charset="utf-8">
    	function ga_tracker() {
    		if (typeof(fc_json.custom_fields['ga']) != "undefined" && jQuery('#fc_payment_method_paypal').is(":checked") == true) {
    			_gaq.push(['_trackPageview', '/paypal_payment']);
    			// setTimeout('return true;', 250); // TODO
    		}
    	}
    	FC.checkout.overload('validateAndSubmit', 'ga_tracker', null);
    </script>
  5. Confirm that the entire section looks something like this:
    <script type="text/javascript" charset="utf-8">
    	if (window.location.hash.search(/utma/) == -1 && typeof(fc_json.custom_fields['ga']) != "undefined") {
    		if (fc_json.custom_fields['ga'].length > 0) {
    			window.location.hash = fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
    		}
    	}
    </script>
    <script type="text/javascript">
      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-XXXXXXX-X']);
      _gaq.push(['_setDomainName', 'none']);
      _gaq.push(['_setAllowLinker', true]);
      _gaq.push(['_setAllowAnchor', true]);
      _gaq.push(['_trackPageview', '/checkout']);
     
      (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();
    </script>
    <script type="text/javascript" charset="utf-8">
    	function ga_tracker() {
    		if (jQuery('#fc_payment_method_paypal').is(":checked") == true || (jQuery('#fc_payment_method_paypal_container').length > 0 && jQuery('#fc_payment_method_paypal_container').find('input[type=radio]').length == 0)) {
    			_gaq.push(['_trackPageview', '/paypal_payment']);
    			// setTimeout('return true;', 250); // TODO
    		}
    	}
    	FC.checkout.overload('validateAndSubmit', 'ga_tracker', null);
    </script>

    You could copy this entire block, but you'll need to replace the XXXXXXX-X with your own account number.

  6. Proceed to the next section.

The Receipt Template

  1. Repeat steps 1, 2, and 3 from the checkout template above but on the receipt template.
  2. Change the _gaq.push(['_trackPageview', '/checkout']); to _gaq.push(['_trackPageview', '/receipt']);
  3. Add the following 3 lines beneath the main Google Analytics code:
    ^^receipt_only_begin^^
    ^^analytics_google_ga_async^^
    ^^receipt_only_end^^
  4. Confirm that the entire section looks something like this:
    <script type="text/javascript" charset="utf-8">
    	if (window.location.hash.search(/utma/) == -1 && typeof(fc_json.custom_fields['ga']) != "undefined") {
    		if (fc_json.custom_fields['ga'].length > 0) {
    			window.location.hash = fc_json.custom_fields['ga'].replace( /\&amp;/g, '&' );
    		}
    	}
    </script>
    <script type="text/javascript">
     
      var _gaq = _gaq || [];
      _gaq.push(['_setAccount', 'UA-XXXXXXX-X']);
      _gaq.push(['_setDomainName', 'none']);
      _gaq.push(['_setAllowLinker', true]);
      _gaq.push(['_setAllowAnchor', true]);
      _gaq.push(['_trackPageview', '/receipt']);
     
      (function() {
        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
      })();
     
    </script>
     
    ^^receipt_only_begin^^
    ^^analytics_google_ga_async^^
    ^^receipt_only_end^^

    You could copy this entire block, but you'll need to replace the XXXXXXX-X with your own account number.

  5. Proceed to the next section (Testing).

Testing

  1. We strongly recommend creating a new profile in Google Analytics to test with. That way you don't have to worry about running 100 transactions and completely destroying the accuracy of the analytics, which is the entire point.
  2. To test, try clearing your browser's cookies (at least for the domains in question: your site domain and FoxyCart.com) and preferably using a browser that you don't use to develop in. So if you use Firefox to administer your site through a CMS and to login to the FoxyCart admin, try testing in Chrome or Safari. The goal is to pretend you're a normal customer.
  3. Try adding something to your cart and proceeding through and completing a checkout.
  4. Clear your cookies, especially any of the Google Analytics cookies, which are named _utm*.
  5. Try adding something to your cart a few times. Don't go to the checkout.
  6. Clear your cookies as before.
  7. Try adding something to your cart then going to the checkout. Go back to the site, add something else, go back to checkout, but don't checkout.
  8. Clear your cookies as before.
  9. If you're using PayPal Express Checkout, try testing that a few times both from the cart and from the checkout. Go all the way through, stop before completing, bail out on the PayPal end of things, etc.
  10. Once you've tested quite a bit go to your Google Analytics → Goals → Funnel Visualization. It should hopefully look something like the image to the right. The key is that the numbers in between the steps are not zero. If you have values there it's tracking the user through the steps, indicating that the Google Analytics info is being passed correctly across domains. If you have zeroes in there, go back through the steps to ensure you have all the code inserted as it should be. Post on our forum if you get stuck.
  11. Party down! You're done.

Checking Cookies

It's often difficult to troubleshoot because it takes upwards of four hours for any transactions to appear in Google Analytics. So if you set up FoxyCart to be tracked in Google Analytics, and you try a few test transactions, it will take at least a few hours before you can see if things are working correctly. There's a faster way: you can look directly at the cookies set by Google Analytics.

GA sets cookies named utma, utmb, utmc, and utmz. Each has a “host” parameter as well as a value. See a detailed description of the information stored in these cookies.

The easiest way to approach this is to view the cookies directly in your browser. Clear out the cookies for your domain, making sure to delete all the utm* cookies as well as any fcsid cookies. (If you're using Firefox, you can install Chris Pederick's Web Developer Toolbar for Firefox, which is amazing, and allows you to clear cookies for a domain (among other things.) Make sure you clear out the utm* cookies both for your domain and for your store's FoxyCart domain. So, example.com and example.foxycart.com. Otherwise you'll get goofy results.

Once you have your cookies cleared, load up a page with a FoxyCart add-to-cart link or form. See what cookies were set. You should see at least an fcsid cookie and 4 __utm* cookies. Take a look at the data in __utma. Now add something to your cart and proceed through to checkout. View your cookies again. Check the __utma for the FoxyCart domain, then compare it to the __utma at your domain. They should be identical, or close to identical. If they're radically different, it's not working. Take a look at the image to the right for a screenshot of what it looks like in Firefox on OS X. (Go Preferences → Privacy (Use constom settings for history) → Show Cookies. It'll actually show them to you as they're set, which is very handy.)

You can also take a close look at the value for the __utmz cookie. This cookie encodes all the essential details of how a visitor came to the site, such as referring site or search keyword. This is the data that you want to see tracked all the way to your final order receipt page. That cookie should contain the same info for both your domain (like example.com) and for your store's FoxyCart domain (like example.foxycart.com).

Site Tools