使用AngularJS跟踪Google Analytics页面浏览情况

223

我正在使用AngularJS作为前端搭建一个新的应用程序。客户端的所有内容都是通过HTML5 pushstate完成的,我想要能够在Google Analytics中跟踪我的页面浏览量。


尝试使用 angulartics http://luisfarzati.github.io/angulartics/ - David
2
angulartics已经被弃用,请使用angular-google-analytics - webdev5
6
有新版本的Angulartics发布了。请访问http://angulartics.github.io/尝试一下。 - Devner
21个回答

241

如果你在你的Angular应用中使用了ng-view,你可以监听$viewContentLoaded事件,并向Google Analytics推送跟踪事件。

假设你已经在主要的index.html文件中设置了跟踪代码为名为var _gaq,并且MyCtrl是你在ng-controller指令中定义的名称。

function MyCtrl($scope, $location, $window) {
  $scope.$on('$viewContentLoaded', function(event) {
    $window._gaq.push(['_trackPageView', $location.url()]);
  });
}

更新:对于新版本的Google Analytics,请使用此代码

function MyCtrl($scope, $location, $window) {
  $scope.$on('$viewContentLoaded', function(event) {
    $window.ga('send', 'pageview', { page: $location.url() });
  });
}

12
对于这个问题,应该使用 _trackPageview 而不是 _trackPageView...我曾经费了10分钟来考虑这个问题 :) - sajal
128
我会使用 $rootScope.$on('$routeChangeSuccess', ...) - bearfriend
5
嗯,虽然已经有一段时间了,但只是从我回答和评论中的一瞥来看,似乎将其应用于 $rootScope 将保证它不会被其他事件或DOM更改所删除,并且使用 routeChangeSuccess 将在每次位置栏更改时触发,而不仅仅是每次更改视图源模板时。这讲得通吗? - bearfriend
5
在$routeChangeSuccess事件中,你可能不知道页面的标题(例如,它可能在控制器中处理来自RESTful服务的数据后设置)。这种情况下,Google Analytics将仅跟踪页面的URL和先前页面的标题。请注意,本文只是翻译,没有任何解释或其他信息。 - Konstantin Tarkus
43
如果您正在使用 GA 新脚本,请改为 $window.ga('send', 'pageview', { page: $location.path() });,而不是 $window._gaq... 的部分。此外,您可能需要从原始的 GA 代码中删除 ga('send', 'pageview');,以防止在首次进入页面时出现重复。 - CWSpear
显示剩余10条评论

58

AngularJS中,当一个新视图被加载时,Google Analytics不会将其视为新的页面加载。幸运的是,有一种方法可以手动告诉GA将URL记录为新的页面视图。

_gaq.push(['_trackPageview', '<url>']);可以完成此任务,但如何将其绑定到AngularJS?

这里有一个可以使用的服务:

(function(angular) { 

  angular.module('analytics', ['ng']).service('analytics', [
    '$rootScope', '$window', '$location', function($rootScope, $window, $location) {
      var track = function() {
        $window._gaq.push(['_trackPageview', $location.path()]);
      };
      $rootScope.$on('$viewContentLoaded', track);
    }
  ]);

}(window.angular));

当您定义 Angular 模块时,可以像这样包含分析模块:

angular.module('myappname', ['analytics']);

更新:

你应该使用新的Universal Google Analytics跟踪代码:

$window.ga('send', 'pageview', {page: $location.url()});

6
需要注意的另一件事是,您需要在某个地方包含“分析”服务。我在app.run中完成了我的部分。 - Nix
这需要包含在每个模块中,还是只需要在初始应用程序中? - designermonkey
2
@Designermonkey 如果您只在主应用程序模块中包含它,它应该可以工作。但是,如果您有一个完全独立的模块,不需要主模块,则可能需要再次包含它。干杯! - Haralan Dobrev
如果您正在使用服务,应该使用“this”关键字定义函数:[来源](http://tylermcginnis.com/angularjs-factory-vs-service-vs-provider/#comment-20762)。例如,在服务中,它将是`this.track = function($window.ga('send', 'pageview', {page: $location.url()}); 这将允许您在**app.run()**函数中使用googleAnalytics.track();` - zcoon

49
app.run(function ($rootScope, $location) {
    $rootScope.$on('$routeChangeSuccess', function(){
        ga('send', 'pageview', $location.path());
    });
});

9
注意:如果您使用最小化/编译,您需要指定参数名称: app.run([" $rootScope","$location",function(... - dplass
如果您不想在每个控制器中包含GA代码,那么这个解决方案非常优秀。 - brz
1
如果你有异步代码动态更改标题,那就不太好了,否则它很棒。 - Johan

40

仅需简单补充。如果你正在使用新版analytics.js,则:

var track = function() {     
 ga('send', 'pageview', {'page': $location.path()});                
};

此外,一个提示是 Google Analytics 不会在本地主机上触发。因此,如果您在本地主机上进行测试,请使用以下内容而不是默认创建(完整文档)。

ga('create', 'UA-XXXX-Y', {'cookieDomain': 'none'});

哦,谢谢。我一直在遇到奇怪的错误,然后发现我的代码片段里甚至没有_gaq,呵呵。谷歌真是傻瓜:更新他们的代码和所有这些!哈哈。 - CWSpear
3
请确保使用 $window 来访问窗口(在 Angular 中,仅使用 ga 很可能是 undefined)。另外,您可能希望从原始的 GA 代码中移除 ga('send', 'pageview');,以防止在首次着陆页面时产生重复。 - CWSpear
6
使用ui-router,您可以像这样发送页面视图:$rootScope.$on('$stateChangeSuccess', function (event, toState, toParams, fromState, fromParams) { ga('send', 'pageview', { 'page': $location.path(), 'title': toState.name }); }); - pherris
2
补充一下:如果您的应用程序中使用了搜索参数,您可以使用$location.url()来跟踪它们。 - Ade
2
我点赞了这个答案,因为使用.path()比使用.url()更好,因为通常你想要排除查询字符串参数。请参见:Google Analytics配置错误#2:查询字符串变量 - frodo2975

11

我创建了一个服务和筛选器,可以帮助你们解决这个问题,并且如果你选择在将来添加其他提供商,也可能有所帮助。

请查看https://github.com/mgonto/angularytics,并让我知道这对你有何帮助。


10

对我来说,将wynnwu和dpineda的答案合并起来是有效的。

angular.module('app', [])
  .run(['$rootScope', '$location', '$window',
    function($rootScope, $location, $window) {
      $rootScope.$on('$routeChangeSuccess',
        function(event) {
          if (!$window.ga) {
            return;
          }
          $window.ga('send', 'pageview', {
            page: $location.path()
          });
        });
    }
  ]);

将第三个参数设置为一个对象(而不仅仅是$location.path()),并使用$routeChangeSuccess而不是$stateChangeSuccess就解决了问题。

希望这可以帮到你。


7

我添加了一个修复程序,以更好地报告路径。 现在,如果您有路由/account/:accountId 即路径为http://somesite.com/account/123 它现在将把路径报告为/account?accountId=123 - SnIcK
@IBootstrap,将路由参数放在查询字符串中有什么好处? - Pavel Nikolov
@IBootstrap 我有同样的问题,将路由参数放在查询字符串中有什么好处? - Dzung Nguyen
1
并非所有的路由都是不同的页面,GA将每个路由视为不同的页面。通过将路由转换为查询字符串,您可以选择忽略查询字符串的某些部分。 - SnIcK

5

我发现 gtag() 函数可用,而不是 ga() 函数。

在 index.html 文件中,在 <head> 部分中:

<script async src="https://www.googletagmanager.com/gtag/js?id=TrackingId"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());
  gtag('config', 'TrackingId');
</script>

在AngularJS代码中:
app.run(function ($rootScope, $location) {
  $rootScope.$on('$routeChangeSuccess', function() {
    gtag('config', 'TrackingId', {'page_path': $location.path()});
  });
});

TrackingId替换为您自己的跟踪ID。


5
在你的index.html中,复制并粘贴ga代码片段,但删除ga('send', 'pageview');这一行。
<!-- Google Analytics: change UA-XXXXX-X to be your site's ID -->
<script>
  (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', 'UA-XXXXXXXX-X');
</script>

我希望将其放在一个独立的工厂文件中my-google-analytics.js并进行自我注入:

angular.module('myApp')
  .factory('myGoogleAnalytics', [
    '$rootScope', '$window', '$location', 
    function ($rootScope, $window, $location) {

      var myGoogleAnalytics = {};

      /**
       * Set the page to the current location path
       * and then send a pageview to log path change.
       */
      myGoogleAnalytics.sendPageview = function() {
        if ($window.ga) {
          $window.ga('set', 'page', $location.path());
          $window.ga('send', 'pageview');
        }
      }

      // subscribe to events
      $rootScope.$on('$viewContentLoaded', myGoogleAnalytics.sendPageview);

      return myGoogleAnalytics;
    }
  ])
  .run([
    'myGoogleAnalytics', 
    function(myGoogleAnalytics) {
        // inject self
    }
  ]);

我喜欢那个自注射的东西 :) Up - Sam Vloeberghs
只是出于好奇,你为什么要将page设置为当前路径,然后将其作为pageview提交?这样做与仅使用$window.ga('send', 'pageview',{page:$location.url()});有何不同之处? - Fizzix
1
我不太记得了,但是看起来它为其他操作或在其他地方记录附加信息留下了灵活性,并且通过明确告诉ga当前页面的情况,可能会更准确,因此ga可以继续准确地运行,而不仅仅是为某个“任意”的页面url记录页面视图。 - ilovett
如果您想在Google中实现实时分析,应该执行“set”操作。关于原因,请参阅文档参考:https://developers.google.com/analytics/devguides/collection/analyticsjs/single-page-applications#overview - fuzzysearch
建议使用“set”命令,以便于在同一页面上发送每个单独的点击(例如GA事件以跟踪用户交互),都使用相同的页面路径值。这与实时分析无关。请参阅https://developers.google.com/analytics/devguides/collection/analyticsjs/single-page-applications。 - Open SEO

5

最佳方法是使用Google Tag Manager根据历史记录监听器触发您的Google Analytics标签。这些内置于GTM接口中,可以轻松地跟踪客户端HTML5交互。

启用内置的History变量,并创建一个触发器,根据历史记录更改触发事件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接