PageSourceSearch

https://sbbooks.eu/wp-content/plugins/full-picture-premium/public/modules/gtools/fupi-gtg-footer.js?ver=10.1.1

js sbbooks.eu collected 2026-10-02 22:47:28 UTC 20,223 bytes, 671 lines download raw bytes

1// Contains functions for tracking data used by GA and GTAG
2
3// WOO EVENTS
4
5FP.fns.send_ga4_evt = ( nr, evt_name, data )=>{
6	if ( ! evt_name ) return;
7	// add fp_ prefix if the first char is a number
8	if ( !isNaN( evt_name.charAt(0) ) ) evt_name = 'fp_' + evt_name;
9	// trim the name to max 40 chars
10	evt_name = evt_name.substring(0, 40);
11	gtag( 'event', evt_name, data);
12	if ( fp.main.debug ) console.log('[FP] GA4 #' + nr + ' event: ' + evt_name, data);
13};
14
15function fupi_gtools_woo_footer(){
16
17    fp.woo.gtg = {};
18    
19	let gads_enabled = fp.loaded.includes('gads'),
20		ga41_enabled = fp.loaded.includes('ga41'),
21		ga42_enabled = fp.loaded.includes('ga42');
22
23	ecommerce_event_send_to = [];
24
25	if ( ga41_enabled ) ecommerce_event_send_to.push( fp.ga41.id2 || fp.ga41.id );
26	if ( ga42_enabled ) ecommerce_event_send_to.push( fp.ga42.id2 || fp.ga42.id );
27	if ( gads_enabled ) ecommerce_event_send_to.push( fp.gads.id2 || fp.gads.id );
28
29	// Helpers
30
31	function add_categories( item, prod ){
32		if ( prod.categories && prod.categories.length > 0 ) {
33			prod.categories.forEach( ( cat, i ) => {
34				if ( i == 0) {
35					item['item_category'] = cat;
36				} else {
37					item['item_category' + ( i + 1 )] = cat;
38				}
39			} );
40		};
41
42		return item;
43	};
44
45	function add_brand( item, prod ){
46		if ( prod.brand && prod.brand.length > 0 ) item['item_brand'] = prod.brand[0];
47		return item;
48	};
49
50	function add_list_name( item, prod ){
51		if ( prod.list_name ) item['item_list_name'] = prod.list_name;
52		return item;
53	}
54
55	function add_index( item, prod ){
56		if ( prod.index ) item['index'] = prod.index;
57		return item;
58	}
59
60	// TRACK IMPRESSIONS
61
62	function track_woo_impress() {
63
64		if ( typeof gtag === 'undefined' ) return;
65		
66		let teasers_arr = [],
67			single_arr = [],
68			value = 0;
69
70		// for each product list
71		for ( let [ list_name, item_ids ] of Object.entries( fpdata.woo.lists ) ) {
72
73			let start_index = 1;
74			
75			// track only items that were not tracked before
76			if ( fp.woo.gtg[list_name] ) {
77				item_ids = item_ids.filter( id => ! fp.woo.gtg[list_name].includes(id) );
78				start_index = fp.woo.gtg[list_name].length + 1;
79			} else {
80				fp.woo.gtg[list_name] = [];
81			};
82
83			item_ids.forEach( ( id, i ) => {
84                
85                let prod = fpdata.woo.products[id],
86                    prod_id = FP.fns.get_woo_prod_id( prod ),
87					item = { 
88					'item_id' : prod_id,
89                    'id' : prod_id,
90					'item_name': FP.fns.get_woo_prod_name(prod),
91					'item_list_name' : list_name,
92					'index' : i + start_index,
93					'price' : prod.price,
94				};
95
96                if ( gads_enabled ) item['google_business_vertical'] = fp.gads.business_type;
97
98				item = add_brand( item, prod );
99				item = add_categories( item, prod );
100
101				if ( list_name == 'single' ) {
102					value += prod.price;
103					single_arr.push( item );
104				} else {
105					teasers_arr.push( item );
106				}
107			});
108
109			// prevent double tracking in case the next teasers are added dynamically
110			fp.woo.gtg[list_name].push(...item_ids);
111		};
112		
113		if ( teasers_arr.length > 0 ) {
114
115			let payload_o = { 
116				'items' : teasers_arr,
117				'currency' : fpdata.woo.currency,
118			};
119				
120			gtag( 'event', 'view_item_list', payload_o );
121			if ( fp.main.debug ) console.log( '[FP] GA4/GAds view_item_list event:', payload_o );
122		};
123
124		if ( single_arr.length > 0 ) {
125
126			let impress_evt_name = 'view_item';
127			if ( fp.woo?.force_item_view_on_url && fp.woo?.force_item_view_on_url.some( url_part => document.location.href.includes(url_part) ) ) {
128				impress_evt_name = 'view_item_list';
129			}
130
131			let payload_o = { 
132				'items' : single_arr, 
133				'currency' : fpdata.woo.currency,
134				'value' : value,
135				// 'send_to' : ecommerce_event_send_to
136			};
137
138			gtag( 'event', impress_evt_name, payload_o );
139			if ( fp.main.debug ) console.log( '[FP] GA4/GAds ' + impress_evt_name + ' event:', payload_o );
140		}
141	};
142
143	if ( ! ( fp.woo.dont_track_views_after_refresh && fpdata.refreshed ) ){
144		track_woo_impress();
145		FP.addAction( ['woo_impress'], track_woo_impress );
146	}
147
148	// TRACK DEFAULT VARIANT VIEW
149	// TRACK VARIANT VIEWS
150
151	function woo_variant_view( variant_id ){
152
153		if (typeof gtag === 'undefined' || !fpdata.woo.products[variant_id]) return;
154
155		let prod = fpdata.woo.products[variant_id],
156			prod_id = FP.fns.get_woo_prod_id(prod),
157			item = {
158				'item_id': prod_id,
159				'id' : prod_id,
160				'item_name': FP.fns.get_woo_prod_name(prod),
161				'item_list_name' : 'single',
162				'price': prod.price
163			};
164
165		item = add_brand(item, prod);
166		item = add_categories(item, prod);
167
168        if ( gads_enabled ) item['google_business_vertical'] = fp.gads.business_type;
169
170		let payload_o = {
171			'items': [item],
172			'currency': fpdata.woo.currency,
173			'value': prod.price,
174			// 'send_to' : ecommerce_event_send_to
175		};
176
177		gtag('event', 'view_item', payload_o);
178		if (fp.main.debug) console.log('[FP] GA4/GAds view_item event:', payload_o);
179	}
180
181	FP.addAction( ['woo_variant_view'], woo_variant_view );
182	FP.addAction( ['woo_def_variant_view'], woo_variant_view );
183
184	// TRACK TEASER CLICKS
185	// TRACK ADD TO CART / REMOVE FROM CART
186	// TRACK ADD TO WISHLIST
187
188	function track_items( data, event_name ){
189
190		if ( typeof gtag === 'undefined' ) return;
191		
192		let products_data = data.products,
193			event_value = data.value,
194			items_a = [],
195			send_event_to_gads = event_name == 'add_to_cart' && gads_enabled && fp.gads.woo_add_to_cart_conv_id;
196
197		if ( ! send_event_to_gads && ! ga41_enabled ) return;
198		
199		products_data.forEach( prod_a => {
200
201			let prod = prod_a[0],
202				prod_id = FP.fns.get_woo_prod_id( prod ),
203				qty = prod_a[1] || prod.qty || 1,
204				item = {
205				'item_id' : prod_id,
206				'id' : prod_id,
207				'item_name' : FP.fns.get_woo_prod_name( prod ),
208				'price' : prod.price,
209				'quantity' : qty,
210			};
211
212			item = add_index(item, prod);
213			item = add_list_name(item, prod);
214			item = add_brand(item, prod);
215			item = add_categories(item, prod);
216
217            if ( send_event_to_gads ) item['google_business_vertical'] = fp.gads.business_type;
218
219			items_a.push( item );
220		} );
221
222		if ( items_a.length == 0 ) return false;
223
224		let payload_o = {
225			'items' : items_a, 
226			'value' : event_value, 
227			'currency' : fpdata.woo.currency, 
228			// 'send_to' : ecommerce_event_send_to
229		};
230
231		gtag( 'event', event_name, payload_o );
232		if ( fp.main.debug ) console.log( '[FP] GA4/GAds ' + event_name + ' event: ', payload_o );
233
234        // GADS Conversion event
235        if ( send_event_to_gads ) {
236			let payload_gads = {...payload_o};
237            payload_gads['send_to'] = ( fp.gads.id2 || fp.gads.id ) + '/' + fp.gads.woo_add_to_cart_conv_id;
238            gtag('event', 'conversion', payload_gads );
239            if ( fp.main.debug ) console.log('[FP] GAds add_to_cart conversion', payload_gads);
240        }
241	}
242
243	FP.addAction( ['woo_teaser_click'], data => {
244		track_items( data, 'select_item' );
245	} );
246
247	FP.addAction( ['woo_add_to_cart'], data =>{
248		track_items( data, 'add_to_cart' );
249	} );
250
251	if ( fp.woo.cart_to_track ) track_items( fp.woo.cart_to_track, 'add_to_cart' ); // when ATC is tracked in cart
252
253	FP.addAction( ['woo_add_to_wishlist'], data => {
254		track_items( data, 'add_to_wishlist');
255	} );
256
257	FP.addAction( ['woo_remove_from_cart'], data => {
258		track_items( data, 'remove_from_cart' );
259	} );
260
261	// TRACK CHECKOUT
262	// TRACK ORDER
263
264	function track_cart( type ){ // type can be either "checkout" or "order"
265
266		// Early returns
267		
268		if ( typeof gtag === 'undefined' ) return;
269
270		let ga4_server_tracking = ga41_enabled && fp.main.is_pro && fp.ga41.server_side && fp.ga41.adv_orders;
271
272		if ( type == 'order' && ga4_server_tracking ) {
273			if ( fp.main.debug ) console.log( '[FP] GA4 purchase event is tracked by the server-side script' );
274			if ( ! fp.loaded.includes('gads') ) return;
275		}
276
277		// Vars
278
279		let items_type = fp.woo.variable_tracking_method == 'track_parents' ? 'joined_items' : 'items',
280			items_a = [],
281			cart = type == 'checkout' ? fpdata.woo.cart : fpdata.woo.order,
282			event_name = type == 'checkout' ? 'begin_checkout' : 'purchase',
283			gads_conv_id = false;
284
285		if ( gads_enabled ) {
286			if ( type == 'checkout' && fp.gads.woo_checkout_conv_id ) {
287				gads_conv_id = fp.gads.woo_checkout_conv_id;
288			} else if ( type == 'order' && fp.gads.woo_conv_id ) {
289				gads_conv_id = fp.gads.woo_conv_id;
290			}
291		}
292
293		if ( type == 'order' && ga4_server_tracking && ! gads_conv_id ) {
294			return;
295		}
296
297		// Get items
298
299		for ( const id in cart[items_type] ) {
300
301			let prod = cart[items_type][id],
302				prod_id = FP.fns.get_woo_prod_id(prod),
303				item = {
304					'item_id' : prod_id,
305					'id' : prod_id,
306					'item_name' : FP.fns.get_woo_prod_name(prod),
307					'price' : prod.price,
308					'quantity' : prod.qty,
309				};
310
311			item = add_brand(item, prod);
312			item = add_categories(item, prod);
313			
314			if ( gads_enabled ) item['google_business_vertical'] = fp.gads.business_type;
315
316			items_a.push( item );
317		}
318
319		if ( items_a.length == 0 ) return false;
320
321		let payload_o = {
322			'items' : items_a, 
323			'value' : cart.value,
324			'currency' : fpdata.woo.currency,
325			'send_to' : ecommerce_event_send_to
326		};
327
328		let console_text = '[FP] GA4/GAds';
329
330		if ( cart.coupons && cart.coupons.length > 0 ) payload_o['coupon'] = cart.coupons.join(',');
331		
332		if ( type == 'order' ) {
333		
334			payload_o['transaction_id'] = fpdata.woo.order.id;
335			payload_o['tax'] = fpdata.woo.order.tax || 0;
336			payload_o['shipping'] = fpdata.woo.order.shipping || 0;	
337			
338			// Send purchase event only to GAds if GA4 is tracked by the server
339			if ( ga4_server_tracking && gads_enabled && gads_conv_id ) {
340				payload_o['send_to'] = ( fp.gads.id2 || fp.gads.id );
341				console_text = '[FP] GAds';
342			}
343		}
344		
345		gtag( 'event', event_name, payload_o );
346		if ( fp.main.debug ) console.log( console_text + ' ' + event_name + ' event: ', payload_o );
347
348		// GADS Conversion event
349		if ( ! gads_enabled || ! gads_conv_id ) return;
350
351		let payload_gads = {...payload_o};
352		
353		payload_gads['send_to'] = ( fp.gads.id2 || fp.gads.id ) + '/' + gads_conv_id; // we set it again in case it was not set before
354		gtag('event', 'conversion', payload_gads );
355		if ( fp.main.debug ) console.log('[FP] GAds ' + event_name + ' conversion', payload_gads);
356	}
357
358	// track order
359	if ( fp.woo.order_data_ready ) {
360		track_cart('order');
361	}
362
363	// track the start of checkout (except when the whole page or its part is refreshed)
364	if ( ! fpdata.refreshed ) {
365		if ( fp.woo.checkout_data_ready ) {
366			if ( fp.ga41 ) fp.ga41.woo_checkout_tracked = true;
367			if ( fp.gads ) fp.gads.woo_checkout_tracked = true;
368			track_cart('checkout');
369		} else {
370			document.addEventListener( 'fupi_woo_checkout_data_ready', ()=>{
371				if ( ( fp.ga41 && ! fp.ga41.woo_checkout_tracked ) || ( fp.gads && ! fp.gads.woo_checkout_tracked ) ) {
372					if ( fp.ga41 ) fp.ga41.woo_checkout_tracked = true;
373					if ( fp.gads ) fp.gads.woo_checkout_tracked = true;
374					track_cart('checkout');
375				}
376			})
377		};
378	}
379
380	FP.loaded('gtools_woo_footer');
381};
382
383// STANDARD EVENTS
384
385function fupi_ga4_footer(nr){
386
387	if ( ! fp.loaded.includes('ga4' + nr) ) return;
388	
389	let _ga = fp['ga4' + nr];
390
391	// TRACK SCROLL
392
393	if ( _ga.track_scroll_method && _ga.track_scroll ) {
394		
395		_ga.track_scroll = FP.formatScrollPoints( _ga.track_scroll );
396		
397		FP.addAction( ['scroll', 'active_time_tick'], function(){
398
399			if ( typeof gtag === 'undefined' ) return;
400
401			if (
402				_ga.track_scroll.length > 0 &&
403				fpdata.activity.total >= fp.track.track_scroll_time &&
404				fpdata.scrolled.current_px >= fp.track.track_scroll_min
405			){
406				var reachedPoint = FP.isScrollTracked( _ga.track_scroll );
407				
408				if ( reachedPoint ) {
409					// remove reached scroll points from array
410					_ga.track_scroll = _ga.track_scroll.filter( function( point ){ return point > reachedPoint } );
411
412					var evt_name = 'scrolled_' + reachedPoint,
413						data = { 'send_to': fp['ga4' + nr].id2 || fp['ga4' + nr].id };
414					
415					if ( _ga.track_scroll_method == 'params' ) {
416						evt_name = 'scroll';
417						data['percent_scrolled'] = reachedPoint;
418					};
419
420					FP.fns.send_ga4_evt( nr, evt_name, data );
421				}
422			}
423		} );
424	}
425
426	// TRACK VIEWS OF ELEMENTS
427	// for performance: waits 250ms for dynamically generated content to finish
428
429	FP.fns['ga4' + nr + '_observe_inters'] = ( newly_added_els = false ) => {
430		
431		let send_el_view_evt = ( el, nr ) => {
432
433			if ( typeof gtag === 'undefined' ) return;
434			
435			let evt_name = el.dataset['ga4' + nr + '_view'],
436				data = { 'send_to': fp['ga4' + nr].id2 || fp['ga4' + nr].id };
437			
438			if ( _ga.track_views_method == 'params' ) {
439				data['viewed_element'] = evt_name;
440				evt_name = 'element_view';
441			};
442			
443			FP.fns.send_ga4_evt( nr, evt_name, data );
444		};
445		
446		FP.intersectionObserver( newly_added_els, _ga.track_views, 'ga4' + nr, send_el_view_evt, true, nr );
447	}
448	
449	if ( _ga.track_views_method && _ga.track_views ) setTimeout( ()=>{
450		FP.fns['ga4' + nr + '_observe_inters']();
451		FP.addAction( ['dom_modified'], FP.fns['ga4' + nr + '_observe_inters'] );
452	}, 250 ); // wait for any dynamically generated content
453	
454	// TRACK AFFILIATE LINKS
455
456	if ( _ga.track_affil_method && _ga.track_affiliate ) {
457
458		FP.addAction( ['click'], function(){
459
460			if ( typeof gtag === 'undefined' ) return;
461			
462			var trackedAffLink = FP.getTrackedAffiliateLink( _ga.track_affiliate );
463
464			if ( ! trackedAffLink ) return;
465			
466			var evt_name = trackedAffLink,
467				data = { 'send_to': fp['ga4' + nr].id2 || fp['ga4' + nr].id };
468			
469			if ( _ga.track_affil_method == 'params' ) {
470				evt_name = 'affiliate_link_click';
471				data['affiliate_link_click'] = trackedAffLink;
472			};
473			
474			FP.fns.send_ga4_evt( nr, evt_name, data );
475		} );
476	}
477
478	// TRACK CLICKS ON EMAIL AND TEL LINKS
479
480	if ( _ga.track_email_tel ) {
481		FP.addAction( ['click'], function(){
482			
483			if ( typeof gtag === 'undefined' ) return;
484
485			if ( fpdata.clicked.link && ( fpdata.clicked.link.is_email || fpdata.clicked.link.is_tel ) ) {
486				
487				var link_type = fpdata.clicked.link.is_email ? 'email' : 'tel',
488					evt_name = link_type + '_click_' + ( fpdata.clicked.link.safe_email || fpdata.clicked.link.safe_tel ),
489					data = { 'send_to': fp['ga4' + nr].id2 || fp['ga4' + nr].id };
490
491				if ( _ga.track_email_tel == 'params' ){
492					evt_name = link_type + '_link_click'
493					data['contact_click'] = fpdata.clicked.link.safe_email || fpdata.clicked.link.safe_tel;
494				}
495				
496				FP.fns.send_ga4_evt( nr, evt_name, data );
497			}
498		} );
499	}
500
501	// TRACK FORM SUBMITS
502
503	if ( _ga.track_forms_method && _ga.track_forms ) {
504
505		FP.addAction( ['form_submit'], function(){
506			
507			if ( typeof gtag === 'undefined' ) return;
508
509			var submittedForm = FP.getSubmittedForm( _ga.track_forms );
510
511			if ( submittedForm ){
512
513				var evt_name = submittedForm,
514					data = { 'send_to': fp['ga4' + nr].id2 || fp['ga4' + nr].id };
515
516				if ( _ga.track_forms_method == 'params' ){
517					evt_name = 'form_submit';
518					data['submitted_form'] = submittedForm;
519				}
520				
521				FP.fns.send_ga4_evt( nr, evt_name, data );
522			}
523		})
524	}
525
526	// TRACK CLICKS ON PAGE ELEMENTS
527
528	if ( _ga.track_elems_method && _ga.track_elems ) {
529
530		FP.addAction( ['click'], function(){
531
532			if ( typeof gtag === 'undefined' ) return;
533
534			var trackedElName  = FP.getClickTarget( _ga.track_elems );
535
536			if ( trackedElName ) {
537
538				var evt_name = trackedElName,
539					data = { 'send_to': fp['ga4' + nr].id2 || fp['ga4' + nr].id };
540
541				if ( _ga.track_elems_method == 'params' ){
542					evt_name = 'element_click',
543					data['element_click'] = trackedElName;
544				}
545				
546				FP.fns.send_ga4_evt( nr, evt_name, data );
547			}
548		})
549	}
550
551	/* <fs_premium_only> */
552	
553	if ( fp.main.is_pro ) {
554		
555		// TRACK ENGAGEMENT
556		// sends current for total calculations
557		if ( _ga.track_engagement ) {
558			FP.addAction( ['page_in_blur'], function (){
559				
560				var data = { 
561					'send_to': _ga.id2 || _ga.id, 
562					'user_engagement_time' : fpdata.activity.current, 
563				};
564
565				if ( typeof gtag !== 'undefined' ) gtag( 'event', 'user_engagement_time', data);
566				if ( fp.main.debug ) console.log('[FP] GA4 #' + nr + ' event: user_engagement_time', data);
567			} );
568		}
569	}
570	/* </fs_premium_only> */
571
572	FP.loaded('ga4' + nr + '_footer');
573};
574
575function fupi_gads_footer(){
576
577	// TRACK EMAIL LINKS
578
579	if ( fp.gads.track_email ) {
580		FP.addAction( ['click'], function(){
581			if ( fpdata.clicked.link && fpdata.clicked.link.is_email ) {
582				gtag( 'event', 'conversion', {'send_to': ( fp.gads.id2 || fp.gads.id ) + '/' + fp.gads.track_email } );
583				if ( fp.main.debug ) console.log('[FP] GAds conversion event: email link click', ( fp.gads.id2 || fp.gads.id ) + '/' + fp.gads.track_email );
584			}
585		} );
586	}
587
588	// TRACK TEL LINKS
589
590	if ( fp.gads.track_tel ) {
591		FP.addAction( ['click'], function(){
592			if ( fpdata.clicked.link && fpdata.clicked.link.is_tel ) {
593				gtag( 'event', 'conversion', {'send_to': ( fp.gads.id2 || fp.gads.id ) + '/' + fp.gads.track_tel } );
594				if ( fp.main.debug ) console.log('[FP] GAds conversion event: tel link click', ( fp.gads.id2 || fp.gads.id ) + '/' + fp.gads.track_tel );
595			}
596		} );
597	}
598
599	// TRACK VIEWS OF ELEMENTS
600	// for performance: waits 250ms for dynamically generated content to finish
601
602	FP.fns.gads_observe_inters = ( newly_added_els = false ) => {
603
604		let send_el_view_evt = el => {
605
606			if ( typeof gtag === 'undefined' ) return;
607
608			gtag( 'event', 'conversion', {'send_to': ( fp.gads.id2 || fp.gads.id ) + '/' + el.dataset['gads_view'] } );
609			
610			if ( fp.main.debug ) console.log('[FP] GAds conversion event: element view', ( fp.gads.id2 || fp.gads.id ) + '/' + el.dataset['gads_view'] );
611		};
612		
613		FP.intersectionObserver( newly_added_els, fp.gads.track_views, 'gads', send_el_view_evt, true);
614	}
615	
616	if ( fp.gads.track_views ) setTimeout( ()=>{
617		FP.fns.gads_observe_inters();
618		FP.addAction( ['dom_modified'], FP.fns.gads_observe_inters );
619	}, 250 ); 
620
621	// TRACK AFFILIATE LINKS
622
623	if ( fp.gads.track_affiliate ) {
624		FP.addAction( ['click'], function(){
625			var trackedAffLink_convID = FP.getTrackedAffiliateLink( fp.gads.track_affiliate );
626			if ( trackedAffLink_convID ) {
627				gtag( 'event', 'conversion', {'send_to' : ( fp.gads.id2 || fp.gads.id ) + '/' + trackedAffLink_convID });
628				if ( fp.main.debug ) console.log('[FP] GAds conversion event: affiliate click', ( fp.gads.id2 || fp.gads.id ) + '/' + trackedAffLink_convID );
629			}
630		} );
631	}
632
633	// TRACK FORM SUBMITS
634
635	if ( fp.gads.track_forms ) {
636		FP.addAction( ['form_submit'], function(){
637			var submittedForm_convID = FP.getSubmittedForm( fp.gads.track_forms );
638			if ( submittedForm_convID ){
639				gtag( 'event', 'conversion', {'send_to' : ( fp.gads.id2 || fp.gads.id ) + '/' + submittedForm_convID } );
640				if ( fp.main.debug ) console.log('[FP] GAds conversion event: form submit', ( fp.gads.id2 || fp.gads.id ) + '/' + submittedForm_convID);
641			}
642		})
643	}
644
645	// TRACK CLICKS ON PAGE ELEMENTS
646
647	if ( fp.gads.track_elems ) {
648		FP.addAction( ['click'], function(){
649			var trackedEl_convID  = FP.getClickTarget( fp.gads.track_elems );
650			if ( trackedEl_convID ) {
651				gtag( 'event', 'conversion', { 'send_to' : ( fp.gads.id2 || fp.gads.id ) + '/' + trackedEl_convID } );
652				if ( fp.main.debug ) console.log('[FP] GAds conversion event: element click', ( fp.gads.id2 || fp.gads.id ) + '/' + trackedEl_convID );
653			}
654		})
655	}
656
657	FP.loaded('gads_footer');
658};
659
660function fupi_ga41_footer(){
661	fupi_ga4_footer( 1 );
662};
663
664function fupi_ga42_footer(){
665	fupi_ga4_footer( 2 );
666};
667
668FP.load('ga41_footer', 'fupi_ga41_footer', ['ga41_config', 'footer_helpers']);
669FP.load('ga42_footer', 'fupi_ga42_footer', ['ga42_config', 'footer_helpers']);
670FP.load('gads_footer', 'fupi_gads_footer', ['gads_config', 'footer_helpers']);
671FP.load('gtools_woo_footer', 'fupi_gtools_woo_footer', ['gtag_config','woo', 'footer_helpers']);

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.