3 . 12 . 15

AngularJS – Universal Analytics Checkpoints

If you’re using Google’s AngularJS or thinking about using AngularJS, you might want to consider these analytics checkpoints. This is purely a view of how to check analytics implementation, not a debate on the pros and cons of Angular, or why you should / shouldn’t use it.
Finally, this post assumes the reader knows what AngularJS is. This also assumes the reader is using Universal Analytics.

Checking Pageview Hits

  • On a traditional website, the analytics snippet has to be present on every single page, such that when pages load, analytics is able to send the pageview. This is defined in the final command line in the snippet:
    ga('send', 'pageview');
  • But SPAs (single page apps) do not reload. So analytics will only fire once, and only in the first instance. Therefore subsequent user journeys are lost.

Live Case Study

A live example of analytics only firing once despite having navigated to “other pages” can be found in, ironically, a website called Made With Angular, a website made in Angular about other websites made using Angular. This was observed during the time of writing.

On loading the homepage: this is the pageview, which is expected:

Then, when navigating to, the first pageview still persists:

From there navigation to but the first pageview remains:

The above shouldn’t be an issue if that is the intended reporting preference, however for those who intend to report on these urls seperately the solution is below:

Set Page Field

  • The fix  is to set the page field and then fire the pageview every time the “virtual page” is invoked. Using the scenario above, when navigating to
    the page can be set as:

    ga('set', {
      page: '/categories/business',
      title: 'Business'
    ga('send', 'pageview');
  • In the example above, I’ve used clean urls without the #. (More on that below)
  • Why not set the location field instead? Analytics recommends the location field should not be updated – inconsistencies can cause the current session to end abruptly and a new session to start. The analytics location field is defined by document.location, therefore this is where campaign params are processed.
  • Setting the page field should be sufficient. Universal Analytics’ single page app dev guidelines states: “The default tracker does not set the page field, but if you set it manually, that value gets used as the page path in reports, overriding the location field’s value.” Which is exactly what we want:clean-urls-analytics

Check Defaults

  • By default, AngularJS will route urls with a #.
  • And by default Universal Analytics page reports ignores anything after # anchor in a URL.
  • Therefore urls like this:


    will just report as: 


For single page websites that are built to look like it has separate pages, what this means is that analytics is ever only going to report the url without the #.

Clean URLs

  • Clean up  urls using the $location service. Chris Sevilleja wrote a fantastic post on this to pretti-fy your urls with the HTML5 History API.
  • But that only works for browsers that support HTML5.

Consider Users On Older Browsers

A fallback for browsers still on HTML4 may need to be considered. There is a wonderful resource on Github called history.js which gracefully provides support for HTML4 browsers (like, IE 9 and below).

  • The question is: is a HTML4 fallback needed, is this an added layer of unnecessary complication? How do we know if people will care?
  • The answer: look into analytics data and check browser reports. Check if older browsers are popular within the website’s user base.
  • There is the argument that if older browsers make up the overwhelming majority on your website, then AngularJS is perhaps not the most suitable framework for your website in the first place ;)

UTM Params

What if we don’t want to clean urls and insist on sending hash urls into analytics?

  • Hash urls can be also sent into analytics by firing a virtual pageview, triggered on hashchange or at the point detected where new content has been invoked like so:
    ga('set', {
      page: location.pathname +  + location.hash,
      title: 'Page Title'
    ga('send', 'pageview');
  • But be aware that when running campaigns, like an email or affiliate campaign, these will be interfere with UTM parameters and campaign tracking will not be accurate.
  • This is because a hash url like “/thispage/#about” that has UTM parameters will default to:

    remember, analytics ignores anything after the #.

  • To retain UTMs, when building campaign urls, place the hash right at the end, after the UTM params like:

Other Checks

  • URL consistency: there is a heavy reliance on firing virtual pageviews with Javascript heavy sites. Ensure the pageview urls are all consistent – analytics reports the same urls with and without trailing slashes or upper and lowercase versions as separate urls. You can use analytics filters to sort this, but it’s better to have everything consistent from the start.
  • In-content tabbed links versus actual pageviews: differentiate between in-content links (like tab#1, tab#2) and hash urls that you want to consider as seperate pages. Both can be pushed into analytics if you so wish however the former may be considered an interaction so should be sent as an event on that page whereas the latter should be considered a separate page white means a separate pageview hit is required. Sending an event is simple:
    ga('send', 'event', 'PDF', 'Download', 'Whitepaper Title');
  • Meta data logic: check that meta data such as canonicals, title, descriptions etc are dynamically added to the right corresponding “pages”.
  • Hashbang deprecated: Google has recently retired the hashbang (#!) method. There is no need to make urls ugli-er anymore. Consider the pre-render method below instead.
  • Do not block crawler access: allow crawlers like Googlebot to crawl your JS and CSS files. This is needed for Google to fetch and render pages effectively.
  • Pre-render: Consider pre-rendering your Javascript-heavy page with services like Prerender. It saves a static HTML version of your website on the fly and serves it to crawlers ensuring your website remains indexable.
  • Always, always test, re-test: Observe the analytics debugger logs and check that hits are being sent as expected.




Maximize business opportunity with data-driven decision making. Find out more about our data team.

Trent Y. is the Analytics & Conversion Director at twentysix. Analytics, usability and conversion strategies. Loves coffee, interested in how data and technology can positively impact our lives. “Learn fast, learn often.”

Share This: