Whether you build or maintain websites for your employer, clients or personal use, it is imperative to know how your users interact with your site(s). Compiling usage statistics is a integral part of site administration and well-informed admins are able to identify the primary areas of your site that users interact with as well as the areas of your site that are light on traffic. This can be a great tool for a number of reasons – it can help identify areas where development teams should concentrate their efforts for optimization and scalability; it can help your business owners determine enhancement priority based on popular features and features that aren’t meeting revenue requirements; and it can be used to gauge the effectiveness of marketing campaigns targeted at your site.

 

Google Analytics is probably the most widely known and easy to implement of all statistics providers. Google Analytics is a free service that  provides functionality useful for sites of all traffic levels. Below, I’ve included an ASP.NET server control that you can use to emit the HTML <head> tag JavaScript necessary to take advantage of Google Analytics. You can use the code below in your site or you can get the full .NET solution from my public C4SC GitHub repository.

 

GoogleAnalytics.cs

using System;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace C4SC.Common.WebControls.Google
{
    /// <summary>
    /// Emits Google Analytics JavaScript. Be sure to include this control on your site's MasterPage or a base page
    /// that will ensure this JavaScript gets emitted inside the HEAD element on every rendered page. 
    /// </summary>
    [DefaultProperty("AccountId")]
    [ToolboxData("<{0}:GoogleAnalytics runat=server></{0}:GoogleAnalytics>")]
    [ToolboxBitmap(typeof(GoogleAnalytics), @"GoogleAnalytics.bmp")]
    public class GoogleAnalytics : WebControl
    {
        private static string _googleAnalyticsJavaScript    = String.Empty;
        private static readonly object _lockObject            = new object();
        private const char Quote                            = '"';

        /// <summary>
        /// Google Analytics Account Id.
        /// </summary>
        public string AccountId
        {
            get { return ((string)ViewState["GoogleAnalyticsAccountId"]); }
            set { ViewState["GoogleAnalyticsAccountId"] = value; }
        }

        /// <summary>
        /// Renders control's begin HTML tag.
        /// </summary>
        /// <remarks>
        /// Pass-through call to ignore the default SPAN tag rendered by WebControl base class. 
        /// </remarks>
        /// <param name="writer"><see cref="HtmlTextWriter"/></param>
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
            return;
        }

        /// <summary>
        /// Renders control's end HTML tag.
        /// </summary>
        /// <remarks>
        /// Pass-through call to ignore the default SPAN tag rendered by WebControl base class.
        /// </remarks>
        /// <param name="writer"><see cref="HtmlTextWriter"/></param>
        public override void RenderEndTag(HtmlTextWriter writer)
        {
            return;
        }

        /// <summary>
        /// Renders control's contents.
        /// </summary>
        /// <param name="output"><see cref="HtmlTextWriter"/></param>
        protected override void RenderContents(HtmlTextWriter output)
        {
            output.Write(GetGoogleAnalyticsJavaScript());
        }
         
        /// <summary>
        /// Builds the Google Analytics JavaScript block.
        /// </summary>
        /// <returns>Google Analytics JavaScript block.</returns>
        protected string GetGoogleAnalyticsJavaScript()
        {
            if (_googleAnalyticsJavaScript.Length == 0)
            {
                StringBuilder bldr = new StringBuilder();

                bldr.AppendLine(@"<script type=" + Quote + "text/javascript" + Quote + ">");
                bldr.AppendLine(@"    var _gaq = _gaq || [];");
                bldr.AppendLine(@"    _gaq.push(['_setAccount', '" + AccountId + "']);");
                bldr.AppendLine(@"    _gaq.push(['_trackPageview']);");
                bldr.AppendLine(@"    (function() {");
                bldr.AppendLine(@"        var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;");
                bldr.AppendLine(@"        ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';");
                bldr.AppendLine(@"        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);");
                bldr.AppendLine(@"    })();");
                bldr.AppendLine(@"</script>");

                lock (_lockObject) { _googleAnalyticsJavaScript = bldr.ToString(); }
            }

            return _googleAnalyticsJavaScript;
        }
    }
}

Web.config <system.Web>

<pages>
    <controls>
        <add namespace="C4SC.Common.WebControls.Google" tagPrefix="c4sc"/>
    </controls>
</pages>

 

Site.master or AnyPage.aspx

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="SiteMasterPage" %>
<%@ Register Assembly="C4SC.Common.WebControls" TagPrefix="c4sc" Namespace="C4SC.Common.WebControls.Google"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Site's Master Page</title>
    <!-- JavaScript and CSS includes... -->
    <c4sc:GoogleAnalytics ID="GoogleAnalytics" runat="server" AccountId="YOUR GOOGLE ANALYTICS ID HERE"></c4sc:GoogleAnalytics>
</head>
<body>
    <form id="form1" runat="server">
        <!-- WebForm Contents -->
    </form>
</body>
</html>

 

A Couple of Extra Notes…

--You’ll notice that I simply return from the RenderBeginTag() and RenderEndTag() methods. I had to override these methods to return nothing or else the WebCotrol base class would wrap the emitted JavaScript in <span> HTML tags. I didn’t want anything wrapping the emitted <script> tags.

--Make sure you add the GoogleAnalytics server control to the HTML <head> tag of your site’s master page(s).

--This code in this post only emits the JavaScript that provide the basic Google Analytics tracking for a single top-level domain. JavaScript for a single domain (with multiple subdomains) or multiple top-level domains require a few more lines of JavaScript. I’ll eventually provide this functionality in my GitHub project along with public properties on the control for configuration.