PageSourceSearch

https://shop.halleckvineyard.com/apps/mansion-flare/scripts/flareai_tag_manager.js

js halleckvineyard.com collected 2026-09-26 02:37:28 UTC 28,343 bytes, 749 lines download raw bytes

1/*
2flareai_tag_manager.js is a library script called by platform-specific script flareai_script.js
3*/
4// GLOBAL VARIABLES
5var flareAIAPIURL = "https://flareai.co/flare_api/index.php";
6var flareAIAPIResponseTimeout = 300000; // timeout is set to 5 mins
7var flareAIReferrerChannelLocalStorageName = "flareAIReferrerChannel";
8var flareAIUTMParametersLocalStorageName = "flareAIUTMParameters";
9var flareAIUserIdLocalStorageName = "flareAIUserId";
10
11// Define an array to store pageviews with timestamps
12var pageviewsWithTimestamps = [];
13var flareAICustomerJourneyLocalStorageName = "flareAICustomerJourney";
14
15// UTM PARAMETER DEFINITIONS
16var flareaiGoogleSearchUTM = "utm_source=google&utm_medium=google_search&utm_campaign=flareai_google_search&utm_id=flareai_utm_id";
17var flareaiBingSearchUTM = "utm_source=bing&utm_medium=bing_search&utm_campaign=flareai_bing_search&utm_id=flareai_utm_id";
18var flareaiDuckDuckGoSearchUTM = "utm_source=duckduckgo&utm_medium=duckduckgo_search&utm_campaign=flareai_duckduckgo_search&utm_id=flareai_utm_id";
19// console.log("document.referrer: "+document.referrer);
20// console.log("window.location.search: "+window.location.search);
21
22// LOCAL FUNCTIONS
23// Function to get the userId from localStorage or set it if not exists
24function getFlareAIUserIDFromLocalStorage() {
25  var flareAIUserId = localStorage.getItem('flareAIUserId');
26
27  // If userId does not exist, create and set it
28  if (!flareAIUserId) {
29    setFlareAIUserIDInLocalStorage();
30    flareAIUserId = localStorage.getItem('flareAIUserId');  // Retrieve the newly set userId
31  }
32
33  return flareAIUserId;
34} 
35
36// Function to set the userId in localStorage
37function setFlareAIUserIDInLocalStorage() {
38  var flareAIUserId = 'user_' + Date.now() + '_' + Math.random().toString(36).substring(2);
39  localStorage.setItem('flareAIUserId', flareAIUserId);
40}
41
42// get flareAIUTMParameters from localStorage
43function getFlareAIUTMParametersFromLocalStorage() {
44var flareAIUTMParameters = localStorage.getItem('flareAIUTMParameters');
45
46// If flareAIUTMParameters does not exist, create and set it
47if (!flareAIUTMParameters) {
48	setFlareAIUTMParametersInLocalStorage();
49	flareAIUTMParameters = localStorage.getItem('flareAIUTMParameters');  // Retrieve the newly set flareAIUTMParameters
50}
51
52return flareAIUTMParameters;
53} // getFlareAIUTMParametersFromLocalStorage
54
55// Function to set the flareAIUTMParameters in localStorage
56function setFlareAIUTMParametersInLocalStorage() {
57var urlParams = new URLSearchParams(window.location.search);
58
59var utmId = urlParams.get('utm_id');
60
61if (utmId !== 'flareai_utm_id') {
62return;
63}
64
65var flareAIUTMParameters = {};
66
67[
68'utm_id',
69'utm_source',
70'utm_medium',
71'utm_campaign',
72'utm_term',
73'utm_content'
74].forEach(function (key) {
75if (urlParams.has(key)) {
76  flareAIUTMParameters[key] = urlParams.get(key);
77}
78});
79
80localStorage.setItem('flareAIUTMParameters', JSON.stringify(flareAIUTMParameters));
81
82} // setFlareAIUTMParametersInLocalStorage
83
84// Example usage
85var flareAIUserId = getFlareAIUserIDFromLocalStorage();
86console.log('flareAIUserId', flareAIUserId);  
87
88setFlareAIUTMParametersInLocalStorage();
89var flareAIUTMParameters = getFlareAIUTMParametersFromLocalStorage();
90// console.log('flareAIUTMParameters', flareAIUTMParameters);  
91
92// ------------------------
93// Function to track pageviews with timestamps
94// ------------------------
95function trackPageviewWithTimestamp() {
96var flareAICustomerJourney = localStorage.getItem(flareAICustomerJourneyLocalStorageName);
97if ( typeof(flareAICustomerJourney) != "undefined" && flareAICustomerJourney != null ) {
98    pageviewsWithTimestamps = JSON.parse(flareAICustomerJourney);
99}
100
101// Get the current page URL
102var currentPage = window.location.href;
103var referrer = document.referrer || "";
104
105// Get the current date and time
106var timestamp = new Date().toLocaleString();
107
108// Create an object to store pageview and timestamp
109var pageviewInfo = {
110    page: currentPage,
111    referrer: referrer,
112    timestamp: timestamp
113};
114
115// Add the object to the pageviewsWithTimestamps array
116pageviewsWithTimestamps.push(pageviewInfo);
117// console.log(pageviewsWithTimestamps);
118
119// Store the updated array in local storage
120localStorage.setItem(flareAICustomerJourneyLocalStorageName, JSON.stringify(pageviewsWithTimestamps));
121
122// Log the pageview with timestamp to the console (or send to your analytics system)
123// console.log("Pageview: " + currentPage + " at " + timestamp);
124} // trackPageviewWithTimestamp
125
126
127// FUNCTION: Get value of a specified key (key=value pair) from URL
128function getParameterValueByKeyFromURL(key, url) {
129if ( !url ) var url = window.location.href;
130key = key.replace(/[\[\]]/g, "\\$&");
131var regex = new RegExp("[?&]" + key + "(=([^&#]*)|&|#|$)"),
132	results = regex.exec(url);
133if (!results) return '';
134else if (!results[2]) return '';
135else return decodeURIComponent(results[2].replace(/\+/g, " "));
136} // getParameterValueByKeyFromURL
137
138
139function getFilenameFromUrl(url) {
140// Create a new URL object
141var parsedUrl = new URL(url);
142// Get the pathname from the URL
143var pathname = parsedUrl.pathname;
144// Extract the filename from the pathname
145var filename = pathname.substring(pathname.lastIndexOf('/') + 1);
146return filename;
147} // getFilenameFromUrl
148
149function getBlogArticleTitle() {
150return (function($) { // This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.
151    var blogArticleTitle = "";
152
153    var metaPropertyOGTitleObject = $('meta[property="og:title"]');
154    if (metaPropertyOGTitleObject.length > 0) {
155      blogArticleTitle = metaPropertyOGTitleObject.attr('content');
156    } else {
157      blogArticleTitle = $('title').text();
158    }
159
160    return blogArticleTitle;
161})(jQuery);	
162} // getBlogArticleTitle
163
164
165function getBlogArticleDescription() {
166return (function($) { // This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.		
167	var blogArticleDescription = "";
168	var metaPropertyOGDescriptionObject = $('meta[property="og:description"]'); // <meta property="og:description" content="Machine Learning Models for Content Generation" />
169	if (metaPropertyOGDescriptionObject.length > 0) { 
170		blogArticleDescription = metaPropertyOGDescriptionObject.attr('content');    
171	}
172
173	if ( blogArticleDescription == "" ) {
174		var metaNameDescriptionObject = $('meta[name="description"]'); // <meta name="description" content="Tennis - New Tech Tennis - Win with New Tech Tennis"/>
175		if (metaNameDescriptionObject.length > 0) { 
176			blogArticleDescription = metaNameDescriptionObject.attr('content');    
177		}
178	}
179
180	return blogArticleDescription;	
181})(jQuery);		
182} // getBlogArticleDescription
183
184
185function getBlogArticleMainImageURL() {
186return (function($) { // This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.	
187	var blogArticleMainImageURL = "";
188
189	var metaPropertyOGImageObject = $('meta[property="og:image"]'); // <meta property="og:image" content="https://www.studiolabs.com/wp-content/uploads/2025/01/flare_content_17501.jpg" />
190	if (metaPropertyOGImageObject.length > 0) { 
191		blogArticleMainImageURL = metaPropertyOGImageObject.attr('content');    
192	}
193		
194	return blogArticleMainImageURL;	
195})(jQuery);	
196} // getBlogArticleMainImageURL
197
198
199function getBlogArticleURL() {
200var blogArticleURL = "";
201var blogArticleURL = window.location.href;
202if ( blogArticleURL.includes('?') ) {
203	var blogArticleURLArray = blogArticleURL.split('?');
204	blogArticleURL = blogArticleURLArray[0];
205}	
206
207return blogArticleURL;	
208} // getBlogArticleURL
209
210
211function getBlogArticlePublishedDate() {
212return (function($) { // This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.	
213	var blogArticleDatePublished = "";	
214
215	var metaPropertyArticlePublishedTimeObject = $('meta[property="article:published_time"]'); // <meta property="article:published_time" content="2025-01-12T12:00:00+00:00" />
216	if (metaPropertyArticlePublishedTimeObject.length > 0) { 
217		blogArticleDatePublished = metaPropertyArticlePublishedTimeObject.attr('content');    
218	}
219
220	if ( blogArticleDatePublished == "" )  {
221		var metaPropertyArticleModifiedTimeObject = $('meta[property="article:modified_time"]'); // <meta property="article:modified_time" content="2024-12-11T07:31:50+00:00" />
222		if (metaPropertyArticleModifiedTimeObject.length > 0) { 
223			blogArticleDatePublished = metaPropertyArticleModifiedTimeObject.attr('content');    
224		}
225	}
226		
227	return blogArticleDatePublished;
228})(jQuery);
229} // getBlogArticlePublishedDate
230
231
232function getBlogArticleModifiedDate() {
233return (function($) { // This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.
234	var blogArticleDateModified = "";	
235
236	var metaPropertyArticleModifiedTimeObject = $('meta[property="article:modified_time"]'); // <meta property="article:modified_time" content="2024-12-11T07:31:50+00:00" />
237	if (metaPropertyArticleModifiedTimeObject.length > 0) { 
238		blogArticleDateModified = metaPropertyArticleModifiedTimeObject.attr('content');    
239	}
240
241	if ( blogArticleDateModified == "" )  {
242		var metaPropertyArticlePublishedTimeObject = $('meta[property="article:published_time"]'); // <meta property="article:published_time" content="2025-01-12T12:00:00+00:00" />
243		if (metaPropertyArticlePublishedTimeObject.length > 0) { 
244			blogArticleDateModified = metaPropertyArticlePublishedTimeObject.attr('content');    
245		}
246	}
247		
248	return blogArticleDateModified;
249})(jQuery);
250} // getBlogArticleModifiedDate
251
252
253function getBlogArticleDataArray() {
254// console.log('in getBlogArticleDataArray');
255var blogArticleDataArray = [];
256
257blogArticleDataArray['filename'] = filename;
258
259var blogArticleTitle = getBlogArticleTitle();
260// console.log('blogArticleTitle: '+blogArticleTitle); 
261blogArticleDataArray['blogArticleTitle'] = blogArticleTitle;
262
263var blogArticleDescription = getBlogArticleDescription(); 
264// console.log('blogArticleDescription: '+blogArticleDescription); 
265blogArticleDataArray['blogArticleDescription'] = blogArticleDescription;
266
267var blogArticleMainImageURL = getBlogArticleMainImageURL();
268// console.log('blogArticleMainImageURL: '+blogArticleMainImageURL);
269blogArticleDataArray['blogArticleMainImageURL'] = blogArticleMainImageURL;
270
271var blogArticleURL = getBlogArticleURL();
272blogArticleDataArray['blogArticleURL'] = blogArticleURL;
273
274// var blogArticleDatePublished = new Date(dateText).toISOString(); // Convert to ISO 8601 format
275var blogArticleDatePublished = getBlogArticlePublishedDate();
276blogArticleDataArray['blogArticleDatePublished'] = blogArticleDatePublished;
277
278var blogArticleDateModified = getBlogArticleModifiedDate();
279blogArticleDataArray['blogArticleDateModified'] = blogArticleDateModified;
280
281// console.log(blogArticleDataArray);
282return blogArticleDataArray;
283} // getBlogArticleDataArray
284
285
286function addSEOOptimizedNewsArticleStructuredData() {
287(function($) { // This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.
288	try {
289		// console.log('$(script#flareAINewsArticleStructuredData).length: '+$('script#flareAINewsArticleStructuredData').length);	
290		if ( $('script#flareAINewsArticleStructuredData').length == 0 ) { // no script#flareAINewsArticleStructuredData exists	
291			var NewsArticleStructuredData = {
292				"@context": "https://schema.org",
293				"@type": "NewsArticle",
294				"headline": blogArticleDataArray['blogArticleTitle'],
295				"datePublished": blogArticleDataArray['blogArticleDatePublished'],
296				"dateModified": blogArticleDataArray['blogArticleDateModified'],
297				"author": {
298					"@type": "Person",
299					"name": "XXX_"+newsArticleAuthorName,
300					"url": newsArticleAuthorURL
301				},
302				"publisher": {
303					"@type": "Organization",
304					"name": organizationName,
305					"logo": {
306					  "@type": "ImageObject",
307					  "url": organizationLogoURL,
308					  "width": 600,
309					  "height": 60
310					}
311				},
312				"description": blogArticleDataArray['blogArticleDescription'],
313				"articleBody": blogArticleDataArray['blogArticleDescription'],
314				"mainEntityOfPage": {
315					"@type": "WebPage",
316					"@id": blogArticleDataArray['blogArticleURL']
317					},
318				"image": {
319					"@type": "ImageObject",
320					"url": blogArticleDataArray['blogArticleMainImageURL'],
321					"height": 800,
322					"width": 1200
323					}
324				};
325			// console.log(NewsArticleStructuredData);
326
327			var scriptTag = $('<script>', {
328				type: 'application/ld+json',
329				id: 'flareAINewsArticleStructuredData',  // Add the ID attribute here
330				html: JSON.stringify(NewsArticleStructuredData)
331			});
332			// console.log('scriptTag: '+scriptTag);
333			$('head').append(scriptTag);
334		} // no script#flareAINewsArticleStructuredData exists
335	} catch (error) {
336		console.error("An error occurred in flareAINewsArticleStructuredData:", error.message);
337	} 
338})(jQuery);
339} // addSEOOptimizedNewsArticleStructuredData
340
341
342function addSEOOptimizedFAQPageStructuredData(){
343(function($) { // This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.
344// console.log('in addSEOOptimizedFAQPageStructuredData');
345try {	
346	if ( $('script#flareAIFAQPageStructuredData').length == 0 ) { // no script#flareAIFAQPageStructuredData exists	
347		// Initialize an empty array to hold the question-answer pairs
348		var faqArray = [];
349
350		$('h3.flareAIFAQ_Question').each(function () {
351			var question = $(this).text();
352			var answer = $(this).next('p.flareAIFAQ_Answer').text();
353
354			faqArray.push({
355				question: question.trim(),
356				answer: answer.trim()
357			});
358		});
359
360		// Log the resulting array to the console
361		// console.log(faqArray);
362		if (faqArray.length > 0) { // faqArray is not empty
363			// Initialize an empty array for JSON-LD format
364			var faqJsonLd = {
365			  "@context": "https://schema.org",
366			  "@type": "FAQPage",
367			  "mainEntity": []
368			};
369
370			// Iterate over the faqArray and add each question-answer pair to the JSON-LD
371			$.each(faqArray, function(index, faq) {
372				if ( faq.answer != "" ) {
373					faqJsonLd.mainEntity.push({
374						"@type": "Question",
375						"name": faq.question,
376						"acceptedAnswer": {
377							"@type": "Answer",
378							"text": faq.answer
379						}
380					});
381				}
382			});
383
384			// Convert the faqJsonLd object to a JSON string
385			var faqJsonLdScriptTag = JSON.stringify(faqJsonLd, null, 2);
386
387			// Create a <script> element to insert the JSON-LD into the DOM
388			$('<script>', {
389				type: 'application/ld+json',
390				id: 'flareAIFAQPageStructuredData',  // Add the ID attribute here
391				html: faqJsonLdScriptTag
392			}).appendTo('head');
393		} // faqArray is not empty
394	} // no script#flareAIFAQPageStructuredData exists
395} catch (error) {
396	console.error("An error occurred in flareAIFAQPageStructuredData:", error.message);
397} 
398})(jQuery);
399} // addSEOOptimizedFAQPageStructuredData
400
401
402/*
403Record form submitted data. Both for no-iframe and iframe. In the case of iframe thisFormObject is null
404*/
405function fDST(thisFormObject = null, flareAIAPIURL, flareAIAPIResponseTimeout, fDSTPostData, conversionType="Confirmed Conversion") {
406(function($) {	// This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.
407	// console.log('in fDST')
408	// console.log('in fDST fDSTPostData', fDSTPostData); 
409	
410	if ( domainName == "jupiterchev.com" ) {
411		return;
412	}
413	
414	// initialize
415	var isAllRequiredFieldsFilledTrueOrFalse = true; 
416	var fDSTAttributesArray = {};
417	var formDataArray = {};
418	var excludedFields = ['g-recaptcha-response', 'g-recaptcha-hidden', 'hs_context', 'state_87', 'input_captcha_prefix_8']; // Add field names to exclude 
419		
420	if ( thisFormObject !== null) { // no-iframe
421		// console.log("IN NO-IFRAME");
422		var requiredFields = [];
423		// Find all the required fields within this form
424		thisFormObject.find("[required]").each(function () {
425		  var fieldName = $(this).attr("name");
426		  requiredFields.push(fieldName);
427		});
428		// console.log('requiredFields', requiredFields);
429	
430		// Example: Log the required fields array to the console
431		// console.log("Form submitted. Required fields: ", requiredFields);
432
433		// CHECK FOR ALL REQUIRED FIELDS IN THE FOR ARE FILLED OR NOT
434		requiredFields.forEach(function (fieldName) {
435		  var input = thisFormObject.find(`[name="${fieldName}"]`);
436		  var value = input.val().trim();
437		  if (!value) { // required fiels valued is empty
438			isAllRequiredFieldsFilledTrueOrFalse = false;
439		  } // required fiels valued is empty
440		});
441		// console.log('isAllRequiredFieldsFilledTrueOrFalse', isAllRequiredFieldsFilledTrueOrFalse);
442		
443		var formDataArray = {};
444		if (
445			fDSTPostData.hasOwnProperty('fDSTAttributesArray') &&
446			fDSTPostData['fDSTAttributesArray']
447		) {
448			fDSTAttributesArray = fDSTPostData['fDSTAttributesArray'];
449			delete fDSTPostData['fDSTAttributesArray'];
450		}
451
452		thisFormObject.find('input, select, textarea').each(function (index) { // loop each form field
453			var field = $(this);
454			var fieldName =
455				field.attr('name') ||
456				field.attr('id') ||
457				'field_' + index;
458				
459			if ($.inArray(fieldName, excludedFields) === -1) {
460				if (field.is(':checkbox')) {
461					formDataArray[fieldName] = field.is(':checked') ? field.val() : '';
462				}
463				else if (field.is(':radio')) {
464					if (field.is(':checked')) {
465						formDataArray[fieldName] = field.val();
466					}
467				}
468				else {
469					formDataArray[fieldName] = field.val();
470				}
471			}
472		}); // loop each form field
473	} else { // iframe
474		// console.log("IN IFRAME");
475		// console.log('fDSTPostData: ', fDSTPostData);
476		/*
477		EXAMPLE: fDSTPostData = {"firstname": "test3 first name",
478            "lastname": "test3 last name",
479            "mobilephone": "+11888888888"
480		};
481		*/
482		if ( fDSTPostData.hasOwnProperty('fDSTAttributesArray') && fDSTPostData['fDSTAttributesArray'] ) {
483			// console.log("fDSTPostData['fDSTAttributesArray'] exists:", fDSTPostData['fDSTAttributesArray']);
484			formData = fDSTPostData['fDSTAttributesArray'];
485			delete fDSTPostData['fDSTAttributesArray']; // This will remove the key from the fDSTPostData object entirely.
486		
487			// Loop through key-value pairs in submissionValues
488			Object.entries(formData).forEach(function([key, value]) {
489				// console.log(key, value);
490				// console.log("key: ", key);
491				if ($.inArray(key, excludedFields) === -1) { // key not in excludedFields
492					// console.log("ADDED key: ", key);
493					formDataArray[key] = value;
494				} // key not in excludedFields
495			});
496		}
497	} // no-iframe OR iframe 
498
499	// COMMON TO IFRAME AND NON IFRAME DATA SAVING
500	if ( isAllRequiredFieldsFilledTrueOrFalse == true ) { // all required fields are filled 
501		
502		fDSTAttributesArray['formDataArray'] = formDataArray;
503		fDSTAttributesArray['formDataLandingPageURL'] = window.location.href;
504		fDSTAttributesArray['landingPageURL'] = "";
505		fDSTAttributesArray['flareAIUserId'] = flareAIUserId;
506		fDSTAttributesArray['conversionType'] = conversionType;
507		var flareAICustomerOrderJourney = [];		
508		var flareAICustomerJourney = localStorage.getItem(flareAICustomerJourneyLocalStorageName);
509		if ( typeof(flareAICustomerJourney) != "undefined" && flareAICustomerJourney != null ) {
510			flareAICustomerOrderJourney = JSON.parse(flareAICustomerJourney);
511			fDSTAttributesArray['landingPageURL'] = flareAICustomerOrderJourney[0]['page'];
512		}
513		fDSTAttributesArray['flareAICustomerOrderJourney'] = flareAICustomerOrderJourney;
514		// console.log("Form submitted with data:", fDSTAttributesArray);
515		
516		var fDSTAttributesJSON = JSON.stringify(fDSTAttributesArray);
517		// console.log("fDSTAttributesJSON: "+fDSTAttributesJSON);
518		fDSTPostData['fDSTAttributesJSON'] = fDSTAttributesJSON;	
519		// console.log("fDSTPostData", fDSTPostData);	
520		if (navigator.sendBeacon) { // browser supports beacon
521			// console.log('browser supports beacon');
522			var fDSTPostDataForSendBeacon = new FormData();
523			for (var key in fDSTPostData) { // each element
524			  if (fDSTPostData.hasOwnProperty(key)) {
525				fDSTPostDataForSendBeacon.append(key, fDSTPostData[key]);
526			  }
527			} // each element
528			fDSTPostDataForSendBeacon.append('requestType', 'sendBeacon'); // used to avaoid CORB Warning message displayed in console
529			// console.log("fDSTPostData", fDSTPostDataForSendBeacon)
530			var resultFDST = navigator.sendBeacon(flareAIAPIURL, fDSTPostDataForSendBeacon);
531			if (resultFDST) { 
532				// console.log('Successfully queued fDST!');
533				if ( conversionType == "Confirmed Conversion" ) {
534					localStorage.clear();
535					flareAIUserId = getFlareAIUserIDFromLocalStorage();
536					// console.log('flareAIUserId', flareAIUserId);
537				}
538			} else {
539			  // console.log('Failure queing fDST');
540			}
541		} else { // No Beacon support
542			// console.log('browser don\'t supports beacon');
543			$.ajax({
544				url: flareAIAPIURL,
545				type: "POST",
546				data: fDSTPostData,
547				timeout: flareAIAPIResponseTimeout,
548			}).done( function(resultResponsePost) {
549				// console.log('resultResponsePost: '+JSON.stringify(resultResponsePost));
550				if ( conversionType == "Confirmed Conversion" ) {
551					localStorage.clear();
552					flareAIUserId = getFlareAIUserIDFromLocalStorage();
553					// console.log('flareAIUserId', flareAIUserId);
554				}
555			}).fail(function(jqueryXMLHttpRequest, jqueryHttpRequestTextStatus) {
556				// console.log( "Request failed in error: " + jqueryHttpRequestTextStatus );
557			}).always(function() {
558			});
559		} // browser supports beacon OR No Beacon support
560	} // all required fields are filled
561})(jQuery);
562
563} // fDST
564
565
566function isURLAttributableToFlare() {
567jQuery(function ($) { // This pattern is called a jQuery IIFE (Immediately Invoked Function Expression) and ensures $ always refers to jQuery inside that scope.
568	var referrer = document.referrer || "";
569	var referrerDomain = "";
570
571	try {
572		if (referrer !== "") {
573			referrerDomain = new URL(referrer).hostname.toLowerCase();
574		}
575	} catch (err) {
576		// console.log("Invalid referrer:", referrer);
577	}
578	// console.log("referrer:", referrer);
579	// console.log("referrerDomain:", referrerDomain);
580
581	var isSearchEngineReferrer =
582		referrerDomain.indexOf("google") !== -1 ||
583		referrerDomain.indexOf("bing") !== -1 ||
584		referrerDomain.indexOf("yahoo") !== -1 ||
585		referrerDomain.indexOf("duckduckgo") !== -1;
586	// console.log('isSearchEngineReferrer', isSearchEngineReferrer);
587	
588	if (isSearchEngineReferrer) {
589		var isURLAttributableToFlarePostData = {
590			operation: 'get',
591			object: 'isURLAttributableToFlare',
592			applicationServiceId: 5,
593			domainName: domainName,
594			url: window.location.href,
595			referrerDomain: referrerDomain
596		};
597		// console.log('isURLAttributableToFlarePostData', isURLAttributableToFlarePostData);
598		$.ajax({
599			url: flareAIAPIURL,
600			type: "POST",
601			data: isURLAttributableToFlarePostData,
602			timeout: flareAIAPIResponseTimeout,
603		}).done( function(resultResponsePost) {
604			// console.log('resultResponsePost: '+JSON.stringify(resultResponsePost));
605			if (resultResponsePost.result != false) {
606				// {"result":{"utmSource":"flareai_always_on_seo_agent","utmCampaign":"ZmxhcmVBSSB0cmFja2luZyAoZmxhcmVpX3V0bV9pZCkgZXhpc3RzLiBHcm93dGggaW4gcGFnZSByYW5raW5nIChBdmVyYWdlIG9yZ2FuaWMgcG9zaXRpb24gLSBBT1ApIDE1IHRvIDUgb24gWWFob28u"}}
607				
608				var currentURL = new URL(window.location.href);
609				var flareAIUTMParameters = {};
610				if (!currentURL.searchParams.has("utm_id")) {
611					currentURL.searchParams.set("utm_id", "flareai_utm_id");
612				}
613				flareAIUTMParameters["utm_id"] = "flareai_utm_id";
614
615				if ( resultResponsePost.result.utmSource) {
616					flareAIUTMParameters["utm_source"] = resultResponsePost.result.utmSource;
617					if (!currentURL.searchParams.has("utm_source")) {
618						currentURL.searchParams.set("utm_source", resultResponsePost.result.utmSource);
619					}
620				}
621				
622				if ( resultResponsePost.result.utmCampaign) {
623					flareAIUTMParameters["utm_campaign"] = resultResponsePost.result.utmCampaign;
624					if (!currentURL.searchParams.has("utm_campaign")) {
625						currentURL.searchParams.set("utm_campaign", resultResponsePost.result.utmCampaign);
626					}
627				}
628				
629				// SET LS
630				localStorage.setItem('flareAIUTMParameters', JSON.stringify(flareAIUTMParameters));
631				
632				window.history.replaceState({}, "", currentURL.toString());
633				// console.log("Updated URL:", currentURL.toString());
634			}			
635		}).fail(function(jqueryXMLHttpRequest, jqueryHttpRequestTextStatus) {
636			// console.log( "Request failed in error: " + jqueryHttpRequestTextStatus );
637		}).always(function() {
638		});		
639	}
640}); // End of JQuery Wrapper
641} // isURLAttributableToFlare 
642
643if (typeof window_url == 'undefined') {
644	var window_url = window.location.href;
645}
646// console.log('window_url: '+window_url);
647if (window_url.endsWith("/")) {
648  window_url = window_url.slice(0, -1);
649}
650var filename = getFilenameFromUrl(window_url)
651// console.log('filename 1: '+filename); 
652
653// ADD flareAI CSS
654var styleElement = document.createElement("style");
655styleElement.type = "text/css";
656styleElement.innerHTML = `
657  .flareAICTAParagraph {
658	padding: 15px 20px;
659    box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
660    transition: box-shadow 0.3s ease;
661  }
662  .flareAICTAParagraph:hover {
663    box-shadow: 8px 8px 15px rgba(0,0,0,0.4);
664  }
665`;
666document.head.appendChild(styleElement);
667
668
669trackPageviewWithTimestamp();
670isURLAttributableToFlare();
671
672// FAQ STRUCTURED DATA
673// console.log('calling addSEOOptimizedFAQPageStructuredData');
674if (typeof jQuery != 'undefined') { // jquery not currently loaded
675	addSEOOptimizedFAQPageStructuredData();
676}
677
678// JQUERY TRIGGER FUNCTIONS
679
680/*
681GET EARNED CLICK AS CONVERSION
682*/
683document.addEventListener('click', function(event) {
684	// console.log('Click event');
685
686	var clickedElement = null;
687	var link = null;
688
689	if (event.target && event.target.closest) {
690		clickedElement = event.target.closest('a, button, [role="button"]');
691		link = event.target.closest('a');
692	}
693
694	var clickedText = "";
695	if (clickedElement !== null && clickedElement.textContent) {
696		clickedText = clickedElement.textContent.trim().toLowerCase();
697	}
698
699	var eventId = "";
700	var eventName = "";
701
702	if (link !== null && link.pathname == '/cart') {
703		eventId = "flareAIGAEvent_Cart_Click";
704		eventName = "Cart Click";
705	} else if (clickedText.indexOf('add to cart') !== -1) {
706		eventId = "flareAIGAEvent_Add_To_Cart_Click";
707		eventName = "Add To Cart Click";
708	} else if (clickedText.indexOf('check out') !== -1) {
709		eventId = "flareAIGAEvent_Check_Out_Click";
710		eventName = "Check Out Click";
711	} else if (clickedText.indexOf('continue shopping') !== -1) {
712		eventId = "flareAIGAEvent_Continue_Shopping_Click";
713		eventName = "Continue shopping Click";
714	} else if (clickedText.indexOf('buy it now') !== -1) {
715		eventId = "flareAIGAEvent_Buy it now_Click";
716		eventName = "Buy it now Click";
717	}	
718	
719
720	if (eventId === "" && eventName === "") {
721		return;
722	}
723
724	var currentURL = new URL(window.location.href);
725	if (!currentURL.searchParams.has("ref") && typeof getFlareAIUserIDFromLocalStorage === "function") {
726		var flareAIUserId = getFlareAIUserIDFromLocalStorage();
727		console.log('flareAIUserId', flareAIUserId);
728
729		if (flareAIUserId) {
730			currentURL.searchParams.set("ref", flareAIUserId);
731			window.history.replaceState({}, "", currentURL.toString());
732		}
733	}
734
735	var fDSTPostData = {
736		'operation': 'post',
737		'object': 'flarefDST',
738		'applicationServiceId': 5,
739		'eventId': eventId,
740		'eventName': eventName,
741		'domainName': domainName
742	};
743
744	try {
745		fDST(null, flareAIAPIURL, flareAIAPIResponseTimeout, fDSTPostData, "Potential Conversion");
746	} catch (err) {
747		// console.error("flareAI LOG in fDST: " + err.message);
748	}
749});

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.