-
Notifications
You must be signed in to change notification settings - Fork 14
Google Analytics helper #37
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Google Analytics helper #37
Conversation
…e tracking (automatically triggered on view change, so the method never has to be called manually) and event tracking.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the idea of this PR and its simplicity, thanks for the proposal 👍
Even though more complete libraries like angulartics, having the possibility to quickly add GA page/event tracking through a simple single file service.
After the PR is fixed, I'll merge it to separate feature branch before going to master so it can be enabled or not via a Yeoman prompt, and directly enter the GA account ID from there.
| // and then it's fired a second time after is has been linked. This is "by design" :-/ | ||
| // (http://stackoverflow.com/questions/31000417/angular-js-viewcontentloaded-loading-twice-on-initial-homepage-load) | ||
| let loadedOnce = false; | ||
| vm.$on('$viewContentLoaded', function () { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use $stateChangeSuccess like the hook to update title on route changes?
This should fix the need for the "hack" :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per ui-router documentation (link) :
State change events are deprecated, DISABLED and replaced by Transition Hooks as of version 1.0
Note that the view load events are not deprecated. So maybe the real solution is to look into transition hooks ? But that's a different beast altogether.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LOL, missed that since we are still on the 0.3.x version and the 1.x version has not been finalized yet 😅
I have created a separate issue for the migration to using $transitions hooks (see #38 ), for the meanwhile it's still a valid change (until 1.0.0 version is out) that will get rid of the ugly hack, and it will simplify the migration task, as it will be needed anyway as we use it elsewhere.
Thanks for pointing that!
|
|
||
| private init(): void { | ||
| if (this.config.analyticsAccount !== null) { | ||
| let analyticsScriptUrl = '//www.google-analytics.com/analytics.js'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be better to define it as a const on the beginning of the file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| private init(): void { | ||
| if (this.config.analyticsAccount !== null) { | ||
| let analyticsScriptUrl = '//www.google-analytics.com/analytics.js'; | ||
| this.createGoogleAnalyticsObject(window, document, 'script', analyticsScriptUrl, 'googleAnalytics'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use this.$window instead of window
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Last parameter should be 'ga' instead of 'googleAnalytics' so other libraries depending on google analytics can also use it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both done (although replacing an explicit field name with an obfuscated one does not sit right with me).
| private config: IApplicationConfig, | ||
| logger: LoggerService) { | ||
|
|
||
| this.logger = logger.getLogger('analyticsService'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Logger not needed if it's not used, or maybe it could be used to log tracked events?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Absolutely, logging tracked events was the point. I must have lost it somewhere along the road ; will fix it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done earlier (with previous changes).
|
|
||
| this.logger = logger.getLogger('analyticsService'); | ||
|
|
||
| this.init(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer a public init() method not called in constructor but in app init (in main.run.ts) explicitely, so we can also pass custom GA configuration as an optional argument for the create call.
This is also mandatory for mobile/Cordova compatibility, as specific configuration is needed for GA to work with file:// protocol used in Cordova.
This would also allow us to disable analytics in debug environment, as it is most of the time only wanted on production and it can mess with unit tests by generating extra HTTP calls.
See this example except from a mobile of mine, to make it work with Cordova (located in init() method of main.run.ts, it uses amgulartics but the idea is the same:
// Setup analytics
if (!config.environment.debug && $window['ga']) {
// Warning, breaks unit tests if included in debug!
$window['ga']('create', config.googleAnalyticsId, {
'storage': 'none',
'clientId': $cordovaDevice.getUUID()
});
// Allow file:// protocol for cordova
$window['ga']('set', 'checkProtocolTask', (data: any) => {
data.set('location', 'https://htf2016.app/');
});
$window['ga']('set', 'appVersion', config.version);
$analytics.eventTrack('App started', { value: vm.festival.version });
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the responsibility of customizing the creation of the GA object lies within the analytics service. All the Cordova specific code can be added in analytics-service instead of main-run.
Regarding disabling of analytics in debug, there are some cases where having them on is useful (typically when one wants to test out a newly-added event tracker). Of course you would want a different analytics account for debugging and for actual production, but that is just a matter of setting up the gulp-replace task around IApplicationConfig.googleAnalyticsId. If you want to disable them entirely in debug mode, it can also be done the same way, by setting the value to null in debug mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe the responsibility of customizing the creation of the GA object lies within the analytics service. All the Cordova specific code can be added in analytics-service instead of main-run.
I completely agree with that, I just posted it to show a mobile setup ;)
Regarding disabling of analytics in debug, there are some cases where having them on is useful (typically when one wants to test out a newly-added event tracker). Of course you would want a different analytics account for debugging and for actual production, but that is just a matter of setting up the gulp-replace task around IApplicationConfig.googleAnalyticsId. If you want to disable them entirely in debug mode, it can also be done the same way, by setting the value to null in debug mode.
In my idea disabling analytics in debug would be done in main.run.ts by calling or not the analyticsService.init(), so if needed the behavior can be changed. But it's a good idea to just check if googleAnalyticsId is defined to activate or not GA in the init() method, so the you just need to move the googleAnalyticsId in the environment object so there can be an value for each environment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: googleAnalyticsId moved from Config to Environment.
| } | ||
| } | ||
|
|
||
| app.service('analyticsService', AnalyticsService); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since it is a service, unit tests are mandatory (though they will be quite simple as GA will be mocked) and should be added :)
| version: string; | ||
| environment: IApplicationEnvironment; | ||
| supportedLanguages: Array<string>; | ||
| analyticsAccount: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be more explicit to rename it googleAnayticsId
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
…r-pro Conflicts: generators/app/templates/sources/main/_main.constants.ts
|
Do not forget the unit tests, so I can merge it ;) |
|
I did not forget them, I just don't see how to proceed, considering than I can not actually mock GA (which is loaded from the Google URL by a private function). I will come back to this issue when I have more time on my hands. |
|
This PR has been merged on feature/analytics so I can add the generation prompt to opt in/out the service. |
Added analytics service in /helpers. This services supports basic page tracking (automatically triggered on view change, so the function never has to be called manually) and event tracking by calling the provided function.