PageSourceSearch

https://www.superdry.com/on/demandware.static/Sites-sd-uk-Site/-/en_GB/v1790228952584/js/einsteinCarousel.js

js superdry.com collected 2026-09-24 10:24:41 UTC 25,065 bytes, 760 lines download raw bytes

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.