Skip to content

Instantly share code, notes, and snippets.

@josephfinlayson
Created June 15, 2016 14:23
Show Gist options
  • Save josephfinlayson/64cd7bfcfa2387b048199f3affeea148 to your computer and use it in GitHub Desktop.
Save josephfinlayson/64cd7bfcfa2387b048199f3affeea148 to your computer and use it in GitHub Desktop.
Analytics decorator
/**
* This function is used to push client side events to redshift. It should only be used for client side only events,
* any event that involves a request to the backend, will create similar events there
*
* ::USAGE::
* ========
*
* analyticsDecorator({
* constant: 'CONSTANT', mapping(arg1, arg2) {
* return {
* userClicked: arg1,
* colorOfButton: arg2
* }
*})
*
* decoratedMethod (arg1, arg2) {}
*
* @param constant {string} This is a constant that will be used for running Map/Reduce jobs or similar, and for
* generating dashboards
* @param mapping {function} This function takes the same arguments as the function we're decorating, and is used to
* provide readable information about the event occurring
* @returns {function}
*/
export default function analyticsDecorator ({constant, mapping}) {
/**
*
* @param classDefintion {object}
* @param methodName {string}
* @param descriptor {object}
* @returns {object}
*/
return function analyticsInterceptor (classDefinition, methodName, descriptor) {
// the method calls that require analytics binding, must also be bound the the class instance, this happens at
// runtime, SHOULD_BIND is so that class is bound marked as needing, and the corresponding methods marked with
// BIND_TO_INSTANCE are bound to the class
classDefinition.SHOULD_BIND = true;
const originalFunc = descriptor.value;
function sendAnalytics (instance, ...args) {
originalFunc.apply(instance, args);
// requestAnimationFrame for minor performance improvements, ensure analytics only runs on client side
window && window.requestAnimationFrame(() => {
let additionalData = {};
if (mapping) {
additionalData = mapping(...args);
}
analytics.track(constant, additionalData);
});
}
sendAnalytics.BIND_TO_INSTANCE = true;
// enumerable is set so that the methods can be enumerated and bound to the class
descriptor.enumerable = true;
descriptor.value = sendAnalytics;
return descriptor;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment