UNPKG

tracking-crm-core

Version:

Framework simplificado y robusto de tracking CRM - Sistema modular para tracking de visitantes, sesiones, eventos y captura de leads optimizado para navegadores

252 lines (251 loc) 8.21 kB
/** * TRACKING CRM FRAMEWORK v2.1 - SIMPLIFICADO * Framework robusto de tracking para navegadores * * @version 2.1.0 * @description Framework modular para tracking de visitantes, sesiones y leads * @author Innova Marketing */ // Variables globales let currentConfig = null; let currentSession = null; let eventBuffer = []; let isInitialized = false; // Utilidades básicas const isBrowser = typeof window !== 'undefined'; const generateUUID = () => { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { const r = Math.random() * 16 | 0; const v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); }; const getDeviceInfo = () => { if (!isBrowser) { return { type: 'unknown', os: 'unknown', browser: 'unknown', screenResolution: 'unknown', viewportSize: 'unknown', userAgent: 'unknown', language: 'unknown', timezone: 'unknown' }; } const userAgent = navigator.userAgent; const viewport = `${window.innerWidth}x${window.innerHeight}`; const screen = `${window.screen.width}x${window.screen.height}`; return { type: /Mobile|Android|iPhone|iPad/.test(userAgent) ? 'mobile' : 'desktop', os: /Windows/.test(userAgent) ? 'Windows' : /Mac/.test(userAgent) ? 'macOS' : /Linux/.test(userAgent) ? 'Linux' : 'unknown', browser: /Chrome/.test(userAgent) ? 'Chrome' : /Firefox/.test(userAgent) ? 'Firefox' : /Safari/.test(userAgent) ? 'Safari' : 'unknown', screenResolution: screen, viewportSize: viewport, userAgent, language: navigator.language || 'unknown', timezone: Intl.DateTimeFormat().resolvedOptions().timeZone || 'unknown' }; }; const getVisitorId = () => { if (!isBrowser) return generateUUID(); let visitorId = localStorage.getItem('tracking_visitor_id'); if (!visitorId) { visitorId = generateUUID(); localStorage.setItem('tracking_visitor_id', visitorId); } return visitorId; }; const sendToEndpoint = async (endpoint, data) => { if (!endpoint) return false; try { const response = await fetch(endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(data) }); return response.ok; } catch (error) { console.error('Error sending to endpoint:', error); return false; } }; // Funciones principales del framework export const initTracker = async (businessId, config = {}) => { if (!isBrowser) return; currentConfig = { businessId, environment: 'production', endpoints: { visitorTracking: 'https://n8n.innovamarketing.uy/webhook/visitor-tracking', leadCapture: 'https://n8n.innovamarketing.uy/webhook/lead-capture', eventTracking: 'https://n8n.innovamarketing.uy/webhook/event-tracking', ...config.endpoints }, debug: { enabled: false, verbose: false, logToConsole: false, ...config.debug }, timing: { heartbeatInterval: 30000, inactivityTimeout: 300000, scrollThrottle: 1000, eventBufferSize: 10, ...config.timing }, ...config }; // Crear nueva sesión currentSession = { sessionId: generateUUID(), visitorId: getVisitorId(), businessId, startTime: new Date().toISOString(), lastActivity: new Date().toISOString(), pageViews: 1, events: [], deviceInfo: getDeviceInfo() }; isInitialized = true; // Enviar inicio de sesión if (currentConfig.endpoints?.visitorTracking) { await sendToEndpoint(currentConfig.endpoints.visitorTracking, { session: currentSession, events: [], deviceInfo: currentSession.deviceInfo, pageInfo: { url: window.location.href, title: document.title, referrer: document.referrer }, userBehavior: { sessionDuration: 0, pageViews: 1, eventsCount: 0 } }); } if (currentConfig.debug?.enabled) { console.log('✅ Tracking inicializado:', { businessId, sessionId: currentSession.sessionId }); } }; export const trackEvent = (eventType, eventName, eventData = {}) => { if (!isInitialized || !currentSession || !currentConfig) return; const event = { eventType, eventName, eventData, timestamp: new Date().toISOString(), pageUrl: window.location.href }; currentSession.events.push(event); currentSession.lastActivity = new Date().toISOString(); eventBuffer.push(event); if (currentConfig.debug?.enabled) { console.log('📊 Evento trackeado:', event); } // Enviar buffer si está lleno if (eventBuffer.length >= (currentConfig.timing?.eventBufferSize || 10)) { flushEvents(); } }; export const captureLead = async (leadData) => { if (!isInitialized || !currentSession || !currentConfig) return false; const enrichedLead = { ...leadData, sessionId: currentSession.sessionId, visitorId: currentSession.visitorId, businessId: currentConfig.businessId, timestamp: new Date().toISOString(), pageUrl: window.location.href, deviceInfo: currentSession.deviceInfo, sessionData: { duration: Date.now() - new Date(currentSession.startTime).getTime(), pageViews: currentSession.pageViews, eventsCount: currentSession.events.length } }; // Trackear evento de lead trackEvent('conversion', 'lead_captured', leadData); // Enviar lead if (currentConfig.endpoints?.leadCapture) { const success = await sendToEndpoint(currentConfig.endpoints.leadCapture, enrichedLead); if (currentConfig.debug?.enabled) { console.log(success ? '✅ Lead capturado' : '❌ Error capturando lead', enrichedLead); } return success; } return false; }; export const getTrackingStatus = () => { return { isInitialized, businessId: currentConfig?.businessId, sessionId: currentSession?.sessionId, visitorId: currentSession?.visitorId, eventsCount: currentSession?.events.length || 0, lastActivity: currentSession?.lastActivity }; }; const flushEvents = async () => { if (!currentConfig?.endpoints?.eventTracking || eventBuffer.length === 0) return; const eventsToSend = [...eventBuffer]; eventBuffer = []; await sendToEndpoint(currentConfig.endpoints.eventTracking, { sessionId: currentSession?.sessionId, visitorId: currentSession?.visitorId, businessId: currentConfig.businessId, events: eventsToSend, timestamp: new Date().toISOString() }); }; export const cleanupTracker = () => { if (eventBuffer.length > 0) { flushEvents(); } currentConfig = null; currentSession = null; eventBuffer = []; isInitialized = false; }; // Funciones de conveniencia export const trackPageView = (url) => { trackEvent('navigation', 'page_view', { url: url || window.location.href }); }; export const trackClick = (element, data) => { trackEvent('interaction', 'click', { element, ...data }); }; export const trackConversion = (type, value, data) => { trackEvent('conversion', type, { value, ...data }); }; // Exponer funciones de debug en desarrollo if (isBrowser && typeof window !== 'undefined') { window.trackingCrmCore = { getStatus: getTrackingStatus, trackEvent, captureLead, flushEvents }; } // Exportaciones por defecto export default { initTracker, trackEvent, captureLead, getTrackingStatus, trackPageView, trackClick, trackConversion, cleanupTracker };