dist/ext/googletagmanager.js

File

			(function(global, undefined) { var kafe = global.kafe, $ = kafe.dependencies.jQuery; kafe.bonify({name:'ext.googletagmanager', version:'1.1.2', obj:(function(){
			
				var
			
					// Process data
					_processData = function(data, options) {
						data = _.clone(data);
						options = options || {};
						options.uri = options.uri || global.location.pathname;
			
						_.forEach(data, function(value, key) {
							var tmpl = _.template(value, {interpolate:/{{([\s\S]+?)}}/g});
							data[key] = tmpl(options);
			
							switch ($.type(options[key])) {
								case 'number': data[key] = Number(data[key]); break;
							}
						});
			
						return data;
					},
			
					_events = {}
				;
			
			
			
				/**
				* ### Version 1.1.2
				* Extra methods for the Google Tag Manager.
				* Requires GTM to be included
				*
				* @module kafe.ext
				* @class kafe.ext.googletagmanager
				*/
				var googletagmanager = {};
			
				/**
				* Add named events to the list of possible event to be tracked, with the possibility of replacement tokens.
				* Default tokens provided:
				*	- {{uri}}: Current pathname
				*
				* @method add
				* @param {Object} events List of possible events and their config
				*	@param {String} events.[0] The event type. Possible values are `ga_event`, `checkoutOption`, `productClick`, `productImpression`, `raw`
				*	@param {Object} events.[1] The event data. Different for each type. View code for implemantation.
				*
				* @example
				*	// Create named events
				*	kafe.ext.googletagmanager.add({
				*		'product-addedtocart': ['ga_event', {
				*			category: 'Cart',
				*			action:   'Product added - {{uri}}',
				*			label:    '{{productname}}',
				*			value:    '{{productvalue}}' // integer only
				*		}],
				*		'checkout-shipping': ['checkoutOption', {
				*			step:  'Shipping method',
				*			label: 'Shipped via {{method}}'
				*		}],
				*		'upsell-shown': ['productImpression', {
				*			id:       '{{sku}} - {{id}}',
				*			name:     '{{name}}',
				*			brand:    '{{productBrand}}',
				*			price:    '{{priceWithoutTaxes}}',
				*			category: '{{category}} / {{subcategory}}',
				*			position: '{{position}}',
				*			list:     'Upsell products',
				*			currency: 'CAD'
				*		}],
				*		'sunset-position': ['raw', {
				*			foo: 'bar',
				*			bar: 'foo'
				*		}]
				*	});
				*/
				googletagmanager.add = function(events) {
					_.merge(_events, events);
				};
			
			
				/**
				* Push a event into the `dataLayer`.
				*
				* @method track
				*	@param {String} name Event name
				*	@param {Object} [tokens] List of replacement tokens
				*
				* @example
				*	kafe.ext.googletagmanager.track('product-addedtocart', { productname: 'Sexy rainbow pants' });
				*	kafe.ext.googletagmanager.track('upsell-shown', [
				*		{
				*			sku: '123',
				*			price: 12.34,
				*			name: 'Sexy rainbow pants'
				*		},
				*		{
				*			sku: '456',
				*			price: 45.67,
				*			name: 'Plain beige skirt'
				*		}
				*	]);
				*/
				googletagmanager.track = function(name, tokens) {
					var deferred = $.Deferred();
			
					var event = _events[name];
			
					if (event) {
						var type = event[0];
						var options;
			
						// Process tokens
						switch (type) {
			
							//-- Multiple
							case 'productImpression':
								options = [];
								_.forEach(tokens, function(itemTokens) {
									options.push( _processData(event[1], itemTokens) );
								});
							break;
			
							//-- Single
							default:
								options = _processData(event[1], tokens);
							break;
						}
			
						// Format to GTM data
						switch (type) {
			
							//-- Google Analytics - Event
							case 'ga_event':
								data = {
									event:         'ga_event',
									eventCategory: options.category,
									eventAction:   options.action,
									eventLabel:    options.label,
									eventValue:    options.value
								};
							break;
			
							//-- Enhanced Ecommerce - Checkout option
							case 'checkoutOption':
								data = {
									event: 'checkoutOption',
									ecommerce: {
										checkout_option: {
											actionField: {
												step:   options.step,
												option: options.option
											}
										}
									}
								};
							break;
			
							//-- Enhanced Ecommerce - Product click
							case 'productClick':
								data = {
									event: 'productClick',
									ecommerce: {
										currencyCode: options.currency,
										click: {
											actionField: {
												list: options.list
											},
											products: [{
												id:       options.id,
												name:     options.name,
												brand:    options.brand,
												price:    options.price,
												category: options.category,
												position: options.position,
												list:     options.list
											}]
										}
									}
								};
							break;
			
							//-- Enhanced Ecommerce - Product impression
							case 'productImpression':
			
								var impressions = [];
			
								_.forEach(options, function(itemOptions) {
									impressions.push({
										id:       itemOptions.id,
										name:     itemOptions.name,
										brand:    itemOptions.brand,
										price:    itemOptions.price,
										category: itemOptions.category,
										position: itemOptions.position,
										list:     itemOptions.list
									});
								});
			
								data = {
									event: 'productImpression',
									ecommerce: {
										currencyCode: options[0].currency,
										impressions:  impressions
									}
								};
							break;
			
							//-- RAW
							case 'raw':
								data = options;
							break;
						}
			
			
						// Resolve when GTM responds
						data.eventCallback = function() {
							if (deferred.state() === 'pending') {
								deferred.resolve();
							}
						};
			
						// Reject after 1 sec
						global.setTimeout(function() {
							if (deferred.state() === 'pending') {
								deferred.reject();
							}
						}, 1000);
			
			
						global.dataLayer.push(data);
			
						return deferred.promise();
					}
				};
			
			
				return googletagmanager;
			
			})()}); })(typeof window !== 'undefined' ? window : this);