From aa9f40d1d6f442de630541ef4ad04b865f3efad9 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Fri, 10 Apr 2015 12:25:48 +0200 Subject: [PATCH 01/25] Adding module version like in nextprot-ui --- app/assets/index.html | 2 ++ app/js/app.js | 1 + app/js/version/interpolate-filter.js | 15 +++++++++++++++ app/js/version/version-directive.js | 16 ++++++++++++++++ app/js/version/version.js | 9 +++++++++ 5 files changed, 43 insertions(+) create mode 100644 app/js/version/interpolate-filter.js create mode 100644 app/js/version/version-directive.js create mode 100644 app/js/version/version.js diff --git a/app/assets/index.html b/app/assets/index.html index 2af9aed..c5c5a9b 100755 --- a/app/assets/index.html +++ b/app/assets/index.html @@ -82,6 +82,8 @@ +
v-
+ -
v-
+
Version:
Build: #
-
Version:
Build: #
+
Version: (build )
-
Version: (build )
- diff --git a/app/js/version/version-directive.js b/app/js/version/version-directive.js index c5de92d..9f6dc40 100644 --- a/app/js/version/version-directive.js +++ b/app/js/version/version-directive.js @@ -13,4 +13,16 @@ angular.module('snorql.version.version-directive', []) return function (scope, elm, attrs) { elm.text(build); }; +}]) +.directive('sqBuildVersion', ['version', 'build', function (version, build) { + + return function (scope, elm, attrs) { + + var content = version; + + if (!isNaN(build)) + content += " (build "+build+")"; + + elm.text(content); + }; }]); From 237734b40c2aa167928f9d4b76775c15337feaaa Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 11:05:07 +0200 Subject: [PATCH 07/25] Remove unused code --- app/js/version/interpolate-filter.js | 15 --------------- app/js/version/version-directive.js | 12 ------------ app/js/version/version.js | 1 - 3 files changed, 28 deletions(-) delete mode 100644 app/js/version/interpolate-filter.js diff --git a/app/js/version/interpolate-filter.js b/app/js/version/interpolate-filter.js deleted file mode 100644 index 809ebf2..0000000 --- a/app/js/version/interpolate-filter.js +++ /dev/null @@ -1,15 +0,0 @@ -'use strict'; - -var VersionService = angular.module('snorql.version.interpolate-filter', []); - -VersionService.filter('interpolateVersion', ['version', function(version) { - return function(text) { - return String(text).replace(/\%VERSION\%/mg, version); - }; -}]); - -VersionService.filter('interpolateBuild', ['build', function (build) { - return function (text) { - return String(text).replace(/\%BUILD\%/mg, build); - }; -}]) diff --git a/app/js/version/version-directive.js b/app/js/version/version-directive.js index 9f6dc40..cefd187 100644 --- a/app/js/version/version-directive.js +++ b/app/js/version/version-directive.js @@ -2,18 +2,6 @@ angular.module('snorql.version.version-directive', []) -.directive('sqVersion', ['version', function(version) { - - return function(scope, elm, attrs) { - elm.text(version); - }; -}]) -.directive('sqBuild', ['build', function (build) { - - return function (scope, elm, attrs) { - elm.text(build); - }; -}]) .directive('sqBuildVersion', ['version', 'build', function (version, build) { return function (scope, elm, attrs) { diff --git a/app/js/version/version.js b/app/js/version/version.js index cc30e06..99afb3b 100644 --- a/app/js/version/version.js +++ b/app/js/version/version.js @@ -1,7 +1,6 @@ 'use strict'; angular.module('snorql.version', [ - 'snorql.version.interpolate-filter', 'snorql.version.version-directive' ]) From 0bf228e553b7fe90e55c2a864d597f5000297727 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 14:42:10 +0200 Subject: [PATCH 08/25] setting up GA for nextprot-snorql with analytics.js --- app/assets/index.html | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/app/assets/index.html b/app/assets/index.html index a69bad8..69ca1a8 100755 --- a/app/assets/index.html +++ b/app/assets/index.html @@ -25,6 +25,26 @@ + + + + + From 94d06f0e94cc1edd7466c080713a190d344313fa Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 14:43:16 +0200 Subject: [PATCH 09/25] Track page view and help page as event. --- app/js/app.js | 68 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 2 deletions(-) diff --git a/app/js/app.js b/app/js/app.js index b5d0d91..1849580 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -38,8 +38,8 @@ function appRun(gitHubContent, config) { // // implement controller SnorqlCtrl -SnorqlCtrl.$inject=['$scope','$timeout','$window','$location','snorql','config','gitHubContent','user'] -function SnorqlCtrl( $scope, $timeout, $window, $location, snorql, config, gitHubContent, user) { +SnorqlCtrl.$inject=['$scope', '$routeParams' ,'$timeout','$window','$location','snorql','config','gitHubContent','user'] +function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorql, config, gitHubContent, user) { // user $scope.user=user; @@ -74,6 +74,70 @@ function SnorqlCtrl( $scope, $timeout, $window, $location, snorql, config, gi mode:'sparql' }; + $scope.$on('$routeChangeSuccess', function(event, next, current) { + gaTrackPageView(); + gaTrackRouteChangeEvent(); + }); + + // Track the page path and query string of the page + function gaTrackPageView() { + + $window.ga('send', 'pageview', $location.url()); + } + + function RouteEvent(funcCategory, funcAction, funcLabel) { + + funcCategory = typeof funcCategory !== 'undefined' ? funcCategory : function() {return ""}; + funcAction = typeof funcAction !== 'undefined' ? funcAction : function() {return ""}; + + var event = { + 'hitType': 'event', + 'eventCategory': 'snorql-'+funcCategory(), + 'eventAction': 'snorql-'+funcAction() + }; + + if (typeof funcLabel !== 'undefined') + event.eventLabel = funcLabel(); + + return event; + } + + function HelpRouteEvent(doctype, docname) { + + var delimitor = '_'; + + var object = new RouteEvent(category, action); + + function category() { + return 'help-'+doctype; + } + + function action() { + return category()+delimitor+docname; + } + + return object; + } + + function gaTrackRouteChangeEvent() { + + var event = {}; + + if ("article" in $routeParams) { + event = new HelpRouteEvent('doc', $routeParams.article); + } + else if ("entity" in $routeParams) { + event = new HelpRouteEvent('entity', $routeParams.entity); + } + + console.log("$location:", $location, ", $routeParams:", $routeParams); + console.log("event:", event); + + if (Object.keys(event).length>0) { + ga('send', event); + } + } + // vocabulary query var vocSparqlQuery='SELECT DISTINCT * WHERE { ?term rdfs:label ?label ; a ?type . filter(regex(?label,"^__CV__","i")) } LIMIT 30'; $scope.searchTerm=function(term){ From 1e5499360a661c210eb753fb6af6b6854b9504bd Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 15:14:36 +0200 Subject: [PATCH 10/25] Tracking route changes for sparql searches --- app/js/app.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/app/js/app.js b/app/js/app.js index 1849580..272853c 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -97,7 +97,7 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq }; if (typeof funcLabel !== 'undefined') - event.eventLabel = funcLabel(); + event.eventLabel = 'snorql-'+funcLabel(); return event; } @@ -119,6 +119,24 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq return object; } + function SparqlSearchRouteEvent(output) { + + var delimitor = '_'; + + function category() { + return 'sparql-search'; + } + + function action() { + + var action = category()+delimitor+output; + + return action; + } + + return new RouteEvent(category, action); + } + function gaTrackRouteChangeEvent() { var event = {}; @@ -129,9 +147,12 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq else if ("entity" in $routeParams) { event = new HelpRouteEvent('entity', $routeParams.entity); } + else if ("query" in $routeParams) { + event = new SparqlSearchRouteEvent($routeParams.output); + } console.log("$location:", $location, ", $routeParams:", $routeParams); - console.log("event:", event); + console.log("ga event:", event); if (Object.keys(event).length>0) { ga('send', event); From 1375b1f6f57eefeba809691a63c80f8d2d3c20dc Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 15:15:53 +0200 Subject: [PATCH 11/25] Tracking success/failure of sparql query promise. --- app/js/app.factory.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app/js/app.factory.js b/app/js/app.factory.js index f58332b..4d00e9e 100644 --- a/app/js/app.factory.js +++ b/app/js/app.factory.js @@ -194,10 +194,23 @@ function snorql($http, $q, $timeout, $location, config) { // html output is done by parsing json params.output='json' this.$promise=$http({method:'GET', url:url,params:params,headers:accept, timeout: this.canceler.promise}); - console.log(this.$promise) + + var gaEvent = { + 'hitType': 'event', + 'eventCategory': 'snorql-sparql-search' + }; + this.$promise.then(function(config){ self.result=(config.data); - console.log(self.result); + + gaEvent.eventAction = gaEvent.eventCategory+'-succeed'; + + ga('send', gaEvent); + }, function() { + + gaEvent.eventLabel = gaEvent.eventCategory+'-fails'; + + ga('send', gaEvent); }) return this; } @@ -229,7 +242,6 @@ function snorql($http, $q, $timeout, $location, config) { // TODO: Refactor; non-standard link makers should be passed into the class by the caller this._getLinkMaker = function(varName) { - //console.log(varName); if (varName == 'property') { return function(uri) { return '?property=' + encodeURIComponent(uri); }; } else if (varName == 'class') { From 3e0a8ebbdd53aef0c4834f7933d05b4ee77e4078 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 15:24:18 +0200 Subject: [PATCH 12/25] Change event cat name separator --- app/js/app.factory.js | 2 +- app/js/app.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/js/app.factory.js b/app/js/app.factory.js index 4d00e9e..a1be9d3 100644 --- a/app/js/app.factory.js +++ b/app/js/app.factory.js @@ -197,7 +197,7 @@ function snorql($http, $q, $timeout, $location, config) { var gaEvent = { 'hitType': 'event', - 'eventCategory': 'snorql-sparql-search' + 'eventCategory': 'snorql-sparql_search' }; this.$promise.then(function(config){ diff --git a/app/js/app.js b/app/js/app.js index 272853c..ed260bd 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -124,7 +124,7 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq var delimitor = '_'; function category() { - return 'sparql-search'; + return 'sparql_search'; } function action() { From 84ac731098878ace34ad52f5f92b1c27c95ddc75 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 15:52:35 +0200 Subject: [PATCH 13/25] Change event name category for help --- app/js/app.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/js/app.js b/app/js/app.js index ed260bd..a186a58 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -109,11 +109,15 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq var object = new RouteEvent(category, action); function category() { - return 'help-'+doctype; + return 'help'; } function action() { - return category()+delimitor+docname; + return category()+delimitor+doctype; + } + + function label() { + return action()+delimitor+docname; } return object; From 249ac732f884ce84e4513102d8c47b85459a2c4e Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 18:17:16 +0200 Subject: [PATCH 14/25] Change event name category for search --- app/js/app.factory.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/js/app.factory.js b/app/js/app.factory.js index a1be9d3..1f20834 100644 --- a/app/js/app.factory.js +++ b/app/js/app.factory.js @@ -197,7 +197,7 @@ function snorql($http, $q, $timeout, $location, config) { var gaEvent = { 'hitType': 'event', - 'eventCategory': 'snorql-sparql_search' + 'eventCategory': 'snorql-search' }; this.$promise.then(function(config){ From c235ec95dce16e899a0b4a4e38e948c9b822f823 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 18:27:16 +0200 Subject: [PATCH 15/25] Tracking selection of sparql example --- app/js/app.js | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/app/js/app.js b/app/js/app.js index a186a58..15816c2 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -128,12 +128,12 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq var delimitor = '_'; function category() { - return 'sparql_search'; + return 'search'; } function action() { - var action = category()+delimitor+output; + var action = category()+delimitor+((output) ? output : 'html'); return action; } @@ -179,6 +179,22 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq }); } + function formatQuery(queryId) { + + function log10(val) { + return Math.log(val) / Math.LN10; + } + var numOf0s = 4-Math.floor(log10(queryId)); + var query = "NXQ_"; + + while (numOf0s--) { + query += '0'; + } + query += snorql.selectedQueryId; + + return query; + } + $scope.executeQuery=function(sparql,output){ var time=Date.now(); $scope.executionTime=false; @@ -205,6 +221,16 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq snorql.queryTitle=snorql.examples[elm].title; $scope.qSelected=elm $('.row-offcanvas').removeClass('active') + + var gaEvent = { + 'hitType': 'event', + 'eventCategory': 'snorql-select_example', + 'eventAction': 'snorql-select_example-'+formatQuery(snorql.selectedQueryId) + }; + + //console.log("event:", gaEvent); + + ga('send', gaEvent); }; $scope.setFilterTag=function(tag){ From 37213d4fdf38d5a72b9a562cb2972bf7ff583b59 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Tue, 14 Apr 2015 19:35:25 +0200 Subject: [PATCH 16/25] Tracking selection of search term --- app/js/app.factory.js | 14 +--------- app/js/app.js | 60 ++++++++++++++++++++++++++++--------------- 2 files changed, 41 insertions(+), 33 deletions(-) diff --git a/app/js/app.factory.js b/app/js/app.factory.js index 1f20834..10b2cf8 100644 --- a/app/js/app.factory.js +++ b/app/js/app.factory.js @@ -195,22 +195,10 @@ function snorql($http, $q, $timeout, $location, config) { params.output='json' this.$promise=$http({method:'GET', url:url,params:params,headers:accept, timeout: this.canceler.promise}); - var gaEvent = { - 'hitType': 'event', - 'eventCategory': 'snorql-search' - }; - this.$promise.then(function(config){ self.result=(config.data); - - gaEvent.eventAction = gaEvent.eventCategory+'-succeed'; - - ga('send', gaEvent); }, function() { - - gaEvent.eventLabel = gaEvent.eventCategory+'-fails'; - - ga('send', gaEvent); + console.log('promise failed'); }) return this; } diff --git a/app/js/app.js b/app/js/app.js index 15816c2..8120191 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -92,12 +92,12 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq var event = { 'hitType': 'event', - 'eventCategory': 'snorql-'+funcCategory(), - 'eventAction': 'snorql-'+funcAction() + 'eventCategory': 'snorql_'+funcCategory(), + 'eventAction': 'snorql_'+funcAction() }; if (typeof funcLabel !== 'undefined') - event.eventLabel = 'snorql-'+funcLabel(); + event.eventLabel = 'snorql_'+funcLabel(); return event; } @@ -106,7 +106,7 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq var delimitor = '_'; - var object = new RouteEvent(category, action); + var object = new RouteEvent(category, action, label); function category() { return 'help'; @@ -133,39 +133,52 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq function action() { - var action = category()+delimitor+((output) ? output : 'html'); + return category()+delimitor+'sparql'; + } + + function label() { - return action; + return action()+delimitor+((output) ? output : 'html'); } - return new RouteEvent(category, action); + return new RouteEvent(category, action, label); } function gaTrackRouteChangeEvent() { - var event = {}; + var gaEvent = {}; if ("article" in $routeParams) { - event = new HelpRouteEvent('doc', $routeParams.article); + gaEvent = new HelpRouteEvent('doc', $routeParams.article); } else if ("entity" in $routeParams) { - event = new HelpRouteEvent('entity', $routeParams.entity); + gaEvent = new HelpRouteEvent('entity', $routeParams.entity); } else if ("query" in $routeParams) { - event = new SparqlSearchRouteEvent($routeParams.output); + gaEvent = new SparqlSearchRouteEvent($routeParams.output); } - console.log("$location:", $location, ", $routeParams:", $routeParams); - console.log("ga event:", event); + console.log("tracking route -> ga event:", gaEvent); - if (Object.keys(event).length>0) { - ga('send', event); + if (Object.keys(gaEvent).length>0) { + ga('send', gaEvent); } } // vocabulary query var vocSparqlQuery='SELECT DISTINCT * WHERE { ?term rdfs:label ?label ; a ?type . filter(regex(?label,"^__CV__","i")) } LIMIT 30'; $scope.searchTerm=function(term){ + + var gaEvent = { + 'hitType': 'event', + 'eventCategory': 'snorql_search' + }; + + gaEvent.eventAction = gaEvent.eventCategory+'_term'; + gaEvent.eventLabel = gaEvent.eventAction+'_'+term; + + console.log("tracking search term -> ga event:", gaEvent); + var time=Date.now(); $scope.executionTime=false; $scope.waiting=true; @@ -173,9 +186,14 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq snorql.executeQuery(vocSparqlQuery.replace('__CV__',term), {output:'html'}).$promise.then(function(){ $scope.waiting=false; $scope.executionTime=(Date.now()-time)/1000; + + ga('send', gaEvent); },function(reason){ - $scope.error=reason.data.message - $scope.waiting=false + $scope.error=reason.data.message; + $scope.waiting=false; + + gaEvent.eventLabel = gaEvent.eventLabel+'_failed'; + ga('send', gaEvent); }); } @@ -224,11 +242,13 @@ function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorq var gaEvent = { 'hitType': 'event', - 'eventCategory': 'snorql-select_example', - 'eventAction': 'snorql-select_example-'+formatQuery(snorql.selectedQueryId) + 'eventCategory': 'snorql_select-example' }; - //console.log("event:", gaEvent); + gaEvent.eventAction = gaEvent.eventCategory; + gaEvent.eventLabel = gaEvent.eventAction+'_'+formatQuery(snorql.selectedQueryId); + + console.log("tracking selection event -> ga event:", gaEvent); ga('send', gaEvent); }; From bb3ce522b05d8dd1cd4e40224723bfc79a795f7a Mon Sep 17 00:00:00 2001 From: fnikitin Date: Thu, 16 Apr 2015 15:56:02 +0200 Subject: [PATCH 17/25] Refactoring: Put spreaded ga tracking code into a independent module, add dependency and inject Tracker object wherever tracking is needed. --- app/js/app.js | 557 +++++++++-------------- app/js/tracker/snorql.tracker.service.js | 158 +++++++ 2 files changed, 377 insertions(+), 338 deletions(-) create mode 100644 app/js/tracker/snorql.tracker.service.js diff --git a/app/js/app.js b/app/js/app.js index 8120191..27cb9a3 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -1,368 +1,249 @@ -(function (angular, undefined) {'use strict'; -/** - * create application snorql and load deps - */ -var app = angular.module('snorql', [ - 'ngRoute', - 'ngResource', - 'npHelp', - 'ui.codemirror', - 'snorql.config', - 'snorql.service', - 'snorql.ui', - 'snorql.version', - 'snorql.user', // user - 'auth0', // authorization (auth0) - 'angular-jwt', // token - 'ipCookie' // cookie -]).controller('SnorqlCtrl',SnorqlCtrl) - .factory('errorInterceptor',errorInterceptor) - .config(appConfig) - .run(appRun) +(function (angular, undefined) { + 'use strict'; + /** + * create application snorql and load deps + */ + var app = angular.module('snorql', [ + 'ngRoute', + 'ngResource', + 'npHelp', + 'ui.codemirror', + 'snorql.config', + 'snorql.service', + 'snorql.ui', + 'snorql.version', + 'snorql.tracker', + 'snorql.user', // user + 'auth0', // authorization (auth0) + 'angular-jwt', // token + 'ipCookie' // cookie + ]); + + app.controller('SnorqlCtrl', SnorqlCtrl) + .factory('errorInterceptor', errorInterceptor) + .config(appConfig) + .run(appRun); // init app -appRun.$inject=['gitHubContent', 'config'] -function appRun(gitHubContent, config) { - gitHubContent.initialize({ - // baseUrl:"http://uat-web2:8080", - helpPath:'rdfhelp.json', - helpTitle:'Generalities', - root:'help', // specify the root of RDF entity routes - githubRepo: '/', - githubApi:config.apiUrl, - githubEditPage : "https://github.com/calipho-sib/nextprot-docs/edit/master/", - githubToken : null - }); -}; + appRun.$inject = ['gitHubContent', 'config'] + function appRun(gitHubContent, config) { + gitHubContent.initialize({ + // baseUrl:"http://uat-web2:8080", + helpPath: 'rdfhelp.json', + helpTitle: 'Generalities', + root: 'help', // specify the root of RDF entity routes + githubRepo: '/', + githubApi: config.apiUrl, + githubEditPage: "https://github.com/calipho-sib/nextprot-docs/edit/master/", + githubToken: null + }); + }; // // implement controller SnorqlCtrl -SnorqlCtrl.$inject=['$scope', '$routeParams' ,'$timeout','$window','$location','snorql','config','gitHubContent','user'] -function SnorqlCtrl( $scope, $routeParams, $timeout, $window, $location, snorql, config, gitHubContent, user) { - // user - $scope.user=user; - - // - // go home link - $scope.home=config.home; - $scope.pushState=config.pushState; - - // - // snorql service provide examples, examples tags, config and executeQuery - $scope.snorql=snorql; - - // - // setup default output - $scope.outputs=['html','json','csv','xml']; - $scope.output='html'; - $scope.showPrefixes = false; - - // - // default message - $scope.message="Executing query ..."; - - $scope.waiting=false; - $scope.filter="" - $scope.filterTag = null; - - // codemirror option - $scope.cmOption = { - lineNumbers: false, - indentWithTabs: true, - uiRefresh:true, - mode:'sparql' - }; - - $scope.$on('$routeChangeSuccess', function(event, next, current) { - gaTrackPageView(); - gaTrackRouteChangeEvent(); - }); - - // Track the page path and query string of the page - function gaTrackPageView() { - - $window.ga('send', 'pageview', $location.url()); - } - - function RouteEvent(funcCategory, funcAction, funcLabel) { - - funcCategory = typeof funcCategory !== 'undefined' ? funcCategory : function() {return ""}; - funcAction = typeof funcAction !== 'undefined' ? funcAction : function() {return ""}; - - var event = { - 'hitType': 'event', - 'eventCategory': 'snorql_'+funcCategory(), - 'eventAction': 'snorql_'+funcAction() + SnorqlCtrl.$inject = ['Tracker', '$scope', '$routeParams', '$timeout', '$window', '$location', 'snorql', 'config', 'gitHubContent', 'user'] + function SnorqlCtrl(Tracker, $scope, $routeParams, $timeout, $window, $location, snorql, config, gitHubContent, user) { + // user + $scope.user = user; + + // + // go home link + $scope.home = config.home; + $scope.pushState = config.pushState; + + // + // snorql service provide examples, examples tags, config and executeQuery + $scope.snorql = snorql; + + // + // setup default output + $scope.outputs = ['html', 'json', 'csv', 'xml']; + $scope.output = 'html'; + $scope.showPrefixes = false; + + // + // default message + $scope.message = "Executing query ..."; + + $scope.waiting = false; + $scope.filter = "" + $scope.filterTag = null; + + // codemirror option + $scope.cmOption = { + lineNumbers: false, + indentWithTabs: true, + uiRefresh: true, + mode: 'sparql' }; - if (typeof funcLabel !== 'undefined') - event.eventLabel = 'snorql_'+funcLabel(); - - return event; - } + $scope.$on('$routeChangeSuccess', function (event, next, current) { + Tracker.trackPageView(); + Tracker.trackRouteChangeEvent(); + }); + + // vocabulary query + var vocSparqlQuery = 'SELECT DISTINCT * WHERE { ?term rdfs:label ?label ; a ?type . filter(regex(?label,"^__CV__","i")) } LIMIT 30'; + $scope.searchTerm = function (term) { + + var time = Date.now(); + $scope.executionTime = false; + $scope.waiting = true; + $scope.error = false; + snorql.executeQuery(vocSparqlQuery.replace('__CV__', term), {output: 'html'}).$promise.then(function () { + $scope.waiting = false; + $scope.executionTime = (Date.now() - time) / 1000; + + Tracker.trackSearchTermEventOnSuccess(term); + }, function (reason) { + $scope.error = reason.data.message; + $scope.waiting = false; + + Tracker.trackSearchTermEventOnFailure(term); + }); + } - function HelpRouteEvent(doctype, docname) { - var delimitor = '_'; + $scope.executeQuery = function (sparql, output) { + var time = Date.now(); + $scope.executionTime = false; + $scope.waiting = true; + $scope.error = false; + $location.search('query', sparql) + $location.search('class', null) + $location.search('property', null) + $location.search('describe', null) + var params = angular.extend($location.search(), {output: output}); + snorql.executeQuery(sparql, params).$promise.then(function () { + $scope.waiting = false; + $scope.executionTime = (Date.now() - time) / 1000; + }, function (reason) { + $scope.error = reason.data.message + $scope.waiting = false + }); + }; - var object = new RouteEvent(category, action, label); + $scope.selectExample = function (elm) { + snorql.query = snorql.examples[elm].sparql; + snorql.description = snorql.examples[elm].description; + snorql.selectedQueryId = snorql.examples[elm].userQueryId; + snorql.queryTitle = snorql.examples[elm].title; + $scope.qSelected = elm + $('.row-offcanvas').removeClass('active') - function category() { - return 'help'; - } + Tracker.trackSelectExampleEvent(snorql.selectedQueryId); + }; - function action() { - return category()+delimitor+doctype; - } + $scope.setFilterTag = function (tag) { + $scope.filterTag = tag; + }; - function label() { - return action()+delimitor+docname; - } + $scope.resetFilters = function () { + $scope.filterTag = null; + }; - return object; - } + $scope.reset = function () { + snorql.reset(); + }; - function SparqlSearchRouteEvent(output) { + $scope.login = function () { + user.login(); + }; - var delimitor = '_'; + $scope.logout = function () { + user.logout(); + }; - function category() { - return 'search'; - } + // + // load sparql examples + snorql.loadExamples() - function action() { + // + // kind of queries, + // query, describe, class, property + snorql.updateQuery($location.search()) + // $scope.executeQuery(snorql.updateQuery($location.search())); + $scope.$on('$locationChangeSuccess', function (url) { + snorql.updateQuery($location.search()) - return category()+delimitor+'sparql'; - } + if ($location.path() === '/') { + $window.document.title = "neXtProt SnorQL"; + } - function label() { + }) + }; - return action()+delimitor+((output) ? output : 'html'); - } - return new RouteEvent(category, action, label); - } - - function gaTrackRouteChangeEvent() { - - var gaEvent = {}; - - if ("article" in $routeParams) { - gaEvent = new HelpRouteEvent('doc', $routeParams.article); - } - else if ("entity" in $routeParams) { - gaEvent = new HelpRouteEvent('entity', $routeParams.entity); - } - else if ("query" in $routeParams) { - gaEvent = new SparqlSearchRouteEvent($routeParams.output); - } - - console.log("tracking route -> ga event:", gaEvent); - - if (Object.keys(gaEvent).length>0) { - ga('send', gaEvent); - } - } - - // vocabulary query - var vocSparqlQuery='SELECT DISTINCT * WHERE { ?term rdfs:label ?label ; a ?type . filter(regex(?label,"^__CV__","i")) } LIMIT 30'; - $scope.searchTerm=function(term){ - - var gaEvent = { - 'hitType': 'event', - 'eventCategory': 'snorql_search' - }; - - gaEvent.eventAction = gaEvent.eventCategory+'_term'; - gaEvent.eventLabel = gaEvent.eventAction+'_'+term; - - console.log("tracking search term -> ga event:", gaEvent); - - var time=Date.now(); - $scope.executionTime=false; - $scope.waiting=true; - $scope.error=false; - snorql.executeQuery(vocSparqlQuery.replace('__CV__',term), {output:'html'}).$promise.then(function(){ - $scope.waiting=false; - $scope.executionTime=(Date.now()-time)/1000; - - ga('send', gaEvent); - },function(reason){ - $scope.error=reason.data.message; - $scope.waiting=false; - - gaEvent.eventLabel = gaEvent.eventLabel+'_failed'; - ga('send', gaEvent); - }); - } - - function formatQuery(queryId) { - - function log10(val) { - return Math.log(val) / Math.LN10; - } - var numOf0s = 4-Math.floor(log10(queryId)); - var query = "NXQ_"; - - while (numOf0s--) { - query += '0'; - } - query += snorql.selectedQueryId; - - return query; - } - - $scope.executeQuery=function(sparql,output){ - var time=Date.now(); - $scope.executionTime=false; - $scope.waiting=true; - $scope.error=false; - $location.search('query',sparql) - $location.search('class',null) - $location.search('property',null) - $location.search('describe',null) - var params=angular.extend($location.search(),{output:output}); - snorql.executeQuery(sparql, params).$promise.then(function(){ - $scope.waiting=false; - $scope.executionTime=(Date.now()-time)/1000; - },function(reason){ - $scope.error=reason.data.message - $scope.waiting=false - }); - }; - - $scope.selectExample=function(elm){ - snorql.query=snorql.examples[elm].sparql; - snorql.description=snorql.examples[elm].description; - snorql.selectedQueryId=snorql.examples[elm].userQueryId; - snorql.queryTitle=snorql.examples[elm].title; - $scope.qSelected=elm - $('.row-offcanvas').removeClass('active') - - var gaEvent = { - 'hitType': 'event', - 'eventCategory': 'snorql_select-example' + /** + * ANGULAR BOOTSTRAP + */ + appConfig.$inject = ['$routeProvider', '$locationProvider', '$httpProvider', 'authProvider', 'jwtInterceptorProvider'] + function appConfig($routeProvider, $locationProvider, $httpProvider, authProvider, jwtInterceptorProvider) { + + authProvider.init({ + clientID: '7vS32LzPoIR1Y0JKahOvUCgGbn94AcFW', + callbackURL: window.location.origin, + domain: 'nextprot.auth0.com', + icon: '/img/np.png' + }); + + jwtInterceptorProvider.tokenGetter = ['ipCookie', function (ipCookie) { + // Return the saved token + return ipCookie('nxtoken'); + }]; + $httpProvider.interceptors.push('jwtInterceptor'); + + // intercept errors + $httpProvider.interceptors.push('errorInterceptor') + + + // List of routes of the application + $routeProvider + // Home page + .when('/', {title: 'welcome to snorql', templateUrl: '/partials/home.html'}) + // Pages (in nextprot-docs/pages): about, copyright... + .when('/:article', {title: 'page', templateUrl: '/partials/page.html'}) + //// Help pages + // GENERALITIES + .when('/help/doc/:article', {title: 'help for snorql', templateUrl: '/partials/doc.html'}) + // RDF ENTITIES + .when('/help/entity/:entity', {title: 'help for snorql', templateUrl: '/partials/help.html'}) + + // Without serve side support html5 must be disabled. + $locationProvider.html5Mode(true); + //$locationProvider.hashPrefix = '!'; }; - gaEvent.eventAction = gaEvent.eventCategory; - gaEvent.eventLabel = gaEvent.eventAction+'_'+formatQuery(snorql.selectedQueryId); - - console.log("tracking selection event -> ga event:", gaEvent); - - ga('send', gaEvent); - }; - - $scope.setFilterTag=function(tag){ - $scope.filterTag=tag; - }; - - $scope.resetFilters=function(){ - $scope.filterTag=null; - }; - - $scope.reset=function(){ - snorql.reset(); - }; - - $scope.login=function(){ - user.login(); - }; - - $scope.logout=function(){ - user.logout(); - }; - - // - // load sparql examples - snorql.loadExamples() - - // - // kind of queries, - // query, describe, class, property - snorql.updateQuery($location.search()) - // $scope.executeQuery(snorql.updateQuery($location.search())); - $scope.$on('$locationChangeSuccess',function(url){ - snorql.updateQuery($location.search()) - - if($location.path()==='/') { - $window.document.title = "neXtProt SnorQL"; - } - - }) -}; - - -/** - * ANGULAR BOOTSTRAP - */ -appConfig.$inject=['$routeProvider','$locationProvider','$httpProvider','authProvider','jwtInterceptorProvider'] -function appConfig($routeProvider, $locationProvider, $httpProvider, authProvider, jwtInterceptorProvider) { - - authProvider.init({ - clientID: '7vS32LzPoIR1Y0JKahOvUCgGbn94AcFW', - callbackURL: window.location.origin, - domain: 'nextprot.auth0.com', - icon: '/img/np.png' - }); - - jwtInterceptorProvider.tokenGetter = ['ipCookie', function (ipCookie) { - // Return the saved token - return ipCookie('nxtoken'); - }]; - $httpProvider.interceptors.push('jwtInterceptor'); - - // intercept errors - $httpProvider.interceptors.push('errorInterceptor') - - - // List of routes of the application - $routeProvider - // Home page - .when('/', {title: 'welcome to snorql', templateUrl: '/partials/home.html'}) - // Pages (in nextprot-docs/pages): about, copyright... - .when('/:article', {title: 'page', templateUrl: '/partials/page.html'}) - //// Help pages - // GENERALITIES - .when('/help/doc/:article',{title: 'help for snorql', templateUrl: '/partials/doc.html'}) - // RDF ENTITIES - .when('/help/entity/:entity',{title: 'help for snorql', templateUrl: '/partials/help.html'}) - - // Without serve side support html5 must be disabled. - $locationProvider.html5Mode(true); - //$locationProvider.hashPrefix = '!'; -}; - -errorInterceptor.$inject=['$q', '$rootScope', '$location'] -function errorInterceptor($q, $rootScope, $location) { - return { - request: function (config) { - return config || $q.when(config); - }, - requestError: function(request){ - return $q.reject(request); - }, - response: function (response) { - return response || $q.when(response); - }, - responseError: function (response) { - if (response && response.status === 0) { - $rootScope.error="The API is not accessible"; - } - if (response && response.status === 401) { - $rootScope.error="You are not authorized to access the resource. Please login or review your privileges."; - } - if (response && response.status === 404) { - $rootScope.error="URL not found"; + errorInterceptor.$inject = ['$q', '$rootScope', '$location'] + function errorInterceptor($q, $rootScope, $location) { + return { + request: function (config) { + return config || $q.when(config); + }, + requestError: function (request) { + return $q.reject(request); + }, + response: function (response) { + return response || $q.when(response); + }, + responseError: function (response) { + if (response && response.status === 0) { + $rootScope.error = "The API is not accessible"; + } + if (response && response.status === 401) { + $rootScope.error = "You are not authorized to access the resource. Please login or review your privileges."; + } + if (response && response.status === 404) { + $rootScope.error = "URL not found"; + } + if (response && response.status >= 500) { + $rootScope.error = "Request Failed"; + } + return $q.reject(response); } - if (response && response.status >= 500) { - $rootScope.error="Request Failed"; - } - return $q.reject(response); - } + }; }; -}; - })(angular); diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js new file mode 100644 index 0000000..c7887c2 --- /dev/null +++ b/app/js/tracker/snorql.tracker.service.js @@ -0,0 +1,158 @@ +'use strict'; + +var TrackingService = angular.module('snorql.tracker', []); + +TrackingService.factory('Tracker', [ + '$window', + '$location', + '$routeParams', + function ($window, $location, $routeParams) { + + var Tracker = function () {}; + + Tracker.prototype.trackPageView = function () { + $window.ga('send', 'pageview', $location.url()); + }; + + Tracker.prototype.trackRouteChangeEvent = function() { + + var gaEvent = {}; + + if ("article" in $routeParams) { + gaEvent = new HelpRouteEvent('doc', $routeParams.article); + } + else if ("entity" in $routeParams) { + gaEvent = new HelpRouteEvent('entity', $routeParams.entity); + } + else if ("query" in $routeParams) { + gaEvent = new SparqlSearchRouteEvent($routeParams.output); + } + + console.log("tracking route -> ga event:", gaEvent); + + if (Object.keys(gaEvent).length>0) { + ga('send', gaEvent); + } + }; + + Tracker.prototype.trackSelectExampleEvent = function(selectedQueryId) { + + var gaEvent = { + 'hitType': 'event', + 'eventCategory': 'snorql_select-example' + }; + + gaEvent.eventAction = gaEvent.eventCategory; + gaEvent.eventLabel = gaEvent.eventAction+'_'+formatQueryId(selectedQueryId); + + console.log("tracking selection event -> ga event:", gaEvent); + + ga('send', gaEvent); + }; + + Tracker.prototype.trackSearchTermEventOnSuccess = function(term) { + + ga('send', newSearchTermEvent(term)); + }; + + Tracker.prototype.trackSearchTermEventOnFailure = function(term) { + + var gaEvent = newSearchTermEvent(term); + + gaEvent.eventLabel = gaEvent.eventLabel+'_failed'; + ga('send', gaEvent); + }; + + function newSearchTermEvent(term) { + + var gaEvent = { + 'hitType': 'event', + 'eventCategory': 'snorql_search' + }; + + gaEvent.eventAction = gaEvent.eventCategory+'_term'; + gaEvent.eventLabel = gaEvent.eventAction+'_'+term; + + console.log("tracking search term -> ga event:", gaEvent); + + return gaEvent; + } + + function RouteEvent(funcCategory, funcAction, funcLabel) { + + funcCategory = typeof funcCategory !== 'undefined' ? funcCategory : function() {return ""}; + funcAction = typeof funcAction !== 'undefined' ? funcAction : function() {return ""}; + + var event = { + 'hitType': 'event', + 'eventCategory': 'snorql_'+funcCategory(), + 'eventAction': 'snorql_'+funcAction() + }; + + if (typeof funcLabel !== 'undefined') + event.eventLabel = 'snorql_'+funcLabel(); + + return event; + } + + function HelpRouteEvent(doctype, docname) { + + var delimitor = '_'; + + var object = new RouteEvent(category, action, label); + + function category() { + return 'help'; + } + + function action() { + return category()+delimitor+doctype; + } + + function label() { + return action()+delimitor+docname; + } + + return object; + } + + function SparqlSearchRouteEvent(output) { + + var delimitor = '_'; + + function category() { + return 'search'; + } + + function action() { + + return category()+delimitor+'sparql'; + } + + function label() { + + return action()+delimitor+((output) ? output : 'html'); + } + + return new RouteEvent(category, action, label); + } + + function formatQueryId(queryId) { + + function log10(val) { + return Math.log(val) / Math.LN10; + } + var numOf0s = 4-Math.floor(log10(queryId)); + var query = "NXQ_"; + + while (numOf0s--) { + query += '0'; + } + query += snorql.selectedQueryId; + + return query; + } + + return new Tracker(); + }]); + From e7f0cf74a4a91aff2a8a2593e6ff50dcd53fc52b Mon Sep 17 00:00:00 2001 From: fnikitin Date: Thu, 16 Apr 2015 17:59:05 +0200 Subject: [PATCH 18/25] Fixing formatQueryId typo --- app/js/tracker/snorql.tracker.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js index c7887c2..6eb6ba3 100644 --- a/app/js/tracker/snorql.tracker.service.js +++ b/app/js/tracker/snorql.tracker.service.js @@ -148,7 +148,7 @@ TrackingService.factory('Tracker', [ while (numOf0s--) { query += '0'; } - query += snorql.selectedQueryId; + query += queryId; return query; } From a421d07755f080cc931cb21725f4dec74f33cb5e Mon Sep 17 00:00:00 2001 From: fnikitin Date: Thu, 16 Apr 2015 18:28:49 +0200 Subject: [PATCH 19/25] Tracking resources routes --- app/assets/index.html | 6 +++--- app/js/app.js | 3 +++ app/js/tracker/snorql.tracker.service.js | 15 ++++++++++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/assets/index.html b/app/assets/index.html index 69ca1a8..f2d4a7c 100755 --- a/app/assets/index.html +++ b/app/assets/index.html @@ -71,9 +71,9 @@ aria-expanded="false">Resources
  • Help
  • diff --git a/app/js/app.js b/app/js/app.js index 27cb9a3..bf16bae 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -104,6 +104,9 @@ }); } + $scope.routingOutside = function(input) { + Tracker.trackTransitionRouteChangeEvent(input); + }; $scope.executeQuery = function (sparql, output) { var time = Date.now(); diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js index 6eb6ba3..c8e61e5 100644 --- a/app/js/tracker/snorql.tracker.service.js +++ b/app/js/tracker/snorql.tracker.service.js @@ -14,6 +14,19 @@ TrackingService.factory('Tracker', [ $window.ga('send', 'pageview', $location.url()); }; + Tracker.prototype.trackTransitionRouteChangeEvent = function(dest) { + + var gaEvent = { + 'hitType': 'event', + 'eventCategory': 'snorql_routing-'+dest + }; + console.log("tracking route -> ga event:", gaEvent); + + if (Object.keys(gaEvent).length>0) { + ga('send', gaEvent); + } + }; + Tracker.prototype.trackRouteChangeEvent = function() { var gaEvent = {}; @@ -31,7 +44,7 @@ TrackingService.factory('Tracker', [ console.log("tracking route -> ga event:", gaEvent); if (Object.keys(gaEvent).length>0) { - ga('send', gaEvent); + //ga('send', gaEvent); } }; From c1b38692d69cb4df86e5df843e3c0d88fa016fcf Mon Sep 17 00:00:00 2001 From: fnikitin Date: Thu, 16 Apr 2015 19:14:46 +0200 Subject: [PATCH 20/25] Refactor search term on success and on failure --- app/js/app.js | 4 ++-- app/js/tracker/snorql.tracker.service.js | 11 ++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/app/js/app.js b/app/js/app.js index bf16bae..1d2b93a 100755 --- a/app/js/app.js +++ b/app/js/app.js @@ -95,12 +95,12 @@ $scope.waiting = false; $scope.executionTime = (Date.now() - time) / 1000; - Tracker.trackSearchTermEventOnSuccess(term); + Tracker.trackSearchTermEvent(term, true); }, function (reason) { $scope.error = reason.data.message; $scope.waiting = false; - Tracker.trackSearchTermEventOnFailure(term); + Tracker.trackSearchTermEvent(term, false); }); } diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js index c8e61e5..8441837 100644 --- a/app/js/tracker/snorql.tracker.service.js +++ b/app/js/tracker/snorql.tracker.service.js @@ -63,16 +63,13 @@ TrackingService.factory('Tracker', [ ga('send', gaEvent); }; - Tracker.prototype.trackSearchTermEventOnSuccess = function(term) { - - ga('send', newSearchTermEvent(term)); - }; - - Tracker.prototype.trackSearchTermEventOnFailure = function(term) { + Tracker.prototype.trackSearchTermEvent = function(term, hasSucceed) { var gaEvent = newSearchTermEvent(term); - gaEvent.eventLabel = gaEvent.eventLabel+'_failed'; + if (hasSucceed) gaEvent.eventLabel = gaEvent.eventLabel+'_success'; + else gaEvent.eventLabel = gaEvent.eventLabel+'_failure'; + ga('send', gaEvent); }; From 9d4b9bab0f6cc08b31828d32f8da1298f4dfc970 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Fri, 17 Apr 2015 11:26:30 +0200 Subject: [PATCH 21/25] Simplify tracker factory --- app/js/tracker/snorql.tracker.service.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js index 8441837..081865b 100644 --- a/app/js/tracker/snorql.tracker.service.js +++ b/app/js/tracker/snorql.tracker.service.js @@ -8,13 +8,13 @@ TrackingService.factory('Tracker', [ '$routeParams', function ($window, $location, $routeParams) { - var Tracker = function () {}; + var tracker = {}; - Tracker.prototype.trackPageView = function () { + tracker.trackPageView = function () { $window.ga('send', 'pageview', $location.url()); }; - Tracker.prototype.trackTransitionRouteChangeEvent = function(dest) { + tracker.trackTransitionRouteChangeEvent = function(dest) { var gaEvent = { 'hitType': 'event', @@ -27,7 +27,7 @@ TrackingService.factory('Tracker', [ } }; - Tracker.prototype.trackRouteChangeEvent = function() { + tracker.trackRouteChangeEvent = function() { var gaEvent = {}; @@ -48,7 +48,7 @@ TrackingService.factory('Tracker', [ } }; - Tracker.prototype.trackSelectExampleEvent = function(selectedQueryId) { + tracker.trackSelectExampleEvent = function(selectedQueryId) { var gaEvent = { 'hitType': 'event', @@ -63,7 +63,7 @@ TrackingService.factory('Tracker', [ ga('send', gaEvent); }; - Tracker.prototype.trackSearchTermEvent = function(term, hasSucceed) { + tracker.trackSearchTermEvent = function(term, hasSucceed) { var gaEvent = newSearchTermEvent(term); @@ -163,6 +163,6 @@ TrackingService.factory('Tracker', [ return query; } - return new Tracker(); + return tracker; }]); From c909d5718e808f71ccb23332738f5d1e50b7fd13 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Fri, 17 Apr 2015 12:14:39 +0200 Subject: [PATCH 22/25] Move ga snippet from index.html to tracker service --- app/assets/index.html | 20 -------- app/js/tracker/snorql.tracker.service.js | 59 ++++++++++++++++-------- 2 files changed, 39 insertions(+), 40 deletions(-) diff --git a/app/assets/index.html b/app/assets/index.html index f2d4a7c..f036c9b 100755 --- a/app/assets/index.html +++ b/app/assets/index.html @@ -25,26 +25,6 @@ - - - - - diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js index 081865b..a9789fe 100644 --- a/app/js/tracker/snorql.tracker.service.js +++ b/app/js/tracker/snorql.tracker.service.js @@ -8,6 +8,8 @@ TrackingService.factory('Tracker', [ '$routeParams', function ($window, $location, $routeParams) { + var separator = '_'; + var tracker = {}; tracker.trackPageView = function () { @@ -18,7 +20,7 @@ TrackingService.factory('Tracker', [ var gaEvent = { 'hitType': 'event', - 'eventCategory': 'snorql_routing-'+dest + 'eventCategory': 'snorql'+separator+'routing-'+dest }; console.log("tracking route -> ga event:", gaEvent); @@ -44,7 +46,7 @@ TrackingService.factory('Tracker', [ console.log("tracking route -> ga event:", gaEvent); if (Object.keys(gaEvent).length>0) { - //ga('send', gaEvent); + ga('send', gaEvent); } }; @@ -52,11 +54,11 @@ TrackingService.factory('Tracker', [ var gaEvent = { 'hitType': 'event', - 'eventCategory': 'snorql_select-example' + 'eventCategory': 'snorql'+separator+'select-example' }; gaEvent.eventAction = gaEvent.eventCategory; - gaEvent.eventLabel = gaEvent.eventAction+'_'+formatQueryId(selectedQueryId); + gaEvent.eventLabel = gaEvent.eventAction+separator+formatQueryId(selectedQueryId); console.log("tracking selection event -> ga event:", gaEvent); @@ -67,8 +69,8 @@ TrackingService.factory('Tracker', [ var gaEvent = newSearchTermEvent(term); - if (hasSucceed) gaEvent.eventLabel = gaEvent.eventLabel+'_success'; - else gaEvent.eventLabel = gaEvent.eventLabel+'_failure'; + if (hasSucceed) gaEvent.eventLabel = gaEvent.eventLabel+separator+'success'; + else gaEvent.eventLabel = gaEvent.eventLabel+separator+'failure'; ga('send', gaEvent); }; @@ -77,11 +79,11 @@ TrackingService.factory('Tracker', [ var gaEvent = { 'hitType': 'event', - 'eventCategory': 'snorql_search' + 'eventCategory': 'snorql'+separator+'search' }; - gaEvent.eventAction = gaEvent.eventCategory+'_term'; - gaEvent.eventLabel = gaEvent.eventAction+'_'+term; + gaEvent.eventAction = gaEvent.eventCategory+separator+'term'; + gaEvent.eventLabel = gaEvent.eventAction+separator+term; console.log("tracking search term -> ga event:", gaEvent); @@ -95,20 +97,18 @@ TrackingService.factory('Tracker', [ var event = { 'hitType': 'event', - 'eventCategory': 'snorql_'+funcCategory(), - 'eventAction': 'snorql_'+funcAction() + 'eventCategory': 'snorql'+separator+funcCategory(), + 'eventAction': 'snorql'+separator+funcAction() }; if (typeof funcLabel !== 'undefined') - event.eventLabel = 'snorql_'+funcLabel(); + event.eventLabel = 'snorql'+separator+funcLabel(); return event; } function HelpRouteEvent(doctype, docname) { - var delimitor = '_'; - var object = new RouteEvent(category, action, label); function category() { @@ -116,11 +116,11 @@ TrackingService.factory('Tracker', [ } function action() { - return category()+delimitor+doctype; + return category()+separator+doctype; } function label() { - return action()+delimitor+docname; + return action()+separator+docname; } return object; @@ -128,20 +128,18 @@ TrackingService.factory('Tracker', [ function SparqlSearchRouteEvent(output) { - var delimitor = '_'; - function category() { return 'search'; } function action() { - return category()+delimitor+'sparql'; + return category()+separator+'sparql'; } function label() { - return action()+delimitor+((output) ? output : 'html'); + return action()+separator+((output) ? output : 'html'); } return new RouteEvent(category, action, label); @@ -163,6 +161,27 @@ TrackingService.factory('Tracker', [ return query; } + // The ga() function provides a single access point for everything in the analytics.js library + // all tracking calls are made via the ga() function + function createAndInitGATracker(propertyId) { + + // Google Analytics + // Asynchronously loads the analytics.js library onto this page + (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'); + + // Creates a new default tracker object + ga('create', propertyId, 'auto'); + } + + // Setup Universal Analytics Web Tracking (analytics.js) + createAndInitGATracker('UA-61448300-1'); + + // Sends a first pageview hit for the current page to Google Analytics + ga('send', 'pageview'); + return tracker; }]); From 8b1256a8cf7c593539d95308e576cf5e21f80bf8 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Fri, 17 Apr 2015 13:13:49 +0200 Subject: [PATCH 23/25] Handle exception tracking --- app/js/tracker/snorql.tracker.service.js | 27 +++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js index a9789fe..56b7f24 100644 --- a/app/js/tracker/snorql.tracker.service.js +++ b/app/js/tracker/snorql.tracker.service.js @@ -6,7 +6,9 @@ TrackingService.factory('Tracker', [ '$window', '$location', '$routeParams', - function ($window, $location, $routeParams) { + 'version', + 'build', + function ($window, $location, $routeParams, version, build) { var separator = '_'; @@ -67,12 +69,27 @@ TrackingService.factory('Tracker', [ tracker.trackSearchTermEvent = function(term, hasSucceed) { - var gaEvent = newSearchTermEvent(term); + if (!hasSucceed) { - if (hasSucceed) gaEvent.eventLabel = gaEvent.eventLabel+separator+'success'; - else gaEvent.eventLabel = gaEvent.eventLabel+separator+'failure'; + var exceptionEvent = { + 'exDescription': 'could not search term "'+term+'"', + 'exFatal': false, + 'appName': 'nextprot-snorql', + 'appVersion': version + }; - ga('send', gaEvent); + if (!isNaN(build)) + exceptionEvent.appVersion += "-build."+build; + + console.log("tracking searching term exception -> ga event:", exceptionEvent); + ga('send', 'exception', exceptionEvent); + } else { + + var gaEvent = newSearchTermEvent(term); + + console.log("tracking searching term event -> ga event:", gaEvent); + ga('send', gaEvent); + } }; function newSearchTermEvent(term) { From 34e985cedf56cd3d94503050b116990b4e3a284d Mon Sep 17 00:00:00 2001 From: fnikitin Date: Fri, 17 Apr 2015 15:54:19 +0200 Subject: [PATCH 24/25] Setting up develop/production tracking id selection. --- app/js/tracker/snorql.tracker.service.js | 25 ++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js index 56b7f24..b70d5fb 100644 --- a/app/js/tracker/snorql.tracker.service.js +++ b/app/js/tracker/snorql.tracker.service.js @@ -2,13 +2,20 @@ var TrackingService = angular.module('snorql.tracker', []); +TrackingService + .value('developTrackingId', 'UA-61448300-1') + .value('productionTrackingId', 'UA-61448300-2') + .value('trackingProduction', 'NX_TRACKING_PROD'); + TrackingService.factory('Tracker', [ '$window', '$location', '$routeParams', - 'version', - 'build', - function ($window, $location, $routeParams, version, build) { + 'version', 'build', + 'developTrackingId','productionTrackingId','trackingProduction', + function ($window, $location, $routeParams, + version, build, + developTrackingId, productionTrackingId, trackingProduction) { var separator = '_'; @@ -193,8 +200,18 @@ TrackingService.factory('Tracker', [ ga('create', propertyId, 'auto'); } + function getTrackingId() { + + var trackingId = (trackingProduction != 'NX_TRACKING_PROD') ? productionTrackingId : developTrackingId; + + console.log('tracking ids: develop:', developTrackingId, ', production:', productionTrackingId); + console.log('tracking '+trackingId); + + return trackingId; + } + // Setup Universal Analytics Web Tracking (analytics.js) - createAndInitGATracker('UA-61448300-1'); + createAndInitGATracker(getTrackingId()); // Sends a first pageview hit for the current page to Google Analytics ga('send', 'pageview'); From 49ca8008d3fc2c5f2c6645bfd010afc8193198b3 Mon Sep 17 00:00:00 2001 From: fnikitin Date: Fri, 17 Apr 2015 17:50:46 +0200 Subject: [PATCH 25/25] Ready to track contact us click --- app/js/tracker/snorql.tracker.service.js | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/app/js/tracker/snorql.tracker.service.js b/app/js/tracker/snorql.tracker.service.js index b70d5fb..6f5bcaf 100644 --- a/app/js/tracker/snorql.tracker.service.js +++ b/app/js/tracker/snorql.tracker.service.js @@ -31,9 +31,10 @@ TrackingService.factory('Tracker', [ 'hitType': 'event', 'eventCategory': 'snorql'+separator+'routing-'+dest }; - console.log("tracking route -> ga event:", gaEvent); if (Object.keys(gaEvent).length>0) { + + console.log("tracking transition route -> ga event:", gaEvent); ga('send', gaEvent); } }; @@ -52,9 +53,9 @@ TrackingService.factory('Tracker', [ gaEvent = new SparqlSearchRouteEvent($routeParams.output); } - console.log("tracking route -> ga event:", gaEvent); - if (Object.keys(gaEvent).length>0) { + + console.log("tracking route -> ga event:", gaEvent); ga('send', gaEvent); } }; @@ -69,7 +70,7 @@ TrackingService.factory('Tracker', [ gaEvent.eventAction = gaEvent.eventCategory; gaEvent.eventLabel = gaEvent.eventAction+separator+formatQueryId(selectedQueryId); - console.log("tracking selection event -> ga event:", gaEvent); + console.log("tracking example selection event -> ga event:", gaEvent); ga('send', gaEvent); }; @@ -99,6 +100,19 @@ TrackingService.factory('Tracker', [ } }; + tracker.trackContactUsEvent = function(subject) { + + var gaEvent = { + 'hitType': 'event', + 'eventCategory': 'snorql'+separator+'contact-us' + }; + + gaEvent.actionCategory = gaEvent.eventCategory+separator+subject; + + console.log("tracking contacting us -> ga event:", gaEvent); + ga('send', gaEvent); + }; + function newSearchTermEvent(term) { var gaEvent = {