add async tracking snippet with command queue exampel

This commit is contained in:
Danny van Kooten 2016-11-25 16:03:47 +01:00
parent 87e7020ce2
commit 31130b8fe4
6 changed files with 71 additions and 26 deletions

0
LICENSE Normal file
View File

View File

@ -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
<!-- Ana tracker -->
<script>
(function(d, w, u, o){
w[o]=w[o]||function(){
(w[o].q=w[o].q||[]).push(arguments)
};
a=d.createElement('script'),
m=d.getElementsByTagName('script')[0];
a.async=1;
a.src=u;
m.parentNode.insertBefore(a,m)
})(document, window, '//ana.dev/tracker.js', 'ana');
ana('setTrackerUrl', '//ana.dev/collect');
ana('trackPageview');
</script>
<!-- / Ana tracker -->
```

View File

@ -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.

1
ana.go
View File

@ -39,6 +39,7 @@ func main() {
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))

View File

@ -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));

View File

@ -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'] );
});