PageSourceSearch

https://www.lacorteditore.it/wp-content/plugins/facebook-for-wooco…/js/frontend/pixel-events.js?ver=3.7.1

js lacorteditore.it collected 2026-09-24 22:16:01 UTC 9,771 bytes, 306 lines download raw bytes

1/**
2 * Facebook Pixel Events - External JavaScript Handler
3 *
4 * This script fires pixel events in an isolated execution context,
5 * ensuring events are sent even if other plugins cause JavaScript errors.
6 *
7 * Supports WooCommerce Blocks via Store API fetch interception.
8 * The pixel event data is read from the Store API response extensions.
9 *
10 * @package FacebookCommerce
11 */
12
13(function() {
14    'use strict';
15
16    // Data from PHP (may be missing if no events were queued for initial render).
17    // Keep Store API interception active even when eventQueue is empty/undefined.
18    var data = (typeof wc_facebook_pixel_data !== 'undefined' && wc_facebook_pixel_data) ?
19        wc_facebook_pixel_data :
20        { eventQueue: [] };
21    var firedEvents = {};
22
23    /**
24     * Build event data object for fbq()
25     *
26     * @param {Object} event Event object from PHP
27     * @return {Object} Prepared event data
28     */
29    function buildEventData(event) {
30        return {
31            method: event.method || 'track',
32            name: event.name,
33            params: event.params || {},
34            eventId: event.eventId || null
35        };
36    }
37
38    /**
39     * Check if event should be skipped (already fired)
40     *
41     * @param {string|null} eventId Event ID for deduplication
42     * @return {boolean} True if should skip
43     */
44    function shouldSkipEvent(eventId) {
45        return eventId && firedEvents[eventId];
46    }
47
48    /**
49     * Mark event as fired for deduplication
50     *
51     * @param {string|null} eventId Event ID
52     */
53    function markEventFired(eventId) {
54        if (eventId) {
55            firedEvents[eventId] = true;
56        }
57    }
58
59    /**
60     * Log warning to console (with safety check)
61     *
62     * @param {string} message Warning message
63     * @param {*} data Additional data to log
64     */
65    function logWarning(message, data) {
66        if (typeof console !== 'undefined' && console.warn) {
67            console.warn('[FB Pixel]', message, data);
68        }
69    }
70
71    /**
72     * Fire a single event using fbq()
73     *
74     * @param {Object} event Event object with name, params, method, eventId
75     */
76    function fireEvent(event) {
77        var eventData = buildEventData(event);
78
79        // Skip if already fired (deduplication)
80        if (shouldSkipEvent(eventData.eventId)) {
81            return;
82        }
83
84        try {
85            var params = eventData.params;
86
87            if (window.FacebookSignals && typeof window.FacebookSignals.trackEvent === 'function') {
88                window.FacebookSignals.trackEvent(eventData.name, params, null, eventData.method, eventData.eventId);
89            } else {
90                if (typeof fbq !== 'function') {
91                    logWarning('fbq not available, skipping event:', eventData.name);
92                    return;
93                }
94
95                if (eventData.eventId) {
96                    fbq(eventData.method, eventData.name, params, {eventID: eventData.eventId});
97                } else {
98                    fbq(eventData.method, eventData.name, params);
99                }
100            }
101
102            markEventFired(eventData.eventId);
103
104        } catch (e) {
105            logWarning('Event error: ' + eventData.name, e);
106        }
107    }
108
109    /**
110     * Fire all queued events from PHP
111     */
112    function fireQueuedEvents() {
113        var events = data.eventQueue;
114
115        if (!events || !Array.isArray(events)) {
116            return;
117        }
118
119        for (var i = 0; i < events.length; i++) {
120            try {
121                fireEvent(events[i]);
122            } catch (e) {
123                logWarning('fireQueuedEvents loop error:', e);
124            }
125        }
126
127        // Clear events after firing to prevent duplicate firing
128        data.eventQueue = [];
129    }
130
131    // =========================================================================
132    // WooCommerce Blocks: Store API approach
133    // =========================================================================
134
135    /**
136     * Process pixel event data from Store API response.
137     *
138     * @param {Object} eventData Event data from Store API extensions
139     */
140    function processStoreApiEvent(eventData) {
141        if (!eventData || !eventData.event) {
142            return;
143        }
144
145        var params = eventData.params || {};
146
147        var event = {
148            method: 'track',
149            name: eventData.event,
150            params: params,
151            eventId: params.event_id || null
152        };
153
154        fireEvent(event);
155    }
156
157    /**
158     * Returns the request URL from a fetch() input.
159     *
160     * @param {*} input fetch() input argument
161     * @return {string}
162     */
163    function getRequestUrl(input) {
164        if (typeof input === 'string') {
165            return input;
166        }
167
168        if (input && typeof input.url === 'string') {
169            return input.url;
170        }
171
172        return '';
173    }
174
175    /**
176     * Checks whether a URL targets the Store API add-item endpoint.
177     *
178     * @param {string} url Request URL
179     * @return {boolean}
180     */
181    function isStoreApiAddItemRequest(url) {
182        return typeof url === 'string' &&
183            (url.indexOf('/wc/store/v1/cart/add-item') !== -1 ||
184             url.indexOf('/wc/store/cart/add-item') !== -1);
185    }
186
187    /**
188     * Checks whether a URL targets the Store API batch endpoint.
189     *
190     * @param {string} url Request URL
191     * @return {boolean}
192     */
193    function isStoreApiBatchRequest(url) {
194        return typeof url === 'string' &&
195            (url.indexOf('/wc/store/v1/batch') !== -1 ||
196             url.indexOf('/wc/store/batch') !== -1);
197    }
198
199    /**
200     * Process Store API response payload and extract plugin extension data.
201     * Handles both direct cart responses and batch responses.
202     *
203     * @param {Object} responseData Parsed Store API response payload
204     */
205    function processStoreApiResponseData(responseData) {
206        if (!responseData || typeof responseData !== 'object') {
207            return;
208        }
209
210        // Direct response shape: { extensions: { 'facebook-for-woocommerce': ... } }
211        if (responseData.extensions && responseData.extensions['facebook-for-woocommerce']) {
212            processStoreApiEvent(responseData.extensions['facebook-for-woocommerce']);
213        } else if (Array.isArray(responseData.responses)) {
214            // Batch response shape: { responses: [ { body: { extensions: ... } } ] }
215            for (var i = 0; i < responseData.responses.length; i++) {
216                var item = responseData.responses[i];
217                if (item && item.body && item.body.extensions && item.body.extensions['facebook-for-woocommerce'] &&
218                    item.status >= 200 && item.status < 300) {
219                    processStoreApiEvent(item.body.extensions['facebook-for-woocommerce']);
220                }
221            }
222        }
223    }
224
225    /**
226     * Set up fetch interceptor to capture Store API responses.
227     * Intercepts cart/add-item and batch requests to fire AddToCart pixel events.
228     */
229    function setupFetchInterceptor() {
230        var originalFetch = window.fetch;
231        if (!originalFetch) {
232            return;
233        }
234
235        window.fetch = function() {
236            var args = arguments;
237            var url = getRequestUrl(args[0]);
238
239            var isAddToCartRequest = isStoreApiAddItemRequest(url);
240            var isBatchRequest = isStoreApiBatchRequest(url);
241
242            return originalFetch.apply(this, args).then(function(response) {
243                if ((isAddToCartRequest || isBatchRequest) && response.ok) {
244                    // Clone response so we can read it without consuming
245                    response.clone().json().then(function(responseData) {
246                        processStoreApiResponseData(responseData);
247                    }).catch(function(e) {
248                        logWarning('Store API JSON parse error:', e);
249                    });
250                }
251                return response;
252            });
253        };
254    }
255
256    /**
257     * Initialize pixel event handling.
258     *
259     * If fbq() is already available, fires queued events immediately.
260     * If not (e.g. consent manager blocking the SDK), uses Object.defineProperty
261     * to set a trap on window.fbq — our handler fires automatically the moment
262     * fbq is assigned, with zero overhead in between. No polling, no timers.
263     *
264     * Also sets up Store API interceptor for WooCommerce Blocks AJAX AddToCart.
265     */
266    function init() {
267        // Set up fetch interceptor for WooCommerce Blocks Store API
268        setupFetchInterceptor();
269
270        if (typeof fbq === 'function') {
271            fireQueuedEvents();
272            return;
273        }
274
275        // fbq doesn't exist yet — watch for it (zero overhead, no timers).
276        // Consent managers block fbq until the
277        // user accepts. This fires the moment they assign window.fbq.
278        var _fbq = window.fbq;
279        Object.defineProperty(window, 'fbq', {
280            configurable: true,
281            enumerable: true,
282            get: function() { return _fbq; },
283            set: function(value) {
284                _fbq = value;
285                if (typeof value === 'function') {
286                    // Restore normal property so FB SDK works normally
287                    Object.defineProperty(window, 'fbq', {
288                        configurable: true,
289                        enumerable: true,
290                        writable: true,
291                        value: value
292                    });
293                    setTimeout(fireQueuedEvents, 0);
294                }
295            }
296        });
297    }
298
299    // Start
300    if (document.readyState === 'complete') {
301        init();
302    } else {
303        window.addEventListener('load', init);
304    }
305
306})();

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.