diff --git a/src/global-methods.js b/src/global-methods.js index 22512fe41..96c5e21fc 100644 --- a/src/global-methods.js +++ b/src/global-methods.js @@ -110,7 +110,13 @@ export default { if (error.response.status && error.response.status != "404") { // Do not route to error logic when no wipers found or no promo found (404s) - router.navigateError(); + const errorPayload = { + cause: `Response error ${error.response.status}`, + currentPage: pageNameToLog, + endpoint: endpoint, + }; + + router.navigateError(errorPayload); // do not log 404 errors from services because we return NotFound // when a service doesn't return an object diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index e970e94a8..d534a7200 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -650,6 +650,14 @@ export default { }); }, + pushPageErrorToDataLayer(error) { + + pushToDataLayerIfDefined({ + event: "page-error", + error: error, + }); + }, + prependActionToMethod(object, method, actionToPrepend) { const baseMethodName = method.name.startsWith("bound ") ? method.name.substring(6) diff --git a/src/router/index.js b/src/router/index.js index da3c1914c..0da560c84 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -65,9 +65,17 @@ const routes = [ // 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); + GoToFunnelStartOn404(next, errorPayload); + return; } // Intercept all navigation if a submitted order exists in storage @@ -206,7 +214,14 @@ const routes = [ return; } - GoToFunnelStartOn404(next); + 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); @@ -214,9 +229,15 @@ const routes = [ } if (!isExistingFmgPageName(to.query.fmgPage)) { - console.log("Not an existing fmg page name:" + to.query.fmgPage); - GoToFunnelStartOn404(next); + 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. @@ -237,9 +258,18 @@ const routes = [ .components.default(); if (!arePagePrerequisitesValid(nextComponent)) { + // prettier-ignore console.log("Page Prereqs not valid for next component: " + nextComponent.default.name); - GoToFunnelStartOn404(next); + + 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 -----------------"); @@ -261,7 +291,16 @@ const routes = [ console.log(new Date() + " Exception in beforeEnter:" + JSON.stringify(error)); // If we don't have a route, go to our 404 page. - GoToFunnelStartOn404(next); + const errorPayload = { + cause: "uncaught error in beforeEnter", + currentPage: from?.query?.fmgPage, + nextPage: to?.query?.fmgPage, + fullError: error, + errorStack: error?.stack, + }; + + GoToFunnelStartOn404(next, errorPayload); + return; } }, }, @@ -397,8 +436,8 @@ router.navigateToExternalUrl = (url, optionalQuery = {}) => { navigateToUrl(url, optionalQuery); }; -router.navigateError = () => { - DisplayPageError(); +router.navigateError = (errorPayload = null) => { + DisplayPageError(errorPayload); }; //Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example. @@ -588,7 +627,19 @@ function GetRouteInfoFromPageName(pageName) { } // Go to our start page on a 404. -function GoToFunnelStartOn404(next) { +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, @@ -607,7 +658,28 @@ function GoToFunnelStartOn404(next) { }); } -async function DisplayPageError() { +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,