PageSourceSearch

https://pauljohncaffeine.in/wp-content/themes/hello-elementor-child/js/EcomTracking.js?ver=1747742001

js pauljohncaffeine.in collected 2026-10-04 02:40:14 UTC 14,295 bytes, 445 lines download raw bytes

1// This script tracks key Ecommerce events such as:
2// 1. "add_to_cart" - Tracks when an item is added to the cart.
3// 2. "view_item" - Tracks when a user views a product.
4// 3. "begin_checkout" - Tracks when the user starts the checkout process.
5// 4. "purchase" - Tracks when the user completes the purchase (after the "Thank You" page).
6// The event data (product information, prices, etc.) is pushed to the dataLayer for analytics tracking (e.g., Google Tag Manager).
7// ============================
8//File-Location : wp-content/themes/your-theme/js/EcommerceTracking.js
9
10// Wait for the DOM to be fully loaded before executing the script
11document.addEventListener("DOMContentLoaded", function () {
12  // Define the default currency code
13  const currencyCode = "INR";
14
15  /**
16   * Push data to the `dataLayer` for GA4 tracking.
17   * @param {string} eventName - The name of the GA4 event (e.g., "add_to_cart").
18   * @param {Object} data - The data object containing event details.
19   */
20  function pushToDataLayer(eventName, data) {
21    window.dataLayer = window.dataLayer || [];
22    window.dataLayer.push({ event: eventName, ecommerce: data });
23  }
24
25  /**
26   * Track "add_to_cart" events based on user interactions.
27   * Handles multiple button types and purchase options.
28   * @param {Event} event - The click event triggered by user interaction.
29   */
30  function trackAddToCart(event) {
31    if (
32      event.target.matches(".product_type_simple") &&
33      !event.target.hasAttribute("data-tracked")
34    ) {
35      // Extract product data from attributes
36      event.target.setAttribute("data-tracked", "true");
37      const itemId =
38        event.target.getAttribute("data-product_id") || "Unknown ID";
39      const itemName =
40        event.target.getAttribute("data-product_name") || "Unknown Product";
41      const priceElement = document.querySelector(".price bdi");
42      const price = priceElement
43        ? parseFloat(priceElement.innerText.replace(/[^\d.]/g, ""))
44        : 0.0;
45
46      // Push event data for a simple add to cart action
47      pushToDataLayer("add_to_cart", {
48        currency: currencyCode,
49        value: price,
50        items: [
51          { item_id: itemId, item_name: itemName, price: price, quantity: 1 },
52        ],
53      });
54    } else if (
55      event.target.matches(".single_add_to_cart_button") &&
56      !event.target.hasAttribute("data-tracked")
57    ) {
58      // Extract product data from the page
59      const productIdElement = document.querySelector(
60        'input[name="product_id"]'
61      ).value || "Unknown Product Id";
62
63      event.target.setAttribute("data-tracked", "true");
64      const itemName =
65        document
66          .querySelector(".elementor-widget-woocommerce-product-title h1")
67          ?.innerText.trim() || "Unknown Product";
68      const price =
69        parseFloat(
70          document
71            .querySelector(".elementor-widget-container .price bdi")
72            ?.innerText.replace(/[^\d.]/g, "")
73        ) || 0.0;
74
75      // Push event data for a single product view
76      pushToDataLayer("add_to_cart", {
77        currency: currencyCode,
78        value: price,
79        //order_type: "One Time Purchase",
80        items: [
81          {
82            item_id: productIdElement,
83            item_name: itemName,
84            price: price,
85            quantity: 1,
86          },
87        ],
88      });
89    }
90    else if (
91        event.target.matches(".single_add_to_cart_button1") &&
92        !event.target.hasAttribute("data-tracked")
93    ) {
94        // Extract product data from the page
95        const productIdElement = document.querySelector(
96            'input[name="product_id"]'
97        )?.value || "Unknown Product Id";
98
99        event.target.setAttribute("data-tracked", "true");
100        const itemName =
101            document
102                .querySelector(".elementor-widget-woocommerce-product-title h1")
103                ?.innerText.trim() || "Unknown Product";
104        const price =
105            parseFloat(
106                document
107                    .querySelector(".elementor-widget-container .price bdi")
108                    ?.innerText.replace(/[^\d.]/g, "")
109            ) || 0.0;
110
111        // Push event data for a single product view
112        pushToDataLayer("add_to_cart", {
113            currency: currencyCode,
114            value: price,
115            //order_type: "One Time Purchase",
116            items: [
117                {
118                    item_id: productIdElement,
119                    item_name: itemName,
120                    price: price,
121                    quantity: 1,
122                },
123            ],
124        });
125    } else if (event.target.closest(".wcsatt-options-prompt-label-one-time")) {
126      // Track one-time purchase option
127      const itemName =
128        document
129          .querySelector(".elementor-widget-woocommerce-product-title h1")
130          ?.innerText.trim() || "Unknown Product";
131      const price =
132        parseFloat(
133          document
134            .querySelector(".elementor-widget-woocommerce-product-price p span")
135            ?.innerText.replace(/[^\d.]/g, "")
136        ) || 0.0;
137
138      pushToDataLayer("add_to_cart", {
139        currency: currencyCode,
140        value: price,
141        items: [{ item_name: itemName, price: price, quantity: 1 }],
142      });
143    } else if (
144      event.target.closest(".wcsatt-options-prompt-label-subscription")
145    ) {
146      // Track subscription option
147      const itemName =
148        document
149          .querySelector(".elementor-widget-woocommerce-product-title h1")
150          ?.innerText.trim() || "Unknown Product";
151      const price =
152        parseFloat(
153          document
154            .querySelector(".elementor-widget-woocommerce-product-price p span")
155            ?.innerText.replace(/[^\d.]/g, "")
156        ) || 0.0;
157
158      pushToDataLayer("add_to_cart", {
159        currency: currencyCode,
160        value: price,
161        order_type: "Subscription",
162        items: [{ item_name: itemName, price: price, quantity: 1 }],
163      });
164    }
165  }
166
167  /**
168   * Track "view_item" events when a product page is loaded.
169   */
170  function trackViewItem() {
171    if (window.location.pathname.includes("/product/")) {
172      const productIdElement =
173          document.querySelector('input[name="product_id"]')
174          ?.value || "Unknown ID";
175
176      const itemName =
177        document
178          .querySelector(".elementor-widget-woocommerce-product-title h1")
179          ?.innerText.trim() || "Unknown Product";
180
181      const price =
182        parseFloat(
183          document
184            .querySelector(".elementor-widget-woocommerce-product-price p span")
185            ?.innerText.replace(/[^\d.]/g, "")
186        ) || 0.0;
187
188      const itemWeight =
189        document
190          .querySelector(
191            ".woocommerce-product-details__short-description div strong"
192          )
193          ?.nextSibling?.textContent.trim() || "Unknown Weight";
194
195      const itemRoastLevel =
196        document.querySelector(".roast_level_title")?.innerText.trim() ||
197        "Unknown Roast Level";
198
199      const itemOrigin =
200        document
201          .querySelector(".elementor-element-bde0230 p")
202          ?.innerText.trim() || "Unknown Origin";
203
204      const itemTastingNotes =
205        document
206          .querySelector(".elementor-element-f1cd0ae p")
207          ?.innerText.trim() || "Unknown Tasting Notes";
208
209      window.dataLayer = window.dataLayer || [];
210      window.dataLayer.push({
211        event: "view_item",
212        currency: "INR",
213        value: price,
214        ecommerce: {
215          items: [
216            {
217              item_id: productIdElement,
218              item_name: itemName,
219              item_weight: itemWeight,
220              item_roast_level: itemRoastLevel,
221              item_origin: itemOrigin,
222              item_tasting_notes: itemTastingNotes,
223              price: price,
224              quantity: 1,
225            },
226          ],
227        },
228      });
229    }
230  }
231
232  /**
233   * Track "begin_checkout" events when the checkout process starts.
234   */
235
236  function trackBeginCheckout() {
237    if (
238      window.location.pathname.includes("/checkout/") &&
239      !window.location.pathname.includes("/checkout/order-pay/") &&
240      !window.location.pathname.includes("/checkout/thank-you/")
241    ) {
242      const cartItems = document.querySelectorAll(".cart_item");
243
244      // Get total order value using the correct class
245      const orderTotalText = document
246        .querySelector(".order-total .total-price .woocommerce-Price-amount")
247        ?.innerText.trim();
248      const totalAmount =
249        parseFloat(orderTotalText?.replace(/[^\d.]/g, "")) || 0;
250
251      const items = Array.from(cartItems).map((item) => {
252        const itemName =
253          item
254            .querySelector(".product-name")
255            ?.childNodes[0].textContent.trim() || "Unknown Product";
256
257        // Log the itemName to debug
258
259        const price =
260          parseFloat(
261            item
262              .querySelector(".product-total .woocommerce-Price-amount")
263              ?.innerText.replace(/[^\d.-]/g, "")
264          ) || 0.0;
265
266        const quantity =
267          parseInt(
268            item
269              .querySelector(".product-name h6")
270              ?.innerText.replace(/[^\d]/g, ""),
271            10
272          ) || 1;
273        const itemId =
274          item.querySelector(".product-name input[type=hidden]")?.value ||
275          "Unknown";
276
277        return {
278          item_id: itemId,
279          item_name: itemName,
280          price: price,
281          quantity: quantity,
282        };
283      });
284
285      sessionStorage.setItem(
286        "checkoutData",
287        JSON.stringify({ currency: currencyCode, totalAmount, items })
288      );
289
290      pushToDataLayer("begin_checkout", {
291        currency: currencyCode,
292        value: totalAmount,
293        items: items,
294      });
295    }
296  }
297
298  /**
299   * Track "purchase" events after order confirmation.
300   */
301  function trackOrderConfirmed() {
302    if (window.location.pathname.includes("/thank-you/")) {
303      let transactionId =
304        document
305          .querySelector(".order-number")
306          ?.innerText.replace("Order #", "")
307          .trim() || "unknown_transaction";
308
309      let email =
310        document
311          .querySelector(
312            ".order-detail .details-wrapper:nth-of-type(1) .order-detail-desc"
313          )
314          ?.innerText.trim() || "unknown_email";
315
316      let phone =
317        document
318          .querySelector(
319            ".order-detail .details-wrapper:nth-of-type(2) .order-detail-desc"
320          )
321          ?.innerText.trim() || "unknown_phone";
322
323      let orderData = document.querySelector("#hidden_order_data");
324      let products = [];
325
326      if (orderData) {
327        let productIds = Array.from(
328          orderData.querySelectorAll("input[name='product_id[]']")
329        ).map((el) => el.value);
330        let productNames = Array.from(
331          orderData.querySelectorAll("input[name='product_name[]']")
332        ).map((el) => el.value);
333        let quantities = Array.from(
334          orderData.querySelectorAll("input[name='quantity[]']")
335        ).map((el) => parseInt(el.value) || 1);
336        let prices = Array.from(
337          orderData.querySelectorAll("input[name='price[]']")
338        ).map((el) => parseFloat(el.value) || 0);
339
340        productIds.forEach((id, index) => {
341          products.push({
342            item_id: id,
343            item_name: productNames[index] || "Unknown Product",
344            quantity: quantities[index],
345            price: prices[index],
346          });
347        });
348      }
349
350      let orderTotal =
351        parseFloat(
352          orderData?.querySelector("input[name='order_total']")?.value
353        ) || 0;
354      let shippingTotal =
355        parseFloat(
356          orderData?.querySelector("input[name='shipping_total']")?.value
357        ) || 0;
358
359      window.dataLayer = window.dataLayer || [];
360      window.dataLayer.push({
361        event: "purchase",
362        ecommerce: {
363          transaction_id: transactionId,
364          currency: "INR",
365          value: orderTotal + shippingTotal, // Total order value including shipping
366          shipping: shippingTotal,
367          items: products,
368        },
369        customer_info: {
370          email: email,
371          phone: phone,
372        },
373      });
374    }
375  }
376
377  /**
378   * Track "view_cart" events when the cart is viewed.
379   */
380  document.addEventListener("click", function (e) {
381    if (e.target.closest(".elementor-menu-cart__toggle_button")) {
382      const cartItems = document.querySelectorAll(
383        ".widget_shopping_cart_content .cart-products-wrapper ul li .line-item-container"
384      );
385      const totalPriceElement = document.querySelector(
386        ".total-wrapper .order-total td strong bdi"
387      );
388      const totalAmount =
389        parseFloat(totalPriceElement?.innerText.replace(/[^\d.-]/g, "")) || 0;
390
391      const items = [];
392      const itemMap = {}; // Object to track unique items by name
393
394      cartItems.forEach((item) => {
395        const itemName =
396          item.querySelector(".item-second-col a")?.innerText.trim() ||
397          "Unknown Product";
398
399        const price =
400          parseFloat(
401            item
402              .querySelector(".item-last-col .item-price")
403              ?.innerText.replace(/[^\d.-]/g, "")
404          ) || 0.0;
405        const quantity =
406          parseInt(
407            item.querySelector(".main_show_qty")?.value.replace(/[^\d]/g, ""),
408            10
409          ) || 1;
410
411        // Fetch the item ID from the <a> tag (data-product_id attribute)
412        const itemId =
413          item
414            .querySelector(".mini-c-close a")
415            ?.getAttribute("data-product_id") || "Unknown ID";
416
417        // Check if the item already exists in the map
418        if (itemMap[itemName]) {
419        } else {
420          itemMap[itemName] = {
421            item_id: itemId,
422            item_name: itemName,
423            price: price,
424            quantity: quantity,
425          };
426        }
427      });
428
429      // Convert the itemMap values to an array
430      const uniqueItems = Object.values(itemMap);
431
432      pushToDataLayer("view_cart", {
433        currency: currencyCode,
434        value: parseFloat(totalAmount.toFixed(2)),
435        items: uniqueItems,
436      });
437    }
438  });
439
440  // Add event listeners for tracking
441  document.addEventListener("click", trackAddToCart);
442  trackViewItem();
443  trackBeginCheckout();
444  trackOrderConfirmed();
445});

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.