PageSourceSearch

https://keytomarkets.com/wp-content/plugins/wp-crm-integration/assets/js/fxbo-attribution.js?ver=1.2.6

js keytomarkets.com collected 2026-10-04 15:03:49 UTC 4,366 bytes, 163 lines download raw bytes

1/**
2 * First-touch campaign attribution capture, plus the consent gate both this
3 * and the conversion event honour.
4 *
5 * Deliberately self-contained: it has no dependency on anything else in this
6 * plugin and knows nothing about the CRM, so it can be lifted into a
7 * site-wide tracking plugin unchanged if that becomes its better home.
8 *
9 * Exposes window.wpfxboAttribution:
10 *   .read()           - the stored attribution values
11 *   .hasConsent()     - whether storing/sending is currently permitted
12 *   .onConsent( fn )  - run fn once consent is (or becomes) available
13 */
14(function () {
15	var config = window.wpfxboTracking || {};
16	var STORAGE_KEY = config.storageKey || 'wpfxbo_attribution';
17	var CONSENT_MODE = config.consentMode || 'off';
18	var CONSENT_CATEGORY = config.consentCategory || 'advertisement';
19
20	var URL_PARAMS = [
21		'utm_source',
22		'utm_medium',
23		'utm_campaign',
24		'gclid',
25		'wbraid',
26		'gbraid',
27		'fbclid',
28	];
29
30	function debug(message) {
31		if (config.debug && window.console) {
32			window.console.warn('[wpfxbo] ' + message);
33		}
34	}
35
36	function getCookie(name) {
37		var match = document.cookie.match(new RegExp('(^|;\\s*)' + name + '=([^;]*)'));
38		return match ? decodeURIComponent(match[2]) : '';
39	}
40
41	/**
42	 * Whether the visitor has agreed to the category these values fall under.
43	 *
44	 * "off"       - no consent framework on the site; nothing to wait for.
45	 * "cookieyes" - read CookieYes' own consent cookie, which stores a
46	 *               "category:yes|no" list.
47	 * "callback"  - defer entirely to a site-supplied global function, for any
48	 *               other consent platform.
49	 */
50	function hasConsent() {
51		if (CONSENT_MODE === 'off') {
52			return true;
53		}
54
55		if (CONSENT_MODE === 'callback') {
56			var name = config.consentCallback || '';
57			var fn = name ? window[name] : null;
58
59			if (typeof fn !== 'function') {
60				debug('consent callback "' + name + '" is not defined; treating as no consent.');
61				return false;
62			}
63
64			return !!fn(CONSENT_CATEGORY);
65		}
66
67		if (CONSENT_MODE === 'cookieyes') {
68			var consent = getCookie('cookieyes-consent');
69
70			if (!consent) {
71				return false;
72			}
73
74			return consent.indexOf(CONSENT_CATEGORY + ':yes') !== -1;
75		}
76
77		return false;
78	}
79
80	function readStored() {
81		try {
82			return JSON.parse(window.localStorage.getItem(STORAGE_KEY)) || {};
83		} catch (e) {
84			return {};
85		}
86	}
87
88	function writeStored(values) {
89		try {
90			window.localStorage.setItem(STORAGE_KEY, JSON.stringify(values));
91		} catch (e) {
92			// Private browsing or storage disabled: attribution just won't persist.
93		}
94	}
95
96	/**
97	 * Capture first-touch attribution. Values already stored win, so the
98	 * original landing URL's campaign data survives later internal navigation.
99	 */
100	function capture() {
101		if (!hasConsent()) {
102			return;
103		}
104
105		var stored = readStored();
106		var params = new URLSearchParams(window.location.search);
107		var changed = false;
108
109		URL_PARAMS.forEach(function (key) {
110			var value = params.get(key);
111			if (value && !stored[key]) {
112				stored[key] = value;
113				changed = true;
114			}
115		});
116
117		if (changed) {
118			writeStored(stored);
119		}
120	}
121
122	/**
123	 * Run a callback as soon as consent is available - immediately if it
124	 * already is, otherwise when the consent platform reports a change.
125	 */
126	function onConsent(callback) {
127		if (hasConsent()) {
128			callback();
129			return;
130		}
131
132		if (CONSENT_MODE === 'off') {
133			return;
134		}
135
136		var settled = false;
137		var check = function () {
138			if (!settled && hasConsent()) {
139				settled = true;
140				callback();
141			}
142		};
143
144		// CookieYes dispatches this once the visitor makes a choice. The
145		// generic consent-update name is listened for too, so another platform
146		// wired through the "callback" mode can reuse the same signal.
147		document.addEventListener('cookieyes_consent_update', check);
148		document.addEventListener('wpfxbo_consent_update', check);
149	}
150
151	window.wpfxboAttribution = {
152		read: readStored,
153		hasConsent: hasConsent,
154		onConsent: onConsent,
155		getCookie: getCookie,
156		debug: debug,
157	};
158
159	// The URL's campaign values are only present on this page load, so capture
160	// them now and again if consent arrives while the visitor is still here.
161	capture();
162	onConsent(capture);
163})();

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.