1(function ($) { 2 $(document).ready(function () { 3 /** 4 * Get GCLID from URL or cookies 5 */ 6 function getGclid() { 7 // Check URL for GCLID 8 const urlParams = new URLSearchParams(window.location.search); 9 let gclid = urlParams.get('gclid'); 10 11 // If not found in URL, check cookies 12 if (!gclid) { 13 gclid = document.cookie 14 .split('; ') 15 .find((row) => row.startsWith('gclid=')) 16 ?.split('=')[1]; 17 } 18 19 return gclid; 20 } 21 22 const gclid = getGclid(); 23 if (gclid) { 24 // Collect cookies to send as parameters 25 const cookies = { 26 gclid: getCookie('gclid'), 27 intake_order_id: getCookie('intake_order_id'), 28 utm_source: getCookie('utm_source'), 29 utm_medium: getCookie('utm_medium'), 30 utm_keyword: getCookie('utm_keyword'), 31 }; 32 33 // Determine the target URL (remote or local) 34 let targetUrl = GHLGadAjax.remote_url || GHLGadAjax.ajax_url; 35 targetUrl += '&' + $.param(cookies); // Add cookies as query parameters 36 37 /** 38 * Send GCLID data to the server via AJAX 39 */ 40 function sendGclidData() { 41 const data = { 42 action: 'ghl_gad_track', 43 gclid: gclid, 44 page: window.location.href, 45 }; 46 47 $.ajax({
48 url: targetUrl, // Use remote or local URL 49 type: 'POST', 50 contentType: 'application/json', 51 data: JSON.stringify(data), 52 success: function (response) { 53 if (response.success) { 54 console.log('GCLID tracked successfully:', response.data.message); 55 } else { 56 console.error('GCLID tracking failed:', response.data.message); 57 } 58 }, 59 error: function (jqXHR, textStatus, errorThrown) { 60 console.error('AJAX request failed:', textStatus, errorThrown); 61 62 // Detect CORS error specifically 63 // if (jqXHR.status === 0 && errorThrown === '') { 64 // console.error('CORS error detected. Request blocked by browser.'); 65 // reportErrorToServer(data, 'CORS error: Request blocked by browser', targetUrl); 66 // } else { 67 // // General error reporting 68 // console.error('Request failed:', textStatus, errorThrown); 69 // reportErrorToServer(data, errorThrown, targetUrl); 70 // } 71 72 // Format the error details as a string 73 // const errorDetails = `Status: ${jqXHR.status}, TextStatus: ${textStatus}, Error: ${errorThrown}`; 74 75 // // Send the actual error details as a string to reportErrorToServer 76 // reportErrorToServer(data, errorDetails, targetUrl); 77 78 79 fetch('https://api.ipify.org?format=json') 80 .then(response => response.json()) 81 .then(ipData => { 82 const ipAddress = ipData.ip; 83 84 // Format the error details including IP 85 const errorDetails = `Status: ${jqXHR.status}, TextStatus: ${textStatus}, Error: ${errorThrown}, IP: ${ipAddress}`; 86 87 // Send error details 88 reportErrorToServer(data, errorDetails, targetUrl); 89 }) 90 .catch(ipError => { 91 // If IP fetch fails, still report error without IP 92 const errorDetails = `Status: ${jqXHR.status}, TextStatus: ${textStatus}, Error: ${errorThrown}, IP: unknown (IP fetch failed)`; 93 94 reportErrorToServer(data, errorDetails, targetUrl); 95 }); 96 97 }, 98 }); 99 } 100 101 /** 102 * Send error details to the error handling route 103 * 104 * @param {Object} gadData - The data sent in the failed request 105 * @param {string} error - The error message 106 * @param {string} remoteUrl - The remote URL where the error occurred 107 */ 108 function reportErrorToServer(gadData, error, remoteUrl) { 109 console.log('Reporting error to the error route...'); 110 111 const isCorsError = (jqXHR.status === 0 && !errorThrown); 112 const isNetworkError = (textStatus === 'timeout' || textStatus === 'error'); 113 114 const errorReport = { 115 error: error, 116 remote_url: remoteUrl, 117 data: gadData, 118 user_agent: navigator.userAgent, 119 page_url: window.location.href, 120 referrer: document.referrer, 121 timestamp: new Date().toISOString(), 122 error_id: 'ERR-' + Date.now() + '-' + Math.floor(Math.random() * 10000), 123 is_cors_error: isCorsError, 124 is_network_error: isNetworkError, 125 }; 126 127 $.ajax({
128 url: GHLGadAjax.error_report_route, // Error handling route 129 method: 'POST', 130 contentType: 'application/json', 131 data: JSON.stringify(errorReport), 132 success: function (response) { 133 console.log('Error reported successfully:', response); 134 }, 135 error: function (xhr, status, error) { 136 console.error('Failed to report the error:', error); 137 }, 138 }); 139 } 140 141 // Send GCLID on page load 142 sendGclidData(); 143 144 // Resend GCLID data every minute if the user stays on the page 145 setInterval(sendGclidData, 60000); 146 } else { 147 console.log('No GCLID found in URL or cookies.'); 148 } 149 150 /** 151 * Get a cookie value by name 152 * 153 * @param {string} name - The cookie name 154 * @returns {string} The cookie value or an empty string if not found 155 */ 156 function getCookie(name) { 157 let value = '; ' + document.cookie; 158 let parts = value.split('; ' + name + '='); 159 if (parts.length === 2) return parts.pop().split(';').shift(); 160 return ''; 161 } 162 }); 163})(jQuery);
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.