if(false || !!document.documentMode){}else{ var MAINORIGINSITEURL = location.origin; var MAINPLERDYURL = "https://a.plerdy.com/"; var mainScriptPlerdy = document.querySelector('[src*="public/js/click/main.js"]'); var mainScriptPlerdy_host, mainScriptPlerdy_host_tracker; if(mainScriptPlerdy){ try{ let mainScriptPlerdy_url = new URL(mainScriptPlerdy.src); if(mainScriptPlerdy_url.host){ mainScriptPlerdy_host = mainScriptPlerdy_url.host; }else{ mainScriptPlerdy_host = "a.plerdy.com"; } }catch(err){ mainScriptPlerdy_host = "a.plerdy.com"; } }else{ mainScriptPlerdy_host = "a.plerdy.com"; } if(mainScriptPlerdy_host == 'a.plerdy.com'){ mainScriptPlerdy_host_tracker = 'https://a.plerdy.com'; mainScriptPlerdy_host = "https://" + mainScriptPlerdy_host; if(typeof _suid !== 'undefined' && (_suid == 37113 || _suid*1 >= 95000)){ mainScriptPlerdy_host_tracker = 'https://f.plerdy.com'; } }else if(mainScriptPlerdy_host == 'test.plerdy.com'){ mainScriptPlerdy_host_tracker = 'https://test.plerdy.com'; mainScriptPlerdy_host = "https://" + mainScriptPlerdy_host; }else if(mainScriptPlerdy_host == 'd.plerdy.com'){ mainScriptPlerdy_host_tracker = 'https://d.plerdy.com'; mainScriptPlerdy_host = "https://" + mainScriptPlerdy_host; }else if(mainScriptPlerdy_host == 'plerdy.loc'){ mainScriptPlerdy_host_tracker = 'http://plerdy.loc'; mainScriptPlerdy_host = "http://" + mainScriptPlerdy_host; }else{ mainScriptPlerdy_host_tracker = 'https://tracker.plerdy.com'; mainScriptPlerdy_host = "https://" + mainScriptPlerdy_host; } var plerdy_config = { plerdy_url0 : mainScriptPlerdy_host+"/", plerdy_url_live : mainScriptPlerdy_host+"/", plerdy_url_save : mainScriptPlerdy_host_tracker+"/click/", plerdy_url_save_test : mainScriptPlerdy_host_tracker+"/click_test/" }; if (!Array.prototype.forEach) { Array.prototype.forEach = function(fn, scope) { for(var i = 0, len = this.length; i < len; ++i) { fn.call(scope, this[i], i, this); } } } if (window.NodeList && !NodeList.prototype.forEach) { NodeList.prototype.forEach = Array.prototype.forEach; } var allowedOriginsForPostPlerdy = [ MAINPLERDYURL.slice(0, -1), mainScriptPlerdy_host_tracker, ];;(function() { // Список тегів, які потребують відстеження const trackedTags = [ 'a', 'button', 'input', 'img', 'label', 'select', 'textarea', 'svg', 'li', 'option', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'span', // Додаємо div та span до списку для обробки 'i' ]; // Модифікована хеш-функція, яка повертає 9-цифровий числовий хеш без провідних нулів function simpleHash(str) { let hash = 5381; for (let i = 0; i < str.length; i++) { hash = ((hash << 5) + hash) + str.charCodeAt(i); // hash * 33 + c } // Отримуємо позитивне число та беремо останні 9 цифр, забезпечуючи, що перша цифра не 0 const numericHash = (Math.abs(hash) % 900000000) + 100000000; // Перетворюємо число на рядок без провідних нулів return numericHash.toString(); } // Об'єкт для відстеження кількості використань кожного базового хешу const hashCountMap = {}; // WeakMap для зберігання відповідності між елементами та їх baseHash const elementBaseHashMap = new WeakMap(); // Функція для генерації унікального ID на основі властивостей елемента function generateTrackingId(element) { try { // Збираємо властивості елемента let tag = element.tagName.toLowerCase(); let id = element.id ? `#${element.id}` : ''; // Використовуємо getAttribute('class') замість element.className let classAttr = element.getAttribute('class'); let classes = classAttr ? `.${classAttr.trim().split(/\s+/).join('.')}` : ''; // Для SVG елементів, можливо, немає текстового контенту, тому безпечно використовувати textContent let text = element.textContent ? element.textContent.trim().replace(/\s+/g, ' ') : ''; // ІГНОРУЄМО data-* з цифрами у значенні let uniqueAttributes = Array.from(element.attributes) .filter(attr => { const name = attr.name.toLowerCase(); if (['class', 'id', 'plerdy-tracking-id'].includes(name)) return false; // якщо це data-* і у значенні є цифри — ігноруємо if (name.startsWith('data-') && /\d/.test(String(attr.value))) return false; if (name === 'onclick' && /\d/.test(String(name))) return false; return true; }) .map(attr => `[${attr.name}="${attr.value}"]`) .join(''); // Створюємо рядок для хешування let hashString = `${tag}${id}${classes}${uniqueAttributes}${text}`; // Генеруємо базовий хеш let baseHash = simpleHash(hashString); // Зберігаємо baseHash для елемента elementBaseHashMap.set(element, baseHash); // Перевіряємо, чи цей базовий хеш вже використовувався if (hashCountMap[baseHash]) { hashCountMap[baseHash]++; } else { hashCountMap[baseHash] = 1; } // Додаємо індекс до базового хешу для унікальності let uniqueHash = `${baseHash}${hashCountMap[baseHash].toString().padStart(2, '0')}`; //console.log(`Generated tracking ID: ${uniqueHash} for element:`, element); // Логування return uniqueHash; } catch (error) { //console.error('Error generating tracking ID:', error, element); return '000000000'; // Фолбек значення для 9 цифр } } function isClickable(element) { const tagName = element.tagName.toLowerCase(); const interactiveTags = [ 'a', 'button', 'input', 'img', 'label', 'select', 'textarea', 'svg', 'li', 'option', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'area' ]; if (interactiveTags.includes(tagName)) { return true; } const role = element.getAttribute('role'); const interactiveRoles = ['button', 'link', 'menuitem', 'checkbox', 'switch', 'tab', 'treeitem', 'option', 'radio']; if (role && interactiveRoles.includes(role)) { return true; } if (element.hasAttribute('onclick')) { return true; } if (element.hasAttribute('tabindex')) { return true; } if (element.isContentEditable) { return true; } if (element.getAttribute('draggable') === 'true') { return true; } if (element.hasAttribute('data-action') || element.hasAttribute('data-event')) { return true; } const computedStyle = window.getComputedStyle(element); if (computedStyle.cursor === 'pointer') { return true; } // Перевірка інших on* атрибутів const eventAttributes = Array.from(element.attributes).filter(attr => /^on\w+/i.test(attr.name)); if (eventAttributes.length > 0) { return true; } // Нова перевірка на клас "btn" if (element.classList && Array.from(element.classList).some(cls => cls.toLowerCase().includes('btn'))) { return true; } return false; } // Кеш для збереження вже згенерованих ID const trackingIdCache = new WeakMap(); // Функція для отримання або генерації ID function getOrGenerateId(element) { if (trackingIdCache.has(element)) { return trackingIdCache.get(element); } const trackingId = generateTrackingId(element); trackingIdCache.set(element, trackingId); return trackingId; } // Функція для встановлення унікального ID function setUniqueId(element) { const trackingId = getOrGenerateId(element); element.setAttribute('plerdy-tracking-id', trackingId); //console.log(`Set tracking ID ${trackingId} for element:`, element); // Логування return trackingId; } // Нова функція для перевірки умови не додавання атрибуту function shouldNotAddAttribute(element) { if (element.tagName.toLowerCase() !== 'div') { return false; } if (element.children.length <= 2) { return false; } // Перевіряємо, чи мають прямі діти своїх дітей for (let i = 0; i < element.children.length; i++) { if (element.children[i].children.length > 0) { return true; } } return false; } // Додаткова функція для ідентифікації попапів function isPopup(element) { // Приклад перевірки за класом або атрибутом, змініть відповідно до вашої реалізації return element.classList.contains('popup') || element.getAttribute('data-popup') === 'true'; } // Функція для додавання tracking-id function addTrackingId(element) { try { const tagName = element.tagName.toLowerCase(); if (tagName === 'i') { const parent = element.closest('a, button'); if (parent) { // беремо tracking-id від батька if (parent.hasAttribute('plerdy-tracking-id')) { element.setAttribute('plerdy-tracking-id', parent.getAttribute('plerdy-tracking-id')); } else { const trackingId = setUniqueId(parent); element.setAttribute('plerdy-tracking-id', trackingId); } } return; // зупиняємось, щоб не генерувати зайвий id } if (tagName === 'li') { // 1. Якщо елемент