1window.FacebookSignal = window.FacebookSignal || { 2 _held: false, 3 _releasing: false, 4 _pixelInitialized: false, 5 _pixelId: null, 6 _pixelUserInfo: {}, 7 _pixelOptions: {}, 8 _pendingPixelEvents: [], 9 _queue: [], 10 _config: {}, 11 _seenEventIds: {}, 12 _fbclid: (function () { 13 try { 14 var match = window.location.search.match(/[?&]fbclid=([^&]*)/); 15 return match ? decodeURIComponent(match[1]) : null; 16 } catch (e) { 17 return null; 18 } 19 })(), 20 21 _readCookie: function (name) { 22 try { 23 var pairs = (document.cookie || '').split(';'); 24 for (var i = 0; i < pairs.length; i++) { 25 var pair = pairs[i].replace(/^\s+/, ''); 26 if (pair.indexOf(name + '=') === 0) { 27 return decodeURIComponent(pair.substring(name.length + 1)); 28 } 29 } 30 } catch (e) {} 31 return null; 32 }, 33 34 init: function (config) { 35 this._config = config || {}; 36 this._attribution = this._config.attribution || {}; 37 38 // Read cookie directly so cached pages resolve the correct held/active 39 // state even when PHP rendered held: false. 40 var cookieState = this._readCookie('wc_facebook_signals_state'); 41 this._held = cookieState ? cookieState === 'held' : !!this._config.held; 42 43 // Sync consent immediately so fbevents.js obeys the current state. 44 if (typeof fbq === 'function') { 45 fbq('consent', this._held ? 'revoke' : 'grant'); 46 } 47 48 try { 49 var raw = window.sessionStorage.getItem('fbpix_seen_event_ids'); 50 this._seenEventIds = raw ? JSON.parse(raw) : {}; 51 } catch (e) { 52 this._seenEventIds = this._seenEventIds || {}; 53 } 54 }, 55 56 initPixel: function (pixelId, userInfo, options) { 57 this._pixelId = pixelId; 58 this._pixelUserInfo = 59 userInfo && typeof userInfo === 'object' && !Array.isArray(userInfo) 60 ? userInfo 61 : {}; 62 this._pixelOptions = options || {}; 63 if (!this._held) { 64 this._runPixelInit(); 65 } 66 }, 67 68 _runPixelInit: function () { 69 if (this._pixelInitialized || !this._pixelId || typeof fbq !== 'function') { 70 return; 71 } 72 if (this._pixelOptions && this._pixelOptions.includeCapiIntegration) { 73 var url = window.location.origin + '?ob=open-bridge'; 74 fbq('set', 'openbridge', this._pixelId, url); 75 } 76 77 if (this._config.capig === '1') { 78 fbq('optinMetaEnabledCapi', this._pixelId); 79 } 80 81 fbq('init', this._pixelId, this._pixelUserInfo, this._pixelOptions); 82 83 this._pixelInitialized = true; 84 this._flushPendingPixelEvents(); 85 }, 86 87 _flushPendingPixelEvents: function () { 88 var pending = this._pendingPixelEvents; 89 this._pendingPixelEvents = []; 90 for (var i = 0; i < pending.length; i++) { 91 var ev = pending[i]; 92 this._firePixelEvent(ev.name, ev.params, ev.method, ev.eventId); 93 } 94 }, 95 96 _fireOrQueuePixelEvent: function (name, params, method, eventId) { 97 if (!this._pixelInitialized) { 98 this._pendingPixelEvents.push({ 99 name: name, 100 params: params || {}, 101 method: method || 'track', 102 eventId: eventId || null, 103 }); 104 return; 105 } 106 this._firePixelEvent(name, params || {}, method || 'track', eventId || null); 107 }, 108 109 _firePixelEvent: function (name, params, method, eventId) { 110 method = method || 'track'; 111 if (eventId) { 112 fbq(method, name, params || {}, { eventID: eventId }); 113 } else { 114 fbq(method, name, params || {}); 115 } 116 }, 117 118 _syncCookie: function (name, serverValue, domain) { 119 if (!serverValue) { 120 return; 121 } 122 var encoded = encodeURIComponent(serverValue); 123 var match = document.cookie.match( 124 new RegExp('(?:^|;\\s*)' + name + '=([^;]*)'), 125 ); 126 var current = match ? match[1] : null; 127 if (current && current !== encoded) { 128 var cookie = 129 name + '=' + encoded + ';path=/;max-age=7776000;SameSite=Lax'; 130 if (domain) { 131 cookie += ';domain=' + domain; 132 } 133 document.cookie = cookie; 134 } 135 }, 136 137 queueEvent: function (eventData) { 138 if (!eventData || !eventData.event_name) { 139 return; 140 } 141 142 if (eventData.event_id && this._seenEventIds[eventData.event_id]) { 143 return; 144 } 145 146 eventData.event_time = 147 eventData.event_time || Math.floor(Date.now() / 1000); 148 eventData.event_source_url = 149 eventData.event_source_url || window.location.href; 150 this._queue.push(eventData); 151 152 if (eventData.event_id) { 153 this._seenEventIds[eventData.event_id] = 1;
154 try { 155 window.sessionStorage.setItem( 156 'fbpix_seen_event_ids', 157 JSON.stringify(this._seenEventIds), 158 ); 159 } catch (e) {} 160 } 161 }, 162 163 trackEvent: function (name, params, userData, method, eventId) { 164 method = method || 'track'; 165 eventId = eventId || (params && params.eventID) || null; 166 167 if (this._held) { 168 this.queueEvent({ 169 event_name: name, 170 custom_data: params || {}, 171 event_id: eventId, 172 event_time: Math.floor(Date.now() / 1000), 173 method: method, 174 }); 175 } else { 176 this._fireOrQueuePixelEvent(name, params || {}, method, eventId); 177 } 178 }, 179 180 hold: function () { 181 this._held = true; 182 fbq('consent', 'revoke'); 183 }, 184 185 release: function () { 186 var self = this; 187 188 if (!self._held || self._releasing || !self._config.ajaxUrl) { 189 return Promise.resolve({ success: true, data: { sent_count: 0 } }); 190 } 191 192 self._releasing = true; 193 194 return new Promise(function (resolve, reject) { 195 var xhr = new XMLHttpRequest(); 196 var url = 197 self._config.ajaxUrl + 198 (self._config.ajaxUrl.indexOf('?') === -1 ? '?' : '&') + 199 'action=' + 200 encodeURIComponent(self._config.releaseAction); 201 202 xhr.open('POST', url, true); 203 xhr.setRequestHeader('Content-Type', 'application/json'); 204 xhr.onload = function () { 205 if (xhr.status < 200 || xhr.status >= 300) { 206 self._releasing = false; 207 reject(new Error('Release AJAX failed: ' + xhr.status)); 208 return; 209 } 210 211 try { 212 var response = JSON.parse(xhr.responseText); 213 self._handleReleaseResponse(response.data || {}); 214 self._releasing = false; 215 resolve(response); 216 } catch (error) { 217 self._releasing = false; 218 reject(error); 219 } 220 }; 221 xhr.onerror = function () { 222 self._releasing = false; 223 reject(new Error('Network error')); 224 }; 225 var attribution = self._config.attribution || {}; 226 xhr.send( 227 JSON.stringify({ 228 events: self._queue, 229 fbclid: self._fbclid, 230 fbp: self._readCookie('_fbp') || attribution.fbp || null, 231 fbc: self._readCookie('_fbc') || attribution.fbc || null, 232 }), 233 ); 234 }); 235 }, 236 237 _handleReleaseResponse: function (data) { 238 var attr = this._config.attribution || {}; 239 var fbpValue = data.fbp || attr.fbp; 240 var fbcValue = data.fbc || attr.fbc; 241 242 if (fbpValue) { 243 var fbpCookie = 244 '_fbp=' + encodeURIComponent(fbpValue) + ';path=/;max-age=7776000;SameSite=Lax'; 245 if (attr.fbpDomain) { 246 fbpCookie += ';domain=' + attr.fbpDomain; 247 } 248 document.cookie = fbpCookie; 249 } 250 251 if (fbcValue) { 252 var fbcCookie = 253 '_fbc=' + encodeURIComponent(fbcValue) + ';path=/;max-age=7776000;SameSite=Lax'; 254 if (attr.fbcDomain) { 255 fbcCookie += ';domain=' + attr.fbcDomain; 256 } 257 document.cookie = fbcCookie; 258 } 259 260 // Update user_info with fresh AAM data from the release response, then 261 // run (or re-run) fbq('init') so the pixel has correct user_info. 262 if ( 263 data.user_info && 264 typeof data.user_info === 'object' && 265 !Array.isArray(data.user_info) 266 ) { 267 this._pixelUserInfo = data.user_info; 268 } 269 this._pixelInitialized = false; 270 this._runPixelInit(); 271 272 fbq('consent', 'grant'); 273 274 for (var i = 0; i < this._queue.length; i++) { 275 var queuedEvent = this._queue[i]; 276 var customData = queuedEvent.custom_data || {}; 277 var trackMethod = queuedEvent.method || (queuedEvent.is_custom ? 'trackCustom' : 'track'); 278 if (queuedEvent.event_id) { 279 fbq(trackMethod, queuedEvent.event_name, customData, { 280 eventID: queuedEvent.event_id, 281 }); 282 } else { 283 fbq(trackMethod, queuedEvent.event_name, customData); 284 } 285 } 286 287 this._queue = []; 288 this._held = false; 289 this._releasing = false; 290 }, 291}; 292 293window.fbwcsignal = window.fbwcsignal || {}; 294(function (api) { 295 var signalConfig = window.facebookSignalConfig || {}; 296 var cookieName = signalConfig.cookieName || ''; 297 var ajaxUrl = signalConfig.ajaxUrl || ''; 298 var signalsAction = signalConfig.signalsAction || ''; 299 var signalsNonce = signalConfig.signalsNonce || ''; 300 301 function setCookie(value) { 302 var expires = new Date(); 303 expires.setTime(expires.getTime() + 365 * 24 * 60 * 60 * 1000); 304 document.cookie = 305 cookieName + 306 '=' + 307 encodeURIComponent(value) + 308 ';expires=' + 309 expires.toUTCString() + 310 ';path=/;SameSite=Lax'; 311 } 312 313 function getCookie() { 314 var match = document.cookie.match( 315 new RegExp('(?:^|;\\s*)' + cookieName + '=([^;]*)'), 316 ); 317 return match ? decodeURIComponent(match[1]) : null; 318 } 319 320 function updateState(state) { 321 var normalizedState = state === 'active' ? 'active' : 'held';
322 setCookie(normalizedState); 323 324 return new Promise(function (resolve, reject) { 325 var xhr = new XMLHttpRequest(); 326 xhr.open('POST', ajaxUrl, true); 327 xhr.setRequestHeader( 328 'Content-Type', 329 'application/x-www-form-urlencoded; charset=UTF-8', 330 ); 331 xhr.onload = function () { 332 if (xhr.status < 200 || xhr.status >= 300) { 333 reject(new Error('Signals AJAX failed: ' + xhr.status)); 334 return; 335 } 336 337 try { 338 var response = JSON.parse(xhr.responseText); 339 if (normalizedState === 'held') { 340 window.FacebookSignal.hold(); 341 resolve(response); 342 return; 343 } 344 345 if (window.FacebookSignal && window.FacebookSignal._held) { 346 window.FacebookSignal.release().then( 347 function () { 348 resolve(response); 349 }, 350 function (error) { 351 reject(error); 352 }, 353 ); 354 return; 355 } 356 357 resolve(response); 358 } catch (error) { 359 reject(error); 360 } 361 }; 362 xhr.onerror = function () { 363 reject(new Error('Network error')); 364 }; 365 xhr.send( 366 'action=' + 367 encodeURIComponent(signalsAction) + 368 '&security=' + 369 encodeURIComponent(signalsNonce) + 370 '&state=' + 371 encodeURIComponent(normalizedState), 372 ); 373 }); 374 } 375 376 api.hold = function () { 377 return updateState('held'); 378 }; 379 380 api.release = function () { 381 return updateState('active'); 382 }; 383 384 api.getState = function () { 385 var value = getCookie(); 386 if (value === 'active' || value === 'held') { 387 return value; 388 } 389 return null; 390 }; 391})(window.fbwcsignal);
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.