// Supporting files import { createWebHistory, createRouter } from "vue-router"; import { storeActions } from "@/constants/store-actions"; import { storeMutations } from "../constants/store-mutations"; import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js"; import { routingTable } from "@/router/router-constants/routing-table.js"; import { globalEvents, globalEventTypes } from "@/constants/events"; import { queryStrings } from "@/constants/query-strings"; import { getQuerystringParameter, buildQuerystringObject } from "@/helpers/querystring-helper"; import { getDeviceIdValue } from "@/helpers/heritage-integration/cookie-helper"; import { showFmgLoadingModal } from "@/helpers/loading-modal-helper"; import { fmgPageValues, funnelStartPageName } from "@/router/router-constants/fmgPage-values"; import { externalParameterStatus } from "@/constants/external-parameters"; // Heritage integration import { isSavedSessionStillActive } from "@/helpers/heritage-integration/session-helper"; import { updateOrCreateFunnelCookie, getFunnelCookie, updateSessionIdCookie, deleteFunnelCookie, getAffiliateCookies, setupAdvertiserTracking, } from "@/helpers/heritage-integration/cookie-helper"; import { loadSessionIfPresent, saveSession } from "@/helpers/heritage-integration/order-helper"; import { getPageToRouteExistingOrderTo, navigateToHeritageFunnel, getImplicitNavigation, } from "@/helpers/heritage-integration/navigation-helper"; import baseMixin from "@/mixins/base-mixin"; import eventBus from "@/helpers/event-bus/event-bus"; import store from "@/store"; import analyticsMixin from "@/mixins/analytics-mixin"; import { experimentTriggers } from "../constants/experiments"; import { applicationConfig } from "../constants/application-config"; import { shouldStripPromoQueryString } from "@/helpers/promotions-helper"; import bailout from "@/layouts/bailout/bailout"; import { nextTick } from "vue"; import { getBoolFromString } from "@/helpers/boolean-helper"; const routes = [ { path: "/bailout", name: "bailout", component: bailout, }, { path: "/", name: "root", async beforeEnter(to, from, next) { // If we have no query string, or we don't have the FmgPage query string. try { log("------------- router index.js beforeEnter start -----------------"); log(" --to: ", to); log(" --cookie: ", getFunnelCookie()); log(` --from.redirectedFrom:>${JSON.stringify(from.redirectedFrom)}<`, ""); await analyticsMixin.methods.validateSession(); // after session is validated, remove the fromHeritage querystring if it exists so session expiration works if (to.query) { delete to.query[queryStrings.FROM_HERITAGE]; } if (getFunnelCookie()?.SuppressConceptFunnel) { log(" --go to heritage suppressConceptFunnel: "); await navigateToHeritageFunnel({ shouldSaveSession: false }); return next(false); } // If the saved session has timed out, clear the session, execute 404 logic. if (getFunnelCookie() !== null && !isSavedSessionStillActive()) { log(" --save session timeout go to start"); const errorPayload = { cause: "expired session", currentPage: from?.query?.fmgPage, nextPage: to?.query?.fmgPage, }; await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE); deleteFunnelCookie(); GoToFunnelStartOn404(next, errorPayload); return; } const fromReturnUser = from?.name === fmgPageValues.RETURN_USER; const fromContentSite = getQuerystringParameter(queryStrings.START_TYPE) === "fmg"; const toReturnUserPage = to.query?.fmgPage === fmgPageValues.RETURN_USER; log(" --fromReturnUser ", fromReturnUser); log(" --to.query.fmgPage ", to.query?.fmgPage); // Intercept all navigation if a submitted order exists in storage if (window.sessionStorage.getItem("submittedOrder") !== null) { if (to.query.fmgPage !== funnelStartPageName) { to.query.fmgPage = fmgPageValues.CONFIRMATION; log(" --has submittedOrder go to confirmation"); } } // On entering the funnel "fresh", read cookie information, decide what to do next. else if (from.redirectedFrom === undefined || fromReturnUser) { // if entering the funnel from the content site, check and see if there is already a vehicle year in vuex. // if so, send them to return-user page. if ( fromContentSite && !toReturnUserPage && store.getters.order.vehicle?.year > 0 ) { log(" --from content site navigate to return user"); var qso = { fmgPage: fmgPageValues.RETURN_USER, }; const newQueryString = buildQuerystringObject(qso, true); log(" -- returnUser add querystring: " + JSON.stringify(newQueryString)); router.push({ path: "/", query: Object.assign({}, newQueryString), }); return; } // clear the saveSessionPromise - if it exists in the vuex store but a new instance was created // the saveSessionPromise will no longer point to a valid promise log(" --clear promise"); baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE); if (!to.query.fmgPage?.startsWith("payment")) { //payment pages used to return from safelitehop so exclude here // Remove the parameter after quote release // for testing end to end locally, see if there is a referralNumber on the querystring // that could have changed in heritage and then stick it in the store and then update the cookie // so load-session runs properly. this can be removed when heritage goes away const referralNumber = getQuerystringParameter( queryStrings.REFERRAL_NUMBER ); const parentAccount = getQuerystringParameter(queryStrings.PARENT_ACCOUNT); const correlationId = getQuerystringParameter(queryStrings.CORRELATION_ID); if (referralNumber) { store.commit(storeMutations.UPDATE_REFERRAL_NUMBER, referralNumber); store.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, parentAccount); store.commit( storeMutations.UPDATE_REFERRAL_CORRELATION_ID, correlationId ); log(" --update cookie"); updateOrCreateFunnelCookie(); } //Affiliate Cookies const affiliateCookies = getAffiliateCookies(); if (affiliateCookies != null && affiliateCookies.length > 0) { store.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies); } setupAdvertiserTracking(); log(" --load session start"); const loadSessionResponse = await loadSessionIfPresent( to.query.isInsurance != null ? to.query.isInsurance == "true" ? true : false : null, to.query.fmgPage ); log(" --load session end"); //Update external parameter state but not when returning from heritage if (!to.query.fmgPage?.startsWith("service-location") && !fromReturnUser) { updateExternalParameterState(); } // clear part related state because heritage selected a new vehicle if ( to.query.fmgPage === fmgPageValues.VEHICLE && getBoolFromString(getFunnelCookie()?.HasDelayedClaimRegistration) && !fromReturnUser ) { store.commit(storeMutations.RESET_GLASS_PARTS_STATE); } // if coming from the return user page, clear the destination page so implicit navigation runs log(" --to.query ", JSON.stringify(to.query)); if (fromReturnUser && to.query) { log(" --clear to.query"); delete to.query[queryStrings.FMG_PAGE]; //to.query[queryStrings.FMG_PAGE] = ""; log(" --to.query cleared ", JSON.stringify(to.query)); } const pageToRedirectTo = await getPageToRouteExistingOrderTo(to); log(" --pageToRedirectTo ", JSON.stringify(pageToRedirectTo)); // This logic may determine that the user should be sent to heritage -- if so, do that here. if (pageToRedirectTo === fmgPageValues.HERITAGE) { // prettier-ignore log(" --go to heritage pageToRedirectTo ", JSON.stringify(pageToRedirectTo)); await navigateToHeritageFunnel({ shouldSaveSession: false }); return next(false); } // Assign our fmgPage so it will load normally like the other pages. to.query.fmgPage = pageToRedirectTo; log(" --assign to: ", JSON.stringify(pageToRedirectTo)); } } // Reroute around pages that should not be available. // Exception 1: Integrated Users should not see vehicle or quote pages. if ( store.getters.payment?.insuranceCoverage?.isVerified || store.getters.order?.referralNumber?.length === 6 ) { if (to.query.fmgPage === fmgPageValues.VEHICLE) { to.query.fmgPage = fmgPageValues.VEHICLE_DAMAGE; } else if ( to.query.fmgPage === fmgPageValues.QUOTE || to.query.fmgPage === fmgPageValues.INSURANCE_COMPANY ) { log(" --block quote page for integrated clients - go to heritage"); // Push to heritage if going to quote & integrated. await navigateToHeritageFunnel({ shouldSaveSession: false }); return next(false); } } 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(); // If we already have our route, go to it. if (router.hasRoute(to.query.fmgPage)) { // Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function. let component = router .getRoutes() .filter((x) => x.name === to.query.fmgPage)[0].components; // If the component hasn't been loaded fully, load it before we check prerequisites. if (component.default.methods === undefined) { component = await component.default(); } if (!arePagePrerequisitesValid(component)) { console.log("Page prereq error: " + component.default.name); if (to.query.fmgPage === fmgPageValues.PAYMENT) { await store.getters.applicationUser.saveSessionPromise; window.location = applicationConfig.PIA_CANCEL_URL; return; } const errorPayload = { cause: "invalid page prerequisites for page", currentPage: from?.query?.fmgPage, nextPage: to?.query?.fmgPage, }; GoToFunnelStartOn404(next, errorPayload); return; } log(" --has route:", to.query.fmgPage); return next({ name: to.query.fmgPage, query: to.query, params: to.params }); } if (!isExistingFmgPageName(to.query.fmgPage)) { const errorPayload = { cause: "invalid page name", currentPage: from?.query?.fmgPage, nextPage: to?.query?.fmgPage, }; GoToFunnelStartOn404(next, errorPayload); return; } // Get route info for the given url. Names will have a 1:1 relationship with names in the Cms. const routeData = GetRouteInfoFromPageName(to.query.fmgPage); log("--routeData:", routeData); // Add our dynamic route. router.addRoute({ path: routeData[0].path, // Always the same path, because we control it with query strings. name: routeData[0].name, component: routeData[0].component, }); // Call the next components arePagePrerequisitesValid method before load. // If it returns false, use the 404 logic. const nextComponent = await router .getRoutes() .filter((x) => x.name === routeData[0].name)[0] .components.default(); if (!arePagePrerequisitesValid(nextComponent)) { // prettier-ignore console.log("Page Prereqs not valid for next component: " + nextComponent.default.name); const errorPayload = { cause: "invalid page prerequisites for page", currentPage: from?.query?.fmgPage, nextPage: to?.query?.fmgPage, }; GoToFunnelStartOn404(next, errorPayload); return; } log("------------- router index.js beforeEnter end -----------------"); // Assign current query string parameters, as well as our fmgPage one. next({ name: routeData[0].name, query: Object.assign(to.query, { fmgPage: routeData[0].name }), params: to.params, }); } catch (error) { global.$logger.logError(`Routing ${error.stack}`); if (to.query?.fmgPage === funnelStartPageName) { deleteFunnelCookie(); await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE); } console.log(new Date() + " Exception in beforeEnter:" + JSON.stringify(error)); // If we don't have a route, go to our 404 page. const errorPayload = { cause: "uncaught error in beforeEnter", currentPage: from?.query?.fmgPage, nextPage: to?.query?.fmgPage, fullError: error, errorStack: error?.stack, }; GoToFunnelStartOn404(next, errorPayload); return; } }, }, ]; const router = createRouter({ history: createWebHistory("/fmg/"), routes, //Cause "page" to begin at the top when route chanages. scrollBehavior(to, from, savedPosition) { // always scroll to top return { top: 0 }; }, }); //---------------------------------------------------------- Router Functions ---------------------------------------------------------- router.beforeEach(async (to, from, next) => { log("------------- router index.js beforeEach start -----------------"); // set lastNavigationPage here to capture state before API calls for analytics. // use current page url query string name when to.name is "root" (due to unresolved navigation in beforeEach) router.lastNavigationPage = to.name == "root" ? analyticsMixin.methods.getPageName() : to.name; const fromQueryPage = from.query?.fmgPage; if (fromQueryPage === undefined) { showFmgLoadingModal(true); } const toQueryPage = to.query?.fmgPage; const notToPIAReturn = toQueryPage != fmgPageValues.PAYMENT_PIA_RETURN; const isInIframe = window !== window.top; if (store.getters.externalParameterState?.isExternalParameter) { // Check if alert event is on the bus const alertEvent = eventBus.readEventFromBus( globalEvents.Categories.GLOBAL_ALERT, globalEvents.SubCategories.PAGE_NOT_FOUND ); //Uknown alerts most likely were added by a failed api call in global-methods const unknownAlertEvent = eventBus.readEventFromBus( globalEvents.Categories.GLOBAL_ALERT, globalEvents.SubCategories.UNKNOWN_ERROR ); // If alert event is on the bus, then display the alert if (alertEvent !== undefined || unknownAlertEvent !== undefined) { store.commit( storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.INACTIVE ); } } // fromPaymentToConfirmation workaround for navigating from an iframe but // isInIframe evaluates to false for some reason when navigating from payment to confirmation const fromPaymentToConfirmation = fromQueryPage === fmgPageValues.PAYMENT && toQueryPage === fmgPageValues.CONFIRMATION; if ((isInIframe && notToPIAReturn) || fromPaymentToConfirmation) { const newUrl = `${window.top.location.origin}${to.href}`; window.top.location.href = newUrl; next(false); // Refresh page if navigating to self to prevent locking. // For now only carved out for vehicle; all modals are opened through anchor tags at the moment, // which also self navigate, but relied on the page remaining the same on self-navigation. } else if (toQueryPage === fromQueryPage && toQueryPage === getRedirectedStartPage()) { router.go(0); next(false); } else { next(); } log("------------- router index.js beforeEach end -----------------"); }); router.afterEach(async (to, from) => { // Update lastPageVisited in the store store.commit(storeMutations.UPDATE_LAST_PAGE_VISITED, to.name); // If saving on navigation is requested, check for saved SessionId or EmailAddress to determine if saving is appropriate if (getBoolFromString(window.history.state.isSavingNavigation)) { if ( store.getters.applicationUser.savedSessionId || store.getters.order.customer?.emailAddress ) { await saveSession({ pageNameToLog: to.query.fmgPage }); } } if (!store.getters.externalParameterState?.isExternalParameter) { showFmgLoadingModal(false); } // Push page view to GA analyticsMixin.methods.pushPageViewToGA(); // Push experiments to Data Layer analyticsMixin.methods.pushExperimentsToDataLayer(); // Push current order status to Data Layer analyticsMixin.methods.pushOrderToDataLayer(); if (to.query.fmgPage == fmgPageValues.CONFIRMATION) { //Push Ecommerce Cart to Data Layer analyticsMixin.methods.pushECommerceCartToDataLayer(); //Push Product Array to Data Layer analyticsMixin.methods.pushProductArrayToDataLayer(); //Push Commission Junction Gtm Data To Data Layer analyticsMixin.methods.pushCommissionJunctionGtmDataToDataLayer(); } }); router.navigateWithoutSaving = ( scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {} ) => { navigate(scenario, currentRoute, false, optionalQuery, optionalParams, optionalPageData); }; router.navigateWithSaving = ( scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {} ) => { navigate(scenario, currentRoute, true, optionalQuery, optionalParams, optionalPageData); }; router.navigateToExternalUrl = (url, optionalQuery = {}) => { log("------------- router navigateToExternalUrl -----------------"); log("url:", url); navigateToUrl(url, optionalQuery); }; router.navigateError = (errorPayload = null) => { DisplayPageError(errorPayload); }; //Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example. router.overrideNavigation = ( scenario, currentRoute, next, isSavingNavigation, optionalQuery = {}, optionalParams = {}, optionalPageData ) => { log("------------- router overrideNavigation -----------------"); log("scenario:", scenario); log("currentRoute:", currentRoute); log("isSavingNavigation:", isSavingNavigation); log("optionalQuery:", optionalQuery); log("optionalParams:", optionalParams); log("optionalPageData:", optionalPageData); navigate( scenario, currentRoute, isSavingNavigation, optionalQuery, optionalParams, optionalPageData ); next(); }; router.getNextPage = () => nextPageName; // PRIVATE VARIABLES var nextPageName; // PRIVATE FUNCTIONS // Navigate to the next route, depending on the scenario. async function navigate( scenario, currentRoute, isSavingNavigation, optionalQuery = {}, optionalParams = {}, optionalPageData = {} ) { if (!scenario) { console.error("No scenario provided. Please review the routing table."); return; } // Match our maps up and navigate if we have a destination. const matchingScenarioMap = getNavigationMap(scenario, currentRoute); const destinationFmgPageValue = matchingScenarioMap.destinationFmgPageValue; if (destinationFmgPageValue !== undefined) { // We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our fmgPage one. nextPageName = destinationFmgPageValue; // Update page data to the store for next page if provided. Otherwise, keep existing page data or set to empty object const existingPageDataForPage = store.getters.pageData(destinationFmgPageValue); baseMixin.methods.savePageDataToStore( destinationFmgPageValue, Object.keys(optionalPageData).length > 0 ? optionalPageData : (existingPageDataForPage ?? {}) ); optionalParams.isSavingNavigation = isSavingNavigation; // add querystring params to the route. if they are already in the store then no need to add them var queryStringsObject = { fmgPage: destinationFmgPageValue, }; const hasZip = getQuerystringParameter(queryStrings.ZIP_CODE); const zip = getQuerystringParameter(queryStrings.ZIP_CODE); const promo = getQuerystringParameter(queryStrings.PROMO); const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR); const logQs = getQuerystringParameter(queryStrings.LOG); baseMixin.methods.dispatchStoreAction(storeActions.SAVE_LOGGING_OPTION, logQs, false); log("------------- router index.js navigate start -----------------"); log(" --scenario: ", scenario); log(" --isSavingNavigation: ", isSavingNavigation); log(" --optionalQuery: ", optionalQuery); log(" --optionalParams: ", optionalParams); log(" --optionalPageData: ", optionalPageData); log(" --nextPageName: ", nextPageName); if ( hasZip && (store.getters.order.serviceLocation.zipCode === undefined || store.getters.order.serviceLocation.zipCode == null) && (store.getters.order.vehicle.registration.zipCode === undefined || store.getters.order.vehicle.registration.zipCode == null) ) { queryStringsObject[queryStrings.ZIP_CODE] = zip; } if (promo && !shouldStripPromoQueryString(currentRoute.query.fmgPage)) { queryStringsObject[queryStrings.PROMO] = promo; } if (pageError) { queryStringsObject[queryStrings.PAGE_ERROR] = pageError; } if (logQs) { queryStringsObject[queryStrings.LOG] = logQs; } log(" querystrings: ", queryStringsObject); log("------------- router index.js navigate end -----------------"); router.push({ name: "root", query: Object.assign(optionalQuery, queryStringsObject), state: optionalParams, }); } else if (matchingScenarioMap.destinationUrl !== undefined) { navigateToUrl(matchingScenarioMap.destinationUrl, optionalQuery); } } // Get navigation map depending on the scenario and the current 'page' you're on. function getNavigationMap(scenario, currentRoute) { const fmgPageValue = currentRoute.query.fmgPage; log("------------- router index.js getNavigationMap start -----------------"); log("fmgPage: " + fmgPageValue + " scenario: " + scenario, ""); log("------------- router index.js getNavigationMap end -----------------"); const matchedQueryValue = routingTable(store) .filter( (item) => item.fmgPageValue === fmgPageValue && item.maps.filter((map) => map.scenario === scenario).length > 0 ) .map((m) => m.maps.filter((map) => map.scenario === scenario))[0] .filter((x) => x.filter === true || x.filter === undefined); return matchedQueryValue[0]; } function log(message, data) { const log = getQuerystringParameter(queryStrings.LOG); baseMixin.methods.dispatchStoreAction(storeActions.SAVE_LOGGING_OPTION, log, false); data = data ?? ""; const outData = typeof data === "object" ? JSON.stringify(data) : data; if (log === "true" || store.getters.applicationUser.loggingOption) { console.log(new Date() + message + outData); } } //---------------------------------------------------------- Private Functions ---------------------------------------------------------- // Navigate to an external url. function navigateToUrl(url, optionalQuery = {}) { // possibly show some loading screen in the future here. var externalUrl = new URL(url); for (const queryKey in optionalQuery) { externalUrl.searchParams.append(queryKey, optionalQuery[queryKey]); } window.location.assign(externalUrl); } // Get route information by page name. // This will no longer reach out to the Cms. There is a 1:1 relationship between page names and route names and layouts. function GetRouteInfoFromPageName(pageName) { // check if pagename is a valid route/component if (!isExistingFmgPageName(pageName)) { return []; } const routeData = [ { path: "/", name: pageName, component: lazyLoadComponent(pageName), }, ]; return routeData; } // Go to our start page on a 404. function GoToFunnelStartOn404(next, errorPayload = null) { if (errorPayload !== null) { errorPayload.type = "GoToFunnelStartOn404"; analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload); console.log( "%cGoToFunnelStartOn404()... errorPayload", "color: white; background-color: blue; padding: 5px;", errorPayload ); } // Put item on the bus eventBus.addEventToBus( globalEvents.Categories.GLOBAL_ALERT, globalEvents.SubCategories.PAGE_NOT_FOUND, { isDismissible: true, messageCopy: "You can get a quote by starting on this page.", messageHeadline: "We're sorry, something went wrong.", type: globalEventTypes.Danger, } ); next({ path: "/", query: { fmgPage: funnelStartPageName }, }); } async function DisplayPageError(errorPayload = null) { console.log("%c running DisplayPageError()... ", "font-size: 20px; color: purple;"); if (errorPayload !== null) { errorPayload.type = "DisplayPageError"; analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload); } else { // very cautiously to avoid additional errors: var currentPage = ""; try { currentPage = getQuerystringParameter(queryStrings.FMG_PAGE); } catch (e) { // pass } errorPayload = { type: "DisplayPageError", cause: "Unknown page error", currentPage: currentPage, }; analyticsMixin.methods.pushPageErrorToDataLayer(errorPayload); } // Put item on the bus eventBus.addEventToBus( globalEvents.Categories.GLOBAL_ALERT, globalEvents.SubCategories.UNKNOWN_ERROR, { isDismissible: true, messageCopy: "", messageHeadline: "We're sorry, something went wrong.", type: globalEventTypes.Danger, } ); if ( store.getters.externalParameterState?.isExternalParameter == externalParameterStatus.ACTIVE ) { store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.INACTIVE); } baseMixin.methods.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE); const pageError = getQuerystringParameter(queryStrings.PAGE_ERROR); // we use the pageError querystring as a counter to how many times a user has experienced an error and been routed here. // once they receive more than 1 pageerrors, we'll reset their state to hopefully correct any issues they may be having. var navPage = fmgPageValues.VEHICLE; if (store.getters.payment?.insuranceCoverage?.isVerified) { navPage = fmgPageValues.VEHICLE_DAMAGE; } if (pageError) { var errorCount = Number(pageError); if (errorCount > 1) { deleteFunnelCookie(); await baseMixin.methods.dispatchStoreAction(storeActions.RESET_STATE); router.push({ path: "/", query: { fmgPage: navPage }, }); } else { errorCount++; router.push({ path: "/", query: { fmgPage: navPage, pageError: errorCount }, }); } } else { router.push({ path: "/", query: { fmgPage: navPage, pageError: "1" }, }); } } function isExistingFmgPageName(pageName) { const names = Object.values(fmgPageValues); return names.some((name) => name === pageName); } // Checks arePagePrerequisitesValid on the component passed in. function arePagePrerequisitesValid(component) { return component.default.methods.arePagePrerequisitesValid(); } // Run SiteEntry and PageEntry triggers for experiments async function runExperiments(nextPage) { if (!store.getters.applicationUser.triggeredSiteEntry) { await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.RUN_EXPERIMENTS_FOR_TRIGGER, { deviceId: getDeviceIdValue(), triggerEvent: experimentTriggers.SITE_ENTRY, triggerValue: applicationConfig.SITE_ENTRY_TRIGGER_VALUE, }, nextPage ); } await baseMixin.methods.dispatchStoreActionWithLogging( storeActions.RUN_EXPERIMENTS_FOR_TRIGGER, { deviceId: getDeviceIdValue(), triggerEvent: experimentTriggers.PAGE_ENTRY, triggerValue: nextPage == "vehicle" ? "vehicle-pageEntry" : nextPage, }, nextPage ); } function getRedirectedStartPage() { if (store.getters.payment?.insuranceCoverage?.isVerified) { return fmgPageValues.VEHICLE_DAMAGE; } else { return funnelStartPageName; } } function updateExternalParameterState() { const externalParameterYear = getQuerystringParameter(queryStrings.VEHICLE_YEAR); const externalParameterMake = getQuerystringParameter(queryStrings.VEHICLE_MAKE); const externalParameterModel = getQuerystringParameter(queryStrings.VEHICLE_MODEL); const externalParameterStyle = getQuerystringParameter(queryStrings.VEHICLE_STYLE); const externalParameterDamage = getQuerystringParameter(queryStrings.VEHICLE_DAMAGE); const externalParameterZipCode = getQuerystringParameter(queryStrings.SERVICE_ZIP); const externalParameterEmail = getQuerystringParameter(queryStrings.EMAIL); const externalParameterIsInsurance = getQuerystringParameter(queryStrings.IS_INSURANCE); const externalParameterVinSelection = getQuerystringParameter(queryStrings.VIN_SELECTION); const externalParameterServicePackage = getQuerystringParameter(queryStrings.SERVICE_PACKAGE); const externalParameterNumberOfChips = getQuerystringParameter(queryStrings.NUMBER_OF_CHIPS); const externalParameterSource = getQuerystringParameter(queryStrings.EXPERIMENTS); if ( externalParameterYear && externalParameterMake && externalParameterModel && externalParameterStyle ) { resetStoreForExternalParameter(); store.commit(storeMutations.UPDATE_IS_EXTERNAL_PARAMETER, externalParameterStatus.ACTIVE); store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_YEAR, externalParameterYear); store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MAKE, externalParameterMake); store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_MODEL, externalParameterModel); store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_STYLE, externalParameterStyle); } if ( externalParameterDamage && (externalParameterDamage.toUpperCase() != "WINDSHIELDREPAIR" || externalParameterNumberOfChips?.length > 0) ) { store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_DAMAGE_TYPE, externalParameterDamage); if (externalParameterDamage.toUpperCase() == "WINDSHIELDREPLACE") { store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_REPAIR, false); store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_NUMBER_OF_CHIPS, null); } else if (externalParameterDamage.toUpperCase() == "WINDSHIELDREPAIR") { store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_REPAIR, true); store.commit( storeMutations.UPDATE_EXTERNAL_PARAMETER_NUMBER_OF_CHIPS, externalParameterNumberOfChips ); } } if (externalParameterZipCode) { store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_ZIP_CODE, externalParameterZipCode); } if (externalParameterEmail) { store.commit( storeMutations.UPDATE_EXTERNAL_PARAMETER_EMAIL_ADDRESS, externalParameterEmail ); } if (externalParameterIsInsurance?.toUpperCase() == "TRUE") { store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_IS_INSURANCE, true); store.commit( storeMutations.UPDATE_EXTERNAL_PARAMETER_SERVICE_PACKAGE, externalParameterServicePackage?.toLowerCase() ); } if (externalParameterDamage?.toUpperCase() != "WINDSHIELDREPAIR") { store.commit( storeMutations.UPDATE_EXTERNAL_PARAMETER_VIN_SELECTION, externalParameterVinSelection ); } if (externalParameterSource) { store.commit(storeMutations.UPDATE_EXTERNAL_PARAMETER_SOURCE, externalParameterSource); } } // if there is an existing external parameter state then they have already been through from an external source(LeadGen) and // are returning. clear out prior related things that need to be selected again like parts and damage type. function resetStoreForExternalParameter() { if ( store.getters.externalParameterState?.isExternalParameter == externalParameterStatus.INACTIVE ) { store.dispatch(storeActions.RESET_VEHICLE_STATE_AND_DEPENDENCIES); store.dispatch(storeActions.SAVE_SERVICE_ZIP_CODE_INFO, { state: null, zipCode: null, zipCodeCtu: null, }); store.dispatch(storeActions.SAVE_EMAIL, null); store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES); } } export default router;