Skip to content

Instantly share code, notes, and snippets.

@LucGosso
Last active June 18, 2018 07:04
Show Gist options
  • Save LucGosso/d74e8299bbcc2084087f81c198c391d6 to your computer and use it in GitHub Desktop.
Save LucGosso/d74e8299bbcc2084087f81c198c391d6 to your computer and use it in GitHub Desktop.
Google Analytics Service v3 C# .netframework examples with Episerver
using EPiServer.Core;
using EPiServer.Framework.Cache;
using EPiServer.ServiceLocation;
using Google.Apis.Analytics.v3;
using Google.Apis.Analytics.v3.Data;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
namespace Gosso.Web.Business.Services
{
[ServiceConfiguration(typeof(IGoogleAnalyticsService), Lifecycle = ServiceInstanceScope.Singleton)]
public class GoogleAnalyticsService: IGoogleAnalyticsService
{
private readonly ISynchronizedObjectInstanceCache _cache;
public GoogleAnalyticsService(ISynchronizedObjectInstanceCache cache)
{
_cache = cache;
GetGoogleAnalyticDaysMostPopular = 15;
}
internal readonly string Key = "itemviewsGA";
internal void CachePageItemsOfType(Dictionary<Guid, PageItemViews> pageitems, string cacheKey)
{
var cache = ServiceLocator.Current.GetInstance<ISynchronizedObjectInstanceCache>();
_cache.Remove(cacheKey);
_cache.Insert(cacheKey, pageitems, CacheEvictionPolicy.Empty);
}
public Dictionary<Guid, PageItemViews> GetItemViewsfromAnalytics(int typeid = 0, bool useCache = true)
{
var cache = ServiceLocator.Current.GetInstance<ISynchronizedObjectInstanceCache>();
var pageItemViews = cache.Get(Key + typeid) as Dictionary<Guid, PageItemViews>;
if (pageItemViews == null || !useCache)
{
var service = GetService();
var request = GetRequest(service, typeid);
pageItemViews = Execute(request);
CachePageItemsOfType(pageItemViews, Key + typeid);
}
return pageItemViews;
}
public IEnumerable<PageData> FilterItemsSortByMostPopular(Dictionary<Guid, PageItemViews> pagesViews, IEnumerable<PageData> articles, string firstSegmentUrl = null)
{
if (pagesViews != null)
{
var pageViewSorted = from f in pagesViews
orderby f.Value.PageViews descending
select f;
if (!string.IsNullOrEmpty(firstSegmentUrl))
{
//sort and filter
pageViewSorted = from f in pageViewSorted
where f.Value.CategoryName == firstSegmentUrl
orderby f.Value.PageViews descending
select f;
}
//match and join
var orderedByIdList = from i in pageViewSorted
join p in articles
on i.Key equals p.ContentGuid
select p;
return orderedByIdList.ToList();
}
return null;
}
private AnalyticsService GetService()
{
// Google Analytics API Service Account Authentication
// found in developer console under APIs & auth / Credentials
var keyFilePath = System.Web.Hosting.HostingEnvironment.MapPath(GetGoogleAnalyticsKeyFilePath) + string.Empty;
// These are the scopes of permissions you need. It is best to request only what you need and not all of them
string[] scopes = new string[] { AnalyticsService.Scope.Analytics }; // View your Google Analytics data
GoogleCredential credential;
using (var stream = new FileStream(keyFilePath, FileMode.Open, FileAccess.Read))
{
credential = GoogleCredential.FromStream(stream)
.CreateScoped(scopes);
}
// Create the Analytics service.
return new AnalyticsService(new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "MyApp",
});
}
private DataResource.GaResource.GetRequest GetRequest(AnalyticsService service, int typeid)
{
//format the profile id
var profileId = GetGoogleAnalyticsProfileId;
if (!profileId.Contains("ga:"))
profileId = $"ga:{profileId}";
var startDate = DateTime.Now.AddDays(-GetGoogleAnalyticDaysMostPopular);
var endDate = DateTime.Now;
var request = service.Data.Ga.Get(profileId, startDate.ToString("yyyy-MM-dd"), endDate.ToString("yyyy-MM-dd"), "ga:pageviews");
request.Dimensions = "ga:pageTitle,ga:dimension1,ga:dimension2,ga:pagepathlevel1,ga:pagepathlevel2,ga:pagepathlevel3,ga:pagepathlevel4";
if (typeid>0)
request.Filters = "ga:dimension2=="+typeid;
return request;
}
private Dictionary<Guid, PageItemViews> Execute(DataResource.GaResource.GetRequest request)
{
// Retrieve data, performing paging if necessary.
var metrics = new Dictionary<Guid, PageItemViews>();
GaData response = null;
do
{
var startIndex = 1;
if (!string.IsNullOrEmpty(response?.NextLink))
{
var uri = new Uri(response.NextLink);
var paramerters = uri.Query.Split('&');
var s = paramerters.First(i => i.Contains("start-index")).Split('=')[1];
startIndex = int.Parse(s);
}
request.StartIndex = startIndex;
response = request.Execute();
ProcessData(response, metrics);
} while (!string.IsNullOrEmpty(response.NextLink));
return metrics;
}
private void ProcessData(GaData response, IDictionary<Guid, PageItemViews> metrics)
{
//var pageTitleIndex = 0;
var pageViewsIndex = 0;
var epiPageguidIndex = 0;
var epiPagePathLevel1Index = 0;
var epiPagePathLevel2Index = 0;
// Find associated columns
for (var index = 0; index < response.ColumnHeaders.Count; index++)
{
var header = response.ColumnHeaders[index];
if (string.Equals(header.Name, "ga:pageviews", StringComparison.OrdinalIgnoreCase))
pageViewsIndex = index;
else if (string.Equals(header.Name, "ga:dimension1", StringComparison.OrdinalIgnoreCase))
epiPageguidIndex = index;
else if (string.Equals(header.Name, "ga:pagepathlevel1", StringComparison.OrdinalIgnoreCase))
epiPagePathLevel1Index = index;
else if (string.Equals(header.Name, "ga:pagepathlevel2", StringComparison.OrdinalIgnoreCase))
epiPagePathLevel2Index = index;
}
foreach (var row in response.Rows)
{
var editpage = row[epiPagePathLevel2Index];
if (editpage.ToLower() == "/cms/")
continue;
// Try to get the item id from the page title
var epiPageguid = row[epiPageguidIndex];
Guid itemId;
if (!Guid.TryParse(epiPageguid.Trim(), out itemId))
continue;
// Get page views
int pageViews;
if (!int.TryParse(row[pageViewsIndex], out pageViews))
pageViews = 0;
var categoryName = "";
//if (!row[epiPagePathLevel1Index].IsNullOrEmpty())//.IsNotNullOrEmpty())
if (!string.IsNullOrEmpty(row[epiPagePathLevel1Index]))
categoryName = row[epiPagePathLevel1Index].Trim();
if (!metrics.ContainsKey(itemId))
{
categoryName = categoryName.TrimEnd('/').TrimStart('/');
metrics.Add(itemId, new PageItemViews { PageViews = pageViews, CategoryName = categoryName });
}
else
{
var entry = metrics[itemId];
entry.PageViews += pageViews;
}
}
}
private string GetGoogleAnalyticsProfileId => ConfigurationManager.AppSettings["GoogleAnalyticsProfileId"];
private string GetGoogleAnalyticsKeyFilePath => ConfigurationManager.AppSettings["GoogleAnalyticsKeyFilePath"];
private int GetGoogleAnalyticDaysMostPopular
{
get;
set;
}
}
public class PageItemViews
{
public int PageViews { get; internal set; }
public string CategoryName { get; internal set; }
}
}
using EPiServer.Core;
using System;
using System.Collections.Generic;
namespace Gosso.Web.Business.Services
{
public interface IGoogleAnalyticsService
{
Dictionary<Guid, PageItemViews> GetItemViewsfromAnalytics(int typeid= 0, bool useCache = true);
IEnumerable<PageData> FilterItemsSortByMostPopular(Dictionary<Guid, PageItemViews> pagesViews, IEnumerable<PageData> articles, string inspiration = null);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment