Single Page Application (SPA) event tracking
Single Page Applications are all the rage, whether you're using Ember, React, Angular, Backbone, Meteor or something similar, more and more people are using these frameworks to build out their frontends.
While SPAs are great for numerous reasons that we won't get into here, they do require a little extra consideration in order to set up client-side tracking than with a traditional webpage.
- Tracking Emulated Pageviews
- What to do with code that lives in the .ready()?
- Moving events to the server-side
Tracking emulated pageviews
Your application should be updating the URL in the address bar to emulate traditional webpage navigation (if you aren't then please do that first!) but full page requests aren't made in most of these instances since the resources have already loaded. This means that the analytics.page() call in the traditional analytics.js snippet won't fire as a user navigates around your site.
This means that you should still place the snippet in the head of your site, but you should remove the .page() call and fire it whenever you're emulating a page load.
Our recommendation is to call analytics.page() from the same block of logic that is updating the view and the url path like below
// The new view has been called to render
If you want to track more than the page field, you can pass through more properties as shown in our docs here. Also, instead of hardcoding in the names of the page or even the page properties, you can use variables that grab that information.
In most SPA frameworks, you can actually automate this pretty easily by attaching the page call to the routing service.
Some additional gotchas with the page call, since the page doesn't reload, the referrer will likely always be the same as they were on the first page call where someone was directed to your site.
What to do with code that lives in the .ready()?
Analytics.js ships with a wonderful little function called analytics.ready(), documentation here, that lets you make calls to the native integrations that Segment loads for you before they actually initialize. For instance, this is where you could choose to load a live chat widget only for users that you haven't yet identified with a userId.
Since the code in your head will be executed only on initial page load or a refresh, you can still make calls to those native tools but you need to be aware that it won't be executed on each emulated page view. If you want to hide the chat tool on a given page, or only show it on a given page, you can use the same technique we advocated above by calling to that library as the page view is changing.
Moving event tracking to the server side
We here at Segment are big proponents of moving events to the server-side when at all possible. For one it's more reliable than the wild wild west that browser-tracking can sometimes be and for another, it will save your mobile users precious bandwidth. That being said, we find that the most successful tracking strategies leverage a combination of our client and server-side libraries.