1/** 2 * HotelBox Booking Bridge â URL enrichment for booking engine links. 3 * 4 * Attribution (utm params, gclid, fbclid) is captured on landing and persisted in a 5 * first-party cookie (first-touch wins). When the visitor later clicks a link to 6 * the booking engine, the params are forwarded from the cookie â not only from the 7 * current URL â so campaign data survives internal navigation between landing and 8 * the "Book" click, and crosses over to the booking-engine domain via the URL. 9 */ 10(function() { 11 'use strict'; 12 13 var config = window.hbBridge || {}; 14 15 // ÐаÑÑÑоениÑÑ Ð´Ð¾Ð¼ÐµÐ¹Ð½ на ÑезеÑваÑионнаÑа ÑиÑÑема, ако админиÑÑÑаÑоÑÑÑ Ð³Ð¾ е попÑлнил. 16 // ÐÑазно = не е попÑлнен; ÐРпада на 'booking.hotelbox.bg' какÑо пÑеди. 17 // 18 // ÐаÑо: ÑÑаÑаÑа ÑезеÑвна ÑÑойноÑÑ Ð½Ðµ ÑÑвпадаÑе Ñ Ð½Ð¸Ñо един Ñеален Ñ Ð¾ÑелÑки домейн, а 19 // пÑовеÑкаÑа по-Ð´Ð¾Ð»Ñ Ð¸Ð·Ð»Ð¸Ð·Ð° пÑи неÑÑвпадение â ÑоеÑÑ Ð½Ð° вÑеки ÑÐ°Ð¹Ñ Ð±ÐµÐ· ÑÑÑно попÑлнена 20 // наÑÑÑойка моÑÑÑÑ Ð¼ÑлÑаливо не пÑавеÑе ниÑо. ÐзмеÑено на пÑода: utm доÑÑигаÑе до 13 Ð¾Ñ 21 // 2743 beacon-а, а hb_sid до ниÑо един. ÐаÑова пÑи липÑваÑа наÑÑÑойка Ñега Ñазпознаваме 22 // ÑезеÑваÑÐ¸Ð¾Ð½Ð½Ð¸Ñ Ð¿Ð¾Ð´Ð´Ð¾Ð¼ÐµÐ¹Ð½ на ÑÐ°Ð¼Ð¸Ñ ÑайÑ. 23 var beDomain = (config.beDomain || '').trim(); 24 25 // ÐомейнÑÑ Ð½Ð° ÑекÑÑÐ¸Ñ ÑÐ°Ð¹Ñ Ð±ÐµÐ· водеÑоÑо www â оÑноваÑа, ÑпÑÑмо коÑÑо Ñе познава 26 // ÑезеÑваÑионниÑÑ Ð¿Ð¾Ð´Ð´Ð¾Ð¼ÐµÐ¹Ð½. 27 var siteHost = window.location.hostname.replace(/^www\./, '').toLowerCase(); 28 29 /** 30 * ÐомейниÑе на ÑезеÑваÑионниÑе ÑиÑÑеми, коиÑо обÑлÑÐ¶Ð²Ð°Ñ Ñ Ð¾ÑелиÑе. 31 * 32 * ÐеÑено на пÑода на 26.08.2026: Ð¾Ñ 18-Ñе доÑÑÑпни ÑайÑа Ñ booking engine 33 * ÐСÐЧÐÐТР18 водÑÑ ÐºÑм booking.quendoo.com, а ниÑо един â кÑм book.<домейн>. 34 * ÐоÑÑк моÑÑÑÑ ÑÑÑÑеÑе ÑоÑно обÑаÑноÑо и заÑова не обогаÑÑваÑе ниÑо: за 35 * ÑедмиÑа до ÑезеÑваÑионнаÑа ÑиÑÑема ÑÑÐ¸Ð³Ð½Ð°Ñ Ð° 6 utm еÑикеÑа Ð¾Ñ 223 ÑезеÑваÑии, 36 * а fbclid â нÑла, пÑи 38 000 ÑеÑии Ñ utm Ð¾Ñ Meta на ÑамиÑе ÑайÑове. 37 * 38 * ЧÑждиÑÑ Ð´Ð¾Ð¼ÐµÐ¹Ð½ знаÑи и Ñе биÑквиÑкаÑа не помага: ÑÑ Ð¶Ð¸Ð²ÐµÐµ на домейна на 39 * Ñ Ð¾Ñела и booking.quendoo.com не Ñ Ð²Ð¸Ð¶Ð´Ð°. ÐдÑеÑÑÑ Ð½Ð° вÑÑзкаÑа е единÑÑвениÑÑ 40 * наÑин еÑикеÑÑÑ Ð´Ð° пÑемине. 41 */ 42 var BE_PROVIDERS = ['quendoo.com', 'bookonlinenow.com', 'booking.hotelbox.bg']; 43 44 function isProviderHost(host) { 45 for (var i = 0; i < BE_PROVIDERS.length; i++) { 46 var p = BE_PROVIDERS[i]; 47 if (host === p || host.slice(-(p.length + 1)) === '.' + p) return true; 48 } 49 return false; 50 } 51 52 /** 53 * Ðоди ли вÑÑзкаÑа кÑм ÑезеÑваÑионнаÑа ÑиÑÑема. 54 * 55 * ТÑиÑе пÑавила Ñа Ð ÐÐÐÐСТÐÐÐÐ, не подÑедени Ñ Ð¸Ð·Ð»Ð¸Ð·Ð°Ð½Ðµ пÑи пÑÑвоÑо: доÑкоÑо 56 * попÑлненаÑа наÑÑÑойка пÑекÑаÑÑваÑе пÑовеÑкаÑа и ÑÐ°Ð¹Ñ Ñ Ð²Ñведен 57 * âbook.<домейн>â оÑÑ Ð²ÑÑлÑÑе иÑÑинÑкаÑа Ñи вÑÑзка кÑм Quendoo. ТоÑно Ñова 58 * обезÑили моÑÑа навÑÑкÑде, кÑдеÑо домейнÑÑ Ð±ÐµÑе попÑлнен. 59 * 60 * ÐÑавилоÑо за поддомейн ÑÑавнÑва ЦЯÐÐТРпÑÑва еÑикеÑна ÑаÑÑ, не подниз: 61 * `facebook.com` ÑÑдÑÑжа âbook.â и пÑи ÑÑавнение по подниз би минал за 62 * ÑезеÑваÑионна вÑÑзка. 63 */ 64 function isBookingHost(hostname) { 65 var host = (hostname || '').toLowerCase().replace(/^www\./, ''); 66 67 if (isProviderHost(host)) return true; 68 69 if (beDomain && host.indexOf(beDomain.toLowerCase().replace(/^www\./, '')) !== -1) return true; 70 71 var dot = host.indexOf('.'); 72 if (dot === -1) return false;
73 74 var label = host.slice(0, dot); 75 var rest = host.slice(dot + 1); 76 77 return (label === 'book' || label === 'booking') && rest === siteHost; 78 } 79 80 // utm_* + click IDs (gclid = Google Ads, fbclid = Meta). 81 var ATTR_KEYS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'gclid', 'fbclid']; 82 var COOKIE = 'hb_attr'; 83 var MAX_AGE = 2592000; // 30 дни 84 85 function readStore() { 86 try { 87 var m = document.cookie.match(/(^| )hb_attr=([^;]+)/); 88 if (m) return JSON.parse(decodeURIComponent(m[2])) || {}; 89 } catch(e) {} 90 return {}; 91 } 92 93 // Host-only cookie (какÑо hb_sid) â оÑелÑва вÑÑÑеÑнаÑа навигаÑÐ¸Ñ Ð½Ð° ÑайÑа. 94 function writeStore(obj) { 95 try { 96 document.cookie = COOKIE + '=' + encodeURIComponent(JSON.stringify(obj)) + 97 ';path=/;max-age=' + MAX_AGE + ';SameSite=Lax'; 98 } catch(e) {} 99 } 100 101 // First-touch: запиÑи attribution пÑи каÑане, без да пÑезапиÑÐ²Ð°Ñ Ð²ÐµÑе Ñловена ÑÑойноÑÑ. 102 function captureAttribution() { 103 var params = new URLSearchParams(window.location.search); 104 var store = readStore(); 105 var changed = false; 106 107 ATTR_KEYS.forEach(function(key) { 108 var value = params.get(key); 109 if (value && !store[key]) { 110 store[key] = value; 111 changed = true; 112 } 113 }); 114 115 if (changed) writeStore(store); 116 return store; 117 } 118 119 var attribution = captureAttribution(); 120 121 document.addEventListener('click', function(e) { 122 var link = e.target.closest('a[href]'); 123 if (!link) return; 124 125 var href = link.getAttribute('href') || ''; 126 127 // Check if link points to booking engine. 128 try { 129 var url = new URL(href, window.location.origin); 130 if (!isBookingHost(url.hostname)) return; 131 // ÐÑÑзка кÑм ÑÐ°Ð¼Ð¸Ñ ÑÐ°Ð¹Ñ Ð½Ðµ Ñе обогаÑÑва â инаÑе вÑÑÑеÑнаÑа навигаÑÐ¸Ñ Ð½Ð° ÑайÑ, 132 // койÑо Ñам живее на book.<домейн>, би ÑÑÑпала пÑоÑледÑваÑи паÑамеÑÑи. 133 if (url.hostname.toLowerCase() === window.location.hostname.toLowerCase()) return; 134 135 // Enrich URL with tracking parameters. 136 url.searchParams.set('hb_sid', window.hb_sid || ''); 137 url.searchParams.set('hb_cid', window.hb_cid || ''); 138 url.searchParams.set('hb_vid', window.hb_vid || ''); 139 url.searchParams.set('hb_ref', window.location.pathname); 140 url.searchParams.set('hb_hotel', config.hotelId || ''); 141 142 // Forward attribution Ð¾Ñ cookie-Ñо (first-touch), Ñ fallback кÑм ÑекÑÑÐ¸Ñ URL. 143 // ÐокÑива ÑлÑÑаÑ, в койÑо поÑÑебиÑелÑÑ ÐºÐ°Ñа Ñ ?utm на една ÑÑÑаниÑа и ÑÑка 144 // âРезеÑвиÑай" нÑколко ÑÑÑаниÑи по-кÑÑно (UTM веÑе го нÑма в URL-а). 145 var current = new URLSearchParams(window.location.search); 146 ATTR_KEYS.forEach(function(key) { 147 var value = attribution[key] || current.get(key) || ''; 148 if (value) { 149 url.searchParams.set(key, value); 150 } 151 }); 152 153 link.setAttribute('href', url.toString()); 154 } catch(ex) { 155 // Invalid URL, ignore. 156 } 157 }, true); 158})();
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.