/** * Скрипт для проброса UTM-меток * * Этот скрипт сохраняет UTM-метки из URL и добавляет их к внутренним ссылкам на сайте. * * @author sglazov.ru * @version 1.0.0 */ (function() { // Конфигурация const config = { // Параметры UTM, которые нужно сохранять utmParams: ['utm_source', 'utm_medium', 'utm_campaign', 'utm_content', 'utm_term', 'utm_title', 'utm_source_type', 'utm_region', 'utm_region_id', 'utm_device', 'utm_retargeting', 'utm_placement'], // Исключения - домены, на которые не нужно добавлять UTM excludeDomains: [], // Базовый домен сайта (если нужно добавлять UTM только для внутренних ссылок) baseDomain: window.location.hostname, // Добавлять UTM к внешним ссылкам addToExternalLinks: false, // Имя cookie для хранения UTM-меток cookieName: 'utm_data', // Срок хранения UTM-меток в днях cookieExpires: 30 }; // Функция для получения параметров из URL function getUrlParams() { const params = {}; const queryString = window.location.search.substring(1); const pairs = queryString.split('&'); for (let i = 0; i < pairs.length; i++) { const pair = pairs[i].split('='); if (pair.length === 2) { params[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]); } } return params; } // Функция для сохранения UTM-меток в cookie function saveUtmToCookie() { const params = getUrlParams(); const utmData = {}; let hasUtm = false; // Собираем UTM-метки config.utmParams.forEach(param => { if (params[param]) { utmData[param] = params[param]; hasUtm = true; } }); // Если есть UTM-метки, сохраняем их в cookie if (hasUtm) { const expires = new Date(); expires.setDate(expires.getDate() + config.cookieExpires); document.cookie = `${config.cookieName}=${JSON.stringify(utmData)}; expires=${expires.toUTCString()}; path=/`; } } // Функция для получения UTM-меток из cookie function getUtmFromCookie() { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.indexOf(`${config.cookieName}=`) === 0) { try { return JSON.parse(cookie.substring(config.cookieName.length + 1)); } catch (e) { console.error('Ошибка при разборе UTM-данных из cookie:', e); return null; } } } return null; } // Функция для добавления UTM-меток к URL function addUtmToUrl(url) { const utmData = getUtmFromCookie(); if (!utmData) return url; // Проверяем, является ли ссылка внешней let isExternal = false; try { const urlObj = new URL(url, window.location.origin); isExternal = !urlObj.hostname.includes(config.baseDomain); } catch (e) { // Если URL относительный, считаем его внутренним isExternal = false; } if (isExternal && !config.addToExternalLinks) return url; // Проверяем, не входит ли домен в исключения if (isExternal) { const urlObj = new URL(url); if (config.excludeDomains.includes(urlObj.hostname)) return url; } // Добавляем UTM-метки к URL const separator = url.includes('?') ? '&' : '?'; const utmString = Object.keys(utmData) .map(key => `${key}=${encodeURIComponent(utmData[key])}`) .join('&'); return `${url}${separator}${utmString}`; } // Функция для обработки всех ссылок на странице function processLinks() { const links = document.querySelectorAll('a[href]'); links.forEach(link => { const href = link.getAttribute('href'); // Пропускаем якоря и javascript: ссылки if (href.startsWith('#') || href.startsWith('javascript:')) return; // Добавляем UTM-метки к ссылке link.setAttribute('href', addUtmToUrl(href)); }); } // Функция для обработки динамически добавленных ссылок function observeLinks() { const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.addedNodes.length) { mutation.addedNodes.forEach(node => { if (node.nodeType === 1) { // ELEMENT_NODE const links = node.querySelectorAll('a[href]'); links.forEach(link => { const href = link.getAttribute('href'); // Пропускаем якоря и javascript: ссылки if (href.startsWith('#') || href.startsWith('javascript:')) return; // Добавляем UTM-метки к ссылке link.setAttribute('href', addUtmToUrl(href)); }); } }); } }); }); observer.observe(document.body, { childList: true, subtree: true }); } // Инициализация function init() { // Сохраняем UTM-метки из URL saveUtmToCookie(); // Обрабатываем существующие ссылки processLinks(); // Наблюдаем за динамически добавленными ссылками observeLinks(); } // Запускаем скрипт после загрузки DOM if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();