Tracking VueJS SPA user behaviour with Google Analytics

You don’t need a blowtorch to make a barbecue.

In the past I used to use the right tool for the right purpose. This led me to employ a lot of tools, and with most turning out to use subscription-based billing, increasing our costs much more that I would have hoped for. So, I adopted a new strategy:

Use as few tools as possible, but use them as much as possible.

When I got to the “How are users using our brand new web-app?” question, the obvious answer was to see how we can use Google Analytics. Their variety of tools and experience in tracking web usage felt impossible to ignore. To top it all off, Google is great with security and performance, and costs are near zero (at least for now).

But how do you track a Single Page Application built in VueJS with Google Analytics? For them, it’s all about page views, referrers and bounce-rate — not really suitable for what we have.

Enter Google Analytics Events

Google Analytics events tracking was pretty obvious, as any kind of interaction with the app was more or less an event.

However, how would we know on which page (or screen) the user triggered that event? One way was to name or categorize the events on the pages that they’re triggered on, but that felt unnatural and prone to issues later down the line.

So, one way was to simulate page views when the user was browsing from screen to screen. This meant that the initial tracking code had to specify that it was not to send a page-view request when the initial application was loaded in the user’s browser.

The important part above is the send_page_view: false bit. This causes the GA code not to send a page view when the app is loaded in the browser window. And we want this because we’re going to send view from our screen-rendering code.

For VueJS, since we’re using vue-router, all we needed to do to send page views when the user was browsing the app was to add an afterEach() event handler:

I saved the tracking ID into a global window attribute, so we could define it in one place and use it all around. This also helped set the corresponding tracking ID for development and production environment at deploy time, so that whenever we played around in the development, testing or staging deployments, metrics for production wouldn’t be affected.

There! Now we have page-views in our VueJS SPA.

Next, events. But how do we categorize events? How do we identify which events are more important than others? How do we track error messages that the user is getting, in the context of what a user is doing?

After a few days of brainstorming, the following event categories emerged:

  1. Engagement — Events where the user actually did something in the app: signed in, added a new monitor, updated their profile information, etc.
  2. Navigation — These are events that caused the web-app to navigate to another page: tapping the logo, sections in the sidebar menu, going back from a details page, etc.
  3. Interaction — These indicate user interaction with an element on the page, which doesn’t update any data in the backend. For example, the user expanded a section, toggled a checkbox or opened the sidebar menu.
  4. Experience — These are events that the user experienced, usually after something they did. An example ‘experience’ event is when the user received a validation error, or a pop-up question came up asking for confirmation. These don’t fall on any of the above categories and we’re sending them to Analytics mentioning that they’re non-interaction events.

Since these were going to be added all over the place in our code, we crafted a set of four helper mixin methods, to be easily used anywhere:

Because most of the events where navigation clicks on various links or buttons, we also have quick helper methods for these:

Now, if we need to track a navigation event, we could just do this in any Vue template like this:

<router-link to=”/dashboard” @click.native=”$root.gaClickCta(‘open_dashboard’)” />

Or in a method, with something like:

What I actually did was to first list all the events that I wanted to track for each screen, and then add them into the code. Having a list first helps answer the question, “What do I want to track?”

Screen View Events

Although I haven’t found much documentation on this subject, it seems Google Analytics has some support for tracking SPA by sending a special kind of event called ‘screen_view’. For me, it wasn’t clear where exactly I could see screen view information and what the difference was between page view and screen view, so I added the screen_view event along with the page view event, in the afterEach() event handler:

My purpose with this was to see in a few weeks or months if this brings valuable information, or if it is in any way better than the pseudo-page view events.


Having all this set in place brings great value in learning how users use our application. Google Analytics does a wonderful job at segmenting visitors and users. It is providing lots and lots of useful information such as geographic and technological statistics about visitors and users.

This type of information never replaces a good, healthy chat with the customers, but it does help identify what features or interface elements they’re using or not using, what devices are they using Monitive from and how much they engage with the app.

This is especially useful when deciding on what to remove from the app, which buttons or links aren’t visible enough, and what repetitive tasks they are performing, thereby allowing us to improve the interface and the whole user experience altogether.