(function () { // Track events we've already seen to prevent loops const processedEvents = new Set(); const originalPush = dataLayer.push; dataLayer.push = function () { const args = Array.from(arguments); // Only process if we have arguments and it's an object if (args[0] && typeof args[0] === 'object') { try { // Skip events that came from the main thread with our special marker if (args[0]._fromPartyTown) { // Process normally but don't forward back return originalPush.apply(dataLayer, arguments); } // Skip events that are already marked as forwarded if (args[0]._forwarded) { return originalPush.apply(dataLayer, arguments); } // Create a unique identifier for this event const eventId = JSON.stringify(args[0]); // Check if we've already seen this exact event if (!processedEvents.has(eventId)) { // Track this event to prevent duplicates processedEvents.add(eventId); // Create a clean copy for dispatching const dispatchPayload = { ...args[0], _forwarded: true }; // Synchronously notify main thread - avoid promise-related issues try { window.dispatchEvent( new CustomEvent("gtm-forward", { detail: dispatchPayload, bubbles: true, // Ensure the event bubbles up cancelable: false // Cannot be cancelled }) ); } catch (dispatchError) { } // Limit the size of our tracking set to prevent memory issues if (processedEvents.size > 200) { processedEvents.clear(); } } } catch (e) { } } // Always call the original push method return originalPush.apply(dataLayer, arguments); }; })();