Click here to Skip to main content
15,867,308 members
Articles / Programming Languages / C#

Server-side Google Analytics Transactions

Rate me:
Please Sign up or sign in to vote.
4.86/5 (10 votes)
21 May 2013CPOL4 min read 42.4K   1.1K   25   4
Handling Google Analytics Transactions on server-side using C# intead of JavaScript on client-side.

Introduction 

Google Analytics Ecommerce is a great way of tracking transactions made in your webshop. Google provides us with an easy way to add this feature to our websites using a piece of JavaScript and the ga.js library. Usually this implementation works perfectly (Google wouldn’t be Google if it wouldn’t) but in some cases we do want to post to the Analytics servers on the server-side. In this article I’ll provide you with a code sample and a working and tested code library (C#) which will handle the posts for you. I’ll briefly explain my code in the article, the entire code will be available for download. 

Background

So why do I need to have my Analytics transactions be posted on the server side? At this company I’ve been working for we use Analytics Ecommerce to analyze the purchases made on a website. After the customer has paid for an order he would return to our website and the order would be handled, the order confirmation would be sent to the customer, and a “thank you” page would show. This “Thank you” page would also run the JavaScript to send the transaction data to Google servers.

However, in some cases the customers wouldn’t return to the website. After the payment they would just close the browser and expect the order will be handled just fine. Which it would because our payment service provider provides us with a request from their server to our website which tells us there has been a successful payment. This request gives us the payment data and the website just handles the order and sends the order confirmation. However since there is no client in this backup, no “Thank you” screen shows, and worse, no JavaScript for Analytics Ecommerce is executed!

After this question on Stack Overflow I started looking into GaDotNet and found that I could easily write my own wrapper to make the Analytics requests. So I did..

Using the code

Analytics transactions are just a bunch of GET web requests to the Analytics servers with a large query string. So all we have to do is find out which data goes in where, build the string, and make a web request. 

In this cheatsheet you can find all the parameters used in Google Analytics requests.   

In my implementation there are three classes used to post a transaction to the Google server. First we need a GoogleRequest object, a Transaction object, and a TransactionItem object for each orderline in the order. Once the DLL is added to your project, you’ll only need something like the code shown below for it to work!   

C#
GoogleRequest request = new GoogleRequest("UA-111111-1", Request);
           
request.Culture = "nl-NL";
request.HostName = System.Web.HttpContext.Current.Request.Url.ToString();
request.PageTitle = "ShoppingCart";
 
//OrderId, City, Country, State, StoreName, Shippincosts, Ordertotal, TaxCosts
Transaction trans = new Transaction(123456, "Groningen", 
  "Nederland", "State", "Store",1.95m, 21.94m, 3.81m);
 
//For each orderline add a new TransactionItem to the Transaction object
foreach (OrderLine ol in OrderLines)
{
   //ProductCode or SKU, ProductName, ItemPrice, Quantity, GroupName
   TransactionItem item = new TransactionItem("fb0001", 
     "photobook", "19.99", "1", "Photobooks");
   trans.AddTransactionItem(item); 
}    

//Now just make a request for this transaction object
request.SendRequest(trans);

The GoogleRequest class holds the basic information needed for every request and makes the request eventually.

C#
public class GoogleRequest
{
   private const string BASE_URL = "http://www.google-analytics.com/__utm.gif?";
 
   private const string ANALYTICS_VERSION = "5.3.7";
   private const string LANGUAGE_ENCODING = "UTF-8";
   private const string BROWSER_JAVA_ENABLED = "0";
 
   //Required parameters but not necessary for us, so just post a default
   private const string SCREEN_RESOLUTION = "1680x1050";
   private const string SCREEN_COLOR_DEPTH = "32-bit";
   private const string FLASH_VERSION = "11.5%20r31";
   private const string REFERAL = "0";
 
    //Internal request counter. Max requests = 500 per session
    private int _RequestCount = 0;
 
    private Random rand;
 
    /// <summary>
   /// Initialize a new GoogleRequest
   /// </summary>
   /// <param name="accountCode">Your Google tracking code (e.g. UA-12345678-1)</param>
   public GoogleRequest(string accountCode)
   {
       rand = new Random();
 
       _RequestCount = 0;           
       AccountCode = accountCode;
   }

   /// <summary>
   /// Initialize a new GoogleRequest with campaign and referer support  
   /// </summary>
   /// <param name="accountCode">Your Google tracking code (e.g. UA-12345678-1)</param> 
   /// <param name="request">The current HttpRequestBase of the webapplication</param>
   public GoogleRequest(string accountCode, HttpRequestBase request)
   {
        _random = new Random();

        _RequestCount = 0;
        _CurrentRequest = request;
        AccountCode = accountCode;
   } 
}  

The complete code for the GoogleRequest class can be found in the downloadable source. The GoogleRequest class holds a few fields which are required by Google for a successful request but which I don’t find necessary for my implementation, so I’ll just post a default value. An account code is always required to make any kind of request, so I chose to pass this in with the constructor of the object. 

The next class we use is the Transaction class. The Transaction class is just an object which holds a few variables which contain the parameters needed for the query string to post a transaction. It also contains a list with its TransactionItems. All parameters are set using the constructor because they are all essential.

C#
public class Transaction : IGoogleEvent
{       
    private readonly string _utmt = "tran";
    private int _orderId;          //(utmtid)
    private string _utmtci;        //Billing city
    private string _utmtco;        //Billing country
    private string _utmtrg;        //Billing region
    private string _utmtst;        //Store name / affiliation
    private string _utmtsp;        //Shipping costs
    private string _utmtto;        //Ordertotal
    private string _utmttx;        //Tax costs 
         
    public Transaction(int orderId, string billingCity, string country, string region, 
		       string storeName, decimal shippingCosts, decimal orderTotal, 
                       decimal taxCosts)
    {
        _items = new List<TransactionItem>();
 
        _orderId = orderId;
        _utmtci = Uri.EscapeDataString(billingCity);
        _utmtco = Uri.EscapeDataString(country);
        _utmtrg = Uri.EscapeDataString(region);
        _utmtst = Uri.EscapeDataString(storeName);
        _utmtsp = shippingCosts.ToString("F").Replace(',','.');
        _utmtto = orderTotal.ToString("F").Replace(',','.');
        _utmttx = taxCosts.ToString("F").Replace(',','.');
    }
}

Finally we have the TransactionItem class. The TransactionItem is almost the same as the Transaction class. This class again holds a few variables which contain the parameters necessary to execute a request for a transaction item.   

C#
public class TransactionItem 
{
    private readonly string _utmt = "item";
 
    private string _utmtid;     //OrderId
    private string _utmipc;     //Product code
    private string_utmipn;     //Product name
    private string _utmipr;     //Productprice (unit price)
    private string _utmiqt;     //Quantity
    private string _utmiva;     //Product category
 
    public TransactionItem(string productCode, string productName, decimal productPrice, 
                           int quantity, string category)     
    {
       _utmipc = Uri.EscapeDataString(productCode);
       _utmipn = Uri.EscapeDataString(productName);
       _utmipr = productPrice.ToString("F");
       _utmiqt = quantity.ToString();
       _utmiva = Uri.EscapeDataString(category);
    }
}

Each class has its own function (private string CreateParameterString()) which generates its part of the querystring needed for the request. The public void SendRequest(IGoogleEvent) eventObject) function then will create the full URL and fire all the requests individually.

C#
/// <summary>
/// Send the request to the google servers!
/// </summary>
/// <param name="eventObject">A corresponding Transaction, Page or Event</param>
public void SendRequest(IGoogleEvent eventObject)
{
    string requestUrl = BASE_URL + CreateParameterString() + 
           "&" + eventObject.CreateParameterString();
 
    FireRequest(requestUrl);
 
    //A transaction also has subrequests for the TransactionItems
    if (eventObject is Transaction)
    {
        Transaction trans = eventObject as Transaction;
 
        foreach (TransactionItem transItem in trans.Items)
        {
            FireRequest(BASE_URL + CreateParameterString() + 
                  "&" + transItem.CreateParameterString());
        }
    }
}  

Each URL consists of a few parts: the base URL of the Google servers, the general part of an Analytics request (generated in the GoogleRequest class), and the specific part (generated in its own class: Transaction or TransactionItem). When this is all done the public void FireRequest(string url) function will make a webrequest for each of these requests.  

C#
private void FireRequest(string url)
{
    WebRequest GaRequest = WebRequest.Create(url);
 
    GaRequest.BeginGetResponse(r =>
    {
        try
        {
            // we don't need the response so this is the end of the request
            var reponse = GaRequest.EndGetResponse(r);
        }
        catch
        {
            //eat the error 
        }
    }, null);
}

Now your data will be processed by Google servers! The real code is a bit more complicated, but I think I have explained how it works with this. 

Points of Interest

The code now only supports Google Analytics Transactions but is built to also have PageViews and Events implemented in the future!

History 

  • 14-11-2012 – Initial version (Analytics Transaction support only) V1.0. 
  • 22-11-2012 - Full support for referer and campaign information for Transactions V1.1.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Junior)
Netherlands Netherlands
Student software engineer and partime .NET backend developer

Comments and Discussions

 
GeneralMy vote of 5 Pin
Niral Soni14-Nov-12 5:42
Niral Soni14-Nov-12 5:42 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.