Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS and Google Analytics

I am trying to dynamically change my GA tracking ID (UA-XXXXXXX-X) depending on which environment the page is being viewed on but I can't seem to find a truly "angular" way to do it. I am using Angulartics but I can't get the base GA code to run which is needed before Angulartics can do anything. If I just put the GA code at the bottom of the page it works as expected but that isn't very Angular like and it still does not allow me to dynamically set the GA ID.

I have tried creating a directive but the tracking code doesn't seem to be run when put inside a directive's controller. I have created a controller that gets the environment from a rest call and then assigns a GA code based on the environment returned but when I run the directive it runs to early and the GA code doesn't fire or it fires while the tracking ID is still undefined. I also tried putting the GA code into the directives template but for some reason the code doesn't fire at all when placed inside script tags inside the ngAnalytics.html template even though i can see it is being correctly added to the page once the dom is loaded. I am new to angular so I know there is a solution but I am not seeing it. My directive is below:

angular.module('ngAnalytics', [])
.directive('ngAnalytics', function( servicesSrvc) {
    return {
        restrict: 'A',
        templateUrl: 'js/directives/ngAnalytics.html',
        controller: ['$scope', function($scope) {
            $scope.trackingID;
            $scope.getEnvDetails = function() {
                var currentEnv = servicesSrvc.getEnv();
                var env;
                currentEnv.then(function(data) {
                    env = JSON.stringify(data.environment);
                    switch(env)
                {
                    case 'local':
                        $scope.trackingID = 'disabled'; // DEV
                        break;
                    case 'dev':
                        $scope.trackingID = 'UA-XXX-X'; // DEV
                        break;
                    ...
                        $scope.trackingID = 'UA-XXX-X'; // Default to dev
                }
                (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
                    (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
                    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
                })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
                ga('create', $scope.trackingID, { 'cookieDomain': 'none' }); // For localhost testing
                //ga('create', $scope.trackingID, 'test.com'); // For dev, qa, prod etc...
                //ga('send', 'pageview'); // MUST BE DISABLED when using Angulartics
            });
        }

    }],
    link: function(scope, iElement, iAttrs, ctrl) {

    }
}
});
like image 834
RAC Avatar asked Dec 26 '13 22:12

RAC


People also ask

How does Google Analytics integrate with AngularJS?

Include the Google Analytics script in your Angular App This should go in the head of your root page (usually index. html) just before the closing </head> tag, it adds the 'ga' object to the window object and dynamically loads the base google analytics script without the call to ga('create', ...).

Does Google still support AngularJS?

AngularJS support has officially ended as of January 2022.

Does Google Analytics use JavaScript?

The Analytics tag is a snippet of JavaScript that collects and sends data to Analytics from a website. You can add the Analytics tag directly to the HTML of each page on your site, or indirectly using a tag management system such as Google Tag Manager.

Is Angular dropped by Google?

If it's efficient for now, there will be no guarantee for later. The Google team stopped supporting AngularJS after the 31st of December, 2021.


1 Answers

I might be misunderstanding your issue. It sounds like a general problem of directive architecture. Is something like this what you're looking for? Live demo (click).

<div analytics="trackingId"></div>

JavaScript:

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope) {
  //set this however you want, the directive doesn't care - or you can move this into the directive if you want
  //$scope.trackingId = 'UA-XXX-X';
  $scope.trackingId = 'disabled';
});

app.directive('analytics', function() {
  return {
    restrict: 'A',
    scope: {
      id: '=analytics'
    },
    link: function(scope, iElement, iAttrs) {
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      scope.$watch('id', function(newId, oldId) {
        if (newId) {
          console.log(newId);
          ga('create', scope.id, { 'cookieDomain': 'none' });
        }
      });
    }
  };
});

The important part here is:

scope.$watch('id', function(newId, oldId) {
  if (newId) {
    ga('create', scope.id, { 'cookieDomain': 'none' });
  }
});

which is saying to run the function only if there is a value for scope.id and the function will run again if the value is set or changed. I'm not sure what you're doing with servicesSrvc, but you could use that service to set scope.id from the controller or in the directive itself, either way, and if you've already setup the $watch, the function will run when you determine the value for scope.id. My answer is based on your comment that the function would run when the value was undefined. This is how you avoid that.

Update

Since you're still having issues understand the process, I have created another demo with some console.logs to guide you. Demo here (click).

var app = angular.module('myApp', []);

app.factory('myService', function($q, $timeout) {
  var myService = {
    getId: function() {
      var deferred = $q.defer();

      console.log('getting id');
      $timeout(function() {
        //deferred.resolve('UA-XXX-X');
        deferred.resolve('disabled');
      }, 2000);

      return deferred.promise;
    }
  };
  return myService;
});

app.directive('analytics', function(myService) {
  return {
    restrict: 'A',
    link: function(scope, iElement, iAttrs) {
      (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
      })(window,document,'script','//www.google-analytics.com/analytics.js','ga');

      var id;
      scope.$watch(
        function() {
          return id; 
        }, 
        function(newId, oldId) {
          if (newId) {
            console.log('watch is calling function');
            ga('create', newId, { 'cookieDomain': 'none' });
          }
        }
      );

      myService.getId().then(function(response) {
        id = response;
        console.log('id set to ' +response);
      });
    }
  };
});
like image 84
m59 Avatar answered Sep 27 '22 18:09

m59