Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#91 Google analytics plugin. Reverse an ecommerce transaction. And pr…
…ocess only already paid orders (not just placed)
- Loading branch information
Showing
13 changed files
with
578 additions
and
159 deletions.
There are no files selected for viewing
197 changes: 197 additions & 0 deletions
197
src/Plugins/Nop.Plugin.Widgets.GoogleAnalytics/Api/GoogleRequest.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
//Contributor: https://www.codeproject.com/Articles/493455/Server-side-Google-Analytics-Transactions | ||
|
||
using System; | ||
using System.Net; | ||
using Nop.Core; | ||
|
||
namespace Nop.Plugin.Widgets.GoogleAnalytics.Api | ||
{ | ||
public class GoogleRequest | ||
{ | ||
#region Fields | ||
|
||
private const string BASE_URL = "http://www.google-analytics.com/__utm.gif?"; | ||
|
||
private const string ANALYTICS_VERSION = "5.3.7"; | ||
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"; | ||
|
||
//Internal request counter. Max requests = 500 per session | ||
private int _requestCount; | ||
private int? _domainHash; | ||
|
||
#endregion | ||
|
||
#region Utilities | ||
|
||
private void FireRequest(string url) | ||
{ | ||
if (_requestCount < 500) | ||
{ | ||
_requestCount++; | ||
|
||
var gaRequest = WebRequest.Create(url); | ||
|
||
try | ||
{ | ||
// we don't need the response so this is the end of the request | ||
var response = gaRequest.GetResponse(); | ||
} | ||
catch (Exception exc) | ||
{ | ||
//eat the error | ||
} | ||
|
||
//TODO comment the code above and uncomment the code below when the issue with multiple products is fixed | ||
//gaRequest.BeginGetResponse(r => | ||
// { | ||
// try | ||
// { | ||
// // we don't need the response so this is the end of the request | ||
// var response = gaRequest.EndGetResponse(r); | ||
// } | ||
// catch | ||
// { | ||
// //eat the error | ||
// } | ||
// }, null); | ||
} | ||
} | ||
|
||
private string CreateParameterString() | ||
{ | ||
return string.Format("utmwv={0}&utms={1}&utmn={2}&utmhn={3}&utmsr{4}&utmvp={5}&utmsc={6}&utmul={7}&utmje={8}&utmfl={9}&utmhid={10}&utmr={11}&utmp={12}&utmac={13}&utmcc={14}", | ||
ANALYTICS_VERSION, | ||
_requestCount, | ||
CommonHelper.GenerateRandomInteger(), | ||
HostName, | ||
SCREEN_RESOLUTION, | ||
SCREEN_RESOLUTION, | ||
SCREEN_COLOR_DEPTH, | ||
Culture, | ||
BROWSER_JAVA_ENABLED, | ||
FLASH_VERSION, | ||
CommonHelper.GenerateRandomInteger(), | ||
"-", | ||
PageTitle, | ||
AccountCode, | ||
GetUtmcCookieString()); | ||
} | ||
|
||
private int DomainHash | ||
{ | ||
get | ||
{ | ||
if (!_domainHash.HasValue) | ||
{ | ||
if (HostName != null) | ||
{ | ||
int a; | ||
int c; | ||
int h; | ||
char chrCharacter; | ||
int intCharacter; | ||
|
||
a = 0; | ||
for (h = HostName.Length - 1; h >= 0; h--) | ||
{ | ||
chrCharacter = char.Parse(HostName.Substring(h, 1)); | ||
intCharacter = (int)chrCharacter; | ||
a = (a << 6 & 268435455) + intCharacter + (intCharacter << 14); | ||
c = a & 266338304; | ||
a = c != 0 ? a ^ c >> 21 : a; | ||
} | ||
|
||
_domainHash = a; | ||
} | ||
_domainHash = 0; | ||
} | ||
|
||
return _domainHash.Value; | ||
} | ||
} | ||
|
||
private string _UtmcCookieString = null; | ||
//The cookie collection string | ||
private string GetUtmcCookieString() | ||
{ | ||
if (_UtmcCookieString == null) | ||
{ | ||
//create the unix timestamp | ||
TimeSpan span = (DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime()); | ||
int timeStampCurrent = (int)span.TotalSeconds; | ||
|
||
//fake the utma | ||
string utma = String.Format("{0}.{1}.{2}.{3}.{4}.{5}", | ||
DomainHash, | ||
CommonHelper.GenerateRandomInteger(), | ||
timeStampCurrent, | ||
timeStampCurrent, | ||
timeStampCurrent, | ||
"2"); | ||
string utmz = String.Format("{0}.{1}.{2}.{3}.utmcsr={4}|utmccn={5}|utmcmd={6}", | ||
DomainHash, | ||
timeStampCurrent, | ||
"1", | ||
"1", | ||
"(direct)", | ||
"(direct)", | ||
"(none)"); | ||
|
||
|
||
_UtmcCookieString = Uri.EscapeDataString(String.Format("__utma={0};+__utmz={1};", utma, utmz)); | ||
} | ||
|
||
return _UtmcCookieString; | ||
} | ||
|
||
#endregion | ||
|
||
#region Methods | ||
|
||
/// <summary> | ||
/// Send the request to the Google servers | ||
/// </summary> | ||
/// <param name="transaction">A corresponding transaction</param> | ||
public void SendRequest(Transaction transaction) | ||
{ | ||
string requestUrl = BASE_URL + CreateParameterString() + "&" + transaction.CreateParameterString(); | ||
FireRequest(requestUrl); | ||
|
||
foreach (var transItem in transaction.Items) | ||
{ | ||
FireRequest(BASE_URL + CreateParameterString() + "&" + transItem.CreateParameterString()); | ||
} | ||
} | ||
|
||
#endregion | ||
|
||
#region Properties | ||
|
||
/// <summary> | ||
/// Your Google tracking code (e.g. UA-12345678-1) | ||
/// </summary> | ||
public string AccountCode { get; set; } | ||
|
||
/// <summary> | ||
/// The language of the customer (e.g. en-US) | ||
/// </summary> | ||
public string Culture { get; set; } | ||
|
||
/// <summary> | ||
/// The hostname of the website making the request (e.g. www.google.com) | ||
/// </summary> | ||
public string HostName { get; set; } | ||
|
||
/// <summary> | ||
/// The title of the page making the request | ||
/// </summary> | ||
public string PageTitle { get; set; } | ||
|
||
#endregion | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/Plugins/Nop.Plugin.Widgets.GoogleAnalytics/Api/Helpers.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
//Contributor: https://www.codeproject.com/Articles/493455/Server-side-Google-Analytics-Transactions | ||
|
||
using System; | ||
|
||
namespace Nop.Plugin.Widgets.GoogleAnalytics.Api | ||
{ | ||
public class Helpers | ||
{ | ||
/// <summary> | ||
/// Converts a DateTime to a UNIX timestamp | ||
/// </summary> | ||
public static int ConvertToUnixTimestamp(DateTime value) | ||
{ | ||
//create Timespan by subtracting the value provided from the Unix Epoch | ||
TimeSpan span = (value - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime()); | ||
|
||
//return the total seconds (which is a UNIX timestamp) | ||
return (int)span.TotalSeconds; | ||
} | ||
} | ||
} |
65 changes: 65 additions & 0 deletions
65
src/Plugins/Nop.Plugin.Widgets.GoogleAnalytics/Api/Transaction.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
//Contributor: https://www.codeproject.com/Articles/493455/Server-side-Google-Analytics-Transactions | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
|
||
namespace Nop.Plugin.Widgets.GoogleAnalytics.Api | ||
{ | ||
public class Transaction | ||
{ | ||
private readonly string _utmt = "tran"; | ||
|
||
private string _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; //Order total | ||
private string _utmttx; //Tax costs | ||
|
||
/// <summary> | ||
/// Create a new E-commerce Transaction | ||
/// </summary> | ||
/// <param name="orderId">Order identifier</param> | ||
/// <param name="billingCity">Billing city</param> | ||
/// <param name="country">Country</param> | ||
/// <param name="region">Region</param> | ||
/// <param name="storeName">Store name</param> | ||
/// <param name="shipping">Shipping</param> | ||
/// <param name="tax">Tax</param> | ||
/// <param name="orderTotal">Order total</param> | ||
public Transaction(string orderId, string billingCity, string country, string region, string storeName, decimal shipping, decimal tax, decimal orderTotal) | ||
{ | ||
Items = new List<TransactionItem>(); | ||
|
||
_orderId = Uri.EscapeDataString(orderId); | ||
|
||
var usCulture = new CultureInfo("en-US"); | ||
_utmtci = Uri.EscapeDataString(billingCity); | ||
_utmtco = Uri.EscapeDataString(country); | ||
_utmtrg = Uri.EscapeDataString(region); | ||
_utmtst = Uri.EscapeDataString(storeName); | ||
_utmtsp = shipping.ToString("0.00", usCulture); | ||
_utmttx = tax.ToString("0.00", usCulture); | ||
_utmtto = orderTotal.ToString("0.00", usCulture); | ||
} | ||
|
||
public string CreateParameterString() | ||
{ | ||
return string.Format("utmt={0}&utmtci={1}&utmtco={2}&utmtrg={3}&utmtid={4}&utmtst={5}&utmtsp={6}&utmtto={7}&utmttx={8}", | ||
_utmt, | ||
_utmtci, | ||
_utmtco, | ||
_utmtrg, | ||
_orderId, | ||
_utmtst, | ||
_utmtsp, | ||
_utmtto, | ||
_utmttx); | ||
} | ||
|
||
public List<TransactionItem> Items { get; set; } | ||
} | ||
} |
51 changes: 51 additions & 0 deletions
51
src/Plugins/Nop.Plugin.Widgets.GoogleAnalytics/Api/TransactionItem.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
//Contributor: https://www.codeproject.com/Articles/493455/Server-side-Google-Analytics-Transactions | ||
|
||
using System; | ||
using System.Globalization; | ||
|
||
namespace Nop.Plugin.Widgets.GoogleAnalytics.Api | ||
{ | ||
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; //Product price (unit price) | ||
private string _utmiqt; //Quantity | ||
private string _utmiva; //Product category | ||
|
||
/// <summary> | ||
/// Create a new TransactionItem | ||
/// </summary> | ||
/// <param name="orderId">Order number</param> | ||
/// <param name="productName">Product name</param> | ||
/// <param name="productPrice">Unit price</param> | ||
/// <param name="quantity">Quantity</param> | ||
/// <param name="category">The product category</param> | ||
public TransactionItem(string orderId, string productCode, string productName, decimal productPrice, int quantity, string category) | ||
{ | ||
var usCulture = new CultureInfo("en-US"); | ||
|
||
_utmtid = Uri.EscapeDataString(orderId); | ||
_utmipc = Uri.EscapeDataString(productCode); | ||
_utmipn = Uri.EscapeDataString(productName); | ||
_utmipr = productPrice.ToString("0.00", usCulture); | ||
_utmiqt = quantity.ToString(); | ||
_utmiva = Uri.EscapeDataString(category); | ||
} | ||
|
||
public string CreateParameterString() | ||
{ | ||
return string.Format("utmt={0}&utmtid={1}&utmipc={2}&utmipn={3}&utmipr={4}&utmiqt={5}&utmiva={6}", | ||
_utmt, | ||
_utmtid, | ||
_utmipc, | ||
_utmipn, | ||
_utmipr, | ||
_utmiqt, | ||
_utmiva); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.