From a0cf6d98648dbeb57003f8679d4e518c65e1de0c Mon Sep 17 00:00:00 2001 From: FrankRua Date: Wed, 13 Apr 2022 17:05:13 -0400 Subject: [PATCH 1/4] Start for calling endpoint --- src/constants/store-actions.js | 1 + src/layouts/vehicle-year/vehicle-year.vue | 3 +-- src/store/index.js | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/constants/store-actions.js b/src/constants/store-actions.js index 640364213..9e87416d4 100644 --- a/src/constants/store-actions.js +++ b/src/constants/store-actions.js @@ -17,6 +17,7 @@ const storeActions = { LOAD_ORDER: "loadOrder", SET_REFERRAL_INFORMATION: "setReferralInformation", VALIDATE_ZIP: "validateZip", + LOG_EXPERIMENT_EXPOSURE: "logExperimentExposure", // DEPENDENCY MUTATIONS RESET_VEHICLE_STATE_AND_DEPENDENCIES: "resetVehicleAndDependencies", diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index 305cef7fc..c04b5bd9d 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -36,8 +36,7 @@ export default { async beforeRouteEnter(to, from, next) { // Call APIs const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); - const yearQuestionInitialDataPromise = - yearQuestion.methods.loadInitialData(); + const yearQuestionInitialDataPromise = yearQuestion.methods.loadInitialData(); // Settle promises and get results const promiseResultMap = [ diff --git a/src/store/index.js b/src/store/index.js index 07336ccf0..fb9c6f525 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -363,6 +363,10 @@ export const actions = { context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId); }, + logExperimentExposure(context, {userId, sessionKey, sessionId, pageName, serverName, pageEvent, universeName }){ + + }, + // Parts API Actions getPartsOrQuestions(context, { carId, glassArray, zipCode, vin = '' }) { return globalMethods.callHttpClient({ From 650fbd564eeb1926a82f3aab73003d46f8b9d08c Mon Sep 17 00:00:00 2001 From: FrankRua Date: Thu, 14 Apr 2022 10:46:35 -0400 Subject: [PATCH 2/4] Log experiment exposure on vehicle-year --- src/constants/cookie-names.js | 5 ++ src/constants/endpoints.js | 4 + src/constants/experiments.js | 6 ++ .../heritage-integration/cookie-helper.js | 79 +++++++++++++++++-- src/layouts/vehicle-year/vehicle-year.vue | 21 +++++ src/store/index.js | 14 +++- 6 files changed, 122 insertions(+), 7 deletions(-) create mode 100644 src/constants/experiments.js diff --git a/src/constants/cookie-names.js b/src/constants/cookie-names.js index 2756a8eb7..c52debc2a 100644 --- a/src/constants/cookie-names.js +++ b/src/constants/cookie-names.js @@ -1,5 +1,10 @@ const cookieNames = { FUNNEL_SESSION_INFO: "FunnelSessionInfo", + + // Existing Safelite.com cookies + DXDEV: "dxdev", + SESSION_ID: "sid", + SESSION_KEY: "skey" }; export { cookieNames }; diff --git a/src/constants/endpoints.js b/src/constants/endpoints.js index 2aa1fe226..2325c29cd 100644 --- a/src/constants/endpoints.js +++ b/src/constants/endpoints.js @@ -63,6 +63,10 @@ const endpoints = { url: "/location/api/v1/location/zip", method: "GET", }, + LogExperimentExposureIfAssigned:{ + url: "/analytics/api/v1/analytics/log-experiment-exposure", + method: "POST", + } }; export { endpoints }; diff --git a/src/constants/experiments.js b/src/constants/experiments.js new file mode 100644 index 000000000..13a51aa7f --- /dev/null +++ b/src/constants/experiments.js @@ -0,0 +1,6 @@ +const experimentUniverses = { + CONCEPT_FUNNEL: 'ConceptFunnel' +}; + +export { experimentUniverses }; + \ No newline at end of file diff --git a/src/helpers/heritage-integration/cookie-helper.js b/src/helpers/heritage-integration/cookie-helper.js index 36516a570..1dfa6af4d 100644 --- a/src/helpers/heritage-integration/cookie-helper.js +++ b/src/helpers/heritage-integration/cookie-helper.js @@ -24,13 +24,13 @@ export function updateOrCreateFunnelCookie() { /* Gets the current instance of the funnel cookie. Returns null if cookie isn't valid JSON. -*/ +*/ export function getFunnelCookie() { const cookieJson = document.cookie ?.split("; ") ?.find(row => row.startsWith(`${cookieNames.FUNNEL_SESSION_INFO}=`)) ?.split("=")[1]; - + try { return JSON.parse(cookieJson); } catch (error) { @@ -45,6 +45,61 @@ export function deleteFunnelCookie() { document.cookie = `${cookieNames.FUNNEL_SESSION_INFO}=; Max-Age=0; path=${applicationConfig.COOKIE_PATH}; ${getCookieDomainValue()}`; } +/* + Gets cookie domain value. Localhost will be empty "". +*/ +export function getCookieDomainValue() { + return location.hostname.includes("localhost") ? "" : `domain=${getDomainWithoutSubdomain()};`; +} + +/* + Gets value of dxdev cookie, and then extracts "did" value from it. + Returns empty string if cookie not found or "did" string not present. +*/ +export function getDeviceIdValue(){ + const cookieValue = getCookieByName(cookieNames.DXDEV); + const cookieValueMatch = cookieValue.match("(?<=did=).*?(?=&)"); + + if(cookieValueMatch){ + return cookieValueMatch[0]; + } + + return ''; +} + +/* + Gets value of sid cookie, returns empty string if not found. +*/ +export function getSessionIdValue(){ + const cookieValue = getCookieByName(cookieNames.SESSION_ID); + + if(cookieValue){ + return cookieValue; + } + + return ''; +} + +/* + Gets value of skey cookie, returns empty string if not found. +*/ +export function getSessionKeyValue(){ + const cookieValue = getCookieByName(cookieNames.SESSION_KEY); + + if(cookieValue){ + return cookieValue; + } + + return ''; +} + +/* +=========================== += PRIVATE FUNCTIONS = +=========================== +*/ + + /* Used to set properties on the funnel cookie. Takes an object with properties to set. Will overwrite existing properties. @@ -65,10 +120,9 @@ function setFunnelCookieProperties(properties) { } } -export function getCookieDomainValue() { - return location.hostname.includes("localhost") ? "" : `domain=${getDomainWithoutSubdomain()};`; -} - +/* + Gets current domain without the subdomain for cookie. +*/ function getDomainWithoutSubdomain() { let url = location.hostname; if (url.includes("localhost")) { @@ -82,3 +136,16 @@ function getDomainWithoutSubdomain() { .slice(-(urlParts.length === 4 ? 3 : 2)) .join('.')}`; } + +/* + Gets cookie value by name, returns empty string if not found. +*/ +function getCookieByName(name) { + const value = "; " + document.cookie; + const parts = value.split("; " + name + "="); + + if (parts.length === 2) { + return parts.pop().split(";").shift(); + } + return ""; +} \ No newline at end of file diff --git a/src/layouts/vehicle-year/vehicle-year.vue b/src/layouts/vehicle-year/vehicle-year.vue index c04b5bd9d..85faa0d61 100644 --- a/src/layouts/vehicle-year/vehicle-year.vue +++ b/src/layouts/vehicle-year/vehicle-year.vue @@ -17,11 +17,16 @@ import yearQuestion from "@/layouts/vehicle-year/year-question/year-question"; import funnelHeader from "@/common-components/funnel-header/funnel-header"; import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; + // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; import { storeMutations } from "@/constants/store-mutations"; import { storeActions } from "@/constants/store-actions"; +import { experimentUniverses } from "@/constants/experiments"; +import { getDeviceIdValue, getSessionIdValue, getSessionKeyValue } from "@/helpers/heritage-integration/cookie-helper"; + +import baseMixin from "@/mixins/base-mixin"; import store from "@/store"; export default { @@ -38,6 +43,18 @@ export default { const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage); const yearQuestionInitialDataPromise = yearQuestion.methods.loadInitialData(); + // Log experiment exposure + const logExperimentExposurePromise = baseMixin.methods.dispatchNonBlockingStoreAction(storeActions.LOG_EXPERIMENT_EXPOSURE, + { + userId: getDeviceIdValue(), + sessionKey: getSessionKeyValue(), + sessionId: getSessionIdValue(), + pageName: to.query.fmgPage, + serverName: 'ConceptFunnel', + pageEvent: { action: '', event: 'ENTRY' }, + universeName: experimentUniverses.CONCEPT_FUNNEL + }, false); + // Settle promises and get results const promiseResultMap = [ { @@ -48,6 +65,10 @@ export default { resultKey: "yearQuestionInitialData", promise: yearQuestionInitialDataPromise, }, + { + resultKey: "logExperimentExposure", + promise: logExperimentExposurePromise, + }, ]; let resultMap = await settleAllPromises(promiseResultMap); diff --git a/src/store/index.js b/src/store/index.js index fb9c6f525..d7f00dca3 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -364,7 +364,19 @@ export const actions = { }, logExperimentExposure(context, {userId, sessionKey, sessionId, pageName, serverName, pageEvent, universeName }){ - + return globalMethods.callHttpClient({ + method: endpoints.LogExperimentExposureIfAssigned.method, + endpoint: endpoints.LogExperimentExposureIfAssigned.url, + payload: { + userId: userId, + sessionKey: sessionKey, + sessionId: sessionId, + pageName: pageName, + serverName: serverName, + pageEvent: pageEvent, + universeName: universeName + } + }) }, // Parts API Actions From cfc39756843d68754c3308725d500e2cebed1f99 Mon Sep 17 00:00:00 2001 From: FrankRua Date: Thu, 14 Apr 2022 11:08:57 -0400 Subject: [PATCH 3/4] Small other changes --- src/global-methods.js | 1 + src/helpers/layout-helper.js | 6 +++--- src/store/index.js | 36 ++++++++++++++++++------------------ 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/global-methods.js b/src/global-methods.js index f0675c02d..c0823f29a 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -30,6 +30,7 @@ export default { } }, (error) => { + console.error(error); return reject(error.response); } ); diff --git a/src/helpers/layout-helper.js b/src/helpers/layout-helper.js index 10f331faf..0a8177e25 100644 --- a/src/helpers/layout-helper.js +++ b/src/helpers/layout-helper.js @@ -15,10 +15,10 @@ export function settleAllPromises(promiseResultMap) { // when returned, so other promises do. Map the results to the object // so that the object is the return data. - if (results[i].value.data === undefined) { - resultMap[promiseName] = results[i].value; + if (results[i]?.value?.data === undefined) { + resultMap[promiseName] = results[i]?.value; } else { - resultMap[promiseName] = results[i].value.data; + resultMap[promiseName] = results[i]?.value?.data; } } diff --git a/src/store/index.js b/src/store/index.js index d7f00dca3..0fc7dec76 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -93,7 +93,7 @@ export const mutations = { updateVehicleVin(state, vin) { state.order.vehicle.vin = vin; }, - updateIsRepair(state, isRepair){ + updateIsRepair(state, isRepair) { state.order.damage.isRepair = isRepair; }, updateNumberOfChips(state, numberOfChips) { @@ -248,7 +248,7 @@ export const actions = { method: endpoints.LookupVinByPlate.method, endpoint: endpoints.LookupVinByPlate.url, payload: { - licensePlate: licensePlate, + licensePlate: licensePlate, licenseState: licenseState }, }); @@ -292,12 +292,12 @@ export const actions = { }, getDamageOptions(context, { carId }) { return globalMethods.callHttpClient({ - methods: endpoints.GetDamageOptions.method, + methods: endpoints.GetDamageOptions.method, endpoint: `${endpoints.GetDamageOptions.url}/${carId}`, payload: {}, }); }, - validateZip(context, {zip}) { + validateZip(context, { zip }) { return globalMethods.callHttpClient({ methods: endpoints.ValidateZip.method, endpoint: `${endpoints.ValidateZip.url}/${zip}` @@ -363,20 +363,20 @@ export const actions = { context.commit(storeMutations.UPDATE_REFERRAL_CORRELATION_ID, referralCorrelationId); }, - logExperimentExposure(context, {userId, sessionKey, sessionId, pageName, serverName, pageEvent, universeName }){ - return globalMethods.callHttpClient({ - method: endpoints.LogExperimentExposureIfAssigned.method, - endpoint: endpoints.LogExperimentExposureIfAssigned.url, - payload: { - userId: userId, - sessionKey: sessionKey, - sessionId: sessionId, - pageName: pageName, - serverName: serverName, - pageEvent: pageEvent, - universeName: universeName - } - }) + logExperimentExposure(context, { userId, sessionKey, sessionId, pageName, serverName, pageEvent, universeName }) { + return globalMethods.callHttpClient({ + method: endpoints.LogExperimentExposureIfAssigned.method, + endpoint: endpoints.LogExperimentExposureIfAssigned.url, + payload: { + userId: userId, + sessionKey: sessionKey, + sessionId: sessionId, + pageName: pageName, + serverName: serverName, + pageEvent: pageEvent, + universeName: universeName + } + }); }, // Parts API Actions From 086be1ab6b6846a693e807763d785b06cbad2b1b Mon Sep 17 00:00:00 2001 From: FrankRua Date: Thu, 14 Apr 2022 11:19:20 -0400 Subject: [PATCH 4/4] default to int --- src/helpers/heritage-integration/cookie-helper.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/heritage-integration/cookie-helper.js b/src/helpers/heritage-integration/cookie-helper.js index 1dfa6af4d..5a9ed4691 100644 --- a/src/helpers/heritage-integration/cookie-helper.js +++ b/src/helpers/heritage-integration/cookie-helper.js @@ -81,7 +81,7 @@ export function getSessionIdValue(){ } /* - Gets value of skey cookie, returns empty string if not found. + Gets value of skey cookie, returns 0 if not found. */ export function getSessionKeyValue(){ const cookieValue = getCookieByName(cookieNames.SESSION_KEY); @@ -90,7 +90,7 @@ export function getSessionKeyValue(){ return cookieValue; } - return ''; + return 0; } /*