PageSourceSearch

https://www.groceryoutlet.com/wp-content/plugins/home-page-deals/assets/js/go-deals.js?ver=2.0.0

js groceryoutlet.com collected 2026-10-02 03:52:59 UTC 24,164 bytes, 1,033 lines download raw bytes

1/*
2 * =========================================================
3 * GO Deals Debug Mode
4 * =========================================================
5 *
6 * false = no GO Deals console output
7 * true  = show GO Deals console output
8 *
9 * Enable this temporarily when debugging.
10 */
11const GO_DEALS_DEBUG = false;
12
13function goDealsLog(...args) {
14    if (GO_DEALS_DEBUG) {
15        console.log(...args);
16    }
17}
18
19function goDealsWarn(...args) {
20    if (GO_DEALS_DEBUG) {
21        console.warn(...args);
22    }
23}
24
25function goDealsError(...args) {
26    if (GO_DEALS_DEBUG) {
27        console.error(...args);
28    }
29}
30
31
32document.addEventListener('DOMContentLoaded', function () {
33
34    /*
35     * =========================================================
36     * Set current store
37     * =========================================================
38     *
39     * Makes sure StoreA exists in sessionStorage.
40     *
41     * If user does not exist:
42     *     create user with StoreA.
43     *
44     * If user exists but StoreA does not exist:
45     *     add StoreA without removing existing values.
46     *
47     * If StoreA already exists:
48     *     leave it unchanged.
49     */
50
51    window.goDealsSetCurrentStore = function (storeNumber) {
52
53        storeNumber = String(storeNumber);
54
55        if (!storeNumber) {
56            return;
57        }
58
59
60        const storeA =
61            Number(storeNumber);
62
63
64        try {
65
66            const storedUser =
67                sessionStorage.getItem('user');
68
69
70            /*
71             * -------------------------------------------------
72             * No user session exists
73             * -------------------------------------------------
74             */
75
76            if (!storedUser) {
77
78                const user = {
79                    StoreA: storeA
80                };
81
82
83                sessionStorage.setItem(
84                    'user',
85                    JSON.stringify(user)
86                );
87
88
89                goDealsLog(
90                    'GO Deals: user session created:',
91                    user
92                );
93
94
95            } else {
96
97                /*
98                 * -------------------------------------------------
99                 * User session already exists
100                 * -------------------------------------------------
101                 */
102
103                let user;
104
105
106                try {
107
108                    user =
109                        JSON.parse(storedUser);
110
111                } catch (error) {
112
113                    goDealsWarn(
114                        'GO Deals: Invalid user session. Recreating it.'
115                    );
116
117                    user = {};
118                }
119
120
121                /*
122                 * -------------------------------------------------
123                 * Add StoreA if missing
124                 * -------------------------------------------------
125                 */
126
127                if (
128                    !user.StoreA
129                ) {
130
131                    user.StoreA =
132                        storeA;
133
134
135                    sessionStorage.setItem(
136                        'user',
137                        JSON.stringify(user)
138                    );
139
140
141                    goDealsLog(
142                        'GO Deals: Added StoreA to existing user session:',
143                        storeA
144                    );
145
146
147                } else {
148
149                    goDealsLog(
150                        'GO Deals: StoreA already exists:',
151                        user.StoreA
152                    );
153                }
154            }
155
156
157        } catch (error) {
158
159            goDealsError(
160                'GO Deals: Unable to synchronize StoreA:',
161                error
162            );
163        }
164
165
166        /*
167         * ---------------------------------------------------------
168         * selected_store cookie
169         * ---------------------------------------------------------
170         */
171
172        document.cookie =
173            'selected_store=' +
174            encodeURIComponent(storeNumber) +
175            '; path=/; max-age=86400';
176
177
178        /*
179         * ---------------------------------------------------------
180         * preferred-store cookie
181         * ---------------------------------------------------------
182         */
183
184        document.cookie =
185            'preferred-store=' +
186            encodeURIComponent(storeNumber) +
187            '; path=/; max-age=' +
188            (365 * 24 * 60 * 60);
189
190
191        /*
192         * ---------------------------------------------------------
193         * Notify existing store-dependent functionality
194         * ---------------------------------------------------------
195         */
196
197        if (
198            window.deps &&
199            window.deps.user &&
200            typeof window.deps.user.changed === 'function'
201        ) {
202
203            try {
204
205                window.deps.user.changed();
206
207            } catch (error) {
208
209                goDealsWarn(
210                    'GO Deals: deps.user.changed() failed:',
211                    error
212                );
213            }
214        }
215
216
217        goDealsLog(
218            'GO Deals: Current store synchronized:',
219            storeNumber
220        );
221    };
222
223
224    /*
225     * =========================================================
226     * Find deal sections
227     * =========================================================
228     */
229
230    const sections =
231        document.querySelectorAll(
232            '.go-deals-section'
233        );
234
235
236    goDealsLog(
237        'GO Deals: Sections found:',
238        sections.length
239    );
240
241
242    if (!sections.length) {
243
244        goDealsLog(
245            'GO Deals: No deal sections found.'
246        );
247
248        return;
249    }
250
251
252    /*
253     * =========================================================
254     * Identify sections
255     * =========================================================
256     */
257
258    const hasWeeklyWin =
259        Array.from(
260            sections
261        ).some(
262            function (sectionElement) {
263
264                return (
265                    sectionElement.getAttribute(
266                        'data-go-deals-section'
267                    ) === 'weekly_win'
268                );
269
270            }
271        );
272
273
274    const hasNormalSections =
275        Array.from(
276            sections
277        ).some(
278            function (sectionElement) {
279
280                const section =
281                    sectionElement.getAttribute(
282                        'data-go-deals-section'
283                    );
284
285
286                return (
287                    section === 'top_deals' ||
288                    section === 'coming_soon'
289                );
290
291            }
292        );
293
294
295    goDealsLog(
296        'GO Deals: Has Weekly Win:',
297        hasWeeklyWin
298    );
299
300
301    goDealsLog(
302        'GO Deals: Has normal sections:',
303        hasNormalSections
304    );
305
306
307    /*
308     * =========================================================
309     * Initialize store
310     * =========================================================
311     *
312     * Backend logic:
313     *
314     * 1. preferred-store exists:
315     *      - use existing store
316     *      - get region from database
317     *
318     * 2. preferred-store does not exist:
319     *      - check Cloudflare country
320     *      - non-US -> no deals
321     *      - US -> find nearby store
322     *
323     * No fallback store is used.
324     */
325
326    goDealsLog(
327        'GO Deals: Calling initialize:',
328        GODealsConfig.initializeUrl
329    );
330
331
332    fetch(
333        GODealsConfig.initializeUrl,
334        {
335            method: 'GET',
336
337            credentials: 'same-origin',
338
339            headers: {
340                'Accept':
341                    'application/json'
342            }
343        }
344    )
345
346
347    /*
348     * =========================================================
349     * Initialize response
350     * =========================================================
351     */
352
353    .then(
354        function (response) {
355
356            goDealsLog(
357                'GO Deals: Initialize HTTP status:',
358                response.status
359            );
360
361
362            if (!response.ok) {
363
364                return response.text()
365                    .then(
366                        function (text) {
367
368                            goDealsError(
369                                'GO Deals: Initialize error response:',
370                                text
371                            );
372
373
374                            throw new Error(
375                                'Unable to initialize store.'
376                            );
377                        }
378                    );
379            }
380
381
382            return response.json();
383        }
384    )
385
386
387    /*
388     * =========================================================
389     * Determine store / country / region
390     * =========================================================
391     */
392
393    .then(
394        function (data) {
395
396            goDealsLog(
397                'GO Deals: Initialize response:',
398                data
399            );
400
401
402            /*
403             * -------------------------------------------------
404             * Validate initialize response
405             * -------------------------------------------------
406             */
407
408            if (
409                !data ||
410                !data.success
411            ) {
412
413                throw new Error(
414                    data && data.message
415                        ? data.message
416                        : 'Unable to initialize store.'
417                );
418            }
419
420
421            /*
422             * -------------------------------------------------
423             * Country
424             * -------------------------------------------------
425             */
426
427            const country =
428                data.country
429                    ? String(
430                        data.country
431                    ).trim().toUpperCase()
432                    : '';
433
434
435            goDealsLog(
436                'GO Deals - Country:',
437                country
438            );
439
440
441            /*
442             * -------------------------------------------------
443             * Non-US
444             * -------------------------------------------------
445             *
446             * No fallback anymore.
447             *
448             * Do not show:
449             *
450             * - Top Deals
451             * - Coming Soon
452             * - Weekly Win
453             */
454
455            if (
456                !country ||
457                country !== 'US'
458            ) {
459
460                goDealsLog(
461                    'GO Deals: Visitor is not in the US. No deals will be displayed.'
462                );
463
464
465                throw new Error(
466                    'GO Deals are only available in the US.'
467                );
468            }
469
470
471            /*
472             * -------------------------------------------------
473             * Store number
474             * -------------------------------------------------
475             */
476
477            const storeNumber =
478                data.store_number
479                    ? String(
480                        data.store_number
481                    ).trim()
482                    : '';
483
484
485            goDealsLog(
486                'GO Deals - Store:',
487                storeNumber
488            );
489
490
491            /*
492             * -------------------------------------------------
493             * Store number is required
494             * -------------------------------------------------
495             */
496
497            if (!storeNumber) {
498
499                throw new Error(
500                    'Store number not found.'
501                );
502            }
503
504
505            /*
506             * -------------------------------------------------
507             * Region
508             * -------------------------------------------------
509             *
510             * Region comes directly from the initialize
511             * REST API.
512             *
513             * No all-stores-4.
514             * No waitForStores().
515             */
516
517            const region =
518                data.region
519                    ? String(
520                        data.region
521                    ).trim()
522                    : '';
523
524
525            goDealsLog(
526                'GO Deals - Region:',
527                region
528            );
529
530
531            /*
532             * -------------------------------------------------
533             * Region is required
534             * -------------------------------------------------
535             */
536
537            if (!region) {
538
539                throw new Error(
540                    'Region not found for selected store.'
541                );
542            }
543
544
545            /*
546             * -------------------------------------------------
547             * IMPORTANT:
548             *
549             * Whether the store came from:
550             *
551             * source = "cookie"
552             *
553             * OR
554             *
555             * source = "ip"
556             *
557             * make sure StoreA exists in sessionStorage.
558             *
559             * We do NOT overwrite StoreA if it already exists.
560             * -------------------------------------------------
561             */
562
563            window.goDealsSetCurrentStore(
564                storeNumber
565            );
566
567
568            /*
569             * =================================================
570             * Render all 3 sections
571             * =================================================
572             */
573
574            goDealsLog(
575                'GO Deals: Calling render:',
576                GODealsConfig.renderUrl
577            );
578
579
580            goDealsLog(
581                'GO Deals: Render request:',
582                {
583                    store_number:
584                        Number(
585                            storeNumber
586                        ),
587
588                    region:
589                        region,
590
591                    country:
592                        country
593                }
594            );
595
596
597            return fetch(
598                GODealsConfig.renderUrl,
599                {
600                    method: 'POST',
601
602                    credentials:
603                        'same-origin',
604
605                    headers: {
606                        'Content-Type':
607                            'application/json',
608
609                        'Accept':
610                            'application/json'
611                    },
612
613                    body:
614                        JSON.stringify({
615                            store_number:
616                                Number(
617                                    storeNumber
618                                ),
619
620                            region:
621                                region,
622
623                            country:
624                                country
625                        })
626                }
627            );
628        }
629    )
630
631
632    /*
633     * =========================================================
634     * Render response
635     * =========================================================
636     */
637
638    .then(
639        function (response) {
640
641            goDealsLog(
642                'GO Deals: Render HTTP status:',
643                response.status
644            );
645
646
647            if (!response.ok) {
648
649                return response.text()
650                    .then(
651                        function (text) {
652
653                            goDealsError(
654                                'GO Deals: Render error response:',
655                                text
656                            );
657
658
659                            throw new Error(
660                                'Unable to load deals.'
661                            );
662                        }
663                    );
664            }
665
666
667            return response.json();
668        }
669    )
670
671
672    /*
673     * =========================================================
674     * Render sections
675     * =========================================================
676     */
677
678    .then(
679        function (data) {
680
681            goDealsLog(
682                'GO Deals: Render response:',
683                data
684            );
685
686
687            if (
688                !data ||
689                !data.success
690            ) {
691
692                throw new Error(
693                    data && data.message
694                        ? data.message
695                        : 'Unable to load deals.'
696                );
697            }
698
699
700            if (
701                !data.sections ||
702                typeof data.sections !== 'object'
703            ) {
704
705                throw new Error(
706                    'Invalid render response.'
707                );
708            }
709
710
711            /*
712             * -------------------------------------------------
713             * Render each section
714             * -------------------------------------------------
715             */
716
717            sections.forEach(
718                function (sectionElement) {
719
720                    /*
721                     * The element may have been removed or
722                     * cleared because of an error.
723                     */
724
725                    if (
726                        !document.body.contains(
727                            sectionElement
728                        )
729                    ) {
730
731                        return;
732                    }
733
734
735                    const section =
736                        sectionElement.getAttribute(
737                            'data-go-deals-section'
738                        );
739
740
741                    const sectionHtml =
742                        data.sections[
743                            section
744                        ];
745
746
747                    goDealsLog(
748                        'GO Deals: Section result:',
749                        {
750                            section:
751                                section,
752
753                            hasHtml:
754                                typeof sectionHtml === 'string' &&
755                                sectionHtml.trim() !== ''
756                        }
757                    );
758
759
760                    if (
761                        typeof sectionHtml === 'string' &&
762                        sectionHtml.trim() !== ''
763                    ) {
764
765                        sectionElement.innerHTML =
766                            sectionHtml;
767
768
769                        goDealsLog(
770                            'GO Deals: Rendered:',
771                            section
772                        );
773
774
775                        /*
776                         * -------------------------------------------------
777                         * Weekly Win More button
778                         * -------------------------------------------------
779                         *
780                         * Hide the Elementor button when Weekly Win
781                         * has data.
782                         */
783
784                        if (section === 'weekly_win') {
785
786                            const winMoreBtn =
787                                document.querySelector('.win-more-btn');
788
789
790                            if (winMoreBtn) {
791
792                                winMoreBtn.style.display = 'none';
793
794
795                                goDealsLog(
796                                    'GO Deals: Weekly Win has data - hiding win-more-btn'
797                                );
798                            }
799                        }
800
801
802                        /*
803                         * Initialize Upcoming Deals slider
804                         * AFTER the HTML has been inserted.
805                         */
806
807                        if (
808                            section === 'coming_soon' &&
809                            typeof window.initGoDealsSlider === 'function'
810                        ) {
811
812                            setTimeout(
813                                function () {
814
815                                    window.initGoDealsSlider(
816                                        sectionElement
817                                    );
818
819                                },
820                                100
821                            );
822                        }
823
824
825                    } else {
826
827                        sectionElement.innerHTML =
828                            '';
829
830
831                        goDealsLog(
832                            'GO Deals: No content for:',
833                            section
834                        );
835                    }
836                }
837            );
838        }
839    )
840
841
842    /*
843     * =========================================================
844     * Error handling
845     * =========================================================
846     *
847     * Any failure means:
848     *
849     * - Top Deals -> nothing
850     * - Coming Soon -> nothing
851     * - Weekly Win -> nothing
852     */
853
854    .catch(
855        function (error) {
856
857            goDealsError(
858                'GO Deals ERROR:',
859                error
860            );
861
862
863            /*
864             * Clear ALL deal sections.
865             */
866
867            document
868                .querySelectorAll(
869                    '.go-deals-section'
870                )
871                .forEach(
872                    function (sectionElement) {
873
874                        const section =
875                            sectionElement.getAttribute(
876                                'data-go-deals-section'
877                            );
878
879
880                        sectionElement.innerHTML =
881                            '';
882
883
884                        goDealsLog(
885                            'GO Deals: Cleared section after error:',
886                            section
887                        );
888                    }
889                );
890        }
891    );
892
893
894    /*
895     * =========================================================
896     * GO Deals Swiper
897     * =========================================================
898     */
899
900    (function () {
901
902        goDealsLog(
903            'GO Deals: Slider script loaded'
904        );
905
906
907        window.initGoDealsSlider = function (container) {
908
909            goDealsLog(
910                'GO Deals: Slider function'
911            );
912
913
914            /*
915             * Mobile only
916             */
917
918            if (window.innerWidth > 768) {
919                return;
920            }
921
922
923            /*
924             * Check Swiper
925             */
926
927            if (typeof Swiper === 'undefined') {
928
929                goDealsError(
930                    'GO Deals: Swiper is not loaded.'
931                );
932
933                return;
934            }
935
936
937            /*
938             * Find slider inside the rendered section
939             */
940
941            const sliderElement = container
942                ? container.querySelector('.go-deals-slider')
943                : document.querySelector('.go-deals-slider');
944
945
946            if (!sliderElement) {
947
948                goDealsLog(
949                    'GO Deals: Slider element not found.'
950                );
951
952                return;
953            }
954
955
956            /*
957             * Already initialized
958             */
959
960            if (sliderElement.swiper) {
961
962                goDealsLog(
963                    'GO Deals: Slider already initialized.'
964                );
965
966                return;
967            }
968
969
970            /*
971             * Check slides
972             */
973
974            const slides =
975                sliderElement.querySelectorAll(
976                    '.swiper-slide'
977                );
978
979
980            goDealsLog(
981                'GO Deals: Upcoming Deals slides:',
982                slides.length
983            );
984
985
986            if (!slides.length) {
987
988                goDealsLog(
989                    'GO Deals: No slides found.'
990                );
991
992                return;
993            }
994
995
996            /*
997             * Initialize Swiper
998             */
999
1000            new Swiper(
1001                sliderElement,
1002                {
1003                    loop: slides.length > 1,
1004
1005                    slidesPerView: 'auto',
1006
1007                    spaceBetween: 0,
1008
1009                    centeredSlides: false,
1010
1011                    grabCursor: true,
1012
1013                    speed: 600,
1014
1015                    autoplay: slides.length > 1
1016                        ? {
1017                            delay: 2500,
1018                            disableOnInteraction: false,
1019                            pauseOnMouseEnter: true
1020                        }
1021                        : false
1022                }
1023            );
1024
1025
1026            goDealsLog(
1027                'GO Deals: Upcoming Deals slider initialized.'
1028            );
1029        };
1030
1031    })();
1032
1033});

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.