UNPKG

@shopgate/pwa-tracking

Version:

Tracking library for the Shopgate Connect PWA.

55 lines • 11 kB
function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}import get from'lodash/get';import find from'lodash/find';import queryString from'query-string';import{logger}from'@shopgate/pwa-core/helpers';import{QR_CODE_TYPE_HOMEPAGE,QR_CODE_TYPE_PRODUCT,QR_CODE_TYPE_PRODUCT_WITH_COUPON,QR_CODE_TYPE_COUPON,QR_CODE_TYPE_CATEGORY,QR_CODE_TYPE_SEARCH,QR_CODE_TYPE_PAGE,SCANNER_FORMATS_BARCODE,SCANNER_FORMATS_QR_CODE}from'@shopgate/pwa-common-commerce/scanner/constants';import{parse2dsQrCode}from'@shopgate/pwa-common-commerce/scanner/helpers';import core from'@shopgate/tracking-core/core/Core';import appConfig,{shopNumber}from'@shopgate/pwa-common/helpers/config';import{i18n}from'@shopgate/engage/core';/** * Converts a price to a formatted string. * @param {number} price The original price. * @return {string|*} The converted price or the original value, if the price was not convertible. */export var convertPriceToString=function convertPriceToString(price){if(typeof price==='number'){return price.toFixed(2);}return price;};/** * Re-format a given product from the store. * @param {Object} productData The product data from the store * @returns {Object|null} The formatted product. */export var formatProductData=function formatProductData(productData){if(!productData){return null;}var id=productData.id,name=productData.name,price=productData.price,manufacturer=productData.manufacturer,_productData$tags=productData.tags,tags=_productData$tags===void 0?[]:_productData$tags,_productData$identifi=productData.identifiers,identifiers=_productData$identifi===void 0?{}:_productData$identifi;var uid=appConfig.tracking.useSkuAsProductId&&identifiers.sku?identifiers.sku:id;return{name:name,manufacturer:manufacturer,tags:tags,uid:uid,amount:{net:convertPriceToString(price.unitPriceNet),gross:convertPriceToString(price.unitPriceWithTax),striked:convertPriceToString(price.unitPriceStriked),currency:price.currency}};};/** * Reformat product data for addToCart from the store to the format our core expects. * @param {Object} product Product from the store * @param {Object} quantity Quantity of the product * @return {Object} */export var formatAddToCartProductData=function formatAddToCartProductData(_ref){var product=_ref.product,quantity=_ref.quantity;return _extends({},formatProductData(product),{quantity:quantity});};/** * Reformat product data from the store to the format our core expects. * @param {Object} product Product from the store * @param {Object} quantity Quantity of the product * @return {Object} */export var formatCartProductData=function formatCartProductData(_ref2){var product=_ref2.product,quantity=_ref2.quantity;return{uid:product.id,name:product.name,amount:{gross:convertPriceToString(product.price.unit)},quantity:quantity};};/** * Reformat order data from web checkout to the format our core expects. * @param {Object} passedOrder Information about the order. * @return {Object} */export var formatPurchaseData=function formatPurchaseData(passedOrder){// Return the passedOrder if the format is already correct if(!passedOrder.totals&&passedOrder.amount){return{order:passedOrder};}var defaults={totals:[],products:[],number:'',currency:''};var order=_extends({},defaults,{},passedOrder);var _ref3=find(order.totals,{type:'grandTotal'})||{},_ref3$amount=_ref3.amount,grandTotal=_ref3$amount===void 0?0:_ref3$amount;var _ref4=find(order.totals,{type:'shipping'})||{},_ref4$amount=_ref4.amount,shipping=_ref4$amount===void 0?0:_ref4$amount;var _ref5=find(order.totals,{type:'tax'})||{},_ref5$amount=_ref5.amount,tax=_ref5$amount===void 0?0:_ref5$amount;var grandTotalNet=grandTotal-tax;var products=order.products.map(function(product){return{uid:product.id||'',productNumber:product.id||'',name:product.name||'',quantity:product.quantity||1,amount:{currency:order.currency,gross:convertPriceToString(get(product,'price.withTax',0)),net:convertPriceToString(get(product,'price.net',0))}};});return{shop:{name:''},order:{number:order.number,amount:{currency:order.currency,gross:convertPriceToString(grandTotal),net:convertPriceToString(grandTotalNet),tax:convertPriceToString(tax)},shipping:{amount:{gross:convertPriceToString(shipping),net:convertPriceToString(shipping)}},products:products,shippingAddress:{city:'',country:''}}};};/** * Reformat order data from native checkout to the format our core expects. * @param {Object} order Information about the order. * @return {Object} */export var formatNativeCheckoutPurchaseData=function formatNativeCheckoutPurchaseData(){var order=arguments.length>0&&arguments[0]!==undefined?arguments[0]:{};var orderNumber=order.orderNumber,total=order.total,taxAmount=order.taxAmount,shippingTotal=order.shippingTotal,currencyCode=order.currencyCode,_order$lineItems=order.lineItems,lineItems=_order$lineItems===void 0?[]:_order$lineItems;var products=lineItems.map(function(_ref6){var quantity=_ref6.quantity,itemCurrencyCode=_ref6.currencyCode,itemTaxAmount=_ref6.taxAmount,price=_ref6.price,_ref6$product=_ref6.product,product=_ref6$product===void 0?{}:_ref6$product;return{uid:(product===null||product===void 0?void 0:product.code)||'',productNumber:(product===null||product===void 0?void 0:product.code)||'',name:(product===null||product===void 0?void 0:product.name)||'',quantity:quantity||1,amount:{currency:itemCurrencyCode,gross:convertPriceToString(price),net:convertPriceToString(price-itemTaxAmount)}};});return{shop:{name:''},order:{number:orderNumber,amount:{currency:currencyCode,gross:convertPriceToString(total),net:convertPriceToString(total-taxAmount),tax:convertPriceToString(taxAmount)},shipping:{amount:{gross:convertPriceToString(shippingTotal),net:convertPriceToString(shippingTotal)}},products:products,shippingAddress:{city:'',country:''}}};};/** * Creates data for the scanner tracking events. * @param {Object} params params * @return {Object} */export var createScannerEventData=function createScannerEventData(_ref7){var event=_ref7.event,format=_ref7.format,payload=_ref7.payload,userInteraction=_ref7.userInteraction;var eventLabel=[];if(payload){eventLabel=[format];if(SCANNER_FORMATS_QR_CODE.includes(format)){var parsedPayload=parse2dsQrCode(payload);if(parsedPayload){var type=parsedPayload.type,data=parsedPayload.data;switch(type){case QR_CODE_TYPE_HOMEPAGE:eventLabel.push('main');break;case QR_CODE_TYPE_PRODUCT:eventLabel.push('product');eventLabel.push(data.productId);break;case QR_CODE_TYPE_PRODUCT_WITH_COUPON:eventLabel.push('productcoupon');eventLabel.push("".concat(data.productId,"_").concat(data.couponCode));break;case QR_CODE_TYPE_COUPON:eventLabel.push('coupon');eventLabel.push(data.couponCode);break;case QR_CODE_TYPE_CATEGORY:eventLabel.push('category');eventLabel.push(data.categoryId);break;case QR_CODE_TYPE_SEARCH:eventLabel.push('search');eventLabel.push(data.searchPhrase);break;case QR_CODE_TYPE_PAGE:eventLabel.push('page');eventLabel.push(data.pageId);break;default:break;}}}else if(SCANNER_FORMATS_BARCODE.includes(format)){if(payload){eventLabel.push(payload);}}}eventLabel=eventLabel.join(' - ');return _extends({eventAction:event},eventLabel&&{eventLabel:eventLabel},{},typeof userInteraction==='boolean'&&{userInteraction:userInteraction});};/** * Creates data for the scanner utm url. * @param {Object} params params * @return {Object} */export var buildScannerUtmUrl=function buildScannerUtmUrl(_ref8){var scannerRoute=_ref8.scannerRoute,format=_ref8.format,payload=_ref8.payload,referer=_ref8.referer;var source='shopgate';var medium='scanner';var campaign="".concat(shopNumber,"Scanner");var term='';if(SCANNER_FORMATS_BARCODE.includes(format)){medium='barcode_scanner';campaign="".concat(shopNumber,"BarcodeScan");term=payload;}else if(SCANNER_FORMATS_QR_CODE.includes(format)){medium='qrcode_scanner';campaign="".concat(shopNumber,"QRScan");var _ref10=parse2dsQrCode(payload)||{},type=_ref10.type,data=_ref10.data;if(type===QR_CODE_TYPE_SEARCH){term=data.searchPhrase;}}var parsedPayload;var utmContent;try{parsedPayload=queryString.parseUrl(payload);}catch(e){// noting to do here }if(parsedPayload&&parsedPayload.query){if(parsedPayload.query.utm_content){utmContent=parsedPayload.query.utm_content;}}var location=scannerRoute.location;var newPath=new URL(location,'http://scanner.com');/* eslint-disable camelcase */var utms={utm_source:source,utm_medium:medium,utm_campaign:campaign,utm_term:term,utm_content:utmContent||referer};/* eslint-enable camelcase */Object.keys(utms).forEach(function(utm){if(!newPath.searchParams.has(utm)&&utms[utm]){newPath.searchParams.set(utm,utms[utm]);}});return"".concat(newPath.pathname).concat(newPath.search);};/** * Creates tracking data for a category. * @param {Object} category The category data from the store. * @returns {Object|null} */export var createCategoryData=function createCategoryData(category){if(!category){return null;}var name=category.name,uid=category.id,path=category.path;return{uid:uid,name:name,path:path};};/** * Creates tracking data for the root category. * @param {Object} rootCategory The category data from the store. * @return {Object|null} */export var createRootCategoryData=function createRootCategoryData(rootCategory){if(!rootCategory){return null;}return{uid:null,name:i18n.text('titles.categories'),path:null};};/** * Creates tracking data for the page view event. * @param {Object} data The input data. * @return {Object} */export var createPageviewData=function createPageviewData(_ref11){var _ref11$page=_ref11.page,page=_ref11$page===void 0?null:_ref11$page,_ref11$cart=_ref11.cart,cart=_ref11$cart===void 0?null:_ref11$cart,_ref11$favorites=_ref11.favorites,favorites=_ref11$favorites===void 0?null:_ref11$favorites,_ref11$search=_ref11.search,search=_ref11$search===void 0?null:_ref11$search,_ref11$category=_ref11.category,category=_ref11$category===void 0?null:_ref11$category,_ref11$product=_ref11.product,product=_ref11$product===void 0?null:_ref11$product,pageConfig=_ref11.pageConfig;var title='';if(pageConfig){title=pageConfig.title;}else if(category&&category.name){title=category.name;}else if(product&&product.name){title=product.name;}return{page:page?_extends({},page,{title:title}):null,cart:cart,favouriteList:{products:favorites},search:search,category:category,product:product};};/** * Helper to pass the redux state to the tracking core * @param {string} eventName The name of the event. * @param {Object} data The tracking data of the event. * @param {Object} state The current redux state. * @return {Core|boolean} */export var track=function track(eventName,data,state){if(typeof core.track[eventName]!=='function'){logger.warn('Unknown tracking event:',eventName);return false;}try{core.track[eventName](data,undefined,undefined,state);}catch(e){logger.error(e);}return core;};