tabs ↹ over ␣ ␣ ␣ spaces

by Jiří {x2} Činčura

Tracking requests to non-HTML resources with Google Analytics

5 May 2014 2 mins Google, Google Analytics

I wanted to ditch the PAD file on ID3 renamer’s website. It was maybe cool five years ago, but I don’t think it’s now. But I wanted at least some confidence that this file is really used sporadically. Not cutting out something in use.

First I thought I will add some logging into the method that generates this file (yep, it’s generated on request, I’m not writing it manually 😉) and later process the data. But that looked like unnecessary work especially because the site uses Google Analytics anyway. Only problem was how to push data to Google Analytics if the result is plain XML file and not an HTML page.

Some API must be there, was my feeling. And indeed it is. Some googling and Measurement Protocol Developer Guide or Measurement Protocol Parameter Reference respectively was what I needed. Simple HTTP POST endpoint to where you push URL encoded parameters. Sweet!

I quickly made a stupidly straightforward code to do what I needed. I only used parameters looking interesting for me, to at least, if lucky, little recognize the caller. In the document above you might find a lot of other parameters (even hit types).

static async Task<bool> SendPageviewRequestAsync(bool isNonInteractive, string trackingId, string documentLocation, string usersIpAddress, string userAgent, string documentReferrer, Guid? clientId = null)
{
	using (var client = new HttpClient())
	{
		using (var content = CreateContent(isNonInteractive, trackingId, documentLocation, usersIpAddress, userAgent, documentReferrer, clientId))
		{
			try
			{
				using (var responseMessage = await client.PostAsync("http://www.google-analytics.com/collect", content).ConfigureAwait(false))
				{
					return responseMessage.IsSuccessStatusCode;
				}
			}
			catch
			{
				return false;
			}
		}
	}
}

static FormUrlEncodedContent CreateContent(bool isNonInteractive, string trackingId, string documentLocation, string usersIpAddress, string userAgent, string documentReferrer, Guid? clientId = null)
{
	return new FormUrlEncodedContent(new Dictionary<string, string>()
	{
		{ "v", "1" },
		{ "t", "pageview" },
		{ "ni", isNonInteractive ? "1" : "0" },
		{ "tid", trackingId },
		{ "cid", (clientId ?? Guid.NewGuid()).ToString() },
		{ "dl", documentLocation },
		{ "uip", usersIpAddress },
		{ "ua", userAgent },
		{ "dr", documentReferrer },
	});
}

Getting the information from HTTP request is left for you as an exercise. 😉

Use it, change it – as you wish.

Profile Picture Jiří Činčura is .NET, C# and Firebird expert. He focuses on data and business layers, language constructs, parallelism, databases and performance. For almost two decades he contributes to open-source, i.e. FirebirdClient. He works as a senior software engineer for Microsoft. Frequent speaker and blogger at www.tabsoverspaces.com.