1/******/ (function() { // webpackBootstrap 2/******/ "use strict"; 3/******/ var __webpack_modules__ = ({ 4
5/***/ "./cartridges/app_superdry/cartridge/client/default/js/helpers/gtmHelpers.js": 6/*!***********************************************************************************!*\ 7 !*** ./cartridges/app_superdry/cartridge/client/default/js/helpers/gtmHelpers.js ***! 8 \***********************************************************************************/ 9/***/ (function(module) { 10 11 12 13/** 14 * Sends a page view event to Google Tag Manager 15 * @param {string} pageType - the type of the page being viewed 16 * @returns {void} 17 */ 18const pageViewEvent = (pageType) => { 19 const event = new CustomEvent("pageViewPushed"); 20 const pageData = document.querySelector(".gtm-page-view-data"); 21 const userData = document.querySelector(".gtm-user-data"); 22 23 if (!pageData || !userData) { 24 return; 25 } 26 27 const pageDataObject = safeParseJSON(pageData.getAttribute("data-gtm")); 28 const userDataObject = safeParseJSON(userData.getAttribute("data-gtm")); 29 30 if (!pageDataObject || !userDataObject) { 31 return; 32 } 33 34 const object = { 35 event: "page_view", 36 page_type: pageType, 37 ...pageDataObject, 38 ...userDataObject 39 }; 40 41 window.dataLayer = window.dataLayer || []; 42 window.dataLayer.push(object); 43 44 document.dispatchEvent(event); 45}; 46 47/** 48* Sends product data to the data layer for Google Tag Manager events. Used for add_to_cart and remove_from_cart events 49* @param {string} productData - JSON string representing product data 50* @returns {void} 51*/ 52const cartEvents = (productData) => { 53 if (!productData) { 54 return; 55 } 56 57 const productDataObject = safeParseJSON(productData); 58 59 if (!productDataObject) { 60 return; 61 } 62 63 window.dataLayer = window.dataLayer || []; 64 window.dataLayer.push({"ecommerce": null}); 65 window.dataLayer.push(productDataObject); 66}; 67 68/** 69* Represents the view cart event and pushes the view cart object to the data layer 70*/ 71const viewCartEvent = () => { 72 const cartPageWrapper = document.querySelector(".cart-page"); 73 74 if (!cartPageWrapper) { 75 return; 76 } 77 78 let viewCartObject = safeParseJSON(cartPageWrapper.getAttribute("data-gtm")); 79 80 if (!viewCartObject) { 81 return; 82 } 83 84 updateItemIndexes(viewCartObject.ecommerce.items); 85 86 window.dataLayer = window.dataLayer || []; 87 window.dataLayer.push({"ecommerce": null}); 88 window.dataLayer.push(viewCartObject); 89}; 90 91/** 92* Handles the view item event for Google Tag Manager 93*/ 94const viewItemEvent = () => { 95 const pdpWrapper = document.querySelector(".product-detail"); 96 const viewItemObject = safeParseJSON(pdpWrapper.getAttribute("data-gtm")); 97 98 if (!viewItemObject) { 99 return; 100 } 101 102 window.dataLayer = window.dataLayer || []; 103 window.dataLayer.push({"ecommerce": null}); 104 window.dataLayer.push(viewItemObject); 105}; 106 107/** 108* Handles the select item event for Google Tag Manager 109*/ 110const selectItemEvent = (wrapper) => { 111 if (!wrapper) { 112 return; 113 } 114 115 const selectItemObject = safeParseJSON(wrapper.getAttribute("data-gtm")); 116 117 if (!selectItemObject) { 118 return; 119 } 120 121 let eventLocation = "Cart Page"; 122 if (document.querySelector(".storepage")?.id === "homepage") { 123 eventLocation = "Homepage"; 124 } 125 126 if (document.querySelector(".search-result-count-wrapper")) { 127 eventLocation = "Search Results"; 128 } 129 130 if (document.querySelector(".pdp-container")) { 131 eventLocation = "PDP"; 132 } 133 134 if (wrapper.parentNode.classList.contains("item")) { 135 eventLocation = "Search Suggestions"; 136 } 137 138 if (document.querySelector(".plp-title")) { 139 eventLocation = "PLP"; 140 } 141 142 let objectValue; 143 selectItemObject.ecommerce.items.forEach((item) => { 144 objectValue = item.price; 145 item.item_list_name = eventLocation; 146 }); 147 148 selectItemObject.event = "select_item"; 149 selectItemObject.ecommerce.value = objectValue; 150 151 window.dataLayer = window.dataLayer || []; 152 window.dataLayer.push({"ecommerce": null}); 153 window.dataLayer.push(selectItemObject); 154}; 155 156const recommendationClickEvent = (title, element) => { 157 if (!element) { 158 return; 159 } 160 161 window.dataLayer = window.dataLayer || []; 162 window.dataLayer.push({ 163 "event": "pdp_recommendation_click", 164 "reco_type": title || "", 165 "reco_product_id": element.getAttribute("data-gtm-product-id"), 166 "reco_product_name": element.getAttribute("data-gtm-product-name"), 167 }); 168}; 169 170/** 171 * Safely parses a JSON string and returns the parsed JSON object or null if parsing fails 172 * @param {string} str - The JSON string to be parsed 173 * @returns {Object | null} The parsed JSON object or null if parsing fails 174 */ 175const safeParseJSON = (str) => { 176 try { 177 return JSON.parse(str); 178 } catch (error) { 179 return null; 180 } 181}; 182 183/**
184* Handles the order confirmation event for Google Tag Manager 185* @param {HTMLElement} wrapper - the HTML element containing the data for the event 186* @returns {void} 187*/ 188const purchaseEvent = (orderId) => { 189 const orderConfirmationWrapper = document.querySelector(".order-confirmation-wrapper"); 190 const orderConfirmationObject = safeParseJSON(orderConfirmationWrapper.getAttribute("data-gtm")); 191 192 if (!orderConfirmationObject) { 193 return; 194 } 195 196 const purchesEventFromDataLayer = window.dataLayer.find(event => event.event === "purchase"); 197 198 if (purchesEventFromDataLayer?.ecommerce?.transaction_id === orderId) { 199 return false; 200 201 } else { 202 updateItemIndexes(orderConfirmationObject.ecommerce.items); 203 204 window.dataLayer = window.dataLayer || []; 205 window.dataLayer.push({"ecommerce": null}); 206 window.dataLayer.push(orderConfirmationObject); 207 } 208}; 209 210/** 211* Parses and pushes the page data object to the data layer 212* @param {string} data - the page data to be parsed and pushed 213* @returns {void} 214*/ 215const checkoutEvents = (data) => { 216 if (!data) { 217 return; 218 } 219 220 const checkoutDataObject = safeParseJSON(data) ? safeParseJSON(data) : data; 221 222 updateItemIndexes(checkoutDataObject.ecommerce.items); 223 224 window.dataLayer = window.dataLayer || []; 225 window.dataLayer.push({"ecommerce": null}); 226 window.dataLayer.push(checkoutDataObject); 227}; 228 229/** 230 * Sorts the interaction event and pushes the data to the data layer 231 * @returns {void} 232 */ 233const sortInteractionEvent = () => { 234 const gridWrapper = document.querySelector(".product-grid"); 235 const sortInteractionObject = safeParseJSON(gridWrapper.getAttribute("data-gtm")); 236 237 if (!sortInteractionObject) { 238 return; 239 } 240 241 window.dataLayer = window.dataLayer || []; 242 window.dataLayer.push(sortInteractionObject); 243}; 244 245/** 246* Updates the indexes of items in the given array 247* @param {Array} items - the array of items to be updated 248* @returns {void} 249*/ 250const updateItemIndexes = (items) => { 251 items.forEach((item, idx) => { 252 item.index = idx; 253 }); 254}; 255 256/** 257* Handles the search event and pushes the search term to the data layer 258* @returns {void} 259*/ 260const searchEvent = () => { 261 const searchInput = document.querySelector(".search-input").value; 262 263 const searchObject = { 264 "event": "user_search", 265 "search_term": searchInput 266 }; 267 268 window.dataLayer = window.dataLayer || []; 269 window.dataLayer.push(searchObject); 270}; 271 272/** 273 * Authenticates customer events and pushes data to the data layer 274 * @param {string} data - the customer data to be authenticated 275 * @param {string} loginType - the type of login (e.g. social, email) 276 * @param {string} isLogin - type of action (login, create) 277 * @returns {void} 278 */ 279const authenticateCustomerEvents = (data, loginType, label, isLogin) => { 280 if (!data) { 281 return; 282 } 283 284 const userDataObject = safeParseJSON(data); 285 286 if (!userDataObject) { 287 return; 288 } 289 290 const object = { 291 event: label, 292 [isLogin ? "login_type" : "create_type"]: loginType, 293 ...userDataObject 294 }; 295 296 window.dataLayer = window.dataLayer || []; 297 window.dataLayer.push(object); 298}; 299 300/** 301 * Handles form submit events and pushes data to the data layer 302 * @param {string} formClass - the class name of the form 303 * @param {string} email - submited email address 304 * @returns {void} 305 */ 306const formSubmitEvents = (formName, email) => { 307 if (!formName) { 308 return; 309 } 310 311 const object = { 312 event: "form_submit", 313 form_type: formName 314 }; 315 316 if (email) { 317 object.user = { 318 user_em: email 319 }; 320 } 321 322 window.dataLayer = window.dataLayer || []; 323 window.dataLayer.push({"ecommerce": null}); 324 window.dataLayer.push(object); 325}; 326 327/** 328 * Logs a featured tile click event to the data layer 329 * @param {string} tileName - the name of the featured tile being clicked 330 * @returns {void} 331 */ 332const featuredTileClick = (tileName) => { 333 const dataLayerObject = { 334 "event": "featured_tile_click", 335 "featured_tile_name": tileName || "" 336 }; 337 338 window.dataLayer = window.dataLayer || []; 339 window.dataLayer.push(dataLayerObject); 340}; 341 342/** 343 * Initializes and triggers an IntersectionObserver to observe elements with the class "last-tracked". 344 * When an observed element intersects with the viewport, it triggers the `viewItemListEvent` function 345 * and then stops observing that element. 346 */ 347function triggerItemListObserver(pageType) { 348 const observer = new IntersectionObserver((entries) => {
349 entries.forEach((entry) => { 350 if (entry.isIntersecting) { 351 viewItemListEvent(pageType); 352 observer.unobserve(entry.target); 353 } 354 }); 355 }); 356 const lastTrackedElements = document.querySelectorAll(".last-tracked"); 357 const lastTrackedElement = lastTrackedElements[lastTrackedElements.length - 1]; 358 observer.observe(lastTrackedElement); 359} 360 361/** 362 * Tracks the view item list event for Google Tag Manager 363 * @param {string} pageType - the type of page where the event is triggered 364 * @param {HTMLElement} targetCarousel - the target carousel element 365 */ 366const viewItemListEvent = (pageType, targetCarousel) => { 367 const productGrids = targetCarousel ? targetCarousel : document.querySelectorAll(".product-grid"); 368 const gridWrapper = productGrids.length > 1 ? productGrids[productGrids.length - 1] : productGrids[0]; 369 const lastTrackedElements = gridWrapper ? gridWrapper.querySelectorAll(".last-tracked") : false; 370 const lastTrackedElement = lastTrackedElements ? lastTrackedElements[lastTrackedElements.length - 1] : false; 371 const indexToSlice = lastTrackedElement ? Array.from(gridWrapper.querySelectorAll(".product-tile")).indexOf(lastTrackedElement) + 1 : 0; 372 const isOutOfBounds = indexToSlice ? indexToSlice >= gridWrapper.querySelectorAll(".product-tile").length : false; 373 374 if (isOutOfBounds) { 375 return; 376 } 377 378 const tiles = targetCarousel ? 379 targetCarousel.querySelectorAll(".product-tile-pd") : 380 Array.from(gridWrapper.querySelectorAll(".product-tile")).slice(indexToSlice, indexToSlice + 10); 381 const eventLocation = pageType ? pageType : document.querySelector(".storepage")?.id === "homepage" ? "Homepage" : document.querySelector(".no-results-wrapper") ? "Search Results" : document.querySelector(".pdp-container") ? "PDP" : "Cart Page"; 382 383 if (eventLocation === "Cart Page") { 384 return; 385 } 386 387 let currency = ""; 388 const dataLayerObject = { 389 "event": "view_item_list", 390 "ecommerce": { 391 "currency": "", 392 "items": [] 393 } 394 }; 395 396 tiles.forEach((tile, index) => { 397 const viewItemObject = safeParseJSON(tile.getAttribute("data-gtm")); 398 viewItemObject.ecommerce.items[0].item_list_name = eventLocation; 399 dataLayerObject.ecommerce.items.push(viewItemObject.ecommerce.items[0]); 400 currency = viewItemObject.ecommerce.currency; 401 if (!targetCarousel && index === tiles.length - 1) { 402 tile.classList.add("last-tracked"); 403 triggerItemListObserver(pageType); 404 } 405 }); 406 407 dataLayerObject.ecommerce.currency = currency; 408 updateItemIndexes(dataLayerObject.ecommerce.items); 409 410 window.dataLayer = window.dataLayer || []; 411 window.dataLayer.push({"ecommerce": null}); 412 window.dataLayer.push(dataLayerObject); 413 414 $("body").trigger("viewItemListEventComplete"); 415}; 416 417/** 418* View promotion event for Google Tag Manager 419* @param {HTMLElement} component - the component to trigger the view promotion event 420* @returns {void} 421*/ 422const promotionEvents = (type, component) => { 423 if (!component) { 424 return; 425 } 426 427 const isPromotion = component.getAttribute("data-ispromotion"); 428 429 if (isPromotion === "false") { 430 return; 431 } 432 433 const creative_name = component.getAttribute("data-creative-name"); 434 const creative_slot = component.getAttribute("data-creative-slot"); 435 const promotion_id = component.getAttribute("data-promotion-id"); 436 const promotion_name = component.getAttribute("data-promotion-name"); 437 438 const dataLayerObject = { 439 "event": type, 440 "ecommerce": { 441 "creative_name": creative_name || "", 442 "creative_slot": creative_slot || "", 443 "promotion_id": promotion_id || "", 444 "promotion_name": promotion_name || "", 445 "items": [] 446 } 447 }; 448 449 if (component.classList.contains("product-tile-carousel-wrapper")) { 450 const eventLocation = document.querySelector(".storepage")?.id === "homepage" ? "Homepage" : document.querySelector(".no-results-wrapper") ? "Search Results" : document.querySelector(".pdp-container") ? "PDP" : "Cart Page"; 451 const productTiles = component.querySelectorAll(".product-tile-pd"); 452
453 productTiles.forEach((tile) => { 454 const viewItemObject = safeParseJSON(tile.getAttribute("data-gtm")); 455 viewItemObject.ecommerce.items[0].item_list_name = eventLocation; 456 dataLayerObject.ecommerce.items.push(viewItemObject.ecommerce.items[0]); 457 }); 458 } 459 460 window.dataLayer = window.dataLayer || []; 461 window.dataLayer.push({"ecommerce": null}); 462 window.dataLayer.push(dataLayerObject); 463}; 464 465/** 466 * Logs a filter interaction event to the data layer 467 * @param {string} filterName - the name of the filter being interacted with 468 * @param {string} filterValue - the value of the filter being interacted with 469 * @returns {void} 470 */ 471const filterInteractionEvent = (filterName, filterValue) => { 472 window.dataLayer = window.dataLayer || []; 473 window.dataLayer.push({ 474 "event": "filter_interaction", 475 "filter_name": filterName || "", 476 "filter_value": filterValue || "" 477 }); 478}; 479 480/** 481* Pushes wishlist view event data to the Google Tag Manager dataLayer. 482* 483* This function checks for the presence of a wishlist page wrapper element with the class 484* ".gtm-page-wish-list". If found, it retrieves and parses the GTM-related JSON data from its 485* "data-gtm" attribute. If the data is valid, it pushes a reset event and the wishlist event 486* object to the global dataLayer array for GTM tracking. 487* 488* @function 489* @returns {void} 490*/ 491const wishlistViewEvent = () => { 492 const wishListPageWrapper = document.querySelector(".gtm-page-wish-list"); 493 494 if (!wishListPageWrapper) { 495 return; 496 } 497 498 let viewWishListObject = safeParseJSON(wishListPageWrapper.getAttribute("data-gtm")); 499 500 if (!viewWishListObject) { 501 return; 502 } 503 504 window.dataLayer = window.dataLayer || []; 505 window.dataLayer.push({"ecommerce": null}); 506 window.dataLayer.push(viewWishListObject); 507}; 508 509module.exports = { 510 pageViewEvent, 511 cartEvents, 512 checkoutEvents, 513 viewCartEvent, 514 viewItemEvent, 515 selectItemEvent, 516 purchaseEvent, 517 searchEvent, 518 authenticateCustomerEvents, 519 sortInteractionEvent, 520 viewItemListEvent, 521 promotionEvents, 522 featuredTileClick, 523 formSubmitEvents, 524 recommendationClickEvent, 525 filterInteractionEvent, 526 wishlistViewEvent 527}; 528 529 530/***/ })
530 531 532/******/ }); 533/************************************************************************/ 534/******/ // The module cache 535/******/ var __webpack_module_cache__ = {}; 536/******/ 537/******/ // The require function 538/******/ function __webpack_require__(moduleId) { 539/******/ // Check if module is in cache 540/******/ var cachedModule = __webpack_module_cache__[moduleId]; 541/******/ if (cachedModule !== undefined) { 542/******/ return cachedModule.exports; 543/******/ } 544/******/ // Create a new module (and put it into the cache) 545/******/ var module = __webpack_module_cache__[moduleId] = { 546/******/ // no module.id needed 547/******/ // no module.loaded needed 548/******/ exports: {} 549/******/ }; 550/******/ 551/******/ // Execute the module function 552/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); 553/******/ 554/******/ // Return the exports of the module 555/******/ return module.exports; 556/******/ } 557/******/ 558/************************************************************************/ 559/*!*********************************************************************************!*\ 560 !*** ./cartridges/app_superdry/cartridge/client/default/js/einsteinCarousel.js ***! 561 \*********************************************************************************/ 562 563 564const gtmHelpers = __webpack_require__(/*! ./helpers/gtmHelpers */ "./cartridges/app_superdry/cartridge/client/default/js/helpers/gtmHelpers.js"); 565 566/** 567 * Validates and Return the cquotient namespace provided by the commerce cloud platform 568 * @returns {Object} - einsteinUtils or null 569 */ 570function getEinsteinUtils() { 571 const einsteinUtils = window.CQuotient; 572 if (einsteinUtils && (typeof einsteinUtils.getCQUserId === "function") && (typeof einsteinUtils.getCQCookieId === "function")) { 573 return einsteinUtils; 574 } 575 return null; 576} 577 578/** 579 * Observes the visibility of initialized carousels and triggers the Google Tag Manager (GTM) view item list event 580 */ 581function gtmTrackingObserver() { 582 const einsteinCarousels = document.querySelectorAll(".product-tile-carousel-wrapper .einstein-carousel"); 583 const observer = new IntersectionObserver((entries) => { 584 entries.forEach((entry) => { 585 if (entry.isIntersecting) { 586 gtmHelpers.viewItemListEvent(undefined, entry.target); 587 gtmHelpers.promotionEvents("view_promotion", entry.target.parentElement); 588 observer.unobserve(entry.target); 589 } 590 }); 591 }); 592 593 einsteinCarousels.forEach((carousel) => { 594 observer.observe(carousel); 595 }); 596} 597 598/** 599 * fills in the carousel with product tile html objects 600 * @param {string} einsteinResponse string html for product tiles 601 * @param {jQuery} $parentElement parent element where recommendations will show. 602 */ 603async function fillDomElement(einsteinResponse, $parentElement) { 604 const recommender = $parentElement.dataset.recommender; 605 606 let recommendedProducts = einsteinResponse[recommender].recs; 607 608 // if no products are returned lets see if there are any fallback product IDs stipulated by the carousel 609 if (!recommendedProducts || recommendedProducts.length === 0) { 610 const fallbackProductIds = $parentElement.dataset.fallbackproductids; 611 if (fallbackProductIds) { 612 recommendedProducts = fallbackProductIds.split(",").map((id) => ({ id })); 613 } 614 } 615 616 if (recommendedProducts && recommendedProducts.length > 0) { 617 const template = $parentElement.dataset.template; 618 const swatches = $parentElement.dataset.swatches; 619 const displayRatings = $parentElement.dataset.displayratings; 620 const components = recommendedProducts.map(function (recommendedProduct) { 621 const tiledefinition = {}; 622 tiledefinition.template = template; 623 tiledefinition.swatches = swatches; 624 tiledefinition.displayratings = displayRatings; 625 tiledefinition.model = { 626 type: "product", 627 id: recommendedProduct.id 628 }; 629 return tiledefinition; 630 }); 631 632 const url = new URL($parentElement.dataset.productLoadUrl); 633 url.searchParams.append("components", JSON.stringify(components)); 634 url.searchParams.append("limit", $parentElement.dataset.limit); 635 url.searchParams.append("recommender", recommender); 636 637 // use the product data sent from einstein to get product tile HTML from our controller 638 const tileData = await fetch(url.href); 639 if (tileData.status === 200) { 640 const tileDataHtml = await tileData.text(); 641 // the HTML contains product tile divs and separate script tags generated by the isObject tag 642 // here we separate the divs to send to the slider and put the script tags below the slider 643 644 const { divs, scripts, amountProductsRendered } = separateDivsAndScripts(tileDataHtml);
645 scripts.forEach(script => { 646 // add after $parentElement 647 $($parentElement).parent().append(script); 648 }); 649 divs.forEach(div => { 650 if ($($parentElement).hasClass("slick-slider")) { 651 $($parentElement).slick("slickAdd", div); 652 } 653 }); 654 655 if (amountProductsRendered === 0) { 656 const $carouselWrapper = $($parentElement).parent(".product-tile-carousel-wrapper"); 657 const $carouselTitle = $carouselWrapper.find(".carousel-title"); 658 $carouselTitle.hide(); 659 } 660 661 gtmTrackingObserver(); 662 } 663 } else { 664 $(".carousel-title").hide(); 665 } 666} 667 668/** 669* Separates div and script elements from an HTML string 670* @param {string} htmlString - the HTML string to be parsed 671* @returns {Object} - an object containing arrays of divs and scripts 672*/ 673function separateDivsAndScripts(htmlString) { 674 const parser = new DOMParser(); 675 const doc = parser.parseFromString(htmlString, "text/html"); 676 677 // Select all div elements 678 const divElements = doc.querySelectorAll("div"); 679 680 // Filter out the outer wrapping divs 681 const outerDivs = Array.from(divElements).filter((div) => { 682 // Check if the div has a parent div 683 return div.parentElement && div.parentElement.tagName === "BODY"; 684 }); 685 const amountProductsRendered = outerDivs && outerDivs.length; 686 687 // Convert the outerDivs NodeList to an array of HTML strings 688 const outerDivsHTML = Array.from(outerDivs).map((div) => div.outerHTML); 689 690 // Select all script elements 691 const scriptElements = doc.querySelectorAll("script"); 692 693 // Convert the scriptElements NodeList to an array of HTML strings 694 const scripts = Array.from(scriptElements).map((script) => script.outerHTML); 695 696 return { divs: outerDivsHTML, scripts, amountProductsRendered }; 697} 698 699/** 700* Populates the Einstein carousel with recommendations 701* @param {HTMLElement} carouselEl - the element to populate 702* @param {Object} einsteinUtils - the EinsteinUtils object 703* @returns {Promise} - a promise that resolves when the carousel is populated 704*/
705const populateEinsteinCarousel = async (carouselEl, einsteinUtils) => { 706 const recommender = carouselEl.dataset.recommender; 707 const recommenderType = carouselEl.dataset.recommendertype; 708 const params = { 709 userId: einsteinUtils.getCQUserId(), 710 cookieId: einsteinUtils.getCQCookieId(), 711 ccver: "1.01" 712 }; 713 if (recommenderType === "product" || recommenderType === "category") { 714 params.anchors = [{id : carouselEl.dataset.context }]; 715 } 716 /** 717 * Processes a recommendation responses 718 * @param {Object} einsteinResponse cquotient object 719 */ 720 function recommendationsReceived(einsteinResponse) { 721 fillDomElement(einsteinResponse, carouselEl); 722 carouselEl.spinner().stop(); 723 } 724 725 if (einsteinUtils.getRecs) { 726 einsteinUtils.getRecs(einsteinUtils.clientId, recommender, params, recommendationsReceived); 727 } else { 728 einsteinUtils.widgets = einsteinUtils.widgets || []; // eslint-disable-line no-param-reassign 729 einsteinUtils.widgets.push({ 730 recommenderName: recommender, 731 parameters: params, 732 callback: recommendationsReceived 733 }); 734 } 735}; 736 737/** 738* Loads product recommendations using Einstein API and populates the corresponding carousels on the page 739* @async 740* @returns {Promise<void>} 741*/ 742const loadRecommendations = async () => { 743 const einsteinUtils = getEinsteinUtils(); 744 if (einsteinUtils) { 745 const einsteinCarousels = document.querySelectorAll(".einstein-carousel"); 746 if (einsteinCarousels.length > 0) { 747 einsteinCarousels.forEach(async (carousel) => { 748 populateEinsteinCarousel(carousel, einsteinUtils); 749 }); 750 } 751 } 752}; 753 754$(document).ready(function () { 755 loadRecommendations(); 756}); 757 758/******/ })() 759; 760//# sourceMappingURL=./einsteinCarousel.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.