Azure App Insights is fantastic to help understand how your site or app is being used, and I’ll spend more time on this in future articles. For now, let’s start with a simple case – you want to know how many users are hitting your SharePoint site, which pages are the most popular, which countries the users are based in and so on. We can add page tracking to all pages in a modern SharePoint site (where the master page cannot be customized to add the script) by using an SPFx Application Customizer – previously, script on modern pages was a problem but it is is easily possible now. Of course, the same approach can be used to add Google Analytics or other similar tracking scripts. However, whatever script you’re adding you should consider that:
- If your site has classic SharePoint pages too, an SPFx App Customizer will not cover these – you’ll need a separate approach for that, such as using a Custom Action to add the script there. (N.B. this is mainly a concern only for publishing sites or older team sites – Office 365 Group sites, modern team sites and communication sites only have modern pages.)
- Any script added with a SPFx App Customizer will appear on system pages too, such as list/library pages or the Site Contents page. That can be useful so you can see which libraries are getting visited the most, but you might decide only true pages are useful, and add a couple of lines of code to filter out these pages – up to you.
Regardless of which page tracking system you use, to get this added to modern SharePoint pages the starting point is always to create an SPFx Application Customizer. If you need a getting started guide, I wrote about these in Use an SPFx Application Customizer to add JavaScript (e.g. header) to every page in a site – in this post I’ll focus on the specific code snippets to add Google Analytics or Azure App Insights page tracking, and then talk a bit more about App Insights.
Integrating Google Analytics
OK, let’s get this one out of the way first. For GA, you just need to add the script reference to the page – and since Google give you a block of JavaScript to add, the classic way of dynamically adding some script works just fine (as opposed to using the SPFx module loader which can be used with external scripts).
It's OK to do this in the onInit() method of your customizer because Google's code specifies that the script should be loaded asynchronously - so the browser won't delay loading the page just for the analytics. Not that choosing the Render() method of an SPFX App Customizer instead would make a huge difference anyway, but in any case, onInit() works just fine for this.
Integrating App Insights
App Insights comes with an SDK with various objects and methods (both client-side and server-side SDKs are available) - arguably this makes it even easier to add than Google Analytics. For a client-side web application such as SPFx, there’s an npm package (applicationinsights-js) so once your SPFx Application Customizer is created you can get started with:
npm i applicationinsights-js --save
At the top of your code, you’ll then need to import the App Insights module to use it:
import {AppInsights} from "applicationinsights-js";
Just like with Google Analytics, one of the other first steps is to ensure you have the service set-up. In this case, you need an Azure subscription and an App Insights resource - this will provide a tracking ID to use in your code:
An App Insights resource will be automatically created for any Azure web apps you have in your subscription (e.g. you might have some Office 365 apps or provider-hosted SharePoint add-ins there), but if none of those are appropriate you should create a new instance. Once you have the instrumentation key, the code you need is this:
The code shown above won’t include the App Insights JS into your bundle – the AppInsights.downloadAndSetup()
method just references Microsoft’s JS on their CDN. The core method to track a page view is simply:
AppInsights.trackPageView();
Your choices now with an Application Customizer are to test it in debug mode by adding parameters to the URL of a modern page, or package it for real deployment as an app package and add to your side (my previous article details both of these approaches). Once your code is executing, you’ll see results over in the Azure portal for any users hitting pages which run that line of code, and you can now track page load performance and other things. Just like other analytics software, various details about the user (location, browser, device etc.) will be recorded:
However, things get more interesting when we help out by changing our code to pass better data as the request is tracked. The other overload which can be used is:
So, you might choose to log some useful info about the page request:
- User login
- User display name
- If user is external
In particular we can use the ‘dimensions’ parameter to pass this kind of data. In SPFx, that code would look like:
Be careful storing user Personally Identifiable Information (PII) of course! I use it purely as an example of what can be done - but in real-life, you might need to store some kind of user token which doesn't actually allow identification of an individual.
But what about other forms of user information? By also fetching some data from the user's Office 365/SharePoint user profile, you could answer things like:
- Which division/department are most of my users from?
- Which region are most of my users from?
- How many directors/managers are accessing the site/app?
And lots of other possibilities too no doubt. Unfortunately you lose the page duration timings with the more detailed overload, unless you do some custom work to put it back – specifically, writing some code to record timing of browser events, and then using the final parameter in the overload above. If you do this, be sure to use the browser events (e.g. the load event) rather than a simple stopwatch, as your code executing in the SPFx App Customizer is only *part* of the full page load of course.
But now I have my page views tracked, and I can do some nice analysis in the Azure portal. I can create some charts in Metrics Explorer (and some charts and tables *are* generated automatically), but the Analytics tool is even more powerful. This definitely isn’t an an end-user/site owner tool, however, as a technical person I can do some querying using an easy syntax with Intellisense-style auto-complete:
(N.B. Those results include page load durations because they used the simple overload).
When you include custom information as part of your call to trackPageView(), by default this comes out in a “customDimensions” column as JSON:
..but that’s not much good if you want to sort/filter on it. You can use the “extend” keyword in an App Insights query to get around this – so to unfold the 3 custom bits of data we logged earlier, we can use:
pageViews | where url !contains "workbench" | extend userLogin = tostring(customDimensions.userLogin), userDisplayName = tostring(customDimensions.userDisplayName), isExternal = tostring(customDimensions.isExternalGuest)
..and now we get that data in individual columns:
You can now play with that data as much as you like.
So overall, adding page tracking is relatively simple and you can work out the best way to analyze your data as you go. The important thing is to get it captured in the first place, either using the default call to trackPageView() or the more advanced one with custom data.
App Insights data retention
At this point it’s probably worth remembering that App Insights only retains data for 90 days, so that’s the longest period you can analyze in a single query. However, if you need longer you can set up Continuous Export to copy your data out (to Azure BLOB storage) and store it forever. Working with it becomes slightly different, but there are details on that page.
Going beyond page tracking
I mention page tracking here because it’s a relatively simple case and combines well with an SPFx Application Customizer. However, I think other use cases for App Insights are perhaps more interesting. What I *really* think is valuable is the idea of dropping AppInsights.TrackEvent() statements through your code, whether it’s an SPFx web part, a custom web API, an Office 365 app, or a provider-hosted SharePoint Add-in (e.g. an MVC site). I’ll talk about this in a future post, but I like the idea of scenarios such as:
- Server side applications (Office 365/SharePoint Add-in)
- How many app launches are happening? By who/where?
- What is happening within the app (e.g. which buttons are being clicked/what functionality is being used)?
- SPFx/Graph
- How many executions is our web part getting per day?
- How long do my web parts take to execute on the client side?
- How long are my async calls taking (e.g. to the Graph)? How different are they for users around the world?
- Provisioning code
- How many sites are we creating per day/week/month?
- How many times do we hit an issue during provisioning?
- How long does provisioning take?
- General
- How many times are we showing an error message to a user?
Of course, there are a million things that could be nice to track once you start to think about it. I’ll talk more about tracking events in the next article.