1//HIGHTOUCH EVENTS APP.JS FILE ââ LAST UPDATED: 8/19/2024 AT 1:44 PM PT// 2// Update: Capture GBRAID and WBRAID Paramters 3// Update: Generate FBC (Facebook Click ID) 4// Update: Generate FBP (Facebook Browser ID) 5 6function removeEmptyProperties(obj){if(typeof obj!=="object"||obj===null)return obj;for(const key in obj)if(obj.hasOwnProperty(key)){const value=obj[key];typeof value==="object"&&value!==null&&(obj[key]=removeEmptyProperties(value));(obj[key]===null||obj[key]===""||obj[key]===undefined)&&delete obj[key]}return Object.keys(obj).length===0&&obj.constructor===Object?{}:obj} 7 8// Enable debugging in development mode 9window.htevents.debug(false); 10 11// Function to get additional parameters 12async function getAdditionalParams() { 13 let ipData = {}; 14 try { 15 const response = await fetch('https://api.ipify.org?format=json'); 16 const data = await response.json(); 17 ipData.ipAddress = data.ip; 18 19 const geoResponse = await fetch(`https://ipapi.co/${data.ip}/json/`); 20 const geoData = await geoResponse.json(); 21 ipData = { 22 ...ipData, 23 userCountry: geoData.country_name, 24 userRegion: geoData.region, 25 userCity: geoData.city, 26 userPostal: geoData.postal 27 }; 28 } catch (error) { 29 console.error("Error fetching IP and geo data:", error); 30 } 31 32 // Capture UTM parameters and additional ad-related parameters 33 const urlParams = new URLSearchParams(window.location.search); 34 const fbclid = urlParams.get('fbclid'); 35 36 return { 37 ...ipData, 38 utmParameters: { 39 source: urlParams.get('utm_source'), 40 medium: urlParams.get('utm_medium'), 41 campaign: urlParams.get('utm_campaign'), 42 id: urlParams.get('utm_id'), 43 term: urlParams.get('utm_term'), 44 content: urlParams.get('utm_content'), 45 fbclid: fbclid, 46 glclid: urlParams.get('glclid'), 47 atrefid: urlParams.get('atrefid'), 48 ad_id: urlParams.get('ad_id'), 49 adset_id: urlParams.get('adset_id'), 50 campaign_id: urlParams.get('campaign_id'), 51 ad_name: urlParams.get('ad_name'), 52 adset_name: urlParams.get('adset_name'), 53 campaign_name: urlParams.get('campaign_name'), 54 placement: urlParams.get('placement'), 55 site_source_name: urlParams.get('site_source_name'), 56 gbraid: urlParams.get('gbraid'), 57 wbraid: urlParams.get('wbraid'), 58 events_uuid: window.app?.uuid ?? "", 59 user_or_session_id: window.app?.user_or_session_id ?? "", 60 }, 61 fbc: getFBC(fbclid), 62 fbp: getFBP(), 63 directory: window.location.pathname.split('/')[1] 64 }; 65} 66 67// Function to get or generate FBC (Facebook Click ID) parameter 68function getFBC(fbclid) { 69 const cookieValue = document.cookie 70 .split('; ') 71 .find(row => row.startsWith('_fbc=')) 72 ?.split('=')[1]; 73 74 return cookieValue || generateFBC(fbclid); 75} 76 77// Function to generate FBC if not found 78function generateFBC(fbclid) { 79 if (!fbclid) return null; 80 const domain = window.location.hostname; 81 const timestamp = Math.floor(Date.now() / 1000); // Current timestamp in seconds 82 const fbc = `fb.1.${timestamp}.${fbclid}`; 83 84 // Store the generated _fbc cookie for future use (expires in 90 days) 85 document.cookie = `_fbc=${fbc}; path=/; expires=${new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toUTCString()}; SameSite=Lax`; 86 87 return fbc; 88} 89 90// Function to get or generate FBP (Facebook Browser ID) parameter 91function getFBP() { 92 const cookieValue = document.cookie 93 .split('; ') 94 .find(row => row.startsWith('_fbp=')) 95 ?.split('=')[1]; 96 97 return cookieValue || generateFBP(); 98} 99 100// Function to generate FBP if not found 101function generateFBP() { 102 const version = 'fb.1.'; 103 const timestamp = Math.floor(new Date().getTime() / 1000); // Current Unix time in seconds 104 const randomNumber = Math.random().toString(36).substring(2, 15); // Random session ID 105 const fbp = version + timestamp + '.' + randomNumber; 106 107 // Store the generated _fbp cookie for future use (expires in 90 days) 108 document.cookie = `_fbp=${fbp}; path=/; expires=${new Date(Date.now() + 90 * 24 * 60 * 60 * 1000).toUTCString()}; SameSite=Lax`; 109 110 return fbp; 111} 112 113// Function to get the category from the dataLayer 114function getCategoryFromDataLayer() { 115 if (window.dataLayer) { 116 const ecommPageType = window.dataLayer.find(item => item.ecomm_pagetype);
117 return ecommPageType ? ecommPageType.ecomm_pagetype : 'Unknown'; 118 } 119 return 'Unknown'; 120} 121 122// Function to track page views 123async function trackPageView() { 124 const additionalParams = await getAdditionalParams(); 125 const eventName = document.title; 126 const eventCategory = getCategoryFromDataLayer(); 127 window.htevents.page( 128 eventCategory, // category of the event from dataLayer 129 eventName, // name of the event from page title 130 { 131 hostname: window.location.hostname, 132 path: window.location.pathname, 133 ...additionalParams 134 }, 135 { 136 // context - can include more metadata if needed 137 ip: additionalParams.ipAddress 138 }, 139 function() { 140 //console.log("Page view tracked:", document.title); 141 } 142 ); 143} 144 145// Track initial page view on load 146trackPageView();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.