JavaScript Event-Tracking

Event-Tracking mit und ohne Google

[im Moment nur für http]

[im Moment nur für http]

In diesem Beispiel werden Aufrufe von externen Links, sprünge auf Sprungmarken, mailto, tel, Downloads, Videos und Audios als auch Ereignisse wie Scrollen auf der Seite oder Verlassen der Seite selbst das umschalten auf einen anderen Tab über XMLHttpRequest (Ajax) an den Server (aufgerufene Adresse) zurückgemeldet. Eine Routine auf dem Server kann dann einfach an Hand der POST Parameter die Zugriffe analysieren.

GoogleAnalytics Code und die Event-Tracking Erweiterung JavaScript (694 bytes) 14.05.2016 12:03
(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-XXXXXXX-X', 'auto');
ga('require', 'displayfeatures');
ga('set', 'anonymizeIp', true);
ga('send', 'pageview');
 
// activate GA event tracking
// Copyright 2016 Udo Schmal www.gocher.me
// http://www.gocher.me/Event-Tracking
(function(){
  var s=document.createElement('script');
  s.src='http://www.gocher.me/code/ga.js';
  document.body.appendChild(s);})();
Art Kategorie Aktion Label Wert
externe Links external click url des Links 1
Sprung zu einer Sprungmarke internal click id der Sprungmarke 1
E-Mail mailto: Link email click E-Mail-Adresse 1
Telefonnummer telefone click Telefonnummer 1
Download Link download click url der Datei 1
Button Klick button click id - Caption 1
Input Type Button Klick input-[type] click id - Value 1
Video Start video play url des Videos Zeit in ms
Video Pause video pause url des Videos Zeit in ms
Video Beendet video ended url des Videos Zeit in ms
Audio Start audio play url der Audiodatei Zeit in ms
Audio Pause audio pause url der Audiodatei Zeit in ms
Audio Beendet audio ended url der Audiodatei Zeit in ms
Anzeige der Seite Time on Page show url der Seite
Zeit in ms
Seite nicht mehr sichtbar, z.B. neuer Tab Time on Page hide gemessene sichtbare Zeit in ms Zeit in ms
Verlassen der Seite Time on Page leave gemessene gesamte sichtbare Zeit in ms Zeit in ms
Scroll Event Scroll Depth Percentage Baseline, 25%, 50%, 75%, 100% 1
Code:
tracking.js JavaScript (10,24 kByte) 11.05.2016 20:40
/*jslint indent: 2, white: true, browser: true, devel: true, plusplus: true, regexp: true */
'use strict';
(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-XXXXXXX-X', 'auto');
ga('require', 'displayfeatures');
ga('set', 'anonymizeIp', true);
ga('send', 'pageview');

function ready(f) {
  if (/complete|loaded/i.test(document.readyState)) {
    f();
  } else {
    setTimeout("ready("+f+")",9);
  }
}
function Analyse() {
  this.scrollTrue = false;
  this.scroll25 = false;
  this.scroll50 = false;
  this.scroll75 = false;
  this.scroll100 = false;
  this.winHeight = null;
  this.docHeight = null;
  this.totalTime = 0;  
  this.startTime = null;
  this.hidden = null;
}
Analyse.prototype = {
  addListener: function (target, eventName, listener) {
    if (target.addEventListener) {
      target.addEventListener(eventName, listener, false);
    } else if (target.attachEvent) {
      target.attachEvent("on"+eventName, listener);
    } else {
      target["on"+eventName] = listener;
    }
  },
  send: function (type, category, action, label, value) {
    // console ouput
    console.log("send('" + type + "', '" + category + "', '" + action + "', '" + label + "', '" + value + "');");
    // google analytics output
    ga('send', type, category, action, label, value);
/*
    // own analyser output
    var xhr;
    try {
      xhr = new XMLHttpRequest(); 
      if (xhr) {
        xhr.onreadystatechange = function (){};
        xhr.open('post', window.location.pathname);
        xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded");
        xhr.send('cmd=' + type + '&category=' + category + '&action=' + action + '&label=' + label + '&value=' + value );
      }
    } catch (e) { };
*/
  },
  click: function (el) {
    var base, baseHref, href, extension, isThisDomain, category = null, action = null, label = null;
    switch (el.tagName.toLowerCase()) {
    case 'a':
      base = document.getElementsByTagName('base');
      baseHref = (base.length > 0 ? baseHref = base[0].href : window.location.protocol + "://" + window.location.host + "/");
      href = el.getAttribute('href');
      if (href === undefined) { 
        href = "";
      }
      isThisDomain = href.match(document.domain.split('.').reverse()[1] + '.' + document.domain.split('.').reverse()[0]);
      if (!href.match(/^javascript:/i)) {
        if (href.match(/^mailto\:/i)) {
          category = "email";
          action = "click";
          label = href.replace(/^mailto\:/i, '');
        } else if (href.match(/^#/i)) {
          category = "internal";
          action = "click";
          label = href.replace(/^#/i, '');
        } else if (href.match(/\.(zip|exe|dmg|pdf|doc.*|xls.*|ppt.*|mp3|txt|rar|wma|mov|avi|wmv|flv|wav)$/i)) {
          extension = (/[.]/.exec(href)) ? /[^.]+$/.exec(href) : undefined;
          category = "download";
          action = "click-" + extension[0].toLowerCase();
          label = href.replace(/ /g, "-");
        } else if (href.match(/^https?\:/i) && !isThisDomain) {
          category = "external";
          action = "click";
          label = href.replace(/^https?\:\/\//i, '');
        } else if (href.match(/^tel\:/i)) {
          category = "telephone";
          action = "click";
          label = href.replace(/^tel\:/i, '');
        }
      }
      break;
    case 'button':
      category = "button";
      action = "click";
      label = (el.getAttribute('id') ?  el.getAttribute('id') + ' - ' : '') + el.textContent || el.innerText;
      break;
    case 'input':
      category = "input-" + el.getAttribute('type');
      action = "click";
      label = (el.getAttribute('id') ?  el.getAttribute('id') + ' - ' : '') + el.value;
      break;
    }
    if ((category !== null) && (action !== null)) {
      this.send('event', category, action, encodeURIComponent(label), 1);
      if ((el.tagName === 'a') && (el.getattribute('target') === undefined || el.getattribute('target').tolowercase() !== '_blank')) {
        setTimeout(function() { location.href = href; }, 400);
        return false;
      }
    }
  },
  resize: function () {
    var body = document.body, doc = document.documentElement;
    this.winHeight = window.innerHeight || doc.clientHeight || body.clientHeight;
    this.docHeight = Math.max(body.scrollHeight, body.offsetHeight, doc.clientHeight, doc.scrollHeight, doc.offsetHeight);
  },
  scroll: function () {
    var scrollPos = 0, scrollPer;
    if (typeof(window.pageYOffset) === 'number') {
      //Netscape compliant
      scrollPos = window.pageYOffset;
    } else if (document.body && document.body.scrollTop) {
      //DOM compliant
      scrollPos = document.body.scrollTop;
    } else if (document.documentElement && document.documentElement.scrollTop) {
      //IE6 standards compliant mode
      scrollPos = document.documentElement.scrollTop;
    }
    scrollPer = (scrollPos / (this.docHeight - this.winHeight)) * 100;
    if ((scrollPer > 90) && !this.scroll100) {
      this.scroll100 = true;
      this.send("event", "Scroll Depth", "Percentage", "100%", 1);
    } else if ((scrollPer > 75) && !this.scroll75) {
      this.scroll75 = true;
      this.send("event", "Scroll Depth", "Percentage", "75%", 1);
    } else if ((scrollPer > 50) && !this.scroll50) {
      this.scroll50 = true;
      this.send("event", "Scroll Depth", "Percentage", "50%", 1);
    } else if ((scrollPer > 25) && !this.scroll25) {
      this.scroll25 = true;
      this.send("event", "Scroll Depth", "Percentage", "25%", 1);
    } else if ((scrollPer > 120) && !this.scrollTrue) {
      this.scrollTrue = true;
      this.send("event", "Scroll Depth", "Percentage", "Baseline", 1);
    }
  },
  unload: function () {
    var diffTime = 0;
    if (this.startTime !== null) {
      diffTime = new Date().getTime() - this.startTime;
    }
    this.send("event", "Time on Page", "leave", window.location.pathname, this.totalTime + diffTime);
  },
  visibilityChange: function () {
    if (document[this.hidden]) {
      var diffTime = new Date().getTime() - this.startTime;
      this.totalTime = this.totalTime + diffTime;
      this.startTime = null;
      this.send("event", "Time on Page", "hide", window.location.pathname, diffTime);
    } else {
      this.startTime = new Date().getTime();
      this.send("event", "Time on Page", "show", window.location.pathname, this.totalTime);
    }
  },
  play: function (el) {
    var label = el.currentSrc.replace(/^https?\:\/\//i, '') || el.id;
    this.send('event', el.tagName.toLowerCase(), 'play', label, (el.currentTime * 1000).toFixed(0));
  },
  pause: function (el) {
    var label = el.currentSrc.replace(/^https?\:\/\//i, '') || el.id;
    this.send('event', el.tagName.toLowerCase(), 'pause', label, (el.currentTime * 1000).toFixed(0));
  },
  ended: function (el) {
    var label = el.currentSrc.replace(/^https?\:\/\//i, '') || el.id;
    this.send('event', el.tagName.toLowerCase(), 'ended', label, (el.currentTime * 1000).toFixed(0));
  },
  iterate:  function (el) {
    var self = this, childs;
    el = el || document.getElementsByTagName("body")[0];
    if (el.nodeType === 1) {
      switch (el.tagName.toLowerCase()) {
        case "a": // ini link click tracking
          if (el.getAttribute('href')) {
            if ((el.getAttribute('href') !== undefined) && (el.getAttribute('href').indexOf('javascript:') === -1)) {
              this.addListener(el, 'click', function (event) { self.click(this); });
            }
          }
          break;
        case "button": // init button click tracking
          this.addListener(el, 'click', function (event) { self.click(this); });
          break;
        case "input": // init input type button click tracking
          if (el.getAttribute('type').match(/(button|image|reset|submit)$/i)) {
            this.addListener(el, 'click', function (event) { self.click(this); });
          }
          break;
        case "video": // init video  tracking
          this.addListener(el, "play", function (event) { self.play(this); });
          this.addListener(el, "pause", function (event) { self.pause(this); });
          this.addListener(el, "ended", function (event) { self.ended(this); });
          break;
        case "audio": // init video & audio tracking
          this.addListener(el, "play", function (event) { self.play(this); });
          this.addListener(el, "pause", function (event) { self.pause(this); });
          this.addListener(el, "ended", function (event) { self.ended(this); });
          break;
      }
      childs = el.firstChild;
      while (childs !== null) {
        if (childs.nodeType === 1) {
          this.iterate(childs);
        }
        childs = childs.nextSibling;
      }
    }
  },
  init: function () {
    this.startTime = new Date().getTime();
    var self = this, el, els, visibilityChange, i;
    // init scroll tracking
    this.resize();
    this.addListener(window, 'resize', function () { self.resize(); });
    this.addListener(window, 'scroll', function () { self.scroll(); });
    // init time on page tracking
    if (document.hidden !== undefined) {
      this.hidden = "hidden";
      visibilityChange = "visibilitychange";
    } else if (document.mozHidden !== undefined) {
      this.hidden = "mozHidden";
      visibilityChange = "mozvisibilitychange";
    } else if (document.msHidden !== undefined) {
      this.hidden = "msHidden";
      visibilityChange = "msvisibilitychange";
    } else if (document.webkitHidden !== undefined) {
      this.hidden = "webkitHidden";
      visibilityChange = "webkitvisibilitychange";
    }
    this.addListener(document, visibilityChange, function () { self.visibilityChange(); }); 
    this.addListener(window, 'unload', function () { self.unload(); });
    this.send("event", "Time on Page", "show", window.location.pathname, this.totalTime);
    this.iterate();
  }
};

ready(function(event) {
  var analyse = new Analyse();
  analyse.init();
});

Autor: , veröffentlicht: , letzte Änderung:

Kontakt

Copyright / License of sources

Copyright (c) 2007-2017, Udo Schmal <udo.schmal@t-online.de>

Permission to use, copy, modify, and/or distribute the software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

Service Infos

CMS Info
UDOs Webserver

0.3.1.24

All in one Webserver

Udo Schmal

Sa, 21 Okt 2017 00:30:10
Development Info
Lazarus LCL 1.9.0.0

Free Pascal FPC 3.1.1

OS:Win64, CPU:x86_64
Hardware Info
Precision WorkStation T3500

Intel(R) Xeon(R) CPU W3530 @ 2.80GHz

x86_64, 1 physical CPU(s), 4 Core(s), 8 logical CPU(s), 2800 MHz