Add Google Analytics to SharePoint modern pages

I had a client requirement to help them add Google Analytics to a modern SharePoint site. The objective was to track all SharePoint page views within the site.

The first thing that came to my mind was to look for a solution available online. As this is a fairly common scenario, I assumed it would be easy to find one for my requirements. But this was also what the client had tried to do before calling us, and they got stuck with some limitations on the solutions that they have found.
There are plenty of solutions available online for using Google Analytics with SharePoint modern pages. From complete implementations, to blog posts with the relevant code snippets. But I was also unable to find one that was able to track full and partial page loads. And so I decided to tweak one to work on the scenarios.

Base solution

The code below is based on the original solution provided by João Ferreira on this blog post. He uses an SPFx application customizer to load the Google Analytics script on every SharePoint page. When testing it, we found that it was not tracking all the page loads, so we updated it slightly.

Additionally, the this.context.application.navigatedEvent event currently has a known bug and fires twice. The workaround provided by jonthenerd worked fine in this scenario.
2019-03-01 update: The bug on the navigatedEvent seems to be fixed now, so I have updated the code below. I have also sent a PR with the changes to the original repository (by João Ferreira). You can find a full implementation project on his post.

Code

The following code uses the approach provided by Google Analytics for tracking Single Page Applications, like SharePoint pages that only load partially..

Hope you fins this useful, and feel free to leave comments or provide feedback.

export default class AnalyticsApplicationCustomizer
  extends BaseApplicationCustomizer<IAnalyticsApplicationCustomizerProperties> {

  private isInitialLoad = true;

  private getFreshCurrentPage(): string {
    return window.location.pathname + window.location.search;
  }


  private navigatedEvent(): void {

    let trackingID: string = this.properties.trackingID;
    if (!trackingID) {
      Log.info(LOG_SOURCE, `${strings.MissingID}`);
    } else {

      if (this.isInitialLoad) {
        this.initialNavigatedEvent(trackingID);
        this.isInitialLoad = false;

      }
      else {
        this.partialNavigatedEvent(trackingID);
      }
    }
  }

  private initialNavigatedEvent(trackingID: string): void {

    console.log("Tracking full page load...");

    var gtagScript = document.createElement("script");
    gtagScript.type = "text/javascript";
    gtagScript.src = `https://www.googletagmanager.com/gtag/js?id=${trackingID}`;
    gtagScript.async = true;
    document.head.appendChild(gtagScript);

    eval(`
          window.dataLayer = window.dataLayer || [];
          function gtag(){dataLayer.push(arguments);}
          gtag('js', new Date());
          gtag('config',  '${trackingID}');
        `);
  }

  private partialNavigatedEvent(trackingID: string): void {

    console.log("Tracking partial page load...");

    eval(`
        if(ga) {
          ga('create', '${trackingID}', 'auto');
          ga('set', 'page', '${this.getFreshCurrentPage()}');
          ga('send', 'pageview');
        }
        `);
  }

  @override
  public onInit(): Promise<void> {

    this.context.application.navigatedEvent.add(this, this.navigatedEvent);

    return Promise.resolve();
  }
}

16 Replies to “Add Google Analytics to SharePoint modern pages”

  1. Hi – Do you find that this is tracking pages reliably for you? I’ve been battling this situation for a while now and had arrived at pretty much the same code as you, but I still can’t get it behaving properly because of the double-post bug (which apparently is being fixed soon, but I’m not sure when). Using your code, the first page load tracks correctly, but clicking to a 2nd page doesn’t fire at all. Clicking to a 3rd page fires the code, but the page url it tracks is for the 2nd page. After a bit of clicking around it seems to somehow catch up with itself and it starts tracking the correct urls, but the behaviour for the first few page clicks is driving me mad!

    1. Hi, yes it was working reliability when I wrote the article, so I assume it is till the case. It was tracking full and partial page loads correctly, and only one page hit was being registered, not two. I have tested the double post bug last week and it was still happening… really hope that a fix for this is available soon.

    1. Hi Rod,

      Sorry the late reply…
      I have actually never checked this, but assume so as we are injecting a scrip tag on the page so we should be able to see it. You should also be able to see the script file being downloaded on the network tag within the browser dev tools.

  2. Hello Joel,

    I’ve tried the version above and the one up to date on the repository of Joao, but none of them allow me to track partial loads on my SharePoint sites, only initial loads are working.

    Are you aware of anything like that? I can’t see which folders and subfolders are consulted the most because the partialNavigatedEvent is not triggered.

    Thanks

    1. Hi Nicolas,
      Not sure I’m afraid. All was working fine at the time I posted the script, but haven’t tested it recently.
      I believe there has been some changes since then to this.context.application.navigatedEvent, so that may be a good starting point for investigating
      Thanks for your feedback

      1. Hi Joel,

        did you allready check if this is an issue for everyone.
        I am looking for reporting on different things: Are these options possible with the google analytics tool?

        1. # of visitors  (unique and repeat); where are they when they access the site (what
        geography)
        2. How many visits (unique and total)
        3. What days/times are most people visiting
        4. What content is most popular: Since we don’t have many documents on the site, we are
        really talking about the number of clicks on links or pages throughout the site, both
        individually and aggregate
        5. Perhaps time spent on site pages
        6. What devices they use to access the site
        7. Where did they come from (e.g. link from Yammer? Link from email? Etc)

        1. Hi Dimitri,

          I never went that far, so suggest you first check Google Analytics documentation. At a first glance, seems possible as I use Google Analytics for this blog and I think it gives me all those metrics.
          Please let me know the result if you have the change to give it a try.

  3. Hi Joel,
    I am trying to do only by webpart instead of extension. Is there will be a problem ? I just want to show visitor details for particular site

    1. Hi,
      Sorry for the late reply
      You should still use an extension, and deploy it to the desired site instead of global deployment.

  4. Hi Joel,

    I am using a code verification tool, “Veracode” on my solution.

    It is showing eval() as security threat and even MSDN article also says the same about eval().

    Is there any other way to trigger ga() functions other than eval() in SPFx.

    For example, below code is a security threat.
    eval(`
    window.dataLayer = window.dataLayer || [];
    function gtag(){dataLayer.push(arguments);}
    gtag(‘js’, new Date());
    gtag(‘config’, ‘${trackingID}’);
    `);

Leave a Reply

Your email address will not be published. Required fields are marked *