Skip to content

Single-Page Application (SPA)/Progressive Web App Tracking (PWA)

It's easy to start tracking your Single Page Application (SPA) or Progressive Web Application (PWA) using MVMCloud Analytics. In this guide, you will see two ways to do this.

Solution 1: Embed MVMCloud Analytics Tag Manager Container Code

If you use Tag Manager to implement the tracking of your website, so in your single page application, whenever there is a new page loaded, you will need your MVMCloud Analytics Tag to be triggered for the page view to be tracked.

To trigger your tag (which calls trackPageView), you can:

  1. In the MVMCloud Analytics Tag Manager container , navigate to Triggers and click Create new Trigger
  2. Select the History Change trigger in the User Engagement section ;
  3. Give your trigger a name, for example "History change";
  4. Click Create new trigger;
  5. Create another trigger, this time selecting Pageview as the trigger type;
  6. Select the Preview trigger in the Preview section;
  7. Give your trigger a name, for example "Page View";
  8. Click Create new trigger ;
  9. Then, navigate to Tags and click Create New Tag and select MVMCloud Analytics as the Tag type;
  10. Select your MVMCloud Analytics configuration variable and set the tracking type to Pageview ;
  11. Set the custom title to {{ PageTitle }} (Page Title);
  12. Set the custom URL to {{ PageOrigin }}/{{ PageHash }} if your SPA (Single-Page Application) or PWA (Progressive Web Application) has a URL to navigate to different pages. Otherwise, set it to {{ PageUrl }};
  13. In the Run this tag when any of the triggers are fired option , select the “History change” and “Page view” triggers that we created;
  14. Use Preview/Debug mode to test and ensure your triggers and tags are working as expected;
  15. After you confirm that the trigger and tag are working as expected, publish the changes to be implemented on your site.

How to trigger PageView, DOMReady and WindowLoad events from MVMCloud Analytics Tag Manager using javascript


In your Single Page App, if you are using the 'Pageview Trigger' to trigger a Pageview, you can trigger a Tag Manager Event {event: 'mvm.PageView'} by calling the following line in JavaScript: window._mvm.push({'event': 'mvm.PageView'});. This would also work similarly when you use the 'DOM Ready Trigger' (call window._mvm.push({'event': 'DOMReady'});) or when you use the 'Window Loaded Trigger' (call _mvm.push({'event': 'WindowLoad'});.

Solution 2: Embedding the Tracking Code manually

If you are not using Tag Manager, you will need to embed the MVMCloud Analytics JavaScript Tracking code to your website or single-page web application, just as you would on a classic website.

To find your codetrackment, go to “Administration” (gear icon) in the top right corner of your MVMCloud Analytics instance, click on “Tracking Code” and adjust it to your needs. You can find more information in our documentation JavaScript Tracking Client.

In the sections below you will learn how to configure the tracking of single page applications (SPAs). It addresses how tracking page views, reset variables, custom dimensions, update referring URLs, search for new content, and implement heatmap and session recording. A comprehensive example illustrates how these elements integrate in a SPA environment.

Tracking a New Page View

The challenge begins when you need to track a new page view. A single-page application is different from a usual website as there is no regular new page load and MVMCloud Analytics cannot detect automatically when a new page is viewed. This means you need to let MVMCloud Analytics know whenever the URL and the page title changes. You can do this using the methods setCustomUrl and setDocumentTitle like this:


window.addEventListener('hashchange', function() {
        _paq.push(['setCustomUrl', '/' + window.location.hash.substr(1)]);
        _paq.push(['setDocumentTitle', 'My New Title']);
        _paq.push(['trackPageView']);
})

Resetting previously set custom variables

If you have set any Custom Variables in scope “page”, you need to make sure to delete these custom variables again as they would be attributed to the new page view as well otherwise:

_paq.push(['deleteCustomVariables', 'page']);
_paq.push(['trackPageView']);

Note: we recommend you use Custom Dimensions instead of Custom Variables as they will be deprecated in the future.

Resetting previously set custom dimensions

Similar to Custom Variables, you also need to unset Custom Dimensions when changing the page as they would otherwise be tracked again.

_paq.push(['deleteCustomDimension', 1]);
_paq.push(['trackPageView']);

Updating the referrer

Depending on whether you want to track the previous page as a referrer for the new page view, you should update the referrer URL by setting it to the previous page URL:

_paq.push(['setReferrerUrl', previousPageUrl]);
_paq.push(['trackPageView']);

Informing MVMCloud Analytics about new content

When you show a new page, your single page DOM may also change. For example, you can replace parts of your page with new content loaded from your server via Ajax. This means you need to tell MVMCloud Analytics to scan the DOM for new content. We will now look at various types of content (videos and audio, forms, links and downloads, Content tracking).

Video and audio Tracking

If you use the Media Analytics feature to track your videos and audios, whenever a new page is displayed you need to call the following method:

_paq.push(['MediaAnalytics::scanForMedia', documentOrElement]);

When you don’t pass any parameter, it will scan the entire DOM for new media. Alternatively, you can pass an element to scan only a certain area of your website or app for new media.

Form tracking

If you use the Form Analytics feature to measure the performance of your online forms, whenever a new page is displayed you need to call the following method:

_paq.push(['FormAnalytics::scanForForms', documentOrElement]);

Where documentOrElement points either to document to re-scan the entire DOM (the default when no parameter is set) or you can pass an element to restrict the re-scan to a specific area.

A/B Testing

If you use the A/B Testing feature to test your experiments, whenever a new page is displayed you need to embed the js code again before tracking a new pageview as explained below:


window.addEventListener('pathchange', function() {
   var _paq = window._paq = window._paq || [];
   _paq.push(['setCustomUrl', window.location.pathname]);
   _paq.push(['setDocumentTitle', document.title]);
   _paq.push(['AbTesting::create', {
      name: 'theExperimentName',
      includedTargets: [{"attribute":"url","type":"starts_with","value":"http:\/\/www.example.org","inverted":"0"}],
      excludedTargets: [],
      variations: [
         {
            name: 'original',
            activate: function (event) {
               // usually nothing needs to be done here
            }
         },
         {
            name: 'blue',
            activate: function(event) {
               // eg $('#btn').attr('style', 'color: ' + this.name + ';');
            }
         }
      ]
   }]);
   _paq.push(['trackPageView']);
});

Supposing that you use the link tracking feature to measure outlinks and downloads, MVMCloud Analytics needs to re-scan the entire DOM for newly added links whenever your DOM changes. To make sure MVMCloud Analytics will track such links, call this method:

_paq.push(['enableLinkTracking']);

Content tracking

If you use the Content Tracking feature, whenever a new page is displayed and some parts of your DOM changes, you need to call this method:

_paq.push(['trackContentImpressionsWithinNode', documentOrElement]);

Where documentOrElement points either to document or an element similar to the other methods. MVMCloud Analytics will then scan the page for newly added content blocks.

Heatmap & Session Recording

To support single-page websites and web applications out of the box, Heatmap & Session Recording will automatically detect a new page view when you call the trackPageView method. This applies if you call trackPageView several times without an actual page reload. MVMCloud Analytics will stop the recording of any activities after each call of trackPageView and re-evaluate whether it should record activities for the new page based on the new URL.

If you have a single-page website and you use trackPageView for any other purposes than an actual page view, it is recommended to disable the default behaviour using this method and let Heatmap & Session Recording explicitly know when there is a new page view by calling the two methods disableAutoDetectNewPageView and setNewPageView.

If you're setting a Custom URL in the single-page website, you may need to use the matchTrackerUrl() in order to allow the MVMCloud Analytics tracker to correctly trigger Heatmaps and Session Recordings.

Measuring Single-Page Apps: Complete Example

In this example we show how everything works together assuming you want to track a new page whenever a hash changes:


var currentUrl = location.href;
window.addEventListener('hashchange', function() {
    _paq.push(['setReferrerUrl', currentUrl]);
     currentUrl = '/' + window.location.hash.substr(1);
    _paq.push(['setCustomUrl', currentUrl]);
    _paq.push(['setDocumentTitle', 'Meu Novo Título']);

    // remove all previously assigned custom variables
    _paq.push(['deleteCustomVariables', 'page']);
    _paq.push(['AbTesting::create', {
       name: 'theExperimentName',
       includedTargets: [{"attribute":"url","type":"starts_with","value":"http:\/\/www.example.org","inverted":"0"}],
       excludedTargets: [],
       variations: [
          {
             name: 'original',
             activate: function (event) {
                // usually nothing needs to be done here
             }
          },
          {
             name: 'blue',
             activate: function(event) {
                // ex: $('#btn').attr('style', 'color: ' + this.name + ';');
             }
          }
       ]
    }]);
    _paq.push(['trackPageView']);

    // make MVMCloud Analytics aware of newly added content
    var content = document.getElementById('content');
    _paq.push(['MediaAnalytics::scanForMedia', content]);
    _paq.push(['FormAnalytics::scanForForms', content]);
    _paq.push(['trackContentImpressionsWithinNode', content]);
    _paq.push(['enableLinkTracking']);
});