From 31130b8fe4a0cae1a498b3942f3c997ad3a0d6a5 Mon Sep 17 00:00:00 2001 From: Danny van Kooten Date: Fri, 25 Nov 2016 16:03:47 +0100 Subject: [PATCH] add async tracking snippet with command queue exampel --- LICENSE | 0 README.md | 21 +++++++++++++++ ROADMAP.md | 1 - ana.go | 3 ++- assets/js/tracker.js | 63 ++++++++++++++++++++++++++++---------------- gulpfile.js | 9 +++++-- 6 files changed, 71 insertions(+), 26 deletions(-) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index 1fd3106..593540a 100644 --- a/README.md +++ b/README.md @@ -4,3 +4,24 @@ Ana. Open Source Web Analytics. This is nowhere near being usable, let alone stable. Treat as a proof of concept. ![Screenshot of the Ana dashboard](https://github.com/dannyvankooten/ana/raw/master/assets/img/screenshot.png?2) + +## Usage + +```html + + + +``` diff --git a/ROADMAP.md b/ROADMAP.md index af7c578..a95debe 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -5,7 +5,6 @@ This is a general draft document for thoughts and todo's. This has no structure. ### What's cooking? -- Async tracking snippet. - Add license file. - Get DB creds from env. - JS client for consuming API endpoints. diff --git a/ana.go b/ana.go index 07c6147..d5d6489 100644 --- a/ana.go +++ b/ana.go @@ -37,8 +37,9 @@ func main() { r.Handle("/api/screen-resolutions", api.Authorize(api.GetScreenResolutionsHandler)).Methods("GET") r.Handle("/api/countries", api.Authorize(api.GetCountriesHandler)).Methods("GET") r.Handle("/api/browsers", api.Authorize(api.GetBrowsersHandler)).Methods("GET") - + r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static/")))) + r.Path("/tracker.js").Handler(http.FileServer(http.Dir("./static/js/"))) r.Handle("/", http.FileServer(http.Dir("./views/"))) http.ListenAndServe(":8080", handlers.LoggingHandler(os.Stdout, r)) diff --git a/assets/js/tracker.js b/assets/js/tracker.js index dad826f..642601b 100644 --- a/assets/js/tracker.js +++ b/assets/js/tracker.js @@ -1,27 +1,37 @@ 'use strict'; -(function() { - function jsonToQueryString(json) { - var keys = Object.keys(json); +var queue = window.ana.q || []; +var trackerUrl = '//ana.dev/collect'; +var commands = { + "trackPageview": trackPageview, + "setTrackerUrl": setTrackerUrl, +}; - // omit empty - keys = keys.filter(function(k) { - return json[k].length > 0; - }); +// convert object to query string +function stringifyObject(json) { + var keys = Object.keys(json); - return '?' + - keys.map(function(k) { - return encodeURIComponent(k) + '=' + - encodeURIComponent(json[k]); - }).join('&'); + // omit empty + keys = keys.filter(function(k) { + return json[k].length > 0; + }); + + return '?' + + keys.map(function(k) { + return encodeURIComponent(k) + '=' + + encodeURIComponent(json[k]); + }).join('&'); +} + +function setTrackerUrl(v) { + trackerUrl = v; +} + +function trackPageview() { + if( navigator.DonotTrack == 1 ) { + return; } - // abort hit if Do Not Track is enabled. - // if( navigator.DonotTrack == 1 ) { - // return; - // } - - var i = document.createElement('img'); var d = { l: navigator.language, p: location.pathname + location.search, @@ -30,8 +40,17 @@ r: document.referrer }; - - i.src = 'http://localhost:8080/collect' + jsonToQueryString(d); - + var i = document.createElement('img'); + i.src = trackerUrl + stringifyObject(d); document.body.appendChild(i); -})(); +} + +// override global ana object +window.ana = function() { + var args = [].slice.call(arguments); + var c = args.shift(); + commands[c].apply(this, args); +}; + +// process existing queue +queue.map((i) => ana.apply(this, i)); diff --git a/gulpfile.js b/gulpfile.js index 2a0a72a..457be8a 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -11,7 +11,7 @@ const rename = require('gulp-rename'); const gutil = require('gulp-util'); const sass = require('gulp-sass'); -gulp.task('default', [ 'browserify', 'sass' ] ); +gulp.task('default', [ 'browserify', 'sass', 'tracker' ] ); gulp.task('browserify', function () { return browserify({ @@ -29,6 +29,11 @@ gulp.task('browserify', function () { .pipe(gulp.dest('./static/js/')) }); +gulp.task('tracker', function() { + return gulp.src('./assets/js/tracker.js') + .pipe(gulp.dest('./static/js')) +}); + gulp.task('sass', function () { var files = './assets/sass/[^_]*.scss'; return gulp.src(files) @@ -39,6 +44,6 @@ gulp.task('sass', function () { }); gulp.task('watch', ['default'], function() { - gulp.watch(['./assets/js/**/*.js'], ['browserify'] ); + gulp.watch(['./assets/js/**/*.js'], ['browserify', 'tracker'] ); gulp.watch(['./assets/sass/**/*.scss'], ['sass'] ); });