diff --git a/src/layouts/entry-page/entry-page.vue b/src/layouts/entry-page/entry-page.vue index 47031709..503827ac 100644 --- a/src/layouts/entry-page/entry-page.vue +++ b/src/layouts/entry-page/entry-page.vue @@ -15,6 +15,7 @@ import { useMainStore } from '@/store'; import showIssLoadingModal from '@/helpers/loading-modal-helper'; import applicationConfig from '@/constants/application-config'; import { toPossessive } from '@/helpers/text-helper'; +import analyticsMixin from '@/mixins/analytics-mixin'; export default { name: 'entry-page', @@ -36,7 +37,6 @@ export default { async mounted() { try { const queryStringParams = this.parseQueryParms(); - const { isAuthorized, clientData, decryptedParams } = await this.validateClientTagOnEntry(queryStringParams); this.unauthorized = !isAuthorized; @@ -46,7 +46,11 @@ export default { return; } + // Populate all the ISS Config values from the service call returns. this.populateISSConfigValues(clientData); + + // Session should only be created / validated on successful client tag validation to avoid unnecessary sessions for unauthorized users. + await analyticsMixin.methods.validateSession(); try { // Check cookie @@ -115,6 +119,8 @@ export default { return { isAuthorized: false }; } + this.mainStore.issConfig.clientTag = clientTag; + const resp = await validateISSClientTag(clientTag); if (!resp) { return { isAuthorized: false }; @@ -141,7 +147,7 @@ export default { isAuthorized = true; } - if (isAuthorized) { + if (isAuthorized) { clientData = resp; } } diff --git a/src/layouts/schedule-page/schedule-page.vue b/src/layouts/schedule-page/schedule-page.vue index c76aacce..0fae07bd 100644 --- a/src/layouts/schedule-page/schedule-page.vue +++ b/src/layouts/schedule-page/schedule-page.vue @@ -741,7 +741,7 @@ export default { startDate, endDate, this.selectedAppointmentType, - this.selectedProvider.providerNumber || mobileProviderNumberToUse, + this.selectedProvider?.providerNumber || mobileProviderNumberToUse, this.selectedMobileZipCode ); // ADD API CALL RESULTS TO EXISTING DATE DATA diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index 4312d65c..d3c139c7 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -554,7 +554,13 @@ export default { const sid = getSessionIdValue(); // cookieNames.SESSION_ID // const skey = getSessionKeyValue(); const referrer = applicationConfig.CURRENT_ENVIRONMENT !== 'Localhost' ? document.referrer : null; + const store = useMainStore(); + const clientTag = store.issConfig.clientTag; + const siteType = store.issConfig.siteType; + const payload = { + clientTag, + siteType: siteType, deviceId, referrer, sessionId: sid, diff --git a/src/router/index.js b/src/router/index.js index abbd9061..1fbe148f 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -35,17 +35,6 @@ const routes = [ return await GoToAccessIsDenied(next); } - await analyticsMixin.methods.validateSession(); - - // Do not run these for the main entry page - as it is not part of the user flow. - if (issPageToUse !== issPageValues.ENTRY_PAGE && issPageToUse !== issPageValues.BAILOUT_PAGE) { - try { - await runExperiments(issPageToUse); - } catch (error) { - console.error('Failed to run experiments during route navigation.', error); - } - } - // Intercept all navigation if a submitted order exists in storage if (useMainStore().hasSubmittedOrder()) { if (to.query.issPage !== issPageValues.ENTRY_PAGE) { @@ -84,15 +73,36 @@ const routes = [ var routeData = []; - try { - routeData = await GetRouteInfoFromPageName(issPageToUse); - } - catch ( error ) { - window.top.location = '/static/error/index.html'; - } + // Only load the routes if we are not on entry-page (this page is the default route and should always be valid) + // or the access-denied page (which is an error page) + const shouldGetRouteInfo = (issPageToUse !== issPageValues.ENTRY_PAGE && issPageToUse !== issPageValues.ACCESS_DENIED); - if (routeData[0].name.toLowerCase() === 'error') { - throw new Error('Page not found!'); + if (shouldGetRouteInfo) { + try { + routeData = await GetRouteInfoFromPageName(issPageToUse); + } + catch ( error ) { + window.top.location = '/static/error/index.html'; + return null; + } + + if (routeData[0].name.toLowerCase() === 'error') { + throw new Error('Page not found!'); + } + } + else { + try { + // Manually create the page route. + routeData.push({ + path: '/', + name: issPageToUse, + component: lazyLoadComponent(issPageToUse) + }); + } + catch ( error ) { + window.top.location = '/static/error/index.html'; + return null; + } } // Add our dynamic route. @@ -177,14 +187,32 @@ router.afterEach(async (to, from) => { store.clearSaveSessionPromise(); } - const skipSaveSession = !!router.options.history.state[routerParams.SKIP_SAVE_SESSION]; - if (from.name !== undefined && !skipSaveSession && !store.hasSubmittedOrder()) { - await saveSession({ bailoutOnError: from.name === issPageValues.ENTRY_PAGE}); - } + // Do not run base page logic (GA logging, session logging etc..) on the entry page or access denied page. + const shouldRunPageLogic = (to.query.issPage !== issPageValues.ENTRY_PAGE && to.query.issPage !== issPageValues.ACCESS_DENIED); + + if (shouldRunPageLogic) { + // Do not run experiments for the bailout page. + const shouldRunExperiments = (to.query.issPage !== issPageValues.BAILOUT_PAGE); + + await analyticsMixin.methods.validateSession(); + + const skipSaveSession = !!router.options.history.state[routerParams.SKIP_SAVE_SESSION]; + if (from.name !== undefined && !skipSaveSession && !store.hasSubmittedOrder()) { + await saveSession({ bailoutOnError: from.name === issPageValues.ENTRY_PAGE}); + } - if (to.query.issPage !== issPageValues.ENTRY_PAGE) { document.title = routerTitles[to.query.issPage] || 'Safelite Solutions®'; + if (shouldRunExperiments) { + try { + // Run experiments for page. + await runExperiments(to.query.issPage); + + } catch (error) { + console.error('Failed to run experiments during route navigation.', error); + } + } + // digital consumer logging analyticsMixin.methods.logDigitalConsumer(); @@ -436,6 +464,16 @@ function arePagePrerequisitesValid(component) { return component.default.methods.arePagePrerequisitesValid === undefined || component.default.methods.arePagePrerequisitesValid(); } +// TODO: Put this function some place common. +function parseQueryParms(queryString) { + // Dump the query string parameters into an object + if (queryString) { + return Object.fromEntries(Object.entries(queryString).map(([key, value]) => [key.toLowerCase(), value])); + } + + return {}; +} + // Run SiteEntry and PageEntry triggers for experiments async function runExperiments(nextPage) { const store = useMainStore(); diff --git a/src/store/index.js b/src/store/index.js index 54f97918..b23f4d47 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -254,6 +254,7 @@ export const getDefaultState = () => ({ clientDisplayName: 'Generic Insurance', // this is the default and will be overridden by the client's name or client display name. clientPossessiveName: 'Generic Insurance\'s', // this is the default and will be overridden by the client's name or client display name converted to possessive or the clients possessive name. clientHeader: {}, + clientTag: '', // ClientTag used by the client to enter the site. styleSheet: '', // Stylesheet used by the client. parentAccountNumber: 0, // Parent account number used by the client. billToAccountNumber: null, @@ -269,7 +270,7 @@ export const getDefaultState = () => ({ policyZipCode: null, dateOfLoss: null }, - siteType: null, + siteType: null, // SiteType / SubType the site is set to (Essential/Advanced). enableNoCompQuote: false } }); @@ -2242,6 +2243,7 @@ export const useMainStore = defineStore({ this.issConfig.clientFullName = 'Generic Insurance'; this.issConfig.clientDisplayName = 'Generic Insurance'; this.issConfig.clientHeader = {}; + this.issConfig.clientTag = ''; this.issConfig.parentAccountNumber = 0; this.issConfig.styleSheet = ''; this.issConfig.isCoverageEnabled = false; @@ -2632,9 +2634,11 @@ export const useMainStore = defineStore({ this.logExperimentIfExists(issPage, experimentUniverses.ISS_FEATURETOGGLE_AREFEES_HIDDEN); this.logExperimentIfExists(issPage, experimentUniverses.ISS_FEATURETOGGLE_AREFEES_OVERRIDDEN); }, - async initializeSession({ userId, sessionId, userAgent, referrer }) { + async initializeSession({ userId, clientTag, siteType, sessionId, userAgent, referrer }) { const payload = { applicationName: applicationConfig.APPLICATION_NAME, + clientTag: clientTag, + subType: siteType, userId, deviceId: userId, sessionId, @@ -2942,7 +2946,9 @@ export const useMainStore = defineStore({ async validateClientTag(clientTag) { return globalMethods.callHttpClient({ method: endpoints.ValidateClientTag.method, - endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}` + endpoint: `${endpoints.ValidateClientTag.url}/${clientTag}`, + logApiCall: false, + bailoutOnError: false }); }, @@ -2956,7 +2962,9 @@ export const useMainStore = defineStore({ return await globalMethods.callHttpClient({ method: endpoints.ValidateClientSignature.method, endpoint: endpoints.ValidateClientSignature.url, - payload + payload, + logApiCall: false, + bailoutOnError: false }); }, diff --git a/src/styles/client-customizations.scss b/src/styles/client-customizations.scss index 0392e5f2..8cb89995 100644 --- a/src/styles/client-customizations.scss +++ b/src/styles/client-customizations.scss @@ -1,8 +1,8 @@ // Each Advanced client with custom colors/styles are defined in this file. -// Begin Liberty Mutual, SafeCo Custom Colors and Styles +// Begin Liberty Mutual, Safeco Custom Colors and Styles .LibertyMutual, -.SafeCo { +.SafecoInsurance { //Define colors for namespaced classes $header-background: #ffd100; $accent-fill: #e6f1f3; // Calendar background @@ -50,7 +50,7 @@ } } -// End Liberty Mutual, SafeCo +// End Liberty Mutual, Safeco