Mobile Corner

Tracking Your Windows Phone App Analytics with VSO's Application Insights

Nick Randolph walks through adding analytics to your Windows Phone application using Application Insights for Visual Studio Online.

After publishing your first Windows Phone application to the Store, you'll probably wonder how that app's being used. Unfortunately, the Store itself only provides minimal information, such as the number of downloads. It's important to add telemetry code during an application's development, rather than trying to retrofit it later. Exactly what events you'll want to track will vary depending on your application, but you may want to start by recording when an application launches and terminates, when it's suspended and resumed, and perhaps recording which pages are viewed and for how long.

There are a number of different analytics tools available: Google Analytics, Flurry and Omniture are just a few. And Microsoft has recently added another: Application Insights for Visual Studio Online, which we'll examine today.

To get started with Application Insights for Visual Studio Online, you'll need to complete the following steps:

  1. A Visual Studio Online account. Visual Studio Online is Microsoft's Team Foundation Server product hosted in the cloud. Follow the links to "Get started for free" to sign in with your Microsoft Account (formerly Windows Live ID) and create your free Visual Studio Online account.
  2. Sign up to the Application Insights Preview. (Note that this service is in preview at the time of writing this article, so these instructions may change without notice.) Make sure you're signed into your Visual Studio Online account. On the right side of the main dashboard, there should be a link to "Try Application Insights." You'll need to request to be added to the waitlist. You'll receive an invitation code sometime in the future as they extend the reach of the preview program
  3. Create an Application Insights Application. From the main Application Insights dashboard, click the link in the top menu bar titled "Add Application." Answer the questions appropriately, based on the type of application you're building -- in this case, a Windows Phone application (at the time of writing, these steps don't include Windows Store applications, but you can follow the Windows Phone setup steps as they're common to both types of applications). You'll need to supply a name for the application you're creating, which for the purposes of this article will be "AnalyticsSample." While it probably makes sense to make this the same as the name of your Windows Phone project, there's no implied relationship, so you can specify any name that makes sense to you. During the creation process, you'll see instructions for getting started using the SDK. For the time being, ignore these as we'll step through these in detail (and at the time of writing, there were some known issues with those instructions).

To demonstrate how to use Application Insights, we'll create both a Windows Phone and Windows 8 application. As the two platforms are closely aligned, it makes sense to write as much code as possible that works across both platforms. For this, we'll be using a portable class library to share our ViewModel code. To add the necessary telemetry code to our application, we need to be able to log event information in both the Windows Store and Windows Phone projects, as well as in our portable class library.

We'll start by creating our three projects:

  • AnalyticsSample.WP: Windows Phone Application
  • AnalyticsSample.Win: Windows Store Application
  • AnalyticsSample.Shared: Portable Class Library

Both the Windows Phone and the Windows Store applications should reference the AnalyticsSample.Shared library. The Application Insights SDK can be accessed via NuGet by right-clicking on the Solution node in Solution Explorer and selecting "Manage NuGet Packages for Solution." Searching for "Application Insights Telemetry SDK" (including the quotes) will yield both Windows Phone and Windows Store versions of the SDK, as shown in Figure 1. Install both SDKs by clicking the Install button alongside the Windows Phone and Windows Store SDKs. Note that you'll only be able to install the SDK version into the corresponding project type (i.e., Windows Phone SDK can only be added to the Windows Phone application), which means the Portable Class Library AnalyticsSample.Shared won't have a reference to the SDK.

[Click on image for larger view.] Figure 1. Application Insights NuGet Packages

At this point, attempting to build either application may yield a compile error, stating that "Application Insights SDK for Windows Phone does not support the AnyCPU target platform." As the Application Insights SDK is implemented as a native library, it can't be referenced by a project set to target AnyCPU. Right-click on the Solution node in Solution Explorer and select Configuration Manager to change the Active solution platform to x86, as per Figure 2.

Use the x86 build configuration for debugging using the Windows Phone emulator; use the ARM build configuration for debugging on a real Windows Phone device and for submitting to the Windows Phone Store.

[Click on image for larger view.] Figure 2. Configuration Manager

Both Windows Store and Windows Phone applications should build successfully, but any attempt to reference any part of the Application Insights SDK will yield a build error. This is because the project references list hasn't updated to include the appropriate assemblies. For both Windows Phone and Windows Store projects, right-click the project node in Solution Explorer and select "Unload Project," then right-click the same project and select "Reload Project." The References list should now include the Microsoft.ApplicationInsights.Telemetry.WindowsStore assembly.

The first step in using the Application Insights SDK is to initiate a new session by calling the following code in the constructor for the core Application class (i.e., in App.xaml.cs):

ClientAnalyticsSession.Default.Start(
  "<application insights application key>");

Important: This line of code needs to go after the call to InitializeComponent() to ensure the application has been correctly initialized.

The Application Insights key for your application can be found in the online portal by selecting Administer Account (the cog icon in the top-right corner next to your account name), followed by the Keys & Download tab. Toward the bottom of the page is the instrumentation key required for both Windows Phone and Windows Store applications.

If you're simply interested in tracking when your application is used, all you need to do is start a new session in the Application constructor. Recorded sessions should appear in the Application Insights online portal after a short delay. Data is transmitted to the cloud by the Application Insights SDK when the application's launched or resumed. If you want to confirm that data's being sent, you can configure the Output window to display native debugging information: Double-click the Properties node for the Windows Phone application, followed by selecting the Debug tab. Under the Debugger Type section, change the UI Task dropdown to Native Only. When your application is run, you should see output similar to the following, confirming that data is being sent off to the Application Insights service:

Application Insights Telemetry: Data file [00130308840033330001] is successfully transmitted to Server.

For more information on what's being recorded during a session, you can use the Windows Phone Power Tools to inspect Isolated Storage. In the MS.CA folder, you'll find temporary files which are used to record session information in JSON.

In addition to simply knowing when an application is run, it's often useful to know what the user's doing within the application. Out of the box, Application Insights offers a number of static methods which can be called to log event, log page views and log time-based event information. For example, the OnNavigatedTo method in the code behind of a page can call LogEvent to indicate that the method had been called:

protected override void OnNavigatedTo(NavigationEventArgs e)
{
  base.OnNavigatedTo(e);

  ClientAnalyticsChannel.Default.LogEvent(
    "OnNavigatedTo on MainPage Completed");

}

This is a simple example of how event information can be logged using Application Insights. There are two issues with logging events in the code behind of a page: It means that the same code has to be repeated in both Windows Phone and Windows Store code; it also means that it's not possible to log events from within the shared logic in the portable class library.

Both these limitations can be overcome by implementing an interface-driven wrapper for the Application Insights SDK. Here's a brief set of steps to implement such a pattern:

  1. Create another portable class library called ApplicationInsights.Shared.
  2. Add the following two interfaces to this library:
    public interface IApplicationInsightsWrapper
    {
      void LogEvent(string eventName);
      void LogEvent(string eventName, 
        IDictionary<string, object> properties);
      void LogPageView(string pagePath);
      ITimedAnalyticsEvent StartTimedEvent(string eventName);
      ITimedAnalyticsEvent StartTimedEvent(
        string eventName, IDictionary<string, object> properties);
    }
    
    public interface ITimedAnalyticsEvent:IDisposable
    {
      string Name { get; }
      IDictionary<string, object> Properties { get; }
      void End();
      void Cancel();
    }
  3. Add the following Analytics class, which will be used to keep a reference to the IApplicationInsightsWrapper. Note that this class might not be necessary if you're using a dependency injection framework capable of instantiating and keeping a reference to the IApplicationInstightsWrapper implementation.
    public static class Analytics
    {
      public static IApplicationInsightsWrapper Default { get; set; }
    }
  4. Next, implement the IApplicationInsightsWrapper by creating a new Windows Phone class library, ApplicationInsights.WP, adding a reference to the ApplicationInsights.Shared project, then adding a class called ApplicationInsightsWrapper which implements this interface, as follows: public class ApplicationInsightsWrapper:
      IApplicationInsightsWrapper
    {
    
      public ApplicationInsightsWrapper (
        string applicationInsightsId)
      {
        ClientAnalyticsSession.Default.Start(applicationInsightsId);
      }
    
    
      public void LogEvent(string eventName)
      {
        ClientAnalyticsChannel.Default.LogEvent(eventName);
      }
    
      public void LogEvent(string eventName, 
        IDictionary<string, object> properties)
      {
        ClientAnalyticsChannel.Default.LogEvent(eventName, properties);
      }
    
    
      public void LogPageView(string pagePath)
      {
        ClientAnalyticsChannel.Default.LogPageView(pagePath);
      }
    
      public ITimedAnalyticsEvent StartTimedEvent(string eventName)
      {
        return new TimedAnalyticsEventWrapper(
          ClientAnalyticsChannel.Default.StartTimedEvent(eventName));
      }
    
      public ITimedAnalyticsEvent StartTimedEvent(string eventName,
        IDictionary<string, object> properties)
      {
        return new TimedAnalyticsEventWrapper(
          ClientAnalyticsChannel.Default.StartTimedEvent(
          eventName,properties));
      }
    }
  5. You'll also need a class called TimedAnalyticsEventWrapper, which as the name suggests wraps the TimeAnalyticsEvent object and implements the ITimedAnayticsEvent interface.
    public class TimedAnalyticsEventWrapper : ITimedAnalyticsEvent
    {
      public TimedAnalyticsEvent TimedEvent { get; set; }
    
      public TimedAnalyticsEventWrapper(
        TimedAnalyticsEvent timedAnalyticsEvent)
      {
        TimedEvent = timedAnalyticsEvent;
      }
    
    
      public string Name
      {
        get
        {
          return TimedEvent.Name;
        }
      }
    
      /// <summary>Properties of the timed analytics event 
      /// in which <key, value> pairs can be added.</summary>
      public IDictionary<string, object> Properties
      {
        get
        {
          return TimedEvent.Properties;
        }
      }
    
      public void Dispose()
      {
        TimedEvent.Dispose();
      }
    
      /// <summary>Ends the timed analytics event and 
      /// logs its total duration.</summary>
      public void End()
      {
        TimedEvent.End();
      }
    
      /// <summary>Cancels timed analytics event and 
      /// prevent data logging on End/Dispose.</summary>
      public void Cancel()
      {
        TimedEvent.Cancel();
      }
    }
  6. The ApplicationInsights.WP project will also need a reference to the Application Insights SDK NuGet package. After adding this reference, don't forget to unload and reload the project to ensure it builds successfully.
  7. Create a Windows Store class library, ApplicationInsights.Win, add a reference to the ApplicationInsights.Shared project, then add both ApplicationInsightsWrapper and TimedAnalyticsEventWrapper class by adding the file as a link (making sure both WP and Win implementations are identical). This project will also require a reference to the Application Insights SDK NuGet package.
  8. Add references to both ApplicationInsights.Shared and ApplicationInsights.WP to the Windows Phone application, AnalyticsSample.WP.
  9. Add references to both ApplicationInsights.Shared and ApplicationInsights.Win to the Windows Store application, AnalyticsSample.Win.
  10. Create an instance of the wrapper class in the App.xaml.cs immediately after the InitializeComponent method call in the constructor of the App class: Analytics.Default = new ApplicationInsightsWrapper( "<application insights application key>");
  11. The last step in this process is to add a reference to the ApplicationInsights.Shared project to the AnalyticsSample.Shared project. This allows you to invoke any of the Application Insight SDK logging events by calling the appropriate method on the IApplicationInsightsWrapper object. For example, the following MainViewModel class illustrates calling log methods as the user arrives and leaves the page:
    public class MainViewModel
    {
      public ITimedAnalyticsEvent PageTime { get; set; }
    
      public async Task Arrive()
      {
        ApplicationInsights.Shared.Analytics.
          Default.LogPageView("Main");
        ApplicationInsights.Shared.Analytics.
          Default.LogEvent("Arrived");
        PageTime = ApplicationInsights.Shared.Analytics.
          Default.StartTimedEvent("Main Page");
      }
    
      public async Task Leave()
      {
        PageTime.End();
        ApplicationInsights.Shared.Analytics.
          Default.LogEvent("Leaving");
      }
    
    }

After writing a lot of additional code, you now have the ability to invoke Application Insight SDK log events from anywhere within your application logic, whether it be in the code behind a page or nested deep within your view model logic. Of course, being able to log this information isn't much good without being able to view the generated event data. Figure 3 illustrates the graphical output displayed in the Application Insights online portal.

[Click on image for larger view.] Figure 3. Application Insights Dashboard

Across the top of the online portal are a number of tabs to drill into different areas. For Windows and Windows Phone applications, the main tab of interest is the Usage tab. On the left edge you can inspect the events logged by your application.

Getting application analytics isn't something you should leave until the end of a project, or worse, after you've already published your application. Most analytics tools are simple to get started with, as they now provide Windows Store and Windows Phone libraries. Application Insights for Visual Studio Online is a useful extension to the Visual Studio Online offering, providing analytics directly from your Visual Studio Online portal.

comments powered by Disqus

Featured

Subscribe on YouTube