diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index 9ce6874ae..dc4da7e1b 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -381,6 +381,234 @@ export default { }); }, + pushProductArrayToDataLayer() { + // Get correct order object + const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder(); + const submittedOrder = baseMixin.methods.getSubmittedOrder(); + + if (hasSubmittedOrder) { + var lineItems = submittedOrder.lineItems ? submittedOrder.lineItems : {}; + + // combine all line items + var combinedLineItems = [ + ...(lineItems.glassParts ?? []), + ...(lineItems.supportingItems ?? []), + ...(lineItems.vaps ?? []), + ...(lineItems.promos ?? []), + ]; + + //Get child parts + combinedLineItems = flattenArray(combinedLineItems); + + var products = []; + var discount = 0; + var coupon = ""; + var subTotal = 0; + for (var i = 0; i < combinedLineItems.length; i++) { + let part = combinedLineItems[i]; + let productSku = part.partNumber; + let productType = part.partType; + let promoCode = part.promoCode; + let productPrice = baseMixin.methods + .getTotalPriceOfAllLineItemsAndChildParts([part], false) + .toFixed(2); + + if (productSku == "DISCOUNT") { + if (coupon) { + coupon += ","; + } + coupon += productSku; + discount = discount + parseFloat(productPrice) * -1; + } else { + products.push({ + productType: productType, + productSku: productSku, + productPrice: productPrice.toString(), + productQuantity: "1", + }); + subTotal += parseFloat(productPrice); + } + } + pushToDataLayerIfDefined({ + productArray: { + coupon: coupon, + discount: discount.toString(), + subTotal: subTotal.toString(), + products: products, + }, + }); + } + }, + + pushECommerceCartToDataLayer() { + const isDefined = (x) => x !== null && x !== undefined; + // Get correct order object + const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder(); + const submittedOrder = baseMixin.methods.getSubmittedOrder(); + if (hasSubmittedOrder) { + var lineItems = submittedOrder.lineItems ? submittedOrder.lineItems : {}; + var supportingItems = + submittedOrder.lineItems && submittedOrder.lineItems.supportingItems + ? submittedOrder.lineItems.supportingItems + : []; + var insurance = submittedOrder.payment && submittedOrder.payment.isInsurance; + var itac = submittedOrder.policy && submittedOrder.policy.isItac; + var nocomp = submittedOrder.policy && submittedOrder.policy.isNoComp; + + var recalLineItem = supportingItems.filter(function (lineItem) { + return lineItem.partType.indexOf("RECALIBRATION") !== -1; + }); + var disposalFee = supportingItems.filter(function (lineItem) { + return lineItem.partType.indexOf("DISPOSAL FEE") !== -1; + }); + var mobileFee = supportingItems.filter(function (lineItem) { + return lineItem.partType.indexOf("MOBILE FEE") !== -1; + }); + var repairFee = supportingItems.filter(function (lineItem) { + return lineItem.partType.indexOf("REPAIR FEE") !== -1; + }); + + var vaps = + submittedOrder.lineItems && submittedOrder.lineItems.vaps + ? submittedOrder.lineItems.vaps + : []; + var wipers = vaps.filter(function (lineItem) { + return ( + lineItem.partType.indexOf("FRONT WIPER") !== -1 || + lineItem.partType.indexOf("REAR WIPER") !== -1 + ); + }); + var rainDefense = vaps.filter(function (lineItem) { + return lineItem.partType.indexOf("RAIN DEFENSE") !== -1; + }); + + // Combine line items + var combinedLineItems = []; + if (lineItems.glassParts) { + combinedLineItems = combinedLineItems.concat(lineItems.glassParts); + } + if (recalLineItem) { + combinedLineItems = combinedLineItems.concat(recalLineItem); + } + if (disposalFee) { + combinedLineItems = combinedLineItems.concat(disposalFee); + } + if (mobileFee && !(insurance && !itac && !nocomp)) { + combinedLineItems = combinedLineItems.concat(mobileFee); + } + if (repairFee) { + combinedLineItems = combinedLineItems.concat(repairFee); + } + if (wipers) { + combinedLineItems = combinedLineItems.concat(wipers); + } + if (rainDefense) { + combinedLineItems = combinedLineItems.concat(rainDefense); + } + + //Remove child Parts if any + combinedLineItems.forEach((lineItem) => { + lineItem.childParts = []; + }); + + var isPricingAvailable = + combinedLineItems.length > 0 && + combinedLineItems.every(function (lineItem) { + return ( + isDefined(lineItem.kitPrice) && + isDefined(lineItem.laborAmount) && + isDefined(lineItem.sellingPrice) + ); + }); + let subtotal = 0; + if (isPricingAvailable) { + subtotal = baseMixin.methods.getTotalPriceOfAllLineItemsAndChildParts( + combinedLineItems, + false + ); + } + pushToDataLayerIfDefined({ + eCommerceCart: { products: combinedLineItems, subTotal: parseInt(subtotal) }, + }); + } + }, + + pushCommissionJunctionGtmDataToDataLayer() { + // helper check for if an object is defined (but maybe falsey) + const isDefined = (x) => x !== null && x !== undefined; + let repairReplace = ""; + let coupons = ""; + let refSequenceNum = ""; + let accountType = ""; + let amount = 0; + let cjEvent = ""; + if (store.getters.applicationUser.affiliateCookies) { + const affiliateCookies = store.getters.applicationUser.affiliateCookies; + var cookieArray = []; + affiliateCookies.forEach((item) => { + let cookieObject = convertCookieStringToObject(item); + cookieArray.push(cookieObject); + }); + const sortedCookies = cookieArray.sort( + (a, b) => + new Date(b.timestamp.replace("/", "T")) - + new Date(a.timestamp.replace("/", "T")) + ); + cjEvent = sortedCookies?.[0]?.tagEvent; + const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder(); + const submittedOrder = baseMixin.methods.getSubmittedOrder(); + + if (hasSubmittedOrder) { + repairReplace = submittedOrder.damage.isRepair ? "Repair" : "Replace"; + const promos = submittedOrder.lineItems.promos ?? []; + if (promos.length === 0) { + coupons = ""; + } else { + const promoCodes = promos.map((promo) => promo.promoCode); + const promoString = promoCodes.reduce((prev, next) => `${prev}_${next}`); + coupons = promoString; + } + refSequenceNum = submittedOrder.referralSequenceNumber; + } + if (isDefined(submittedOrder.payment.isInsurance)) { + accountType = submittedOrder.payment.isInsurance ? "insurance" : "cash"; + } else { + accountType = ""; + } + const lineItems = submittedOrder.lineItems ?? {}; + const combinedLineItems = [ + ...(lineItems.glassParts ?? []), + ...(lineItems.supportingItems ?? []), + ...(lineItems.vaps ?? []), + ...(lineItems.promos ?? []), + ]; + + const isPricingAvailable = + combinedLineItems.length > 0 && + combinedLineItems.every( + (lineItem) => + isDefined(lineItem.kitPrice) && + isDefined(lineItem.laborAmount) && + isDefined(lineItem.sellingPrice) + ); + if (accountType == "cash" && isPricingAvailable) { + const quoteAmountWithDiscount = baseMixin.methods + .getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, false) + .toFixed(2); + amount = parseFloat(quoteAmountWithDiscount); + } + } + pushToDataLayerIfDefined({ + commissionJunctionGtmData: { + cj_commission_junction_event: cjEvent, + cj_referral_sequence_number: refSequenceNum, + cj_amount: amount.toString(), + cj_repair_replace: repairReplace, + cj_coupon: coupons, + }, + }); + }, + prependActionToMethod(object, method, actionToPrepend) { const baseMethodName = method.name.startsWith("bound ") ? method.name.substring(6) @@ -493,3 +721,24 @@ function getValueToLog(value, valueToLogType) { } return value; } + +function flattenArray(arr) { + let result = []; + arr.forEach((item) => { + result.push(item); + if (item.childParts) { + result = result.concat(item.childParts); + delete item.childParts; // Remove childParts after flattening + } + }); + return result; +} + +function convertCookieStringToObject(cookieValue) { + const cookieObject = cookieValue.split("&").reduce((acc, pair) => { + const [key, value] = pair.split("="); + acc[key] = value; + return acc; + }, {}); + return cookieObject; +} diff --git a/src/router/index.js b/src/router/index.js index 23b61282c..cbd2d2eab 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -145,6 +145,12 @@ const routes = [ await runExperiments(to.query.fmgPage); + //Affiliate Cookies + const affiliateCookies = getAffiliateCookies(); + if (affiliateCookies != null && affiliateCookies.length > 0) { + store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies); + } + setupAdvertiserTracking(); // Process funnel cookie. updateOrCreateFunnelCookie(); @@ -307,6 +313,17 @@ router.afterEach(async (to, from) => { // Push current order status to Data Layer analyticsMixin.methods.pushOrderToDataLayer(); + + if (to.query.fmgPage == fmgPageValues.CONFIRMATION) { + //Push Product Array to Data Layer + analyticsMixin.methods.pushProductArrayToDataLayer(); + + //Push Ecommerce Cart to Data Layer + analyticsMixin.methods.pushECommerceCartToDataLayer(); + + //Push Commission Junction Gtm Data To Data Layer + analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer(); + } }); router.navigateWithoutSaving = (