{"version":3,"file":"FaceBookCAPI.js","names":["FaceBookCAPI","a","setters","Component","default","deepMerge","Event","stringify","ajax","safeGet","on","off","getData","execute","constructor","element","options","arguments","length","qualifiedVisitTimeout","urls","capi","initCache","selectors","document","initState","state","pageScrolled","qualifiedVisitTimeoutExpired","bindEvents","onSignUpSuccess","bind","once","oncePageScrolled","onAddToBagEvent","onStoreLocatorEvent","onProductDetailEvent","onVTOEvent","afterInit","pageViewTimer","setTimeout","checkQualifiedVisit","checkCheckoutEvents","checkPurchaseEvent","data","sendRequest","eventName","checkoutEvents","fisrtStepEvents","filter","event","step","orderConfirmationPageId","test","orderNumber","JSON","category","action","label","getDefaultProductParams","product","productID","id","productName","encodeURIComponent","name","quantity","productPrice","price","eventAction","products","map","requestData","method","body","headers","\"Content-Type\"","destroy","removeListener"],"sources":["components/analytics/FaceBookCAPI.js"],"sourcesContent":["import Component from 'core/Component';\nimport { deepMerge } from 'toolbox/deepMerge';\nimport { Event } from 'services/EventEmitter';\nimport { stringify } from 'toolbox/queryString';\nimport { ajax } from 'toolbox/ajax';\nimport { safeGet } from 'toolbox/object';\nimport { on, off } from 'toolbox/event';\nimport { getData } from 'services/DataLayer';\n\n/**\n * FaceBookCAPI is used to listed to different page events and send data via ajax calls\n * @class\n * @classdesc This is a description of the FaceBookCAPI class. (must be edited)\n * @extends Component\n */\nexport default class FaceBookCAPI extends Component {\n /**\n * Constructor of the class that mainly merge the options of the components\n * @param {HTMLElement} element HTMLElement of the component\n * @param {object} options options that belongs to the component\n */\n constructor(element, options = {}) {\n super(element, deepMerge({\n // Your custom options goes here\n qualifiedVisitTimeout: 2000, // timeout for page qualified visit event\n urls: {\n capi: '', // request url\n },\n }, options));\n }\n\n /**\n * All selectors must be cached. Never cache elements that are out of the component scope\n */\n initCache() {\n this.selectors.document = document;\n }\n\n /**\n * Init the different state of the component\n * It helps to avoid heavy DOM manipulation\n */\n initState() {\n // identify if page was scrolled. Required for qualifiedVisit event\n this.state.pageScrolled = false;\n // time to qualify visit elapsed\n this.state.qualifiedVisitTimeoutExpired = false;\n }\n\n /**\n * Should contain only event listeners and nothing else\n * All the event handlers should be into a separated function. No usage of anonymous function\n */\n bindEvents() {\n // need to listen to the bubbled event\n on('signup.success', this.selectors.document, this.onSignUpSuccess.bind(this));\n // track page scroll\n Event.once('page.scrolled', this.oncePageScrolled.bind(this));\n Event.on('analytics.event', this.onAddToBagEvent.bind(this));\n Event.on('analytics.event', this.onStoreLocatorEvent.bind(this));\n Event.on('analytics.event', this.onProductDetailEvent.bind(this));\n Event.on('analytics.event', this.onVTOEvent.bind(this));\n }\n\n /**\n * After init\n * Run any script after the component is fully initialized\n */\n afterInit() {\n this.pageViewTimer = setTimeout(() => {\n this.state.qualifiedVisitTimeoutExpired = true;\n this.checkQualifiedVisit();\n }, this.options.qualifiedVisitTimeout);\n\n // check \"server\" triggered analytic events\n this.checkCheckoutEvents();\n this.checkPurchaseEvent();\n }\n\n /**\n * Newsletter sign up success handler\n * @param {object} data - data object\n */\n onSignUpSuccess(data) {\n if (safeGet(data, 'detail.content.success')) {\n this.sendRequest({\n eventName: 'subscription',\n });\n }\n }\n\n /**\n * pageScrolled event handler\n * mark page as scrolled, this is required for qualified visit event\n */\n oncePageScrolled() {\n this.state.pageScrolled = true;\n this.checkQualifiedVisit();\n }\n\n /**\n * determine if qualified visit event should be triggered\n */\n checkQualifiedVisit() {\n if (this.state.pageScrolled && this.state.qualifiedVisitTimeoutExpired) {\n this.sendRequest({\n eventName: 'qualifiedVisit',\n });\n }\n }\n\n /**\n * check if checkout analytics events should be triggered\n */\n checkCheckoutEvents() {\n const data = getData();\n\n const checkoutEvents = safeGet(data, 'events', []);\n\n const fisrtStepEvents = checkoutEvents.filter((event) => {\n const step = safeGet(event, 'ecommerce.checkout.actionField.step');\n return step === 1;\n });\n\n // initialize checkout event\n if (fisrtStepEvents.length && safeGet(fisrtStepEvents[0], 'ecommerce.checkout.products', []).length) {\n this.sendRequest({\n eventName: 'initiateCheckout',\n });\n }\n }\n\n /**\n * Determine Purchase event should be triggered\n */\n checkPurchaseEvent() {\n const data = getData();\n\n // purchase event\n if (data) {\n const orderConfirmationPageRegExp = new RegExp('confirmation|orderconfirmation|ngorderconfirmation');\n const orderConfirmationPageId = safeGet(data, 'page.id');\n\n // if order confirmation page is rendered, send purchase analytics\n if (orderConfirmationPageRegExp.test(orderConfirmationPageId)) {\n const orderNumber = safeGet(data, 'orderData.orderNo');\n\n if (orderNumber) {\n this.sendRequest({\n eventName: 'purchase',\n data: JSON.stringify({\n orderNumber,\n }),\n });\n }\n }\n }\n }\n\n /**\n * VTO analytics event handler\n * @param {object} data - event data\n */\n onVTOEvent(data) {\n const vtoCategory = new RegExp('virtual try on');\n const vtoAction = new RegExp('select');\n const vtoLabel = new RegExp('upload a photo|live camera');\n\n // vto event\n if (vtoCategory.test(data.category) && vtoAction.test(data.action) && vtoLabel.test(data.label)) {\n this.sendRequest({\n eventName: 'vto',\n });\n }\n }\n\n /**\n * Returns default product params\n * @param {Object} product product object\n * @return {Object} product params data\n */\n getDefaultProductParams(product) {\n return {\n productID: product.id,\n productName: encodeURIComponent(product.name),\n quantity: product.quantity,\n productPrice: product.price,\n };\n }\n\n /**\n * Product Details analytics event handler\n * @param {object} data - event data\n */\n onProductDetailEvent(data) {\n const viewContentRegExp = new RegExp('Product Detail');\n\n // view content event\n if (viewContentRegExp.test(data.eventAction)) {\n const products = safeGet(data, 'ecommerce.detail.products', []).map(product => this.getDefaultProductParams(product));\n\n if (products.length) {\n this.sendRequest({\n eventName: 'viewContent',\n data: JSON.stringify(products[0]),\n });\n }\n }\n }\n\n /**\n * StoreLocator analytics event handler\n * @param {object} data - event data\n */\n onStoreLocatorEvent(data) {\n const storeLocatorRegExp = new RegExp('store locator|salon locator');\n\n // store locator event\n if (storeLocatorRegExp.test(data.category)) {\n this.sendRequest({\n eventName: 'findLocation',\n });\n }\n }\n\n /**\n * AddToBag analytics event handler\n * @param {object} data - event data\n */\n onAddToBagEvent(data) {\n const addToBagRegExp = new RegExp('Add to Cart');\n\n // add to bag event\n if (addToBagRegExp.test(data.eventAction)) {\n const products = safeGet(data, 'ecommerce.add.products', []).map(product => this.getDefaultProductParams(product));\n\n if (products.length) {\n this.sendRequest({\n eventName: 'addToCart',\n data: JSON.stringify(products),\n });\n }\n }\n }\n\n /**\n * Send request via ajax call\n * @param {object} requestData - data to send\n * @param {string} requestData.eventName - event name\n * @param {string} requestData.data - data to send in json format\n */\n sendRequest(requestData) {\n // exit if there is no event name\n if (!requestData || !requestData.eventName) {\n return;\n }\n // add empty data object to make request object consistent\n if (!requestData.data) {\n requestData.data = {};\n }\n ajax(this.options.urls.capi, {\n method: 'POST',\n body: stringify(requestData),\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n });\n }\n\n /**\n * Destroy is called automatically after the component is being removed from the DOM\n * You must always destroy the listeners attached to an element to avoid any memory leaks\n */\n destroy() {\n off('signup.success', this.selectors.document);\n Event.removeListener('analytics.event');\n Event.removeListener('page.scrolled');\n }\n}\n"],"mappings":"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","ignoreList":[]}