/** * 4Ventures — Universal Attribution Script v1.0 * Almacena parámetros UTM y Click IDs en cookie '_4v_attr' (90 días) * e inyecta automáticamente en formularios y enlaces de WhatsApp. */ (function() { 'use strict'; var COOKIE_NAME = '_4v_attr'; var COOKIE_DAYS = 90; function getQueryParam(name) { var results = new RegExp('[\?&]' + name + '=([^&#]*)').exec(window.location.href); return results !== null ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null; } function setCookie(name, value, days) { var expires = ''; if (days) { var date = new Date(); date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); expires = '; expires=' + date.toUTCString(); } var secure = location.protocol === 'https:' ? '; Secure' : ''; document.cookie = name + '=' + encodeURIComponent(JSON.stringify(value)) + expires + '; path=/; SameSite=Lax' + secure; } function getCookie(name) { var nameEQ = name + '='; var ca = document.cookie.split(';'); for (var i = 0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0) === ' ') c = c.substring(1, c.length); if (c.indexOf(nameEQ) === 0) { try { return JSON.parse(decodeURIComponent(c.substring(nameEQ.length, c.length))); } catch (e) { return null; } } } return null; } function detectReferrerSource() { var ref = document.referrer.toLowerCase(); if (!ref) return { source: 'direct', medium: 'none' }; if (ref.indexOf('google.') !== -1) return { source: 'google', medium: 'organic' }; if (ref.indexOf('bing.') !== -1) return { source: 'bing', medium: 'organic' }; if (ref.indexOf('instagram.') !== -1) return { source: 'instagram', medium: 'social' }; if (ref.indexOf('facebook.') !== -1) return { source: 'facebook', medium: 'social' }; if (ref.indexOf('linkedin.') !== -1) return { source: 'linkedin', medium: 'social' }; if (ref.indexOf('tiktok.') !== -1) return { source: 'tiktok', medium: 'social' }; if (ref.indexOf('youtube.') !== -1) return { source: 'youtube', medium: 'social' }; try { var url = new URL(ref); return { source: url.hostname, medium: 'referral' }; } catch(e) { return { source: 'referral', medium: 'referral' }; } } function captureAttribution() { var utmSource = getQueryParam('utm_source'); var utmMedium = getQueryParam('utm_medium'); var utmCampaign = getQueryParam('utm_campaign'); var utmContent = getQueryParam('utm_content'); var utmTerm = getQueryParam('utm_term'); var gclid = getQueryParam('gclid'); var fbclid = getQueryParam('fbclid'); var ttclid = getQueryParam('ttclid'); var liFatId = getQueryParam('li_fat_id'); var clickId = gclid || fbclid || ttclid || liFatId || null; var clickType = gclid ? 'gclid' : fbclid ? 'fbclid' : ttclid ? 'ttclid' : liFatId ? 'li_fat_id' : null; var existingAttr = getCookie(COOKIE_NAME); // Si hay nuevos parámetros en URL, actualizamos o creamos if (utmSource || clickId) { var newAttr = { source: utmSource || (gclid ? 'google' : fbclid ? 'meta' : ttclid ? 'tiktok' : liFatId ? 'linkedin' : 'unknown'), medium: utmMedium || (clickId ? 'cpc' : 'unknown'), campaign: utmCampaign || '', content: utmContent || '', term: utmTerm || '', click_id: clickId, click_type: clickType, landing_page: window.location.href, referrer: document.referrer || '', timestamp: new Date().toISOString() }; setCookie(COOKIE_NAME, newAttr, COOKIE_DAYS); return newAttr; } // Si no hay params y ya hay cookie previa, la mantenemos if (existingAttr) { return existingAttr; } // Si es primera visita sin parámetros, deducimos del referrer var refData = detectReferrerSource(); var defaultAttr = { source: refData.source, medium: refData.medium, campaign: '', content: '', term: '', click_id: null, click_type: null, landing_page: window.location.href, referrer: document.referrer || '', timestamp: new Date().toISOString() }; setCookie(COOKIE_NAME, defaultAttr, COOKIE_DAYS); return defaultAttr; } function injectHiddenFields(attr) { var forms = document.querySelectorAll('form'); var fieldKeys = ['source', 'medium', 'campaign', 'content', 'term', 'click_id', 'click_type', 'landing_page', 'referrer']; forms.forEach(function(form) { fieldKeys.forEach(function(key) { var inputName = 'utm_' + key; if (key === 'click_id' || key === 'click_type' || key === 'landing_page' || key === 'referrer') { inputName = key; } var val = attr[key] || ''; var existing = form.querySelector('input[name="' + inputName + '"]'); if (existing) { existing.value = val; } else { var input = document.createElement('input'); input.type = 'hidden'; input.name = inputName; input.value = val; form.appendChild(input); } }); }); } function injectWhatsAppLinks(attr) { if (!attr.click_id && !attr.source) return; var links = document.querySelectorAll('a[href*="wa.me"], a[href*="api.whatsapp.com"]'); var tag = ' [ref:' + (attr.source || 'web') + (attr.click_id ? '-' + attr.click_id.substring(0, 8) : '') + ']'; links.forEach(function(link) { var href = link.getAttribute('href'); if (href && href.indexOf('[ref:') === -1) { if (href.indexOf('text=') !== -1) { link.setAttribute('href', href + encodeURIComponent(tag)); } else { var sep = href.indexOf('?') !== -1 ? '&' : '?'; link.setAttribute('href', href + sep + 'text=' + encodeURIComponent('Hola,' + tag)); } } }); } // Inicialización inmediata y en DOMContentLoaded var currentAttr = captureAttribution(); function init() { injectHiddenFields(currentAttr); injectWhatsAppLinks(currentAttr); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } // Exponer API global window._4v = { getAttribution: function() { return currentAttr; }, refresh: captureAttribution, inject: init }; })();