It was harder than I expected. Hope this helps.
Demo with examples
Javascript
$(document).off("ready.ga").on("ready", function () {
pageLoc = $(location).attr('href');
(function ($, window, undef) {
$.extend($.expr[":"], {
ga: function (a) {
var attr = a.attributes,
len = attr.length;
while (len--) {
if (attr[len].name.indexOf("data-ga-") !== -1) {
return true;
}
}
return false;
}
});
$.gaaApi = {
trackEvent: {
event: {
value: "_trackEvent",
validation: "isString",
type: "string"
},
category: {
value: null,
validation: "optString",
type: "currentloc"
},
action: {
value: null,
validation: "optString",
type: "string"
},
label: {
value: null,
validation: "optString",
type: "string"
},
value: {
value: null,
validation: "optInt",
type: "integer"
},
nonInteraction: {
value: null,
validation: "optBool",
type: "boolean"
}
},
trackPageview: {
event: {
value: ["trackPageview", $(location).attr('href')],
validation: "isString",
type: "string"
},
url: {
value: undef,
validation: "optString",
type: "string"
}
}
};
var validation = {
isString: function (obj) {
var empty = true;
if (obj && typeof obj === "string") {
empty = /^\s*$/.test(obj);
}
return !(empty);
},
optString: function (obj) {
if (obj === undef) {
return true;
}
return validation.isString(obj);
},
isInt: function (obj) {
return (/^[\-+]?\d+$/).test(obj) || (obj === +obj && obj === (obj | 0));
},
optInt: function (obj) {
if (obj === undef) {
return true;
}
return validation.isInt(obj);
},
isFloat: function (obj) {
return (/^[\-+]?\d+(\.\d+)?$/).test(obj) || (obj === +obj && obj !== (obj | 0));
},
optFloat: function (obj) {
if (obj === undef) {
return true;
}
return validation.isFloat(obj);
},
isBool: function (obj) {
return (obj === true || obj === "true") || (obj === false || obj === "false");
},
optBool: function (obj) {
if (obj === undef) {
return true;
}
return validation.isBool(obj);
}
},
methods = {
validate: function (param, name, location) {
var $element = this.$element,
data = $element.data("ga-" + name.toLowerCase()),
isValid;
if (!validation[param.validation]) {
throw new TypeError("Unknown validation type");
}
isValid = validation[param.validation](data);
if (!isValid) {
throw new Error("object validation error on " + name);
}
switch (param.type) {
case "integer":
return data ? parseInt(data, 10) : null;
case "float":
return data ? parseFloat(data) : null;
case "boolean":
return data ? Boolean(data) : null;
case "currentloc":
return data;
default:
return data ? data + "" : null;
}
},
createArgs: function () {
var binder = this,
event = this.event,
args = $.map(event, function (val, key, pageLoc) {
var pageLoc = $(location).attr('href');
var value;
if (key === "event") {
value = val.value;
} else {
value = methods.validate.call(binder, val, key, pageLoc);
}
return value;
});
return args;
}
},
gaa = function (element, options) {
this.$element = $(element);
this.options = $.extend({}, $.fn.gaa.defaults, options);
};
gaa.prototype = {
constructor: gaa,
trackEvent: function () {
var trackedEvent = $.Event("tracked.ga");
var currentLoc = $(location).attr('href');
this.args = methods.createArgs.call(this);
if (this.options.logit) {
if (window.console && window.console.log) {
console.log("pushing to Google analytics", this.args);
this.$element.trigger(trackedEvent).trigger(currentLoc);
}
} else {
var gaq = window._gaq;
if (gaq) {
var binder = this;
$.when(gaq.push(args)).done(
function () {
this.$element.trigger(trackedEvent);
setTimeout(function () {
var href = binder.attr("href");
if (href && href.indexOf("#") !== 0) {
window.location = href;
}
}, 100);
});
} else {
throw new ReferenceError(" _gaq not there");
}
}
}
};
$.fn.gaa = function (options) {
return this.each(function () {
var $this = $(this),
data = $this.data("ga"),
opts = typeof options === "object" ? options : null;
if (!data) {
$this.data("ga", (data = new gaa(this, opts)));
}
if (typeof options === "string") {
data[options]();
} else {
var handler = data.options.handler.toLowerCase(),
event = data.$element.attr("data-ga-event");
$.extend(data.options, {
event: event
});
data.event = $.gaaApi[data.options.event];
if (handler === "load") {
data.trackEvent();
} else {
data.$element.on(handler + ".ga", function (e) {
e.preventDefault();
data.trackEvent();
});
}
}
});
};
$.fn.gaa.defaults = {
event: ["trackEvent", "giveLocation"],
handler: "load",
logit: false
};
$.fn.gaa.Constructor = gaa;
$(document).on("ready.ga", function () {
$(":ga").each(function () {
$(this).gaa();
});
});
}(jQuery, window));
var options = {
event: "trackEvent",
handler: "click",
logit: true,
};
var options2 = {
event: "trackPageview",
handler: "click",
logit: true,
};
var options3 = {
event: "trackPageview",
handler: "load",
logit: true
};
$("load.trigger").gaa(options3);
$("button.button1").gaa(options2).click(function () {
console.log('\nmore button events\n', 'heres the URL:', location.href)
});
$("#clickme").gaa(options).click(function () {
$(this).toggleClass("changeIt");
});
});
index.html
<load class="trigger">loading triggers ga event</load>
<button class="button1">fire ga event with address</button>
<button class="button1" id="clickme">multiple events</button>
jquery .
event: {
value: ["trackPageview",$(location).attr('href')],
validation: "isString",
type: "string"
}
, , ga. ,
$("#button").gaa(options).click(function () {
$(this).toggleClass("changeIt");
});
.
. location.href, . , DOM, _gaq.