/* INTEGRATION NOTE: // Custom script to add Mavenoid ;(function(m,a,v,e,n,o,i,d) { d=m.createElement(a);d.async=true;d.src="https://widget-hosts.mavenoid.com/custom-embedding-scripts/"+n+".js"; i=m.getElementsByTagName(a)[0];i.parentNode.insertBefore(d,i);v[e]=v[e]||[]; })(document,"script",window,"mavenoid","husqvarna-north-america"); */ // --- begin mavenoid embedded troubleshooter --- (function (m, a, v, e, n, o, i, d) { n = m.createElement(a); n.async = true; n.src = "https://husqvarna.mavenoid.com/embedded/embedded.js"; o = m.getElementsByTagName(a)[0]; o.parentNode.insertBefore(n, o); v[e] = v[e] || []; })(document, "script", window, "mavenoid"); // --- end mavenoid embedded troubleshooter --- var baseUrl = "https://shop.husqvarna.com"; var regionRegex = /(?:husqvarna|husqvarnagroup)\.com\/(.+?)(?:\/|$)/; var { href, search, hostname } = document.location; var regionRegexMatch = regionRegex.exec(href); var region = null; if (regionRegexMatch) { region = regionRegexMatch[1]; } else if (href.includes("husqvarna.custhelp.com")) { region = "us"; } const INSTALLATION_PATHS = [ "/discover/epos-support", "/discover/automower-installation-made-simple", ]; var regionLangMap = { // --- French --- "ca-fr": "fr", // --- English --- "ca-en": "en", us: "en", }; var currentLang = region ? regionLangMap[region] : "en"; var isPopOverShown = false; var popOverElement = null; var EXTERNAL_SCRIPTS = { async openDirectly(input) { await directlyEscalation(input); return { formData: [{ id: "result", value: { type: "string", value: "ok" } }], }; }, async trackHQEvent() { window.dataLayer.push({ event: "mavenoid_referral" }); return { formData: [] }; }, async navigateToUrl(url) { window.location.href = url; return { formData: [] }; }, async addToCart(input) { const userContext = await getUserContext(); if (userContext?.error) return formDataError(userContext.error); const res = await addPartNumberToCart(input); if (!res.ok) return formDataError(await res.text()); return { formData: [{ id: "result", value: { type: "string", value: "ok" } }], }; }, }; function formDataError(msg) { console.error(msg); return { formData: [ { id: "error", value: { type: "string", value: msg }, }, ], }; } async function getContext() { // Get user context of shopper // API details: https://help.hcltechsw.com/commerce/9.0.0/restapi/code/authentication_and_session_management.html return await fetch( `${baseUrl}/wcs/resources/store/11251/usercontext/@self/contextdata`, { method: "GET", headers: { "Content-Type": "application/json", }, credentials: "include", }, ); } async function createGuest() { // Create a guest // API details: https://help.hcltechsw.com/commerce/9.0.0/restapi/code/authentication_and_session_management.html return await fetch( `${baseUrl}/wcs/resources/store/11251/guestidentity?updateCookies=true`, { method: "POST", headers: { "Content-Type": "application/json", }, credentials: "include", }, ); } async function getUserContext() { // callerId === -1002 means anonymous user. // Create guest identity first to get WC tokens before calling cart API. const contextResponse = await getContext(); if (!contextResponse.ok) return { error: await contextResponse.text() }; const userContext = await contextResponse.json(); if (userContext?.basicInfo?.runAsId === -1002) { const guestResponse = await createGuest(); if (!guestResponse.ok) return { error: await guestResponse.text() }; } } async function addPartNumberToCart({ partNumber, quantity }) { // Add order item to cart // API details: https://help.hcltechsw.com/commerce/8.0.0/restapi/code/cart.html return await fetch(`${baseUrl}/wcs/resources/store/11251/cart/`, { method: "POST", headers: { "Content-Type": "application/json", }, credentials: "include", body: JSON.stringify({ orderItem: [ { partNumber, quantity, }, ], }), }); } async function loadCSS() { var cssId = "popOverStyle"; if (!document.getElementById(cssId)) { var head = document.getElementsByTagName("head")[0]; var link = document.createElement("link"); link.id = cssId; link.rel = "stylesheet"; link.type = "text/css"; link.href = "https://widget-hosts.mavenoid.com/custom-embedding-scripts/stylesheets/husqvarna/popover.css"; head.appendChild(link); } } function keydownEventListener(e) { if (e.keyCode === 27) { // ESC key handler closeMinimodal(); } } function closePopOver() { if (!isPopOverShown) return; isPopOverShown = false; document.body.style.overflow = null; document.removeEventListener("keydown", keydownEventListener); if (popOverElement) { const m = popOverElement; m.classList.add("closing"); setTimeout(() => { document.body.removeChild(m); popOverElement = null; }, 100); } } async function showPopOver() { await loadCSS(); setTimeout(() => { if (!isPopOverShown) { isPopOverShown = true; popOverElement = popOverElement || document.createElement("div"); popOverElement.id = "mavenoid-popover-container"; // MAVENOID_BUTTON_CONTAINER_DIV_ID popOverElement.className = "mavenoid-speech-bubble"; popOverElement.innerHTML = `
${ currentLang === "fr" ? "En quoi pouvons-nous vous aider?" : "How can we help you?" }
`; popOverElement.addEventListener("click", () => { closePopOver(); mavenoid.push({ event: "troubleshooter-show" }); }); Array.from( popOverElement.querySelectorAll(".js-mavenoid-close-speech-bubble"), ).forEach((elt) => elt.addEventListener("click", (ev) => { ev.stopPropagation(); closePopOver(); }), ); document.addEventListener("keydown", keydownEventListener); document.body.appendChild(popOverElement); } }, 0); } function showPopoverOnHover() { // TODO: load the font in advance and remove delay document.documentElement.style.setProperty("--popOverTime", "0.5s"); try { var floatingButton = document .getElementsByTagName("mavenoid-assistant")[0] .querySelector("#mavenoid-shadow-root") .shadowRoot.querySelector(".floating-button-content"); floatingButton.addEventListener("click", function () { closePopOver(); }); floatingButton.addEventListener("mouseenter", function () { if (!isPopOverShown) { showPopOver(); } }); floatingButton.addEventListener("mouseleave", function () { closePopOver(); }); } catch (err) { // } } function getDirectlySDK(product) { if (window.DirectlyRTM) { return window.DirectlyRTM; } (function (d, i, r, e, c, t, l, y) { // @ts-expect-error i[r] = i[r] || function () { (i[r].cq = i[r].cq || []).push(arguments); }; // @ts-expect-error l = d.createElement("script"); l.id = "directlyRTMScript"; l.src = e; l.async = 1; y = d.head || d.getElementsByTagName("head")[0]; // @ts-expect-error if ( d.readyState === "complete" || d.readyState === "loaded" || d.readyState === "interactive" ) { y.appendChild(l); } else if (i.addEventListener) { // @ts-expect-error i.addEventListener("DOMContentLoaded", function () { y.appendChild(l); }); } else { // @ts-expect-error i.attachEvent("onload", function () { y.appendChild(l); }); } })( document, window, "DirectlyRTM", "https://app.directly.com/widgets/rtm/embed.js", ); window.DirectlyRTM("config", { id: getDirectlyId(), lang: getDirectlyLang(), metadata: { Brand: getDirectlyBrand(product), rtm: getDirectlyRtmConfig(), }, }); return window.DirectlyRTM; } function getDirectlyId() { // Allow overriding Directly ID from `?mavenoid-directly-dev=1` // RTM Name in Directly: Mavenoid RTM var overrideUseDev = new URLSearchParams(search).get("mavenoid-directly-dev") === "1" || hostname === "acc-stage.husqvarna.com"; return overrideUseDev ? "2c99829d89aa1933018a40e73cdb0825" // dev : "2c9985ab8acaa066018afaa07ccf5e61"; // prod } function getDirectlyLang() { switch (region) { case "ca-fr": return "fr"; default: return "en"; } } function getDirectlyBrand(product) { var isAutomower = product?.id === 6915264 || product?.id === 4017449; var brand = isAutomower ? "Automower" : "Husqvarna"; if (region.includes("ca")) { brand += "-CA"; } return brand; } function getDirectlyRtmConfig() { return { returnUrl: `https://www.husqvarna.com/${ ["us", "ca-en", "ca-fr"].includes(region) ? region : "us" }/support/`, URL: href, }; } function extractMetadata(transcript, product) { var metadata = { // The following metadata is recommended by Directly - removing them // can break their integration. Brand: getDirectlyBrand(product), rtm: getDirectlyRtmConfig(), source: "Mavenoid", }; var index = 1; var QA = transcript.filter( (e) => e.type === "question" || e.type === "solution", ); for (var element of QA) { var question = element.title; var answer = element.answer ? element.answer : "Unknown reply"; if (question) { metadata[`Question ${index}: ${question}`] = answer; index++; } } return metadata; } async function directlyEscalation(input) { var transcript = input.transcript; var product = input.product; var directlySDK = getDirectlySDK(product); var metadata = extractMetadata(transcript, product); console.log("[Mavenoid-Directly] Metadata", metadata); // Track questionID // Implementation note: due the the interactivity of Directly, it is possible // that we receive more than 1 event per session (with similar, or different IDs) directlySDK("onNavigate", function (path) { if (path.path && path.path.includes("/question/")) { console.log("[Mavenoid-Directly] Question navigate"); } }); // The question needs to be filled for Directly to work correctly. // We take the FTS inputed text by default, and if that was not filled // in the session, then we just have a hardcoded english sentence to go. // We could do something smarter like picking the first question card but // that risks of having bad results. var freeTextSearch = transcript.find( (e) => e.type === "free-text-search" && e.searchTerm != "", ); var questionForDirectly = input.question; var questionText = questionForDirectly ? questionForDirectly : freeTextSearch ? freeTextSearch.searchTerm : `I have a question about my ${product.name}`; var name = input.name; var email = input.email; if (name && email) { directlySDK("askQuestion", { name, email, questionText, metadata, }); } else { directlySDK("set", "metadata", metadata); directlySDK("openAskForm"); directlySDK("maximize"); } // Wait for directly to be ready or the timeout to be resolved // This is due to the production setup where there is a clashing DirectlyRTM // instance. await new Promise(function (resolve) { directlySDK("onReady", function () { resolve(); }); setTimeout(resolve, 200); }); // Unmount the iframe a bit after the last call from the caller is made (in QuestionComponent) // If the unmount call is done synchronously, the iframe will unload, resulting // in the awaiting function to never resume. setTimeout(function () { window.mavenoid.push({ event: "troubleshooter-unmount" }); }, 100); } // Integrate with hash-based opening function hashIntegration() { function hashChange(hash) { var allowedHashUrls = [ "mavenoid-run-time-tool", "mavenoid-general-automower", "mavenoid-main-menu", "mavenoid-chat-with-us", "mavenoid-automower-buying-guide", ]; if (!hash) return; var hashparams = new URLSearchParams(hash.slice(1)); if (!allowedHashUrls.some((key) => hashparams.has(key))) return; loadMavenoid(true); closePopOver(); } // First run and event listener hashChange(window.location.hash); window.addEventListener("hashchange", (e) => { hashChange(window.location.hash); }); } function getMavenoidClientId(openByDefault = false) { if ( INSTALLATION_PATHS.some((path) => window.location.pathname.includes(path)) ) return "ma_4vchgvdk45i_9o7krmg5r5g9av6hiossk7oqvq9dmof70som"; //Touchpoint: Husqvarna North America - Installation Flow (Wide Theme) return openByDefault ? "ma_50d487uqp3q_ujh8h54ptf29l6f7dn0np9726njulglcos6m" // Touchpoint: Husqvarna North America - Open By Default : "ma_50ugfsq91kn_54npomkmsumecaglghsng2osss8lkq8nf35u"; // Touchpoint: Husqvarna North America } function openMavenoidAt(flowPath) { // Added Flow Paths: // Run Time Tool: "run-time-tool" // General Automower: "general-automower" // Main Menu: "main-menu" // Chat With Us: "chat-with-us" // Automower Buying Guide: "automower-buying-guide" mavenoid.push({ event: "assistant-mount", clientId: "ma_50d487uqp3q_ujh8h54ptf29l6f7dn0np9726njulglcos6m", defaultLang: currentLang, initFormData: { "country-code": region ? region.split("-")[0] : "", "full-country-code": region ? region : "", "flow-path": flowPath ? flowPath : "", }, externalScripts: EXTERNAL_SCRIPTS, }); closePopOver(); } function loadMavenoid(openByDefault = false) { mavenoid.push({ event: "assistant-mount", clientId: getMavenoidClientId(openByDefault), defaultLang: currentLang, initFormData: { "country-code": region ? region.split("-")[0] : "", "full-country-code": region ? region : "", }, externalScripts: EXTERNAL_SCRIPTS, }); } showPopOver(); setTimeout(function () { showPopoverOnHover(); }, 3000); loadMavenoid(); hashIntegration();