Initial digital session logging commits.
This commit is contained in:
parent
efee204fc8
commit
02b3e3c3f9
4 changed files with 346 additions and 0 deletions
|
|
@ -181,6 +181,14 @@ const endpoints = Object.freeze({
|
||||||
url: `${ANALYTICS_BASE_URL}/initialize`,
|
url: `${ANALYTICS_BASE_URL}/initialize`,
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
},
|
},
|
||||||
|
LogDigitalConsumer: {
|
||||||
|
url: "/analytics/api/v1/analytics/digitalconsumer-log",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
|
LogIssSessionData: {
|
||||||
|
url: "/analytics/api/v1/analytics/digitalconsumer-session-logging",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
GetExperimentsByUser: {
|
GetExperimentsByUser: {
|
||||||
url: `${ANALYTICS_BASE_URL}/get-experiments`,
|
url: `${ANALYTICS_BASE_URL}/get-experiments`,
|
||||||
method: 'GET'
|
method: 'GET'
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,178 @@ export default {
|
||||||
return baseMethod.apply(object, arguments);
|
return baseMethod.apply(object, arguments);
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
logDigitalConsumer() {
|
||||||
|
const store = useMainStore();
|
||||||
|
const currentPageName = this.getPageNameByQueryString();
|
||||||
|
const universes = store.applicationUser.experiments;
|
||||||
|
const deviceId = getDeviceIdValue(); // cookieNames.DXDEV
|
||||||
|
const userId = getUserIdValue(); // cookieNames.ISS_USER_ID
|
||||||
|
const sid = getSessionIdValue(); // cookieNames.SESSION_ID
|
||||||
|
|
||||||
|
const variationNames = universes
|
||||||
|
.filter((item) => item.universeName === experimentSettings.CONCEPT_FUNNEL)
|
||||||
|
.map((item) => item.variationName)
|
||||||
|
.filter(Boolean); // removes undefined/null
|
||||||
|
|
||||||
|
const conceptVariation = variationNames.length > 0 ? variationNames[0] : "";
|
||||||
|
|
||||||
|
const isConceptExposed = universes.find(
|
||||||
|
(item) => item.universeName === experimentSettings.CONCEPT_FUNNEL
|
||||||
|
)?.isExposed;
|
||||||
|
|
||||||
|
// TODO: Find equivalent ISS methods for these:
|
||||||
|
const submittedOrder = null;//baseMixin.methods.getSubmittedOrder();
|
||||||
|
const hasSubmittedOrder = false;//baseMixin.methods.hasSubmittedOrder();
|
||||||
|
const hasSubmittedOrderAtConfirmationPage =
|
||||||
|
hasSubmittedOrder && currentPageName?.toLowerCase() == routeData.CONFIRMATION.name;
|
||||||
|
|
||||||
|
var payload = {
|
||||||
|
deviceId: deviceId,
|
||||||
|
sessionId: sid,
|
||||||
|
actionName: `Browser page:${currentPageName}`,
|
||||||
|
referralSequenceNumber: hasSubmittedOrderAtConfirmationPage
|
||||||
|
? submittedOrder.referralSequenceNumber
|
||||||
|
: store.order.referralSequenceNumber,
|
||||||
|
referralNumber: hasSubmittedOrderAtConfirmationPage
|
||||||
|
? submittedOrder.referralNumber
|
||||||
|
: store.order.referralNumber,
|
||||||
|
workOrderId: hasSubmittedOrderAtConfirmationPage
|
||||||
|
? submittedOrder.workOrderId
|
||||||
|
: store.order.workOrderId,
|
||||||
|
workOrderNumber: hasSubmittedOrderAtConfirmationPage
|
||||||
|
? submittedOrder.workOrderNumber
|
||||||
|
: store.order.workOrderNumber,
|
||||||
|
conceptVariation: conceptVariation,
|
||||||
|
isConceptExposed: isConceptExposed,
|
||||||
|
};
|
||||||
|
|
||||||
|
store.logDigitalConsumer(payload);
|
||||||
|
},
|
||||||
|
|
||||||
|
// This sends session data to the session logging endpoint on the analytics service.
|
||||||
|
// From there, it uses aws kinesis data stream, DigitalConsumer-Session-Data-Stream,
|
||||||
|
// and aws FireHose stream, DigitalConsumer-Session-Firehose, to push data to an
|
||||||
|
// S3 bucket, safelite-dev-digitalconsumer-session-data-us-east-2/1.
|
||||||
|
// This bucket data is then picked up by snowflake for analytics use.
|
||||||
|
pushIssSessionData() {
|
||||||
|
const store = useMainStore();
|
||||||
|
const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder();
|
||||||
|
const submittedOrder = baseMixin.methods.getSubmittedOrder();
|
||||||
|
const order = hasSubmittedOrder ? submittedOrder : store.order;
|
||||||
|
|
||||||
|
const hasSubmittedApplicationUser = baseMixin.methods.hasSubmittedApplicationUser();
|
||||||
|
const submittedApplicationUser = baseMixin.methods.getSubmittedApplicationUser();
|
||||||
|
const applicationUser = hasSubmittedApplicationUser
|
||||||
|
? submittedApplicationUser
|
||||||
|
: store.applicationUser;
|
||||||
|
|
||||||
|
const isEarlyBird = order?.lineItems?.supportingItems?.find(
|
||||||
|
(lineItem) => lineItem.partType == partTypeStrings.EARLY_BIRD
|
||||||
|
);
|
||||||
|
|
||||||
|
const promoCodes = Array.isArray(order?.lineItems?.promos)
|
||||||
|
? order?.lineItems?.promos
|
||||||
|
.map((item) => item.promoCode)
|
||||||
|
.filter((code) => code)
|
||||||
|
.join(", ")
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const glassProducts = order?.damage?.glassToReplace?.map(
|
||||||
|
(part) => `${part.glassLocation}-${part.glassName}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const format = (part) => `${part?.partNumber}-${part?.partType ? part.partType : ""}`;
|
||||||
|
const mapParts = (arr) => (arr ?? []).map(format);
|
||||||
|
|
||||||
|
const glassParts = mapParts(order?.lineItems?.glassParts);
|
||||||
|
const supportingItems = mapParts(order?.lineItems?.supportingItems);
|
||||||
|
const vaps = mapParts(order?.lineItems?.vaps);
|
||||||
|
const childParts = [].concat(
|
||||||
|
...(order?.lineItems?.glassParts ?? []).map((gp) => mapParts(gp?.childParts))
|
||||||
|
);
|
||||||
|
const allParts = [...glassParts, ...supportingItems, ...vaps, ...childParts];
|
||||||
|
|
||||||
|
if (applicationUser?.pageData?.quote?.servicePackageSelected) {
|
||||||
|
allParts.push(applicationUser.pageData.quote.servicePackageSelected);
|
||||||
|
}
|
||||||
|
|
||||||
|
var appointment = `${order?.schedule?.date ?? ""} ${order?.schedule?.startTime ?? ""}`;
|
||||||
|
var currentPageName = this.getPageNameByQueryString();
|
||||||
|
/*
|
||||||
|
// add query strings to the page name for debugging. on the vehicle page, if from an external link, pull it from the stash
|
||||||
|
if (currentPageName === "vehicle") {
|
||||||
|
if (!window.location.search) {
|
||||||
|
if (store.getters.externalParameterState?.qsStash) {
|
||||||
|
currentPageName += `${store.getters.externalParameterState.qsStash}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentPageName += `${window.location.search}`;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (window.location.search) {
|
||||||
|
currentPageName += `${window.location.search}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
var sessionData = {};
|
||||||
|
sessionData.currentPage = currentPageName;
|
||||||
|
sessionData.sid = getSessionIdValue();
|
||||||
|
sessionData.deviceId = getDeviceIdValue();
|
||||||
|
sessionData.fmgSessionId = applicationUser?.savedSessionId;
|
||||||
|
sessionData.skey = getskeyValue().toString();
|
||||||
|
sessionData.userId = getUserIdValue();
|
||||||
|
sessionData.carId = order?.vehicle?.carId;
|
||||||
|
sessionData.vehicleYear = order?.vehicle?.year;
|
||||||
|
sessionData.vehicleMake = order?.vehicle?.make;
|
||||||
|
sessionData.vehicleModel = order?.vehicle?.model;
|
||||||
|
sessionData.vehicleStyle = order?.vehicle?.style;
|
||||||
|
sessionData.hasVin = order?.vehicle?.vin ? true : false;
|
||||||
|
sessionData.cashOrInsuranceAccountType = order?.payment?.isInsurance
|
||||||
|
? "Insurance"
|
||||||
|
: "Cash";
|
||||||
|
sessionData.damageType = order?.damage?.isRepair ? "Repair" : "Replace";
|
||||||
|
sessionData.productType = allParts;
|
||||||
|
sessionData.eon = order?.eon;
|
||||||
|
sessionData.referralNumber = order?.referralNumber;
|
||||||
|
sessionData.referralSequenceNumber = order?.referralSequenceNumber;
|
||||||
|
sessionData.referralDate = order?.referralDate;
|
||||||
|
sessionData.workOrderNumber = order?.workOrderNumber;
|
||||||
|
sessionData.workOrderId = order?.workOrderId;
|
||||||
|
sessionData.isPia = order?.payment?.isPia ?? false;
|
||||||
|
sessionData.piaType = order?.payment?.piaType;
|
||||||
|
sessionData.parentAccountNumber = order?.payment?.parentAccountNumber;
|
||||||
|
sessionData.billToAccountNumber = order?.payment?.billToAccountNumber;
|
||||||
|
sessionData.settledTenderAmount = order?.settledTenderAmount;
|
||||||
|
sessionData.recalRequired = containsRecalParts(order?.lineItems);
|
||||||
|
sessionData.recalType = getRecalPartNumbers(order?.lineItems?.glassParts);
|
||||||
|
sessionData.serviceZipCode = order?.serviceLocation?.provider?.address?.zipCode
|
||||||
|
? order?.serviceLocation?.provider?.address?.zipCode
|
||||||
|
: order?.serviceLocation?.zipCode;
|
||||||
|
sessionData.providerCtu = order?.serviceLocation?.provider?.address?.zipCodeCtu
|
||||||
|
? order?.serviceLocation?.provider?.address?.zipCodeCtu
|
||||||
|
: order?.serviceLocation?.zipCodeCtu;
|
||||||
|
sessionData.appointmentDate = appointment;
|
||||||
|
sessionData.serviceType = order?.serviceLocation?.appointmentType;
|
||||||
|
sessionData.promoCodes = promoCodes;
|
||||||
|
sessionData.hasTechnicianNotes = order?.serviceLocation?.techNotes ? true : false;
|
||||||
|
sessionData.paymentMethod = order?.payment?.piaType;
|
||||||
|
sessionData.isTextingOptedIn = order?.customer?.isSmsOptIn ? true : false;
|
||||||
|
sessionData.isEarlyBird = isEarlyBird ? true : false;
|
||||||
|
sessionData.insuranceCo = order?.policy?.insuranceCompanyName;
|
||||||
|
sessionData.deductible = order?.policy?.currentDeductible;
|
||||||
|
sessionData.isVerified = order?.payment?.insuranceCoverage?.isVerified ?? false;
|
||||||
|
sessionData.coverageStatus = order?.payment?.insuranceCoverage?.coverageStatus;
|
||||||
|
sessionData.coverageSubStatus = order?.payment?.insuranceCoverage?.coverageSubStatus;
|
||||||
|
sessionData.isNoComp = order?.policy?.isNoComp;
|
||||||
|
sessionData.isItac = order?.policy?.isItac;
|
||||||
|
sessionData.subTotalPrice = getSubTotal(order?.lineItems);
|
||||||
|
sessionData.totalPrice = getAmountDue(order?.lineItems, true);
|
||||||
|
sessionData.userAgent = navigator.userAgent;
|
||||||
|
sessionData.cashPriceSubTotal = order?.cashPriceSubTotal;
|
||||||
|
|
||||||
|
store.logIssSessionData(sessionData);
|
||||||
|
},
|
||||||
|
|
||||||
async initSession() {
|
async initSession() {
|
||||||
regenerateDeviceId();
|
regenerateDeviceId();
|
||||||
|
|
|
||||||
|
|
@ -178,6 +178,12 @@ router.afterEach(async (to, from) => {
|
||||||
if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
|
if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
|
||||||
document.title = routerTitles[to.query.issPage] || 'Safelite Solutions®';
|
document.title = routerTitles[to.query.issPage] || 'Safelite Solutions®';
|
||||||
|
|
||||||
|
// digital consumer logging
|
||||||
|
analyticsMixin.methods.logDigitalConsumer();
|
||||||
|
|
||||||
|
// digital consumer ISS session logging to snowflake
|
||||||
|
//analyticsMixin.methods.pushIssSessionData();
|
||||||
|
|
||||||
// Push page view to GA
|
// Push page view to GA
|
||||||
analyticsMixin.methods.pushPageViewToGA();
|
analyticsMixin.methods.pushPageViewToGA();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2622,6 +2622,166 @@ export const useMainStore = defineStore({
|
||||||
updateTriggeredSiteEntry(wasSiteEntryTriggered) {
|
updateTriggeredSiteEntry(wasSiteEntryTriggered) {
|
||||||
this.applicationUser.triggeredSiteEntry = wasSiteEntryTriggered;
|
this.applicationUser.triggeredSiteEntry = wasSiteEntryTriggered;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
logDigitalConsumer(
|
||||||
|
{
|
||||||
|
deviceId,
|
||||||
|
sessionId,
|
||||||
|
actionName,
|
||||||
|
referralSequenceNumber,
|
||||||
|
referralNumber,
|
||||||
|
workOrderId,
|
||||||
|
workOrderNumber,
|
||||||
|
conceptVariation,
|
||||||
|
isConceptExposed,
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
var payload = {
|
||||||
|
sessionId: sessionId,
|
||||||
|
deviceId: deviceId,
|
||||||
|
actionName: actionName ?? "",
|
||||||
|
referralSequenceNumber: referralSequenceNumber ?? "",
|
||||||
|
referralNumber: referralNumber ?? "",
|
||||||
|
applicationName: "ISS", //baseMixin.methods.isMobileDevice() ? "2.0 Mobile" : "2.0",
|
||||||
|
workOrderId: workOrderId ?? "",
|
||||||
|
workOrderNumber: workOrderNumber ?? "",
|
||||||
|
conceptVariation: conceptVariation,
|
||||||
|
isConceptExposed: isConceptExposed,
|
||||||
|
};
|
||||||
|
|
||||||
|
console.error("Logging Digital Consumer Action: ", payload);
|
||||||
|
|
||||||
|
return globalMethods.callHttpClient({
|
||||||
|
method: endpoints.LogDigitalConsumer.method,
|
||||||
|
endpoint: endpoints.LogDigitalConsumer.url,
|
||||||
|
payload,
|
||||||
|
logApiCall: false,
|
||||||
|
bailoutOnError: false
|
||||||
|
}).then(
|
||||||
|
(response) => response,
|
||||||
|
(error) => {
|
||||||
|
console.log(`Analytics Service Error: ${error.data}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
logIssSessionData(
|
||||||
|
{
|
||||||
|
currentPage,
|
||||||
|
sid,
|
||||||
|
deviceId,
|
||||||
|
issSessionId,
|
||||||
|
skey,
|
||||||
|
userId,
|
||||||
|
carId,
|
||||||
|
vehicleYear,
|
||||||
|
vehicleMake,
|
||||||
|
vehicleModel,
|
||||||
|
vehicleStyle,
|
||||||
|
hasVin,
|
||||||
|
cashOrInsuranceAccountType,
|
||||||
|
damageType,
|
||||||
|
productType,
|
||||||
|
eon,
|
||||||
|
referralNumber,
|
||||||
|
referralSequenceNumber,
|
||||||
|
referralDate,
|
||||||
|
workOrderNumber,
|
||||||
|
workOrderId,
|
||||||
|
isPia,
|
||||||
|
piaType,
|
||||||
|
parentAccountNumber,
|
||||||
|
billToAccountNumber,
|
||||||
|
settledTenderAmount,
|
||||||
|
recalRequired,
|
||||||
|
recalType,
|
||||||
|
serviceZipCode,
|
||||||
|
providerCtu,
|
||||||
|
appointmentDate,
|
||||||
|
serviceType,
|
||||||
|
promoCodes,
|
||||||
|
hasTechnicianNotes,
|
||||||
|
paymentMethod,
|
||||||
|
isTextingOptedIn,
|
||||||
|
isEarlyBird,
|
||||||
|
insuranceCo,
|
||||||
|
deductible,
|
||||||
|
isVerified,
|
||||||
|
coverageStatus,
|
||||||
|
coverageSubStatus,
|
||||||
|
isNoComp,
|
||||||
|
isItac,
|
||||||
|
subTotalPrice,
|
||||||
|
totalPrice,
|
||||||
|
userAgent,
|
||||||
|
cashPriceSubTotal,
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
var payload = {
|
||||||
|
currentPage: currentPage,
|
||||||
|
sid: sid,
|
||||||
|
deviceId: deviceId,
|
||||||
|
fmgSessionId: issSessionId,
|
||||||
|
skey: skey,
|
||||||
|
userId: userId,
|
||||||
|
carId: carId,
|
||||||
|
vehicleYear: vehicleYear,
|
||||||
|
vehicleMake: vehicleMake,
|
||||||
|
vehicleModel: vehicleModel,
|
||||||
|
vehicleStyle: vehicleStyle,
|
||||||
|
hasVin: hasVin,
|
||||||
|
cashOrInsuranceAccountType: cashOrInsuranceAccountType,
|
||||||
|
isVerified: isVerified,
|
||||||
|
coverageStatus: coverageStatus,
|
||||||
|
coverageSubStatus: coverageSubStatus,
|
||||||
|
damageType: damageType,
|
||||||
|
productType: productType,
|
||||||
|
eon: eon,
|
||||||
|
referralNumber: referralNumber,
|
||||||
|
referralSequenceNumber: referralSequenceNumber,
|
||||||
|
referralDate: referralDate,
|
||||||
|
workOrderNumber: workOrderNumber,
|
||||||
|
workOrderId: workOrderId,
|
||||||
|
isPia: isPia,
|
||||||
|
piaType: piaType,
|
||||||
|
parentAccountNumber: parentAccountNumber,
|
||||||
|
settledTenderAmount: settledTenderAmount,
|
||||||
|
recalRequired: recalRequired,
|
||||||
|
recalType: recalType,
|
||||||
|
serviceZipCode: serviceZipCode,
|
||||||
|
providerCtu: providerCtu,
|
||||||
|
appointmentDate: appointmentDate,
|
||||||
|
serviceType: serviceType,
|
||||||
|
promoCodes: promoCodes,
|
||||||
|
hasTechnicianNotes: hasTechnicianNotes,
|
||||||
|
paymentMethod: paymentMethod,
|
||||||
|
isTextingOptedIn: isTextingOptedIn,
|
||||||
|
isEarlyBird: isEarlyBird,
|
||||||
|
insuranceCo: insuranceCo,
|
||||||
|
deductible: deductible,
|
||||||
|
isNoComp: isNoComp,
|
||||||
|
isItac: isItac,
|
||||||
|
subTotalPrice: subTotalPrice,
|
||||||
|
totalPrice: totalPrice,
|
||||||
|
userAgent: userAgent,
|
||||||
|
cashPriceSubTotal: cashPriceSubTotal,
|
||||||
|
billToAccountNumber: billToAccountNumber,
|
||||||
|
};
|
||||||
|
|
||||||
|
return globalMethods.callHttpClient({
|
||||||
|
method: endpoints.LogIssSessionData.method,
|
||||||
|
endpoint: endpoints.LogIssSessionData.url,
|
||||||
|
payload,
|
||||||
|
logApiCall: false,
|
||||||
|
bailoutOnError: false
|
||||||
|
}).then(
|
||||||
|
(response) => response,
|
||||||
|
(error) => {
|
||||||
|
console.log(`Analytics Service Error: ${error.data}`);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
updateContactInfo(contactInfo) {
|
updateContactInfo(contactInfo) {
|
||||||
this.order.customer.firstName = contactInfo?.firstName ?? this.order.customer.firstName;
|
this.order.customer.firstName = contactInfo?.firstName ?? this.order.customer.firstName;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue