Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (function($, APP, undefined) {
- APP.Helpers.GTM = {
- data: {},
- debug: APP.GTM.debug || false,
- };
- /**
- * Проверяет загружен ли GTM
- * @return boolean
- */
- APP.Helpers.GTM.isActive = function() {
- window.dataLayer = window.dataLayer || [];
- var isInited = dataLayer
- .filter(function(value){
- return value.event == 'gtm.js'
- })
- .length > 0;
- var isReady = dataLayer
- .filter(function(value){
- return value.event == 'gtm.dom'
- })
- .length > 0;
- return (isInited && isReady);
- };
- /**
- * Парсит элемент промоблока
- * @param $el
- */
- APP.Helpers.GTM.getPromotion = function($el) {
- return {
- 'id': $el.data('id'),
- 'name': $el.data('name'),
- 'creative': $el.attr('href'),
- 'position': $el.data('position')
- };
- };
- /**
- * Проверяет отображаемые промо блоки и отправляет события по ним
- * + вешает событие для проверки изменения размера экрана для повторной проверки
- */
- APP.Helpers.GTM.checkPromoViewBlock = function($block) {
- if( !$block.data('promoViewSended') && $block.is(':visible') ) {
- $block.data('promoViewSended', true);
- var promotions = [];
- $block.find('.js-gtm-promoView--element').each(function(){
- promotions.push( APP.Helpers.GTM.getPromotion($(this)) );
- });
- APP.Helpers.GTM.promoView(promotions);
- } else if( !$block.data('promoViewInited') ){
- APP.Helpers.onResize(function() {
- APP.Helpers.GTM.checkPromoViewBlock($block)
- });
- }
- $block.data('promoViewInited', true);
- };
- /**
- * Обработчик клика на промоблок
- */
- APP.Helpers.GTM.handlerPromoClick = function(el, ev) {
- ev.preventDefault();
- var $el = $(el);
- var data = {};
- data.promotion = APP.Helpers.GTM.getPromotion($el);
- data.callback = function() {
- document.location = $el.attr('href');
- }
- APP.Helpers.GTM.promoClick(data);
- };
- /**
- * Отправка данных в GTM
- */
- APP.Helpers.GTM.push = function(data) {
- if( !data )
- return;
- // GTM как то умудряется запускать eventCallback даже если его основной скрипт вырезан блокировщиком рекламы
- // из-за этого он запускается дважды (см конец данной функции),
- // поэтому добавил очистку callback, для предотвращения двойного запуска
- // w1serg
- if( data.eventCallback ) {
- var oldEventCallback = data.eventCallback;
- data.eventCallback = function() {
- oldEventCallback();
- oldEventCallback = function() {};
- };
- // Задержка до запуска callback, вне зависимости от успешности отправки в GTM
- data.eventTimeout = 2000;
- }
- var err = false;
- try {
- if( !dataLayer )
- window.dataLayer = [];
- dataLayer.push(data);
- } catch (err) {
- // console.log(err);
- }
- // Если не загружен GTM – возможно он блокирован и не загрузится вовсе
- // Если ошибка
- // Если есть callback
- // Cразу запускаем callback
- if(
- (err !== false || !APP.Helpers.GTM.isActive())
- && data.eventCallback
- ) {
- data.eventCallback();
- }
- };
- /**
- * Событие отправки формы
- */
- APP.Helpers.GTM.formSent = function(data) {
- data.page = data.page || window.location.href;
- APP.Helpers.GTM.push({
- 'event': 'отправка формы',
- 'formSent': data
- });
- };
- /**
- * Событие открытия окна
- */
- APP.Helpers.GTM.windowOpened = function(data) {
- data.page = data.page || window.location.href;
- APP.Helpers.GTM.push({
- 'event': 'раскрытие окна формы',
- 'windowOpened': data
- });
- };
- /**
- * Событие оформления зазаза: новый шаг заказа
- * все параметры передаются через один объект data = {step: '', products: [{}], callback: function(){} }
- *
- * @param step номер этапа
- * @param products [{ 'name': 'Triblend Android T-Shirt', 'id': '12345', 'price': '15.25', 'brand': 'Google', 'category': 'Apparel', 'variant': 'Gray', 'quantity': 1 }]
- * @param callback событие для выполнения после отправки
- */
- APP.Helpers.GTM.orderSetState = function(data) {
- if( !data || !data.step || !data.products ) {
- if( data && data.callback ) {
- data.callback();
- }
- return false;
- }
- var actionField = {'step': data.step};
- if( data.step == 1 && !data.option ) {
- data.option = APP.Helpers.getNamePage();
- }
- if( data.option ) {
- actionField.option = data.option;
- }
- if( APP.Helpers.GTM.debug ) {
- alert("event: checkout\n\nStep: " + data.step + "\nProduct count: " + data.products.length);
- }
- APP.Helpers.GTM.push({
- 'event': 'checkout',
- 'ecommerce': {
- 'checkout': {
- 'actionField': actionField,
- 'products': data.products
- }
- },
- 'eventCallback': function() {
- if( data.callback )
- data.callback();
- }
- });
- };
- /**
- * Событие выбора способа оплаты
- *
- * @param data данные для отправки
- */
- APP.Helpers.GTM.getCheckoutOptionParams = function(data) {
- if (!data || !data.step || !data.paymentName ) {
- return false;
- }
- var actionField = {
- 'step': data.step,
- 'option': data.paymentName,
- };
- return {
- 'ecommerce': {
- 'checkout_option': {
- 'actionField': actionField
- }
- }
- };
- };
- /**
- * Событие оплаты заказа
- * все параметры передаются через один объект data = {id: 'T12345', total: '2411', shipping: '140', products: [{}], callback: function(){} }
- *
- * @param step номер этапа
- * @param products [{ 'name': 'Triblend Android T-Shirt', 'id': '12345', 'price': '15.25', 'brand': 'Google', 'category': 'Apparel', 'variant': 'Gray', 'quantity': 1 }]
- * @param callback событие для выполнения после отправки
- */
- APP.Helpers.GTM.orderSetPurchase = function(data) {
- if( !data || !data.id || !data.products || !data.total || !data.shipping ) {
- return false;
- }
- var actionField = {
- 'id': data.id,
- 'revenue': data.total,
- 'shipping': data.shipping,
- };
- if( APP.Helpers.GTM.debug ) {
- alert("event: purchase\n\nTotal: " + data.total);
- }
- APP.Helpers.GTM.push({
- 'event': 'purchase',
- 'ecommerce': {
- 'purchase': {
- 'actionField': actionField,
- 'products': data.products
- }
- },
- 'eventCallback': function() {
- if( data.callback )
- data.callback();
- }
- });
- };
- /**
- * Событие просмотра промоблока
- * @param array promotions
- */
- APP.Helpers.GTM.promoView = function(promotions) {
- APP.Helpers.GTM.push({
- 'event': 'promotionView',
- 'ecommerce': {
- 'promoView': {
- 'promotions': promotions
- }
- }
- });
- };
- /**
- * Событие клика на промоблок
- * все параметры передаются через один объект data = {promotion: {}, callback: function(){} }
- * @param object promotion
- * @param function callback
- */
- APP.Helpers.GTM.promoClick = function(data) {
- data.callback = data.callback || function(){};
- APP.Helpers.GTM.push({
- 'event': 'promotionClick',
- 'ecommerce': {
- 'promoClick': {
- 'promotions': [data.promotion]
- }
- },
- 'eventCallback': data.callback
- });
- };
- /**
- * Событие добавления к сравнению. data = {name: '', place: ''}
- *
- * @param data
- */
- APP.Helpers.GTM.compareAdd = function(data) {
- APP.Helpers.GTM.push({
- event: 'сравнение товаров',
- compareItems: {
- type: 'добавление к сравнению',
- place: data.place,
- item: data.name
- }
- });
- };
- /**
- * Событие удаления из сравнения. data = {name: '', place: ''}
- *
- * @param data
- */
- APP.Helpers.GTM.compareRemove = function(data) {
- APP.Helpers.GTM.push({
- event: 'сравнение товаров',
- compareItems: {
- type: 'удаление из сравнения',
- item: data.name
- }
- });
- };
- /**
- * Возвращает объект со списком товаров, переданным Helper::echoGtmProductList
- *
- * @param $container
- * @return object
- */
- APP.Helpers.GTM.parseProductList = function($container) {
- return $container.data('products');
- };
- /**
- * Функционал для работы с нумерацией внутри списка товаров
- * NB: Функция вызывает себя при определении, см замыкание
- *
- * @return object
- */
- APP.Helpers.GTM.position = function() {
- var module = {};
- var lists = {};
- module.getNext = function(listName) {
- if( !lists[listName] ) {
- lists[listName] = 0;
- }
- lists[listName]++;
- return lists[listName];
- }
- module.setCurrent = function(listName, offset) {
- lists[listName] = offset;
- }
- return module;
- }();
- /**
- * Контейнер для данных по товарам
- * NB: Функция вызывает себя при определении, см замыкание
- *
- * @return object
- */
- APP.Helpers.GTM.products = function() {
- var module = {};
- var list = {};
- var generalList = 'general';
- module.add = function(products, listName) {
- products.forEach(function(item) {
- listName = listName || item['list'] || generalList;
- if( !list[ listName ] ) {
- list[ listName ] = {};
- }
- list[ listName ][ item['id'] ] = item;
- });
- };
- module.get = function(id, listName) {
- var product = false;
- listName = listName || generalList;
- if( list[ listName ] && list[ listName ][ id ] ) {
- product = $.extend({}, list[ listName ][ id ]);
- }
- return product;
- };
- module.getArray = function() {
- return list;
- };
- return module;
- }();
- /**
- * Проверяет контейнер на наличие блоков со списками товаров
- * + отправляет для каждого из них событие в GTM
- *
- * @param $container
- */
- APP.Helpers.GTM.initProductImpressions = function($container) {
- var $lists = $container.find('.js-product-list[data-type=impressions]');
- if( $lists.length > 0 ) {
- $lists.each(function() {
- $list = $(this);
- // Инициализировать можно только один раз
- if( $list.data('product-impressions-status') == 'inited' ) {
- return;
- }
- $list.data('product-impressions-status', 'inited');
- var products = APP.Helpers.GTM.parseProductList($list);
- var currency = $list.data('currency');
- var listName = $list.data('list-name');
- var offset = $list.data('offset'); // Должен учитывать отсутствие параметра - считаем по факту, либо 0 - обнуляем принудительно каждый раз
- if( products && products.length > 0 && currency && listName ) {
- // Дополняем данные для товаров
- if( typeof offset !== 'undefined' ) {
- APP.Helpers.GTM.position.setCurrent(listName, offset);
- }
- products.map(function(val) {
- val['position'] = APP.Helpers.GTM.position.getNext(listName)
- val['list'] = listName;
- return val;
- });
- // Сохраняем для дальнейшего использования при кликах
- APP.Helpers.GTM.products.add(products);
- // Отправим сразу как только покажется на экране
- APP.Helpers.whenVisibleCallback($list.parent(), function() {
- APP.Helpers.GTM.sendProductImpressions(currency, products, listName, offset);
- });
- }
- });
- }
- };
- /**
- * Отправляет данные по списками товаров в GTM
- *
- * @param string currency Валюта товаров
- * @param array products Список товаров
- */
- APP.Helpers.GTM.sendProductImpressions = function(currency, products, listName, offset) {
- if( APP.Helpers.GTM.debug ) {
- alert("event: productView\n\nList: " + listName + "\nProduct count: " + products.length);
- }
- APP.Helpers.GTM.push({
- 'event': 'productView',
- 'ecommerce': {
- 'currencyCode': currency,
- 'impressions': products
- }
- });
- };
- /**
- * Обработчик для отправки Product Click
- *
- * @param el
- * @param ev
- */
- APP.Helpers.GTM.handlerProductClick = function(el, ev) {
- var $el = $(el);
- var itemData = APP.Helpers.GTM.getItemDataByEl($el);
- if( itemData === false || !itemData.productId || !itemData.gtmListName ) {
- return;
- }
- ev.preventDefault();
- var callback = function() {
- if( APP.Helpers.GTM.debug ) {
- var debugGo = confirm('Goto: ' + $el.attr('href'));
- }
- if( !APP.Helpers.GTM.debug || debugGo )
- {
- document.location = $el.attr('href');
- }
- }
- var product = APP.Helpers.GTM.products.get( itemData.productId, itemData.gtmListName );
- if( !product )
- {
- callback();
- }
- else
- {
- if( APP.Helpers.GTM.debug ) {
- var dataProduct = '';
- $.each(product, function(index, value) {
- dataProduct += "\n" + index + ": " + value;
- });
- alert("event: productClick\n" + dataProduct);
- }
- APP.Helpers.GTM.push({
- 'event': 'productClick',
- 'ecommerce': {
- 'click': {
- 'actionField': {'list': product.list},
- 'products': [product]
- }
- },
- 'eventCallback': callback
- });
- }
- };
- /**
- * Обработчик для открытия быстрого просмотра
- * Вызывается в APP.Controls.ProductQuickViewButton
- * @param $el
- * @param ev
- */
- APP.Helpers.GTM.handlerProductQuickView = function($el, ev) {
- var itemData = APP.Helpers.GTM.getItemDataByEl($el);
- if( itemData === false || !itemData.productId || !itemData.gtmListName ) {
- return;
- }
- var product = APP.Helpers.GTM.products.get( itemData.productId, itemData.gtmListName );
- if( product )
- {
- if( APP.Helpers.GTM.debug ) {
- var dataProduct = '';
- $.each(product, function(index, value) {
- dataProduct += "\n" + index + ": " + value;
- });
- alert("event: productQuickViewWindowOpened\n" + dataProduct);
- }
- APP.Helpers.GTM.products.add([product], 'productQuickView');
- APP.Helpers.GTM.push({
- 'event': 'productQuickViewWindowOpened',
- 'ecommerce': {
- 'currencyCode': product.currency,
- 'detail': {
- 'actionField': {'list': product.list},
- 'products': [product]
- }
- }
- });
- }
- };
- /**
- * Возвращает данные по товару
- * @param $el
- * @return object
- */
- APP.Helpers.GTM.getItemDataByEl = function($el) {
- var $item = $el.closest('[data-gtm-product-id]');
- if( $item.length > 0 )
- {
- var data = {
- 'productId': $item.data('gtm-product-id'),
- 'gtmListName': $item.data('gtm-list-name')
- };
- return data;
- }
- return false;
- };
- /**
- * Обертка для инициализации всего функционала GTM относящегося к спискам товаров
- * @param $context
- */
- APP.Helpers.GTM.initProductList = function($context) {
- // Product Impressions
- APP.Helpers.GTM.initProductImpressions($context);
- // Product Click
- APP.Helpers.GTM.initProductClick($context);
- };
- /**
- * Обертка для инициализации отслеживания перехода на карточку товара
- * @param $context
- */
- APP.Helpers.GTM.initProductClick = function($context) {
- $context.find('.js-gtm-product-link').each(function () {
- $(this).on('click', function(ev) {
- APP.Helpers.GTM.handlerProductClick(this, ev);
- });
- });
- };
- /**
- * Обертка для инициализации всего функционала GTM относящегося к детальной карточке товара
- * @param context
- */
- APP.Helpers.GTM.initProductDetail = function($context) {
- // Send event
- $context.find('.js-product-list[data-type=product-detail]').each(function()
- {
- $product = $(this);
- var products = APP.Helpers.GTM.parseProductList($product);
- if( products.length > 0 )
- {
- var listName = $product.data('list-name');
- products.map(function(val) {
- val['list'] = listName;
- return val;
- });
- // Сохраняем для дальнейшего использования при кликах
- APP.Helpers.GTM.products.add(products);
- if( APP.Helpers.GTM.debug ) {
- var dataProduct = '';
- $.each(products[0], function(index, value) {
- dataProduct += "\n" + index + ": " + value;
- });
- alert("event: productDetailView\n" + dataProduct);
- }
- APP.Helpers.GTM.push({
- 'event': 'productDetailView',
- 'ecommerce': {
- 'actionField': {'list': listName},
- 'detail': {
- 'products': products
- }
- }
- });
- }
- });
- };
- /**
- * Обработчик для действий с корзиной
- * @param $el
- * @param type remove|other
- * @param data
- */
- APP.Helpers.GTM.handlerProductBasketAction = function ($el, type, data) {
- var itemData = APP.Helpers.GTM.getItemDataByEl($el);
- // listName может отсутствовать, т.к. используется не только в списках, но и на детальной странице и пр.
- if( itemData === false || !itemData.productId ) {
- return;
- }
- var product = APP.Helpers.GTM.products.get( itemData.productId, itemData.gtmListName );
- if( product )
- {
- var ecomerceData = {};
- if( type == 'remove' ) {
- var event = 'removeFromCart';
- var type = 'remove';
- if( data['quantity'] ) {
- product['quantity'] = data['quantity'];
- }
- if( !product['quantity'] ) {
- var basketItem = APP.Basket.getItemByProductId(itemData.productId);
- if( basketItem ) {
- product['quantity'] = basketItem['quantity'];
- }
- }
- } else {
- var event = 'addToCart';
- var type = 'add';
- ecomerceData['currencyCode'] = product.currency;
- if( data['quantity'] ) {
- product['quantity'] = data['quantity'];
- }
- if( !product['quantity'] ) {
- product['quantity'] = 1;
- }
- }
- ecomerceData[type] = {'products': [product]};
- if( APP.Helpers.GTM.debug ) {
- var dataProduct = '';
- $.each(product, function(index, value) {
- dataProduct += "\n" + index + ": " + value;
- });
- alert("event: " + event + "\n" + dataProduct);
- }
- APP.Helpers.GTM.push({
- 'event': event,
- 'ecommerce': ecomerceData
- });
- }
- };
- /**
- * Обработчик для события изменения количества товара в корзине
- * @param $el
- * @param data
- */
- APP.Helpers.GTM.handlerBasketChange = function($el, data) {
- var type = false;
- var diff = 0;
- var itemId = data["BASKET_ITEM_ID"];
- var quantityNew = data["QUANTITY"];
- var action = data["ACTION"];
- var fromOld = action == 'restoreItem';
- var item = APP.Basket.getItemById(itemId, fromOld);
- if( item )
- {
- var quantityOld = item.quantity;
- switch (action) {
- case 'recalculate':
- diff = quantityNew - quantityOld;
- if( diff > 0 )
- {
- type = 'add';
- }
- else if( diff < 0 )
- {
- type = 'remove';
- }
- break;
- case 'deleteItem':
- diff = quantityOld;
- type = 'remove';
- break;
- case 'restoreItem':
- diff = quantityOld;
- type = 'add';
- }
- }
- if( type ) {
- APP.Helpers.GTM.handlerProductBasketAction($el, type, {'quantity': Math.abs(diff)});
- }
- };
- /**
- * Передаем значение подсказки по которой кликнул пользователь
- * @param value
- */
- APP.Helpers.GTM.clickSearchHint = function(value) {
- if( APP.Helpers.GTM.debug ) {
- alert("event: searchHintsClick" + "\n\nsearchHint: " + value);
- }
- APP.Helpers.GTM.push({
- 'searchHint': value,
- 'event': 'searchHintsClick'
- });
- };
- /**
- * Передаем данные об изменении формы
- */
- APP.Helpers.GTM.formChange = function (formName, params) {
- var result = {
- event: 'UX',
- form: formName,
- };
- $.extend(true, result, params);
- if (APP.Helpers.GTM.debug) {
- var debugParams = '';
- $.each(result, function (index, value) {
- debugParams += "\n" + index + ": " + value;
- });
- alert("event: formChange\n" + debugParams);
- }
- APP.Helpers.GTM.push(result);
- };
- /**
- * Передаем данные при загрузки формы (предустановленные значения)
- */
- APP.Helpers.GTM.formInit = function (formName, fields) {
- var common = {
- event: 'UX',
- form: formName,
- nonInteraction: 1
- };
- fields = fields.map(function(field) {
- return $.extend(true, [], common, field);
- });
- if (APP.Helpers.GTM.debug) {
- var debugParams = "\n[";
- var outerIndex = 0;
- $.each(fields, function (index, field) {
- debugParams += outerIndex++ > 0 ? ",\n{" : "{";
- var innerIndex = 0;
- for (var name in field) {
- if (field.hasOwnProperty(name)) {
- debugParams += (innerIndex++ > 0 ? " | " : "") + name + ": " + field[name];
- }
- }
- debugParams += "}";
- });
- debugParams += "]";
- alert("event: formInit\n" + debugParams);
- }
- APP.Helpers.GTM.push(fields);
- };
- APP.Helpers.GTM.formSubmit = function (formName, isValid, callback, ecommerceParams) {
- var result = {
- event: 'UX',
- form: formName,
- action: 'submit',
- valid: isValid ? 1 : 0,
- eventCallback: callback || false
- };
- if (ecommerceParams) {
- ecommerceParams = APP.Helpers.GTM.getCheckoutOptionParams(ecommerceParams);
- if (ecommerceParams) {
- $.extend(true, result, ecommerceParams);
- }
- }
- if (APP.Helpers.GTM.debug) {
- var debugParams = '';
- $.each(result, function (index, value) {
- debugParams += "\n" + index + ": " + value;
- });
- alert("event: formSubmit\n" + debugParams);
- }
- APP.Helpers.GTM.push(result);
- };
- })(jQuery, window.APP);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement