/** * ANALYTICS.JS - Google Analytics 4 and social pixels * Loads asynchronously with consent management */ // Configuration const ANALYTICS_CONFIG = { GA4_ID: 'G-XXXXXXXXXX', // Replace with actual GA4 ID META_PIXEL_ID: '123456789', // Replace with actual Meta Pixel ID TIKTOK_PIXEL_ID: 'TIKTOK123', // Replace with actual TikTok Pixel ID }; // Consent management (basic implementation) let analyticsConsent = localStorage.getItem('analytics_consent') !== 'false'; // Initialize Google Analytics 4 function initGA4() { if (!analyticsConsent || !ANALYTICS_CONFIG.GA4_ID) return; // Load gtag script const script = document.createElement('script'); script.async = true; script.src = `https://www.googletagmanager.com/gtag/js?id=${ANALYTICS_CONFIG.GA4_ID}`; document.head.appendChild(script); // Initialize dataLayer and gtag window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } window.gtag = gtag; gtag('js', new Date()); gtag('config', ANALYTICS_CONFIG.GA4_ID, { send_page_view: true, allow_google_signals: true, allow_ad_personalization_signals: true }); // Track initial page view gtag('event', 'page_view', { page_title: document.title, page_location: window.location.href, page_path: window.location.pathname }); console.log('GA4 initialized'); } // Initialize Meta Pixel function initMetaPixel() { if (!analyticsConsent || !ANALYTICS_CONFIG.META_PIXEL_ID) return; // Meta Pixel base code !function(f,b,e,v,n,t,s) {if(f.fbq)return;n=f.fbq=function(){n.callMethod? n.callMethod.apply(n,arguments):n.queue.push(arguments)}; if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0'; n.queue=[];t=b.createElement(e);t.async=!0; t.src=v;s=b.getElementsByTagName(e)[0]; s.parentNode.insertBefore(t,s)}(window, document,'script', 'https://connect.facebook.net/en_US/fbevents.js'); fbq('init', ANALYTICS_CONFIG.META_PIXEL_ID); fbq('track', 'PageView'); console.log('Meta Pixel initialized'); } // Initialize TikTok Pixel function initTikTokPixel() { if (!analyticsConsent || !ANALYTICS_CONFIG.TIKTOK_PIXEL_ID) return; // TikTok Pixel base code !function (w, d, t) { w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie"],ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};for(var i=0;i { if (!formStarted) { formStarted = true; gtag('event', 'form_start', { event_category: 'form', event_label: 'application_form', value: 1 }); } }, { once: true }); } // Track video interactions (if any) const videos = document.querySelectorAll('video'); videos.forEach(video => { video.addEventListener('play', () => { gtag('event', 'video_play', { event_category: 'engagement', event_label: video.src || 'embedded_video', value: 1 }); }); video.addEventListener('ended', () => { gtag('event', 'video_complete', { event_category: 'engagement', event_label: video.src || 'embedded_video', value: 1 }); }); }); // Track file downloads document.addEventListener('click', (e) => { const link = e.target.closest('a'); if (!link) return; const href = link.getAttribute('href'); if (href && (href.includes('.pdf') || href.includes('.doc') || href.includes('.zip'))) { gtag('event', 'file_download', { event_category: 'engagement', event_label: href, value: 1 }); } }); // Track external link clicks document.addEventListener('click', (e) => { const link = e.target.closest('a'); if (!link) return; const href = link.getAttribute('href'); if (href && (href.startsWith('http') && !href.includes(window.location.hostname))) { gtag('event', 'external_link_click', { event_category: 'engagement', event_label: href, value: 1 }); } }); } // Track ecommerce events (if applicable) function trackConversionEvents() { // Track form submission as conversion const form = document.getElementById('formJoin'); if (form && typeof gtag !== 'undefined') { form.addEventListener('submit', () => { // This will be called before the form is actually submitted setTimeout(() => { gtag('event', 'conversion', { send_to: `${ANALYTICS_CONFIG.GA4_ID}/lead_generation`, event_category: 'lead', event_label: 'application_submitted', value: 1 }); // Meta Pixel conversion if (typeof fbq !== 'undefined') { fbq('track', 'Lead', { content_name: 'Job Application', content_category: 'Recruitment', value: 1, currency: 'MXN' }); } // TikTok Pixel conversion if (typeof ttq !== 'undefined') { ttq.track('SubmitForm', { content_type: 'application', content_name: 'Job Application' }); } }, 100); }); } } // Enhanced user engagement tracking function trackEngagement() { let engagementStartTime = Date.now(); let maxScrollDepth = 0; let interactions = 0; // Track interactions ['click', 'scroll', 'keydown'].forEach(eventType => { document.addEventListener(eventType, () => { interactions++; }, { passive: true }); }); // Track scroll depth more granularly function updateScrollDepth() { const scrollTop = window.pageYOffset; const docHeight = document.documentElement.scrollHeight - window.innerHeight; const scrollPercent = Math.min(100, Math.round((scrollTop / docHeight) * 100)); if (scrollPercent > maxScrollDepth) { maxScrollDepth = scrollPercent; } } window.addEventListener('scroll', updateScrollDepth, { passive: true }); // Send engagement data before page unload function sendEngagementData() { if (typeof gtag === 'undefined') return; const timeOnPage = Math.round((Date.now() - engagementStartTime) / 1000); gtag('event', 'engagement_summary', { event_category: 'engagement', custom_parameters: { time_on_page: timeOnPage, max_scroll_depth: maxScrollDepth, interactions_count: interactions } }); } // Send data on page visibility change or unload document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'hidden') { sendEngagementData(); } }); window.addEventListener('beforeunload', sendEngagementData); } // Consent banner (basic implementation) function showConsentBanner() { if (localStorage.getItem('analytics_consent') !== null) return; const banner = document.createElement('div'); banner.className = 'consent-banner'; banner.innerHTML = ` `; // Add basic styles banner.style.cssText = ` position: fixed; bottom: 0; left: 0; right: 0; background: rgba(45, 45, 45, 0.95); color: white; padding: 1rem; z-index: 9999; backdrop-filter: blur(8px); `; document.body.appendChild(banner); // Set up event listeners const acceptBtn = banner.querySelector('.consent-accept'); const rejectBtn = banner.querySelector('.consent-reject'); acceptBtn.addEventListener('click', () => setConsent(true)); rejectBtn.addEventListener('click', () => setConsent(false)); // Consent function function setConsent(accepted) { localStorage.setItem('analytics_consent', accepted.toString()); analyticsConsent = accepted; banner.remove(); if (accepted) { initializeAnalytics(); } } } // Main initialization function function initializeAnalytics() { if (!analyticsConsent) return; // Only initialize with valid IDs (not placeholder values) if (ANALYTICS_CONFIG.GA4_ID && !ANALYTICS_CONFIG.GA4_ID.includes('XXXXXXXXXX')) { initGA4(); } if (ANALYTICS_CONFIG.META_PIXEL_ID && !ANALYTICS_CONFIG.META_PIXEL_ID.includes('123456789')) { initMetaPixel(); } if (ANALYTICS_CONFIG.TIKTOK_PIXEL_ID && !ANALYTICS_CONFIG.TIKTOK_PIXEL_ID.includes('TIKTOK123')) { initTikTokPixel(); } // Wait for DOM to be ready for event tracking if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { trackCustomEvents(); trackConversionEvents(); trackEngagement(); }); } else { trackCustomEvents(); trackConversionEvents(); trackEngagement(); } } // Enhanced error tracking window.addEventListener('error', (e) => { if (typeof gtag !== 'undefined') { gtag('event', 'exception', { description: e.error?.message || 'Unknown error', fatal: false }); } }); // Initialize everything function init() { // Show consent banner if needed showConsentBanner(); // Initialize analytics if consent already given if (analyticsConsent) { initializeAnalytics(); } } // Start initialization if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }