DigitalConsumer.FixMyGlass/src/mixins/analytics-mixin.js
2024-01-31 14:58:18 -05:00

333 lines
12 KiB
JavaScript

import { storeActions } from "@/constants/store-actions";
import {
getDeviceIdValue,
getSessionIdValue,
getSessionKeyValue,
getUserIdValue,
regenerateDeviceId,
regenerateUserId,
refreshSessionExpiration,
areAllSessionCookiesSet,
setSessionIdIfUnset,
setSessionKeyIfUnset,
} from "@/helpers/heritage-integration/cookie-helper";
import { queryStrings } from "@/constants/query-strings";
import { experimentSettings } from "@/constants/experiments";
import {
analyticsPageEvents,
GaCategories,
GaActions,
GaLabels,
GaEvents,
ValueToLogTypes,
} from "@/constants/analytics";
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
import store from "@/store";
import baseMixin from "@/mixins/base-mixin";
import { applicationConfig } from "../constants/application-config";
export default {
methods: {
getPageName() {
return getPageNameByQueryString();
},
async logPageView(pageEvent) {
const currentPageName = getPageNameByQueryString();
await this.validateSession();
const refSequenceNum =
store.getters.order.referralSequenceNumber ||
store.getters.submittedOrder?.referralSequenceNumber;
var payload = {
userId: getUserIdValue(),
sessionKey: getSessionKeyValue(),
pageName: currentPageName,
sessionId: getSessionIdValue(),
action: "",
event: pageEvent,
shouldUseSessionId: false,
experimentsForUser: store.getters.applicationUser.experiments,
referralSequenceNumber: refSequenceNum,
parentAccountNumber: store.getters.order.payment.parentAccountNumber,
};
await baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false);
},
async logCustomEvent(category, action, label, value) {
const currentPageName = getPageNameByQueryString();
await this.validateSession();
const refSequenceNum =
store.getters.order.referralSequenceNumber ||
store.getters.submittedOrder?.referralSequenceNumber;
var payload = {
userId: getUserIdValue(),
sessionKey: getSessionKeyValue(),
pageName: currentPageName,
sessionId: getSessionIdValue(),
category: category,
action: action,
label: label,
value: value,
shouldUseSessionId: false,
experimentsForUser: store.getters.applicationUser.experiments,
referralSequenceNumber: refSequenceNum,
parentAccountNumber: store.getters.order.payment.parentAccountNumber,
};
await baseMixin.methods.dispatchStoreAction(
storeActions.LOG_CUSTOM_EVENT,
payload,
false
);
},
async pushEventToGA(category, action, label, pushToLogApp = false, valueToLogType = null) {
const currentPageName = getPageNameByQueryString();
const labelToLog = getValueToLog(label, valueToLogType);
const eventToBePushed = {
event: GaEvents.GENERIC_EVENT,
category: category,
action: action,
label: labelToLog,
value: undefined,
path: `/fmg/?${queryStrings.FMG_PAGE}=${currentPageName}`,
};
pushToDataLayerIfDefined(eventToBePushed);
if (pushToLogApp) {
await this.logCustomEvent(category, action, labelToLog, undefined);
}
},
async pushPageViewToGA() {
const currentPageName = getPageNameByQueryString();
const pageViewEvent = {
event: GaEvents.PAGE_VIEW_EVENT,
pagePath: `/fmg/?${queryStrings.FMG_PAGE}=${currentPageName}`,
pageTitle: currentPageName,
};
pushToDataLayerIfDefined(pageViewEvent);
await this.logPageView(analyticsPageEvents.ENTRY);
},
pushSubmittedOrderToDataLayer() {
// check if submitted order exists; exit if not.
const hasSubmittedOrder = store.getters.hasSubmittedOrder;
if (!hasSubmittedOrder) {
return;
}
const order = store.getters.submittedOrder;
// assemble data for payload
// // reduce promocode array
const promos = order.lineItems.promos ?? [];
const promoCodes = promos.map((promo) => promo.promoCode);
const promoString =
promoCodes.length === 0 ? "" : promoCodes.reduce((prev, next) => `${prev},${next}`);
// // reduce glass array
const glassToReplace = order.damage.glassToReplace ?? [];
const glassToReplaceNames = glassToReplace.map(
(glassPiece) => `${glassPiece.glassLocation}/${glassPiece.glassName}`
);
const glassString =
glassToReplaceNames.length === 0
? ""
: glassToReplaceNames.reduce((prev, next) => `${prev},${next}`);
// // calculate subtotal
const lineItems = order.lineItems;
const combinedLineItems = [
...(lineItems.glassParts ?? []),
...(lineItems.supportingItems ?? []),
...(lineItems.vaps ?? []),
...(lineItems.promos ?? []),
];
const subtotal = baseMixin.methods
.getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, false)
.toFixed(2);
// // get correct zip code
const providerZip = order.serviceLocation.provider.address.zipCode;
const serviceZip =
order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
? order.serviceLocation.zipCode
: providerZip;
// // calculate total
const total = baseMixin.methods
.getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, true)
.toFixed(2);
const payload = {
serviceZipCode: serviceZip,
damageType: order.damage.isRepair ? "repair" : "replace",
accountType: order.payment.isInsurance ? "insurance" : "cash",
promoCodes: promoString,
vehicleYear: `${order.vehicle.year}`,
vehicleMake: order.vehicle.make,
vehicleModel: order.vehicle.model,
vehicleStyle: order.vehicle.style,
glassToReplace: glassString,
workOrderId: parseInt(order.workOrderId),
providerCtu: parseInt(order.serviceLocation.zipCodeCtu),
orderNumber: order.workOrderNumber,
priceTotal: parseFloat(total),
priceSubTotal: parseFloat(subtotal),
isRecalibrationOnOrder: store.getters.isRecalibrationOnSubmittedOrder,
appointmentType: order.serviceLocation.appointmentType,
};
// push to data layer.
pushToDataLayerIfDefined(payload);
},
pushExperimentsToDataLayer() {
const experiments = store.getters.applicationUser.experiments;
experiments?.forEach((exp) => {
// Set Google Dimension Index based on experiment settings.
let googleDimensionIndex = 99;
if (exp.settings[experimentSettings.GOOGLE_CUSTOM_DIMENSION_INDEX] !== undefined) {
googleDimensionIndex =
exp.settings[experimentSettings.GOOGLE_CUSTOM_DIMENSION_INDEX];
}
// Create object with dimension index and value.
const experimentWithDimension = {
[`experimentId_${googleDimensionIndex}`]: exp.universeId,
[`variationId_${googleDimensionIndex}`]: exp.variationId,
[`experimentName_${googleDimensionIndex}`]: exp.universeName,
[`variationName_${googleDimensionIndex}`]: exp.variationName,
[`customDimension_${googleDimensionIndex}`]: `${exp.universeId}_${exp.variationId}_${exp.universeName}_${exp.variationName}`,
};
// Push to the data layer with the Google Custom Dimension Index.
pushToDataLayerIfDefined(experimentWithDimension);
});
},
prependActionToMethod(object, method, actionToPrepend) {
const baseMethodName = method.name.startsWith("bound ")
? method.name.substring(6)
: method.name;
const baseMethod = object[baseMethodName];
object[baseMethodName] = function () {
actionToPrepend.apply(this, arguments);
return baseMethod.apply(object, arguments);
};
},
async initSession() {
regenerateDeviceId();
regenerateUserId();
const userId = getUserIdValue(); // cookieNames.FUNNEL_USER_ID
const deviceId = getDeviceIdValue(); // cookieNames.DXDEV
const sessionId = getSessionIdValue(); // cookieNames.SESSION_ID
const userAgent = navigator.userAgent; // navigator.userAgent
const referrer =
applicationConfig.CURRENT_ENVIRONMENT != "Localhost" ? document.referrer : null; // see above
const payload = {
userId: userId,
deviceId: deviceId,
sessionId: sessionId,
userAgent: userAgent,
referrer: referrer,
};
const response = await baseMixin.methods.dispatchStoreAction(
storeActions.INITIALIZE_SESSION,
payload,
false
);
if (response?.data) {
if (response.data.sessionKey) {
setSessionKeyIfUnset(response.data.sessionKey);
}
if (response.data.sessionId) {
setSessionIdIfUnset(response.data.sessionId);
}
}
},
noSession() {
return !areAllSessionCookiesSet();
},
async validateSession() {
if (this.noSession()) {
await this.initSession();
}
refreshSessionExpiration();
},
removeParamsFromEndpoint(endpoint) {
const endpointWithoutParams = endpoint.split("?")[0];
const numSlashesBeforeParams = 6;
let splitString = endpointWithoutParams.split("/");
if (splitString.length > numSlashesBeforeParams) {
splitString = splitString.slice(0, numSlashesBeforeParams);
return splitString.join("/");
} else {
return endpointWithoutParams;
}
},
},
computed: {
analyticsPageEvents() {
return analyticsPageEvents;
},
GaCategories() {
return GaCategories;
},
GaActions() {
return GaActions;
},
GaLabels() {
return GaLabels;
},
ValueToLogTypes() {
return ValueToLogTypes;
},
},
};
function pushToDataLayerIfDefined(data) {
if (window.dataLayer !== undefined) {
window.dataLayer.push(data);
}
}
function getPageNameByQueryString() {
const params = new URLSearchParams(location.search);
if (params.has(queryStrings.FMG_PAGE)) {
return params.get(queryStrings.FMG_PAGE);
} else {
return "";
}
}
function getValueToLog(value, valueToLogType) {
if (valueToLogType != null && valueToLogType === ValueToLogTypes.LAST_5) {
return value.slice(-5);
}
return value;
}