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!
GoogleRequest request = new GoogleRequest("UA-111111-1", Request);
request.Culture = "nl-NL";
request.HostName = System.Web.HttpContext.Current.Request.Url.ToString();
request.PageTitle = "ShoppingCart";
Transaction trans = new Transaction(123456, "Groningen",
"Nederland", "State", "Store",1.95m, 21.94m, 3.81m);
foreach (OrderLine ol in OrderLines)
{
TransactionItem item = new TransactionItem("fb0001",
"photobook", "19.99", "1", "Photobooks");
trans.AddTransactionItem(item);
}
request.SendRequest(trans);
The GoogleRequest
class holds the basic information needed for every request and makes the request eventually.
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";
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";
private int _RequestCount = 0;
private Random rand;
public GoogleRequest(string accountCode)
{
rand = new Random();
_RequestCount = 0;
AccountCode = accountCode;
}
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 TransactionItem
s. All parameters are set using the constructor because they are all essential.
public class Transaction : IGoogleEvent
{
private readonly string _utmt = "tran";
private int _orderId;
private string _utmtci;
private string _utmtco;
private string _utmtrg;
private string _utmtst;
private string _utmtsp;
private string _utmtto;
private string _utmttx;
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.
public class TransactionItem
{
private readonly string _utmt = "item";
private string _utmtid;
private string _utmipc;
private string_utmipn;
private string _utmipr;
private string _utmiqt;
private string _utmiva;
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.
public void SendRequest(IGoogleEvent eventObject)
{
string requestUrl = BASE_URL + CreateParameterString() +
"&" + eventObject.CreateParameterString();
FireRequest(requestUrl);
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.
private void FireRequest(string url)
{
WebRequest GaRequest = WebRequest.Create(url);
GaRequest.BeginGetResponse(r =>
{
try
{
var reponse = GaRequest.EndGetResponse(r);
}
catch
{
}
}, 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.