1FP.fns.ga4_set_g_ids = function(nr, type, ID) { 2 3 let ga_ids = FP.readCookie('fp_ga_ids'); 4 5 if ( ga_ids ) { 6 ga_ids = JSON.parse( ga_ids ); 7 } else { 8 ga_ids = {}; 9 } 10 11 ga_ids['ga4' + nr + '_' + type] = ID; 12 13 FP.setCookie( 'fp_ga_ids', JSON.stringify(ga_ids) ); 14} 15 16function fupi_load_gads(){ 17 18 if ( ! fp.loaded.includes('ga41') || fp.ga41.id != fp.gads.id ) { 19 if ( fp.vars.gtag_enh_conv ) { 20 window.gtag( 'config', fp.gads.id, { 'allow_enhanced_conversions': true } ); 21 } else { 22 window.gtag( 'config', fp.gads.id ); 23 } 24 } 25 26 /* <fs_premium_only> */ 27 let aw_id = fp.gads.id2 || fp.gads.id; 28 29 if ( fp.main.is_pro ) { 30 // CUSTOM EVENTS 31 function gads_send_custom_events( evt ) { 32 let params = FP.addEvtParams( { 'send_to': aw_id + '/' + evt.conv_label }, evt.params ); // removed 'send_to': _ga.id2 || _ga.id 33 gtag( 'event', 'conversion', params ); 34 if ( fp.main.debug ) console.log('[FP] GAds custom conversion event: ' + aw_id + '/' + evt.conv_label ); 35 } 36 37 FP.initCondTracking( fp.gads.custom_events, gads_send_custom_events ); 38 } 39 /* </fs_premium_only> */ 40 41 FP.loaded('gads_config', 'gads'); 42}; 43 44function fupi_load_ga4( nr ) { 45 46 var _ga = fp[ 'ga4' + nr ], 47 params = {}; 48 49 if ( fp?.gads?.id && fp?.gads?.id == fp.ga41.id && fp.vars.gtag_enh_conv ) { 50 params.allow_enhanced_conversions = true; 51 } 52 53 // CHANGE COOKIE PREFIX 54 // optional for the tracking ID #1 55 if ( _ga.cookie_prefix && nr == '1' ) params.cookie_prefix = '_fp4' + nr; 56 57 // enable GA's debug mode 58 // @ https://support.google.com/analytics/answer/7201382?hl=en 59 if ( fpdata?.cookies?.ga4_debug ) params.debug_mode = true; 60 61 /* <fs_premium_only> */ 62 if ( fp.main.is_pro ) { 63 64 // CHANGE COOKIE PREFIX 65 // obligatory for tracking ID #2 66 if ( nr == '2' ) params.cookie_prefix = '_fp4' + nr; 67 68 // SET "USER ID" (ENCODED) 69 if ( _ga.set_user_id && fpdata.user.id ) { 70 params.user_id = window.btoa(fpdata.user.id).split('=').join(''); 71 } 72 } 73 /* </fs_premium_only> */ 74 75 // SEND CLEAN "PAGE TITLE" 76 if ( _ga.clean_page_title && fpdata.page_title && fpdata.page_title.length > 0 ) { 77 params.page_title = fpdata.page_title; 78 79 // "SEO TITLE" CUSTOM DIMENSION 80 if ( _ga.seo_title ) { 81 params.seo_title = document.title; 82 } 83 } 84 85 // "PAGE LANGUAGE" CUSTOM DIMENSION 86 if ( _ga.page_lang ) { 87 params[_ga.page_lang] = document.documentElement.lang || 'undefined'; 88 } 89 90 // "PAGE TYPE" CONTENT GROUPING 91 if ( _ga.page_type && fpdata.page_type && fpdata.page_type.length > 1 ) { 92 params[_ga.page_type] = fpdata.page_type; 93 } 94 95 // "PAGE ID" CUSTOM DIMENSION 96 if ( _ga.page_id && fpdata.page_id && fpdata.page_id > 0 ) { 97 params[_ga.page_id] = '' + fpdata.page_id; 98 } 99 100 // "PAGE NUMBER" CUSTOM DIMENSION 101 if ( _ga.page_number && fpdata.page_number > 0 ) { 102 params[_ga.page_number] = '' + fpdata.page_number; 103 } 104 105 // "AUTHOR DISPLAY NAME" CUSTOM DIMENSION 106 if ( _ga.post_author && fpdata.author_name && fpdata.author_name.length > 0 ) { 107 params[_ga.post_author] = fpdata.author_name; 108 } 109 110 // "AUTHOR ID" CUSTOM DIMENSION 111 if ( _ga.author_id && fpdata.author_id > 0 ) { 112 params[_ga.author_id] = '' + fpdata.author_id; 113 } 114 115 // "PUBLISHED DATE" CUSTOM DIMENSION 116 if ( _ga.post_date && fpdata.published && fpdata.published.length > 0 ) { 117 params[_ga.post_date] = fpdata.published; 118 } 119 120 /* <fs_premium_only> */ 121 if ( fp.main.is_pro ) { 122 // "CUSTOM META" CUSTOM DIMENSIONS 123 if ( _ga.track_cf ) { 124 for (const i in _ga.track_cf ) { 125 126 let dimension_name = _ga.track_cf[i].dimname, 127 field_data = _ga.track_cf[i].id, 128 field_type = field_data.includes('|') ? field_data.split('|')[0] : 'post', 129 field_id = field_data.includes('|') ? field_data.split('|')[1] : field_data; 130 131 field_type = field_type == 'post' ? 'custom' : field_type + '_custom'; 132 133 if ( fpdata[field_type] && ( fpdata[field_type][field_id] || fpdata[field_type][field_id] === false ) ) { 134 params[dimension_name] = fpdata[field_type][field_id] + ''; 135 } 136 } 137 } 138 } 139 /* </fs_premium_only> */ 140 141 // "SEARCH RESULTS" CUSTOM METRIC 142 if ( _ga.search_results_nr && _ga.search_results_nr.length > 0 && fpdata.search_results && fpdata.search_results > 0 ) { 143 params[_ga.search_results_nr] = parseInt(fpdata.search_results); 144 } 145 146 // "USER ROLE" USER PROPERTY 147 if ( _ga.user_role ) { 148 if ( fpdata.user.role && fpdata.user.role.length > 0 ) { 149 params[_ga.user_role] = fpdata.user.role; 150 } 151 } 152 153 // "TAXONOMY TERMS" CUSTOM DIMENSION 154 if ( _ga.tax_terms && fpdata.terms && fpdata.terms.length > 0 ) { 155 156 var term_arr = fpdata.terms.map( function (term_data) { 157 var term = _ga.send_tax_terms_titles ? term_data.name : term_data.slug; 158 term += _ga.add_tax_term_cat ? ' (' + term_data.taxonomy + ')' : ''; 159 return term; 160 } ); 161 162 params[_ga.tax_terms] = term_arr.join(', '); 163 } 164 165 window.gtag( 'config', _ga.id, params ); 166 167 /* <fs_premium_only> */ 168 if ( fp.main.is_pro ) { 169 170 // Server Side Tracking 171 // ! only for GA #1 172 173 if ( nr == 1 ) { 174 175 // Save GA4 client ID in a variable 176 // This function is fired by GA's script! It does not give instant results! 177 if ( typeof gtag !== 'undefined' ) { 178 179 gtag('get', fp.ga41.id2 || fp.ga41.id, 'client_id', clientID => { 180 FP.fns.ga4_set_g_ids(nr, 'client', clientID); 181 } ); 182 183 gtag('get', fp.ga41.id2 || fp.ga41.id, 'session_id', sessionID => { 184 FP.fns.ga4_set_g_ids(nr, 'session', sessionID); 185 } ); 186 } 187 188 // Hook up server order tracking 189 190 FP.addAction( ['woo_prepare_for_server_tracking_order'], server_data => { 191 192 // STOP if we don't track the order server-side 193 if ( ! fp.ga41.server_side || ! fp.ga41.adv_orders ) return server_data; 194 195 // STOP if we don't have required data 196 let ga_ids = FP.readCookie('fp_ga_ids');
197 if ( ga_ids ) ga_ids = JSON.parse( ga_ids ); 198 if ( ! ga_ids || ! ga_ids.ga41_client || ! ga_ids.ga41_session || ! fpdata.consents || ! fpdata.consents.can_track_stats ) return server_data; 199 200 let ga4_data = { 201 'ga41_client_id' : ga_ids.ga41_client, 202 'ga41_session_id' : ga_ids.ga41_session, 203 'enable_debug_view' : fpdata.cookies.ga4_debug == 'on', 204 'supports' : ['purchase', 'refund'], 205 }; 206 207 // if ( fp.ga42 && fp.ga42.server_side ) { // adv_orders already set in ga41 208 // ga4_data['ga42_client_id'] = ga_ids?.ga41_clientID || false; 209 // ga4_data['ga42_session_id'] = ga_ids?.ga42_sessionID || false; 210 // } 211 212 // prepare data for the server-side purchase tracking 213 server_data.push( ['ga4', ga4_data] ); 214 return server_data; 215 } ); 216 } 217 218 // TRACK JS ERRORS 219 // THX: https://blog.sentry.io/2016/01/04/client-javascript-reporting-window-onerror 220 // THX: https://medium.com/@Esakkimuthu/track-javascript-errors-and-how-to-fix-the-errors-60e160851296 221 if ( _ga.js_err_dimens ) { 222 window.onerror = (msg, url, lineNo, columnNo, error)=>{ 223 224 // make sure no unwanted errors slip through 225 if ( ! msg || msg.indexOf('debug-evaluate') != -1 || msg.indexOf('ResizeObserver loop limit exceeded') != -1 ) return; 226 227 let data = { 228 'send_to': fp['ga4' + nr].id2 || fp['ga4' + nr].id, 229 }; 230 231 if ( msg.indexOf('Script Error') > -1 ){ 232 data['js_error_details'] = 'External script error: see browser console for details'; 233 } else { 234 235 // we are not sending an error.stack since it is always longer than 100 chars (GA limit) 236 237 if ( url ){ 238 if ( url != document.location.href ) { 239 // get only file name 240 url = url.split('?').shift(); 241 url = ' at ' + url.split('/').pop(); 242 } else { 243 // replace URL with a notice - the url is not important since GA collects it with the event 244 url = ' in an inline script'; 245 } 246 } 247 248 lineNo = lineNo ? ' Line:' + lineNo : ''; 249 columnNo = columnNo ? ' Col:' + columnNo : ''; 250 251 // replaces double quotes with apostrophes (GA replaces quotes with HTML entities which take too many characters) 252 msg = msg.replaceAll('"', '\''); 253 254 let message = msg + url + lineNo + columnNo; 255 message = message.substring(0,100); 256 257 data['js_error_details'] = message; 258 } 259 260 gtag( 'event', 'js_error', data ); 261 if ( fp.main.debug ) console.log('[FP] GA4 #' + nr + ' event: JS error', data ); 262 263 return false; 264 } 265 } 266 267 // Conditional tracking 268 269 function ga4_send_custom_events( evt ){ 270 var params = FP.addEvtParams( { 'send_to': _ga.id2 || _ga.id }, evt.params ); 271 gtag( 'event', evt.evt_name, params); 272 if ( fp.main.debug ) console.log( '[FP] GA4 #' + nr + ' custom tracking: ' + evt.evt_name, params ); 273 } 274 275 FP.initCondTracking( _ga.custom_events, ga4_send_custom_events ); 276 } 277 /* </fs_premium_only> */ 278 279 FP.loaded('ga4' + nr + '_config', 'ga4' + nr ); 280} 281 282function fupi_enable_gtag() { 283 284 // First, fix GAds IDs 285 if ( fp.gads ) { 286 if ( 287 fp.gads.id && 288 ! fp.gads.id.includes('AW-') && 289 ! fp.gads.id.includes('GT-') && 290 ! fp.gads.id.includes('G-') 291 ) fp.gads.id = 'AW-' + fp.gads.id; 292 293 if ( 294 fp.gads.id2 && 295 ! fp.gads.id2.includes('AW-') && 296 ! fp.gads.id2.includes('GT-') && 297 ! fp.gads.id2.includes('G-') 298 ) fp.gads.id2 = 'AW-' + fp.gads.id2; 299 } 300 301 // set gtag date 302 if ( ! fp.loaded.includes('gtg') ) { 303 window.gtag('js', new Date()); 304 } 305 306 fp.vars.gtag_enh_conv = false; 307 308 /* <fs_premium_only> */ 309 if ( fp.main.is_pro ) { 310 311 // SET ENCHANCED CONVERSIONS DATA 312 313 if ( 314 fpdata.consents.can_track_stats && 315 fpdata.consents.can_track_market && 316 fpdata['user'] && 317 ( ( fp?.ga41 && fp?.ga41?.enh_conv ) || ( fp?.gads?.id && fp?.gads?.enh_conv ) ) 318 ) { 319 320 fp.vars.gtag_enh_conv = true; 321 322 let cus_data = {}, 323 cus_address = {}; 324 325 if ( fpdata['user']['email_sha256'] ) cus_data['sha256_email_address'] = fpdata['user']['email_sha256'].replaceAll(' ', ''); 326 if ( fpdata['user']['phone_sha256'] ) cus_data['sha256_phone_number'] = fpdata['user']['phone_sha256'].replace(' ',''); 327 328 // Address (in sub array) 329 330 if ( fpdata['user']['first_name_sha256'] ) cus_address['sha256_first_name'] = fpdata['user']['first_name_sha256']; 331 if ( fpdata['user']['last_name_sha256'] ) cus_address['sha256_last_name'] = fpdata['user']['last_name_sha256']; 332 if ( fpdata['user']['address'] ) cus_address['street'] = fpdata['user']['address']; 333 if ( fpdata['user']['city'] ) cus_address['city'] = fpdata['user']['city']; 334 if ( fpdata['user']['region'] ) cus_address['region'] = fpdata['user']['region']; 335 if ( fpdata['user']['postcode'] ) cus_address['postal_code'] = fpdata['user']['postcode']; 336 if ( fpdata['user']['country'] ) cus_address['country'] = fpdata['user']['country']; 337 338 // Add address to the main object if it is not empty 339 if ( Object.keys(cus_address).length != 0 ) cus_data['address']
339= cus_address; 340 341 // Set the data 342 if ( Object.keys(cus_data).length != 0 ) gtag( 'set', 'user_data', cus_data ); 343 } 344 } 345 /* </fs_premium_only> */ 346 347 FP.loaded('gtag_config', 'gtg'); 348}; 349 350function fupi_load_ga41(){ 351 fupi_load_ga4( 1 ); 352}; 353 354function fupi_load_ga42(){ 355 fupi_load_ga4( 2 ); 356}; 357 358FP.load('gtag_config', 'fupi_enable_gtag', ['head_helpers', 'gtag_file']); 359 360if ( fp.ga41?.id ) { 361 FP.load('ga41_config', 'fupi_load_ga41', ['gtag_config']); 362 /* <fs_premium_only> */ 363 if ( fp.main.is_pro && fp?.ga42?.id ) FP.load('ga42_config', 'fupi_load_ga42', ['gtag_config']); 364 /* </fs_premium_only> */ 365} 366 367if ( fp.gads?.id ) FP.load('gads_config', 'fupi_load_gads', ['gtag_config']);
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.