PageSourceSearch

https://www.bed-wet.com/modules/ganalyticspro/views/js/bt_g4.js

js bed-wet.com collected 2026-10-08 11:46:15 UTC 21,944 bytes, 674 lines download raw bytes

1/**
2 * Google Analytics : GA4
3 *
4 * @author    https://versus.pro/
5 * @copyright Business Tech - https://www.businesstech.fr/
6 * @license   see file: LICENSE.txt
7 *
8 *           ____    _______
9 *          |  _ \  |__   __|
10 *          | |_) |    | |
11 *          |  _ <     | |
12 *          | |_) |    | |
13 *          |____/     |_|
14 */
15
16// Expose gtag globally as early as possible
17window.dataLayer = window.dataLayer || [];
18window.gtag = window.gtag || function () { dataLayer.push(arguments); }
19
20/**
21 * Set default consent to denied (privacy by default)
22 */
23function setDefaultConsentDenied() {
24    if (btGapTag && (btGapTag.bUseConsent || btGapTag.bforceTag)) {
25        gtag("consent", "default", {
26            ad_storage: "denied",
27            analytics_storage: "denied",
28            ad_user_data: "denied",
29            ad_personalization: "denied",
30        });
31    }
32}
33
34function getGtagConfigOptions(extraOptions) {
35    const options = extraOptions ? Object.assign({}, extraOptions) : {};
36
37    if (
38        btGapTag &&
39        btGapTag.gaUserIdMode === "hidden" &&
40        Number(btGapTag.gaUserId) > 0
41    ) {
42        options.user_id = String(btGapTag.gaUserId);
43    }
44
45    return options;
46}
47
48// Initialize gtag as early as possible
49setDefaultConsentDenied();
50gtag('js', new Date());
51gtag('config', btGapTag.gaId, getGtagConfigOptions());
52
53document.addEventListener('DOMContentLoaded', function () {
54    // Handle consent mode
55    handleConsentMode();
56
57    // Process refunds and partial refunds
58    processRefunds();
59
60    // Handle specific tracking types
61    if (btGapTag.tagContent && btGapTag.tagContent.tracking_type) {
62        handleTrackingType();
63    }
64
65    // Add event listeners for cart updates and user actions
66    addEventListeners();
67});
68
69/**
70 * Handle consent mode based on configuration
71 */
72function handleConsentMode() {
73    if (btGapTag.bUseConsent) {
74        if (btGapTag.bUseAxeption == 1) {
75            setDefaultConsentDenied();
76            handleAxeptioConsent();
77        } else if (btGapTag.bUseAxeption == 0) {
78            setDefaultConsentDenied();
79            handleCustomConsent();
80        } else {
81            setDefaultConsentDenied();
82        }
83    } else if (btGapTag.bforceTag) {
84        setDefaultConsentDenied();
85    }
86}
87
88/**
89 * Handle Axeptio consent
90 */
91function handleAxeptioConsent() {
92    function launchGoogleAnalytics() {
93        gtag("js", new Date());
94        gtag("config", btGapTag.gaId, getGtagConfigOptions());
95    }
96
97    window._axcb = window._axcb || [];
98    window._axcb.push(function (axeptio) {
99        axeptio.on("cookies:complete", function (choices) {
100            if (choices.google_analytics) {
101                gtag("consent", "update", { analytics_storage: "granted" });
102                launchGoogleAnalytics();
103            }
104        });
105    });
106}
107
108/**
109 * Handle custom consent
110 */
111function handleCustomConsent() {
112    // Set initial consent state
113    setConsentState(btGapTag.iConsentConsentLvl);
114
115    // Handle consent button clicks
116    [btGapTag.bConsentHtmlElement, btGapTag.bConsentHtmlElementSecond].forEac
116h(element => {
117        if (element) {
118            $(element).on("click", updateConsent);
119        }
120    });
121
122    // Remove ACB referrer cookie if installed
123    if (btGapTag.acbIsInstalled) {
124        $.ajax({
125            type: "POST",
126            url: btGapTag.ajaxUrl,
127            dataType: "json",
128            data: { ajax: 1, action: "removedAcbReferrer", token: btGapTag.token },
129        });
130    }
131}
132
133/**
134 * Set consent state based on consent level
135 */
136function setConsentState(consentLevel) {
137    let consentState = {
138        ad_storage: "denied",
139        analytics_storage: "denied",
140        ad_user_data: "denied",
141        ad_personalization: "denied",
142    };
143
144    switch (consentLevel) {
145        case 1: // stats
146            consentState.analytics_storage = "granted";
147            break;
148        case 2: // market
149            consentState.ad_storage = "granted";
150            consentState.ad_user_data = "granted";
151            consentState.ad_personalization = "granted";
152            break;
153        case 3: // all
154            consentState = {
155                ad_storage: "granted",
156                analytics_storage: "granted",
157                ad_user_data: "granted",
158                ad_personalization: "granted",
159            };
160            break;
161    }
162
163    gtag("consent", "update", consentState);
164
165    if (btGapTag.referer != null) {
166        gtag('set', 'page_referrer', btGapTag.referer);
167    }
168}
169
170/**
171 * Update consent via AJAX
172 */
173function updateConsent() {
174    $.ajax({
175        type: "POST",
176        url: btGapTag.ajaxUrl,
177        dataType: "json",
178        data: { ajax: 1, action: "updateConsent", token: btGapTag.token },
179        success: function () {
180            gtag("js", new Date());
181            gtag("config", btGapTag.gaId, getGtagConfigOptions({ cookie_update: false }));
182            gtag("consent", "update", {
183                ad_storage: "granted",
184                analytics_storage: "granted",
185                ad_user_data: "granted",
186                ad_personalization: "granted",
187            });
188        },
189    });
190}
191
192/**
193 * Process refunds and partial refunds
194 */
195function processRefunds() {
196    if (btGapTag.bRefund) {
197        sendRefundEvent("sendRefund", "refunds");
198    }
199    if (btGapTag.bPartialRefund) {
200        sendRefundEvent("sendPartialRefund", "refunds_partial");
201    }
202}
203
204/**
205 * Send refund event via AJAX
206 */
207function sendRefundEvent(action, dataKey) {
208    $.ajax({
209        type: "POST",
210        url: btGapTag.ajaxUrl,
211        dataType: "json",
212        data: { ajax: 1, action: action, token: btGapTag.token },
213        success: function (jsonData) {
214            jsonData[dataKey].forEach(function (data) {
215                let eventData = {
216                    currency: data.currency || data.refund_data.currency,
217                    value: data.value || data.refund_data.value,
218                    transaction_id: data.transaction_id || data.refund_data.transaction_id,
219                    shipping: data.shipping || data.refund_data.shipping,
220                    tax: data.tax || data.refund_data.tax,
221                };
222                if (data.has_product) {
223                    eventData.items = data.product;
224                }
225                gtag("event", "refund", eventData);
226            });
227        },
228    });
229}
230
231/**
232 * Handle specific tracking types
233 */
234function handleTrackingType() {
235    const trackingType = btGapTag.tagContent.tracking_type.value;
236    const handlers = {
237        view_item_list: handleViewItemList,
238        view_item: handleViewItem,
239        view_promotion: handleViewPromotion,
240        view_cart: handleViewCart,
241        begin_checkout: handleBeginCheckout,
242        add_shipping_info: handleAddShippingInfo,
243        add_payment_info: handleAddPaymentInfo,
244        purchase: handlePurchase,
245        generate_lead: () => gtag("event", "generate_lead"),
246        search: () => gtag("event", "search", { search_term: btGapTag.tagContent.content_name.value }),
247    };
248
249    if (handlers[trackingType]) {
250        handlers[trackingType]();
251    }
252}
253
254/**
255 * Handle view item list event
256 */
257function handleViewItemList() {
258    if (typeof btGapTag.tagContent.contents !== "undefined") {
259        const items = btGapTag.tagContent.contents.value.map(item => item);
260        gtag("event", "view_item_list", {
261            item_list_id: btGapTag.tagContent.content_name.value,
262            item_list_name: btGapTag.tagContent.content_name.value,
263            items: items,
264        });
265    }
266
267    // Add click event listeners for products and wishlist
268    addProductClickListeners();
269    addWishlistClickListeners();
270}
271
272/**
273 * Add click event listeners for products
274 */
275function addProductClickListeners() {
276    $(btGapTag.elementCategoryProduct).each(function () {
277        $(this).on("click", function () {
278            sendSelectItemEvent($(this).attr("data-id-product"), "selectItem");
279        });
280    });
281}
282
283/**
284 * Add click event listeners for wishlist
285 */
286function addWishlistClickListeners() {
287    $(btGapTag.elementWishCat).each(function () {
288        $(this).on("click", function () {
289            sendSelectItemEvent($(this).attr("data-id-product"), "selectItem", "add_to_wishlist");
290        });
291    });
292}
293
294/**
295 * Send select item event via AJAX
296 */
297function sendSelectItemEvent(productId, action, eventName = "select_item") {
298    $.ajax({
299        type: "POST",
300        url: btGapTag.ajaxUrl,
301        dataType: "json",
302        data: { ajax: 1, action: action, iProductId: productId, token: btGapTag.token },
303        success: function (jsonData) {
304            gtag("event", eventName, {
305                item_list_id: btGapTag.tagContent.content_name.value,
306                item_list_name: btGapTag.tagContent.content_name.value,
307                items: jsonData.data,
308            });
309        },
310    });
311}
312
313/**
314 * Handle view item event
315 */
316function handleViewItem() {
317    const items = btGapTag.tagContent.contents.value.map(item => item);
318    gtag("event", "view_item", {
319        currency: btGapTag.tagContent.currency.value,
320        value: btGapTag.tagContent.value.value,
321        items: items,
322    });
323
324    $(btGapTag.elementWishProd).on("click", function () {
325        gtag("event", "add_to_wishlist", {
326            currency: btGapTag.tagContent.currency.value,
327            value: btGapTag.tagContent.value.value,
328            items: items,
329        });
330    });
331}
332
333/**
334 * Handle view promotion event
335 */
336function handleViewPromotion() {
337    const items = btGapTag.tagContent.contents.value.map(item => item);
338    gtag("event", "view_promotion", {
339        item_list_id: btGapTag.tagContent.content_name.value,
340        item_list_name: btGapTag.tagContent.content_name.value,
341        items: items,
342    });
343
344    $(btGapTag.elementCategoryProduct).each(function () {
345        $(this).on("click", function () {
346            sendSelectItemEvent($(this).attr("data-id-product"), "selectPromotion", "select_promotion");
347        });
348    });
349}
350
351/**
352 * Handle view cart event
353 */
354function handleViewCart() {
355    const items = btGapTag.tagContent.contents.value.map(item => item);
356    gtag("event", "view_cart", {
357        currency: btGapTag.tagContent.currency.value,
358        value: btGapTag.tagContent.value.value,
359        items: items,
360    });
361}
362
363/**
364 * Handle begin checkout event
365 */
366function handleBeginCheckout() {
367    const items = btGapTag.tagContent.contents.value.map(item => item);
368    gtag("event", "begin_checkout", {
369        currency: btGapTag.tagContent.currency.value,
370        value: btGapTag.tagContent.value.value,
371        coupon: btGapTag.tagContent.coupon_name.value,
372        items: items,
373    });
374}
375
376/**
377 * Handle add shipping info event
378 */
379function handleAddShippingInfo() {
380    const items = btGapTag.tagContent.contents.value.map(item => item);
381    // Function to get the value of the checked delivery option
382    function getCheckedDeliveryOption() {
383        const checkedOption = document.querySelector('.delivery-options input[type="radio"]:checked');
384        if (checkedOption) {
385            const label = document.querySelector(`label[for="${checkedOption.id}"]`);
386            if (label) {
387                const carrierName = label.querySelector('.carrier-name');
388                return carrierName ? carrierName.textContent.trim() : '';
389            }
390        }
391        return '';
392    }
393
394    // Add event listener for selection changes
395    document.querySelectorAll('.delivery-options input[type="radio"]').forEach(radio => {
396        radio.addEventListener('change', () => {
397            const selectedCarrier = getCheckedDeliveryOption();
398            if (selectedCarrier) {
399                sendShippingEvent(radio.value, selectedCarrier);
400            }
401        });
402    });
403
404    // Send event for default option on page load
405    const defaultCarrier = getCheckedDeliveryOption();
406    if (defaultCarrier) {
407        const defaultRadio = document.querySelector('.delivery-options input[type="radio"]:checked');
408        if (defaultRadio) {
409            sendShippingEvent(defaultRadio.value, defaultCarrier);
410        }
411    }
412
413    function sendShippingEvent(carrierId) {
414        $.ajax({
415            type: "POST",
416            url: btGapTag.ajaxUrl,
417            dataType: "json",
418            data: { ajax: 1, action: "sendCarrier", idCarrier: carrierId, token: btGapTag.token },
419            success: function (jsonData) {
420                gtag("event", "add_shipping_info", {
421                    currency: btGapTag.tagContent.currency.value,
422                    value: btGapTag.tagContent.value.value,
423                    coupon: btGapTag.tagContent.coupon_name.value,
424                    shipping_tier: jsonData.sCarrierName,
425                    items: items,
426                });
427            },
428        });
429    }
430
431    $(btGapTag.elementShipping).each(function () {
432        $(this).on("click", function () {
433            sendShippingEvent($(this).val());
434        });
435    });
436
437    // Send default carrier on page load
438    sendShippingEvent($(btGapTag.elementShipping + ":checked").val());
439}
440
441/**
442 * Handle add payment info event
443 */
444function handleAddPaymentInfo() {
445    const items = btGapTag.tagContent.contents.value.map(item => item);
446
447    $('.ps-shown-by-js').each(function () {
448        $(this).on("click", function () {
449            gtag("event", "add_payment_info", {
450                currency: btGapTag.tagContent.currency.value,
451                value: btGapTag.tagContent.value.value,
452                coupon: btGapTag.tagContent.coupon_name.value,
453                payment_type: $('label[for="' + $(this).attr("id") + '"]').text().trim(),
454                items: items,
455            });
456        });
457    });
458}
459
460/**
461 * Handle purchase event
462 */
463function handlePurchase() {
464    const items = btGapTag.tagContent.contents.value.map(item => item);
465    gtag("event", "purchase", {
466        currency: btGapTag.tagContent.currency.value,
467        value: btGapTag.tagContent.value.value,
468        transaction_id: btGapTag.tagContent.content_id.value,
469        coupon: btGapTag.tagContent.coupon_name.value,
470        shipping: btGapTag.tagContent.value_shipping ? btGapTag.tagContent.value_shipping.value : 0,
471        tax: btGapTag.tagContent.value_tax ? btGapTag.tagContent.value_tax.value : 0,
472        items: items,
473    });
474
475    // Check if enhanced conversion is enabled
476    if (btGapTag.gaEnhancedConversion) {
477        // Verify if any relevant data is present before triggering the tag
478        const hasRelevantData = btGapTag.gaEnhancedConversionData.email ||
479            btGapTag.gaEnhancedConversionData.phone_number ||
480            (btGapTag.gaEnhancedConversionData.address && Object.values(btGapTag.gaEnhancedConversionData.address).some(Boolean));
481
482        if (hasRelevantData) {
483            gtag("set", "user_data", {
484                "email": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.email ? btGa
484pTag.gaEnhancedConversionData.email : '',
485                "phone_number": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.phone_number ? btGapTag.gaEnhancedConversionData.phone_number : '',
486                "address": {
487                    "first_name": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.address && btGapTag.gaEnhancedConversionData.address.first_name ? btGapTag.gaEnhancedConversionData.address.first_name : '',
488                    "last_name": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.address && btGapTag.gaEnhancedConversionData.address.last_name ? btGapTag.gaEnhancedConversionData.address.last_name : '',
489                    "street": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.address && btGapTag.gaEnhancedConversionData.address.street ? btGapTag.gaEnhancedConversionData.address.street : '',
490                    "city": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.address && btGapTag.gaEnhancedConversionData.address.city ? btGapTag.gaEnhancedConversionData.address.city : '',
491                    "region": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.address && btGapTag.gaEnhancedConversionData.address.region ? btGapTag.gaEnhancedConversionData.address.region : '',
492                    "postal_code": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.address && btGapTag.gaEnhancedConversionData.address.postal_code ? btGapTag.gaEnhancedConversionData.address.postal_code : '',
493                    "country": btGapTag.gaEnhancedConversionData && btGapTag.gaEnhancedConversionData.address && btGapTag.gaEnhancedConversionData.address.country ? btGapTag.gaEnhancedConversionData.address.country : ''
494                }
495            });
496        }
497    }
498
499}
500
501/**
502 * Add event listeners for cart updates and user actions
503 */
504function addEventListeners() {
505    if (typeof prestashop !== 'undefined') {
506        prestashop.on('updatedProduct', handleUpdatedProduct);
507        prestashop.on('clickQuickView', handleQuickView);
508        prestashop.on('updateCart', handleCartUpdate);
509    }
510
511    $(btGapTag.elementlogin).on("click", () => gtag("event", "login", { method: "Website direct" }));
512    $(btGapTag.elementsignup).on("click", () => gtag("event", "sign_up", { method: "Website direct" }));
513    $("video.pvr-video-player").on("click", () => gtag("event", "video_start"));
514}
515
516/**
517 * Handle updated product event
518 */
519function handleUpdatedProduct(event) {
520    if (event) {
521        $.ajax({
522            type: "POST",
523            url: btGapTag.ajaxUrl,
524            dataType: "json",
525            data: {
526                ajax: 1,
527                action: "updateCombination",
528                id_product_attribute: event.id_product_attribute,
529                id_product: $('input[name="id_product"]').val(),
530                token: btGapTag.token,
531            },
532            success: function (jsonData) {
533                gtag("event", "view_item", {
534                    currency: jsonData.currency,
535                    value: jsonData.value,
536                    items: jsonData.data,
537                });
538            },
539        });
540    }
541}
542
543/**
544 * Handle quick view event
545 */
546function handleQuickView(event) {
547    if (event) {
548        $.ajax({
549            type: "POST",
550            url: btGapTag.ajaxUrl,
551            dataType: "json",
552            data: {
553                ajax: 1,
554                action: "updateQuickView",
555                id_product_attribute: event.dataset.idProductAttribute,
556                id_product: event.dataset.idProduct,
557                token: btGapTag.token,
558            },
559            success: function (jsonData) {
560                gtag("event", "view_item", {
561                    currency: jsonData.currency,
562                    value: jsonData.value,
563                    items: jsonData.data,
564                });
565            },
566        });
567    }
568}
569
570/**
571 * Handle cart update event
572 */
573function handleCartUpdate(event) {
574    if (event && event.reason) {
575        if (event.reason.linkAction === "add-to-cart") {
576            handleAddToCart(event);
577        } else if (event.reason.linkAction === "delete-from-cart") {
578            handleRemoveFromCart(event);
579        }
580    }
581}
582
583/**
584 * Handle add to cart event
585 */
586function handleAddToCart(event) {
587    const productData = extractProductData(event);
588    $.ajax({
589        type: "POST",
590        url: btGapTag.ajaxUrl,
591        dataType: "json",
592        data: {
593            ajax: 1,
594            action: "cartPageList",
595            id_product_attribute: productData.idProductAttribute,
596            id_product: productData.idProduct,
597            quantity: productData.quantity,
598            token: btGapTag.token,
599        },
600        success: function (jsonData) {
601            gtag("event", "add_to_cart", {
602                currency: jsonData.currency,
603                value: jsonData.value,
604                items: jsonData.data,
605            });
606        },
607    });
608}
609
610/**
611 * Handle remove from cart event
612 */
613function handleRemoveFromCart(event) {
614    const productData = extractProductData(event);
615    $.ajax({
616        type: "POST",
617        url: btGapTag.ajaxUrl,
618        dataType: "json",
619        data: {
620            ajax: 1,
621            action: "removeCart",
622            iProductId: productData.idProduct,
623            token: btGapTag.token,
624        },
625        success: function (jsonData) {
626            gtag("event", "remove_from_cart", {
627                currency: jsonData.currency,
628                value: jsonData.value,
629                items: jsonData.data,
630            });
631        },
632    });
633}
634
635/**
636 * Extract product data from event
637 *
638 * This function handles different event object structures that can come from:
639 * 1. Direct add to cart events (event.reason.idProduct)
640 * 2. AJAX responses (event.resp)
641 * 3. Cart update events (event.reason.cart.products)
642 *
643 * The fallback chain for each property ensures we can extract the data regardless
644 * of which event triggered the action. This is necessary because:
645 * - Product attributes (like size/color) come in different formats
646 * - Product IDs may be nested differently based on the event source
647 * - Quantity can be found in multiple locations or default to 1
648 *
649 * Using optional chaining (?.) prevents errors when accessing nested properties
650 * that might not exist in all event structures.
651 */
652function extractProductData(event) {
653    // More robust property verification
654    const idProductAttribute = event.reason?.idProductAttribute ||
655        event.resp?.id_product_attribute ||
656        event.reason?.cart?.products?.[0]?.id_product_attribute ||
657        0;
658
659    const idProduct = event.reason?.idProduct ||
660        event.resp?.id_product ||
661        event.reason?.cart?.products?.[0]?.id_product ||
662        0;
663
664    const quantity = event.reason?.cart?.products_count ||
665        event.resp?.quantity ||
666        event.reason?.cart?.products?.[0]?.quantity ||
667        1;
668
669    return {
670        idProductAttribute,
671        idProduct,
672        quantity
673    };
674}

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.