PageSourceSearch

https://kebchi.fr/assets/js/kebchi-product-viewed.js?v=20260806l

js kebchi.fr collected 2026-09-25 07:57:40 UTC 6,398 bytes, 127 lines download raw bytes

1/**
2 * Klaviyo Viewed Product + Kebchi Tracker ViewContent auto pour /dons/*
3 *
4 * - Mappe l'URL courante vers un produit (urlProductMap statique).
5 * - Override les prix depuis BD (window._kebchi_dbPrices setté inline plus haut).
6 * - Lit le bouton "add-tree-btn" / "add-pack-btn" pour récupérer nom/prix dynamiques.
7 * - Fire Klaviyo "Viewed Product" + KebchiTracker.track('ViewContent') si prix valide.
8 *
9 * Dépendances (déjà chargées avant) :
10 *  - window._kebchi_dbPrices (inline dans header.php — bloc tracking pixels)
11 *  - window.KebchiTracker (chargé async via /tracking/js/kebchi-tracker.js)
12 */
13(function () {
14  // ⚠️ Ordre important : URLs plus spécifiques (mouton-afrique) AVANT les génériques (mouton).
15  //    'price' = fallback si BD indispo (override auto par window._kebchi_dbPrices si code matche).
16  var urlProductMap = {
17    '/dons/mouton-afrique'    : { id: 'mouton-afrique',     name: 'Mouton Afrique',        categories: ['Donation', 'Sacrifice', 'Afrique'], price: 139 },
18    '/dons/mouton-france'     : { id: 'mouton-france',      name: 'Mouton France',         categories: ['Donation', 'Sacrifice', 'France'],  price: 339 },
19    '/dons/arbre-fruitier'    : { id: 'arbre-fruitier',     name: 'Arbre Fruitier',        categories: ['Donation', 'Arbre'] },
20    '/dons/puits'             : { id: 'puits',              name: 'Puits',                 categories: ['Donation', 'Eau'],         price: 899 },
21    '/dons/colis-alimentaire' : { id: 'colis-alimentaire',  name: 'Colis Alimentaire',     categories: ['Donation', 'Alimentaire'], price: 19  },
22    '/dons/orphelins'         : { id: 'orphelins',          name: 'Orphelins',             categories: ['Donation', 'Orphelins'],   price: 39  },
23    '/dons/parrainage'        : { id: 'parrainage',         name: 'Parrainage',            categories: ['Donation', 'Abonnement'],  price: 39  },
24    '/dons/france'            : { id: 'don-france',         name: 'Don France',            categories: ['Donation', 'France'],      price: 309 },
25    '/dons/aqiqa'             : { id: 'aqiqa',              name: 'Aqiqa',                 categories: ['Donation', 'Aqiqa'],       price: 189 },
26    '/dons/mouton'            : { id: 'mouton',             name: 'Mouton (Sacrifice)',    categories: ['Donation', 'Sacrifice'],   price: 179 },
27    '/dons/afrique'           : { id: 'don-afrique',        name: 'Afrique',               categories: ['Donation', 'Afrique'],     price: 159 },
28    '/dons/abonnement'        : { id: 'abonnement',         name: 'Abonnement',            categories: ['Donation', 'Abonnement'] },
29    '/dons/iftar'             : { id: 'iftar',              name: 'Iftar',                 categories: ['Donation', 'Ramadan'] },
30    '/dons/ruche'             : { id: 'ruche',              name: 'Ruche',                 categories: ['Donation', 'Ruche'] },
31    '/dons/libre'             : { id: 'don-libre',          name: 'Don Libre',             categories: ['Donation'] },
32    '/ramadan'                : { id: 'ramadan',            name: 'Ramadan',               categories: ['Donation', 'Ramadan'] },
33  };
34
35  // Override prices depuis BD (table produits) — essaie 3 stratégies :
36  //   1. Match exact sur code (ex: mouton_afrique → 139€)
37  //   2. Snake_case du kebab (ex: don-libre → don_libre)
38  //   3. Premier segment = categorie BD (ex: colis-alimentaire → colis → 19€, arbre-fruitier → arbre → 16€)
39  var dbPrices = window._kebchi_dbPrices || {};
40  Object.keys(urlProductMap).forEach(function (k) {
41    var item = urlProductMap[k];
42    var dbPrice = dbPrices[item.id]
43      || dbPrices[item.id.replace(/-/g, '_')]
44      || dbPrices[item.id.split('-')[0]];
45    if (dbPrice && dbPrice > 0) item.price = dbPrice;
46  });
47
48  function getBaseProduct() {
49    var path = window.location.pathname;
50    for (var fragment in urlProductMap) {
51      if (path.indexOf(fragment) === 0) return urlProductMap[fragment];
52    }
53    return null;
54  }
55
56  function getPageProduct() {
57    var btn = document.querySelector('.add-tree-btn, .add-pack-btn');
58    if (!btn || !btn.dataset.item) return null;
59    try {
60      var item = JSON.parse(btn.dataset.item);
61      if (item.id && item.nom && item.prix) return item;
62    } catch (e) {}
63    return null;
64  }
65
66  function fireViewedProduct() {
67    var base = getBaseProduct();
68    if (!base) return;
69    var page = getPageProduct();
70    var price = (page && page.prix) || base.price || 0;
71
72    // Skip ViewContent si pas de prix valide : evite de polluer TikTok/Meta
73    // avec des events "value: undefined" (warning TikTok 38% events affected).
74    // Ces pages restent trackees via PageView (qui n'attend pas de value).
75    if (!price || price <= 0) return;
76
77    // Klaviyo — Viewed Product
78    var _learnq = window._learnq || [];
79    _learnq.push(['track', 'Viewed Product', {
80      'ProductName': page ? page.nom : base.name,
81      'ProductID': base.id,
82      'Categories': base.categories,
83      'URL': window.location.href,
84      'ImageURL': page ? (page.image_url || '') : '',
85      'Price': price,
86    }]);
87
88    // Kebchi Tracker — ViewContent (fan-out Meta/TikTok/Snap)
89    if (window.__kebchi_vc_fired) return;
90    (function waitTracker(retry) {
91      if (!window.KebchiTracker) {
92        if ((retry || 0) < 30) return setTimeout(function () { waitTracker((retry || 0) + 1); }, 200);
93        return;
94      }
95      if (window.__kebchi_vc_fired) return;
96      window.__kebchi_vc_fired = true;
97      var payload = {
98        content_ids: [base.id],
99        content_name: page ? page.nom : base.name,
100        content_type: 'donation',
101        content_category: (base.categories && base.categories[1]) ? base.categories[1].toLowerCase() : 'donation',
102        currency: 'EUR'
103      };
104      if (price && price > 0) payload.value = price;
105      window.KebchiTracker.track('ViewContent', payload);
106    })(0);
107  }
108
109  function tryFire(attempt) {
110    var page = getPageProduct();
111    if (page || attempt >= 5) {
112      fireViewedProduct();
113    } else {
114      setTimeout(function () { tryFire(attempt + 1); }, 400);
115    }
116  }
117
118  if (document.readyState === 'loading') {
119    document.addEventListener('DOMContentLoaded', function () { tryFire(0); });
120  } else {
121    tryFire(0);
122  }
123})();
124
125// Marqueur pour sanity check (voir bas de header.php)
126window.__kebchi_loaded = window.__kebchi_loaded || {};
127window.__kebchi_loaded.productViewed = true;

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.