1window.addEventListener("DOMContentLoaded", startup, false); 2 3let visibleAds = new Set(); 4let previouslyVisibleAds = null; 5 6let adObserver; 7let refreshIntervalID = 0; 8 9var rounded = function(number){ 10 return +number.toFixed(2); 11} 12 13function startup() { 14 document.addEventListener("visibilitychange", handleVisibilityChange, false); 15 16 let observerOptions = { 17 root: null, 18 rootMargin: "0px", 19 threshold: buildThresholdList(), // бÑло [0.0, 0.75] 20 }; 21 22 adObserver = new IntersectionObserver(intersectionCallback, observerOptions); 23 24 const analyticsBlocks = document.querySelectorAll("[data-analytics-block]"); 25 26 var params = {}; 27 params["structure"] = []; 28 var index = 0; 29 analyticsBlocks.forEach((block) => { 30 adObserver.observe(block); 31 index++; 32 params["structure"].push(block.dataset.analyticsBlock + " " + index); 33 }); 34 trackEvent('page_structure', params); 35 36 refreshIntervalID = window.setInterval(handleRefreshInterval, 300); 37} 38 39// ÑÑÐ¾Ð±Ñ Ð»Ð¾Ð²Ð¸ÑÑ Ð¸Ð·Ð¼ÐµÐ½ÐµÐ½Ð¸Ðµ видимоÑÑи и доли ÑкÑана 40function buildThresholdList() { 41 const thresholds = []; 42 for (let i = 0; i <= 100; i++) thresholds.push(i / 100); 43 return thresholds; 44} 45 46// какÑÑ Ð´Ð¾Ð»Ñ ÑкÑана Ð·Ð°Ð½Ð¸Ð¼Ð°ÐµÑ Ð²Ð¸Ð´Ð¸Ð¼Ð°Ñ ÑаÑÑÑ Ð±Ð»Ð¾ÐºÐ° 47function getViewportOccupancy(entry) { 48 const iRect = entry.intersectionRect; 49 if (!iRect) return 0; 50 const intersectArea = Math.max(0, iRect.width) * Math.max(0, iRect.height); 51 const rootRect = entry.rootBounds; 52 const viewportArea = rootRect ? rootRect.width * rootRect.height : window.innerWidth * window.innerHeight; 53 return viewportArea > 0 ? intersectArea / viewportArea : 0; 54} 55 56 57function handleVisibilityChange() { 58 if (document.hidden) { 59 if (!previouslyVisibleAds) { 60 previouslyVisibleAds = new Set(visibleAds); 61 visibleAds = new Set(); 62 previouslyVisibleAds.forEach(function (adBox) { 63 updateAdTimer(adBox); 64 adBox.dataset.lastViewStarted = 0; 65 }); 66 } 67 } else if (previouslyVisibleAds) { 68 previouslyVisibleAds.forEach(function (adBox) { 69 adBox.dataset.lastViewStarted = performance.now(); 70 }); 71 visibleAds = previouslyVisibleAds; 72 previouslyVisibleAds = null; 73 } 74} 75 76 77/*function intersectionCallback(entries) { 78 entries.forEach(function (entry) { 79 let adBox = entry.target; 80 81 if (entry.isIntersecting) { 82 if (entry.intersectionRatio >= 0.75) { 83 adBox.dataset.lastViewStarted = entry.time; 84 visibleAds.add(adBox); 85 adBox.dataset.analyticsBlocksend = "N"; 86 } 87 } else { 88 visibleAds.delete(adBox); 89 if(adBox.dataset.formStart == 'Y'){ 90 adBox.dataset.formStart = 'N'; 91 const elementWithAnalytics = adBox.querySelector('[data-analytics-element]'); 92 const params = { 93 block_id: adBox.dataset.analyticsBlock, 94 element_id: elementWithAnalytics.dataset.analyticsElement, 95 last_view_started: rounded(adBox.dataset.lastViewStarted/1000), 96 request_from: adBox.dataset.requestFrom, 97 value: rounded(adBox.dataset.totalViewTime/1000), 98 }; 99 if (adBox.dataset.analyticsElement) { 100 params.element_id = adBox.dataset.analyticsElement; 101 } 102 trackEvent('form_end_view', params); 103 } 104 if (adBox.dataset.totalViewTime >= 1000) { 105 adBox.dataset.analyticsBlocksend = "Y"; 106 } 107 } 108 }); 109}*/ 110 111function intersectionCallback(entries) { 112 entries.forEach(function (entry) { 113 const adBox = entry.target; 114 115 const occupiesViewport = getViewportOccupancy(entry) >= 0.70; 116 const enoughVisible = entry.intersectionRatio >= 0.75 || occupiesViewport; 117 118 if (entry.isIntersecting && enoughVisible) { 119 if (!visibleAds.has(adBox)) { // важно: не пеÑеÑÑÑанавливаÑÑ ÑÑаÑÑ, еÑли Ñже ÑÑиÑаем 120 adBox.dataset.lastViewStarted = entry.time; 121 visibleAds.add(adBox); 122 adBox.dataset.analyticsBlocksend = "N"; 123 } 124 } else if (!entry.isIntersecting) { 125 // как бÑло 126 visibleAds.delete(adBox); 127 if (adBox.dataset.formStart == 'Y') { 128 adBox.dataset.formStart = 'N'; 129 const elementWithAnalytics = adBox.querySelector('[data-analytics-element]'); 130 const params = { 131 block_id: adBox.dataset.analyticsBlock, 132 element_id: elementWithAnalytics?.dataset.analyticsElement, 133 last_view_started: rounded(adBox.dataset.lastViewStarted/1000), 134 request_from: adBox.dataset.requestFrom, 135 value: rounded(adBox.dataset.totalViewTime/1000), 136 }; 137 if (adBox.dataset.analyticsElement) params.element_id = adBox.dataset.analyticsElement; 138 trackEvent('form_end_view', params); 139 } 140 if (adBox.dataset.totalViewTime >= 1000) { 141 adBox.dataset.analyticsBlocksend = "Y"; 142 } 143 } 144 }); 145} 146 147
148function handleRefreshInterval() { 149 let redrawList = []; 150 151 visibleAds.forEach(function (adBox) { 152 let previousTime = adBox.dataset.totalViewTime; 153 updateAdTimer(adBox); 154 155 if (previousTime != adBox.dataset.totalViewTime) { 156 redrawList.push(adBox); 157 } 158 }); 159 160 if (redrawList.length) { 161 window.requestAnimationFrame(function (time) { 162 redrawList.forEach(function (adBox) { 163 if (adBox.dataset.totalViewTime >= 1000 && adBox.dataset.analyticsBlocksend != "Y") { 164 const params = { 165 block_id: adBox.dataset.analyticsBlock, 166 last_view_started: rounded(adBox.dataset.lastViewStarted/1000), 167 request_from: adBox.dataset.requestFrom, 168 value: rounded(adBox.dataset.totalViewTime/1000), 169 }; 170 if (adBox.dataset.analyticsElement) { 171 params.element_id = adBox.dataset.analyticsElement; 172 } 173 trackEvent('block_view', params); 174 adBox.dataset.analyticsBlocksend = "Y"; 175 } 176 }); 177 }); 178 } 179} 180 181function updateAdTimer(adBox) { 182 let lastStarted = adBox.dataset.lastViewStarted; 183 let currentTime = performance.now(); 184 185 if (lastStarted) { 186 let diff = currentTime - lastStarted; 187 188 adBox.dataset.totalViewTime = (adBox.dataset.totalViewTime ? parseFloat(adBox.dataset.totalViewTime) : 0) + diff; 189 } 190 191 adBox.dataset.lastViewStarted = currentTime; 192} 193 194function trackEvent(eventName, params) { 195 196 // ÐÑоÑÑо вÑводим в конÑÐ¾Ð»Ñ Ð´Ð»Ñ Ð´ÐµÐ¼Ð¾Ð½ÑÑÑаÑии 197 console.log(`Tracking event: ${eventName}`, params); 198 ym(49308325, 'reachGoal', eventName, params); 199} 200 201 202function trackVisibleAnalyticsElements() { 203 const observer = new IntersectionObserver( 204 (entries) => { 205 entries.forEach((entry) => { 206 if (entry.isIntersecting) { 207 // ÐÐ»ÐµÐ¼ÐµÐ½Ñ Ð²Ð¸Ð´Ð¸Ð¼ 208 const element = entry.target; 209 if (!element.dataset.analyticsFired) { // ÐÑовеÑÑем, не ÑÑабоÑало ли ÑобÑÑие Ñже 210 let startTime = null; 211 212 // ФÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¾ÑÑÐ»ÐµÐ¶Ð¸Ð²Ð°Ð½Ð¸Ñ Ð²Ñемени видимоÑÑи 213 function trackVisibilityTime(timestamp) { 214 if (!startTime) startTime = timestamp; 215 const progress = timestamp - startTime; 216 217 if (entry.isIntersecting) { 218 // ÐÐ»ÐµÐ¼ÐµÐ½Ñ Ð²Ñе еÑе видим, пÑодолжаем оÑÑлеживаÑÑ 219 element.dataset.visibleTimer = progress; 220 element.dataset.visibleTimerNew = entry.time; 221 requestAnimationFrame(trackVisibilityTime); 222 } else { 223 // ÐÐ»ÐµÐ¼ÐµÐ½Ñ Ð±Ð¾Ð»ÑÑе не видим, ÑбÑаÑÑваем ÑÐ°Ð¹Ð¼ÐµÑ 224 startTime = null; 225 } 226 } 227 228 // ÐаÑинаем оÑÑлеживание вÑемени видимоÑÑи 229 requestAnimationFrame(trackVisibilityTime); 230 } 231 } 232 }); 233 }, 234 { 235 threshold: 0.5 // ÐÐ»ÐµÐ¼ÐµÐ½Ñ Ð´Ð¾Ð»Ð¶ÐµÐ½ бÑÑÑ Ð²Ð¸Ð´Ð¸Ð¼ Ñ Ð¾ÑÑ Ð±Ñ Ð½Ð° 50% 236 } 237 ); 238 239 const analyticsElements = document.querySelectorAll("[data-analytics-element]"); 240 241 analyticsElements.forEach((block) => { 242 observer.observe(block); 243 }); 244} 245 246// ÐапÑÑкаем оÑÑлеживание поÑле загÑÑзки ÑÑÑаниÑÑ 247document.addEventListener("DOMContentLoaded", trackVisibleAnalyticsElements); 248 249 250document.addEventListener("DOMContentLoaded", function(){ 251 document.addEventListener('click', (event) => { 252 // ÐÐ°Ñ Ð¾Ð´Ð¸Ð¼ ближайÑий ÑодиÑелÑÑкий ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ñ Ð°ÑÑибÑÑом data-analytics-element 253 const targetElement = event.target.closest('[data-analytics-element]'); 254 255 // ÐÑли ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ñ data-analytics-element не найден, вÑÑ Ð¾Ð´Ð¸Ð¼ из ÑÑнкÑии 256 if (!targetElement) { 257 return; 258 } 259 const blockElement = targetElement.closest('[data-analytics-block]'); 260 261 if(targetElement.dataset.analyticsType == "form") { 262 const isInput = event.target.closest('input'); 263 if (!isInput) { 264 return; 265 } 266 if (isInput.type == 'submit') { 267 const block_id = blockElement ? blockElement.dataset.analyticsBlock || '' : ''; // Ðазвание блока в коÑоÑом Ð»ÐµÐ¶Ð¸Ñ ÑÐ»ÐµÐ¼ÐµÐ½Ñ 268 const element_id = targetElement.dataset.analyticsElement || ''; // Ðазвание ÑлеменÑа 269 const element_type = targetElement.dataset.analyticsType || ''; // Тип ÑлеменÑа 270 const css_selector = getCssSelector(isInput); // ФÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ CSS-ÑелекÑоÑа 271 const visibilityTime = rounded(targetElement.dataset.visibleTimer/1000); // ÑколÑко полÑзоваÑÐµÐ»Ñ ÑмоÑÑел на ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿Ñежде Ñем кликнÑÑÑ 272 const visibilityTimeNew = rounded(targetElement.dataset.visibleTimerNew/1000); // ÑколÑко пÑоÑло вÑемени Ð¾Ñ Ð·Ð°Ð³ÑÑзки ÑÑÑаниÑÑ Ð´Ð¾ Ð
272ºÐ»Ð¸ÐºÐ° 273 274 const eventParams = { 275 block_id: block_id, 276 element_id: element_id, 277 element_type: element_type, 278 css_selector: css_selector, 279 last_view_started: visibilityTimeNew, 280 value: visibilityTime, 281 }; 282 // ÐÑзÑваем ÑÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¾ÑпÑавки даннÑÑ Ð°Ð½Ð°Ð»Ð¸Ñики 283 trackEvent('form_try_submit', eventParams); 284 } 285 else { 286 const block_id = blockElement ? blockElement.dataset.analyticsBlock || '' : ''; // Ðазвание блока в коÑоÑом Ð»ÐµÐ¶Ð¸Ñ ÑÐ»ÐµÐ¼ÐµÐ½Ñ 287 const element_id = targetElement.dataset.analyticsElement || ''; // Ðазвание ÑлеменÑа 288 const element_type = targetElement.dataset.analyticsType || ''; // Тип ÑлеменÑа 289 const input_name = isInput.name || ''; // название инпÑÑа 290 const css_selector = getCssSelector(isInput); // ФÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ CSS-ÑелекÑоÑа 291 const visibilityTime = rounded(targetElement.dataset.visibleTimer/1000); // ÑколÑко полÑзоваÑÐµÐ»Ñ ÑмоÑÑел на ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿Ñежде Ñем кликнÑÑÑ 292 const visibilityTimeNew = rounded(targetElement.dataset.visibleTimerNew/1000); // ÑколÑко пÑоÑло вÑемени Ð¾Ñ Ð·Ð°Ð³ÑÑзки ÑÑÑаниÑÑ Ð´Ð¾ клика 293 294 const eventParams = { 295 block_id: block_id, 296 element_id: element_id, 297 element_type: element_type, 298 element_text: input_name, 299 css_selector: css_selector, 300 last_view_started: visibilityTimeNew, 301 value: visibilityTime, 302 }; 303 304 if(blockElement.dataset.formStart =='Y'){ 305 trackEvent('input_click', eventParams); 306 } 307 else { 308 blockElement.dataset.formStart = 'Y'; 309 trackEvent('form_start', eventParams); 310 } 311 } 312 } 313 else { 314 315 // ÐолÑÑаем знаÑÐµÐ½Ð¸Ñ Ð°ÑÑибÑÑов data-analytics-* 316 const block_id = blockElement ? blockElement.dataset.analyticsBlock || '' : ''; // Ðазвание блока в коÑоÑом Ð»ÐµÐ¶Ð¸Ñ ÑÐ»ÐµÐ¼ÐµÐ½Ñ 317 const element_id = targetElement.dataset.analyticsElement || ''; // Ðазвание ÑлеменÑа 318 const element_type = targetElement.dataset.analyticsType || ''; // Тип ÑлеменÑа 319 const element_text = targetElement.textContent.trim() || ''; // ТекÑÑ ÑлеменÑа 320 const css_selector = getCssSelector(targetElement); // ФÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ CSS-ÑелекÑоÑа 321 const visibilityTime = rounded(targetElement.dataset.visibleTimer/1000); // ÑколÑко полÑзоваÑÐµÐ»Ñ ÑмоÑÑел на ÑÐ»ÐµÐ¼ÐµÐ½Ñ Ð¿Ñежде Ñем кликнÑÑÑ 322 const visibilityTimeNew = rounded(targetElement.dataset.visibleTimerNew/1000); // ÑколÑко пÑоÑло вÑемени Ð¾Ñ Ð·Ð°Ð³ÑÑзки ÑÑÑаниÑÑ Ð´Ð¾ клика 323 324 if (targetElement.dataset.target) { 325 document.querySelector(targetElement.dataset.target).dataset.requestFrom = block_id; 326 } 327 328 // ФоÑмиÑÑем обÑÐµÐºÑ Ñ Ð¿Ð°ÑамеÑÑами 329 const eventParams = { 330 block_id: block_id, 331 element_id: element_id, 332 element_type: element_type, 333 element_text: element_text, 334 css_selector: css_selector, 335 last_view_started: visibilityTimeNew, 336 value: visibilityTime, 337 }; 338 339 // ÐÑзÑваем ÑÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¾ÑпÑавки даннÑÑ Ð°Ð½Ð°Ð»Ð¸Ñики 340 trackEvent('element_click', eventParams); 341 342 // ÐÑладоÑнÑй вÑвод в конÑÐ¾Ð»Ñ 343 } 344 345 }); 346 347 // ФÑнкÑÐ¸Ñ Ð´Ð»Ñ Ð¿Ð¾Ð»ÑÑÐµÐ½Ð¸Ñ CSS-ÑелекÑоÑа ÑлеменÑа (пÑÐ¸Ð¼ÐµÑ ÑеализаÑии) 348 function getCssSelector(element) { 349 let selector = element.tagName.toLowerCase(); 350 351 if (element.id) { 352 selector += `#${element.id}`; 353 } else if (element.className) { 354 selector += `.${element.className.split(' ').join('.')}`; 355 } 356 357 return selector; // ÐÑоÑÑой ÑелекÑоÑ, можно ÑÑовеÑÑенÑÑвоваÑÑ 358 } 359});
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.