PageSourceSearch

https://maritime-executive.com/js/google-reach-error-handler.js?v=v2025.09.29.011646

js maritime-executive.com collected 2026-10-01 06:30:00 UTC 8,998 bytes, 283 lines download raw bytes

1/**
2 * Google Reach Measurement Error Handler for Maritime Executive
3 * 
4 * Handles errors from Google's reach and frequency measurement system
5 * and prevents console spam from failed reach_worklet.js requests
6 */
7
8(function () {
9    'use strict';
10
11    // Configuration
12    const config = {
13        suppressReachErrors: true,
14        logErrorsToConsole: false,
15        maxErrorsLogged: 5,
16        errorLogInterval: 60000 // 1 minute
17    };
18
19    // Track errors to prevent spam
20    let errorCount = 0;
21    let lastErrorTime = 0;
22    let errorBuffer = [];
23
24    /**
25     * Handle Google Reach measurement errors
26     */
27    function handleReachError(error, url) {
28        const now = Date.now();
29
30        // Add to error buffer
31        errorBuffer.push({
32            timestamp: now,
33            url: url,
34            error: error
35        });
36
37        // Clean old errors from buffer (keep last hour)
38        const oneHourAgo = now - (60 * 60 * 1000);
39        errorBuffer = errorBuffer.filter(e => e.timestamp > oneHourAgo);
40
41        // Only log periodically to avoid spam
42        if (now - lastErrorTime > config.errorLogInterval) {
43            if (config.logErrorsToConsole && errorBuffer.length > 0) {
44                console.group('[Google Reach] Error Summary');
45                console.warn(`${errorBuffer.length} reach measurement errors in the last hour`);
46                console.log('Most recent error:', errorBuffer[errorBuffer.length - 1]);
47                console.groupEnd();
48            }
49            lastErrorTime = now;
50        }
51    }
52
53    /**
54     * Monkey patch fetch to catch reach worklet errors
55     */
56    function patchFetch() {
57        if (typeof window.fetch !== 'function') return;
58
59        const originalFetch = window.fetch;
60
61        window.fetch = function (...args) {
62            const url = args[0];
63
64            return originalFetch.apply(this, args)
65                .catch(error => {
66                    // Check if this is a reach measurement error
67                    if (typeof url === 'string' &&
68                        (url.includes('googletagservices.com/agrp') ||
69                            url.includes('reach_worklet') ||
70                            url.includes('model_person_country_code'))) {
71
72                        handleReachError(error, url);
73
74                        if (config.suppressReachErrors) {
75                            // Return a resolved promise to prevent further error propagation
76                            return Promise.resolve(new Response('{}', {
77                                status: 200,
78                                statusText: 'OK',
79                                headers: { 'Content-Type': 'application/json' }
80                            }));
81                        }
82                    }
83
84                    // Re-throw other errors
85                    throw error;
86                });
87        };
88    }
89
90    /**
91     * Patch XMLHttpRequest to catch reach worklet errors
92     */
93    function patchXHR() {
94        const originalOpen = XMLHttpRequest.prototype.open;
95        const originalSend = XMLHttpRequest.prototype.send;
96
97        XMLHttpRequest.prototype.open = function (method, url, ...args) {
98            this._url = url;
99            return originalOpen.call(this, method, url, ...args);
100        };
101
102        XMLHttpRequest.prototype.send = function (data) {
103            const xhr = this;
104            const originalOnError = xhr.onerror;
105            const originalOnLoad = xhr.onload;
106
107            // Handle error events
108            xhr.onerror = function (event) {
109                if (xhr._url &&
110                    (xhr._url.includes('googletagservices.com/agrp') ||
111                        xhr._url.includes('reach_worklet') ||
112                        xhr._url.includes('model_person_country_code'))) {
113
114                    handleReachError(event, xhr._url);
115
116                    if (config.suppressReachErrors) {
117                        // Prevent error from propagating
118                        event.stopPropagation();
119                        event.preventDefault();
120                        return;
121                    }
122                }
123
124                if (originalOnError) {
125                    originalOnError.call(xhr, event);
126                }
127            };
128
129            // Handle load events with error status
130            xhr.onload = function (event) {
131                if (xhr.status >= 400 && xhr._url &&
132                    (xhr._url.includes('googletagservices.com/agrp') ||
133                        xhr._url.includes('reach_worklet') ||
134                        xhr._url.includes('model_person_country_code'))) {
135
136                    handleReachError(`HTTP ${xhr.status}`, xhr._url);
137                }
138
139                if (originalOnLoad) {
140                    originalOnLoad.call(xhr, event);
141                }
142            };
143
144            return originalSend.call(this, data);
145        };
146    }
147
148    /**
149     * Override console.error to filter reach errors
150     */
151    function patchConsoleError() {
152        if (!config.suppressReachErrors) return;
153
154        const originalError = console.error;
155
156        console.error = function (...args) {
157            const message = args.join(' ');
158
159            // Check if this is a reach measurement error
160            if (message.includes('googletagservices.com/agrp') ||
161                message.includes('reach_worklet') ||
162                message.includes('model_person_country_code') ||
163                message.includes('Internal Server Error')) {
164
165                // Count the error but don't log it
166                errorCount++;
167                return;
168            }
169
170            // Log other errors normally
171            originalError.apply(console, args);
172        };
173    }
174
175    /**
176     * Disable Google Reach measurement if requested
177     */
178    function disableReachMeasurement() {
179        // This needs to be done early, before Google Tag loads
180        if (window.googletag) {
181            googletag.cmd.push(function () {
182                try {
183                    // Disable reach measurement
184                    googletag.pubads().setPrivacySettings({
185                        restrictDataProcessing: true
186                    });
187
188                    // Disable personalized ads (reduces reach tracking)
189                    googletag.pubads().setRequestNonPersonalizedAds(1);
190
191                    console.log('[Google Reach] Measurement disabled');
192                } catch (e) {
193                    console.warn('[Google Reach] Could not disable measurement:', e.message);
194                }
195            });
196        }
197    }
198
199    /**
200     * Add global error handler for unhandled promise rejections
201     */
202    function addGlobalErrorHandler() {
203        window.addEventListener('unhandledrejection', function (event) {
204            const error = event.reason;
205            const message = error ? error.toString() : '';
206
207            if (message.includes('googletagservices.com/agrp') ||
208                message.includes('reach_worklet') ||
209                message.includes('model_person_country_code')) {
210
211                handleReachError(error, 'promise_rejection');
212
213                if (config.suppressReachErrors) {
214                    event.preventDefault();
215                }
216            }
217        });
218
219        window.addEventListener('error', function (event) {
220            const message = event.message || '';
221            const filename = event.filename || '';
222
223            if (message.includes('reach_worklet') ||
224                filename.includes('reach_worklet') ||
225                message.includes('googletagservices.com/agrp')) {
226
227                handleReachError(event.error, filename);
228
229                if (config.suppressReachErrors) {
230                    event.preventDefault();
231                }
232            }
233        });
234    }
235
236    /**
237     * Initialize error handling
238     */
239    function init() {
240        console.log('[Google Reach] Error handler initializing...');
241
242        // Apply patches
243        patchFetch();
244        patchXHR();
245        patchConsoleError();
246        addGlobalErrorHandler();
247
248        // Optionally disable reach measurement
249        // disableReachMeasurement();
250
251        console.log('[Google Reach] Error handler initialized');
252    }
253
254    /**
255     * Expose utilities for debugging
256     */
257    window.GoogleReachHandler = {
258        getErrorCount: () => errorCount,
259        getErrorBuffer: () => [...errorBuffer],
260        clearErrors: () => {
261            errorCount = 0;
262            errorBuffer = [];
263        },
264        enableLogging: () => {
265            config.logErrorsToConsole = true;
266        },
267        disableLogging: () => {
268            config.logErrorsToConsole = false;
269        },
270        suppressErrors: () => {
271            config.suppressReachErrors = true;
272        },
273        allowErrors: () => {
274            config.suppressReachErrors = false;
275        },
276        disableReachMeasurement: disableReachMeasurement,
277        config: config
278    };
279
280    // Initialize immediately
281    init();
282
283})(); 

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.