I hadn't blogged about this before, because the solution was really simple. From looking around the net a bit, though, I see that folks have really struggled with this with other RIA platforms. So read below to see how simple this was to do in Silverlight.
For the Carbon Calculator project, we had to integrate HitBox usage tracking into the application. Steve was in charge of that implementation and was able to get it out and working in fairly short order. This was pretty simple for us because:
- Steve's a smart guy
- I used the usercontrol-as-screen pattern (I spoke about this in my ReMIX 07 Boston session)
- Silverlight lets you call back to JavaScript
How we did it
HitBox, like many analytics packages, requires that you create some setup JavaScript code and then post (or get) to a URL on each page hit. Steve put all the normal setup code in the hosting page just as one normally would do with any normal HTML page.
The two things needed on the page side were a call to LoadHitBox() (function below) when the silverlight control is created, and then a callback for handling logging the page. Technically we could have reimplemented all or most of this directly in Silverlight using C#, but that was not necessary for this to work and work well.
Javascript code:
function LoadHitBox()
{
var control = document.getElementById("SilverlightControl");
control.Content.HitBoxHandler.OnLogPageName = OnLogPageNameHandler;
}
function OnLogPageNameHandler(sender, args)
{
try
{
var pagename = args.PageName;
_hbLink(pagename);
}
catch(e)
{
//eat it
}
}
The next piece required was to set up the callback inside Silverlight
C# code:
[Scriptable]
public class HitBoxEventArgs : EventArgs
{
private string _pageName;
public HitBoxEventArgs(string pageName)
{
_pageName = pageName;
}
[Scriptable]
public string PageName
{
get { return _pageName; }
set { _pageName = value; }
}
}
[Scriptable]
public class HitBox
{
private static HitBox _instance;
[Scriptable]
public event EventHandler OnLogPageName;
private HitBox()
{
}
public static void Initialize()
{
if (_instance == null)
{
_instance = new HitBox();
WebApplication.Current.RegisterScriptableObject("HitBoxHandler", _instance);
}
}
public static HitBox Current
{
get
{
return _instance;
}
}
public void LogPageToHitBox(string pageName)
{
try
{
if (OnLogPageName != null)
OnLogPageName(this, new HitBoxEventArgs(pageName));
}
catch {} //eat it.
}
}
Finally, the code to raise the event to do the page logging simply uses the screens type name as the page name. If that isn't sufficient (my type names were verbose and easy to understand) you could add a property to the base page class and simply use that value as the page name. This code was called from the Show() method of the page base class (the one from which all user control screens were derived)
C# Code
//this will invoke a javascript event that logs to hitbox
private void LogPageToHitbox()
{
//Get the name of this class it will be logged as the link
try
{
string pageName = this.GetType().Name;
HitBox.Current.LogPageToHitBox(pageName);
}
catch
{
//eat it
}
}
I'll write more on the "usercontrols as screens" approach in a future posting. For non-screen oriented apps, the hardest thing will be deciding exactly what you want to track. For us, it was pretty easy.
A similar approach can be used for most other javascript-friendly tracking clients.