| 
 | 1 | +// No-results analytics only  | 
 | 2 | +(() => {  | 
 | 3 | +    const MAX_WAIT_MS = 8000;  | 
 | 4 | +    const POLL_INTERVAL_MS = 200;  | 
 | 5 | +    let flushed = false;  | 
 | 6 | +    const queue = [];  | 
 | 7 | + | 
 | 8 | +    const enqueueOrSend = (event, props) => {  | 
 | 9 | +        if (typeof window.plausible === 'function') {  | 
 | 10 | +            window.plausible(event, { props });  | 
 | 11 | +            flushed = true;  | 
 | 12 | +        } else {  | 
 | 13 | +            queue.push([event, props]);  | 
 | 14 | +        }  | 
 | 15 | +    };  | 
 | 16 | + | 
 | 17 | +    const flushQueueIfReady = () => {  | 
 | 18 | +        if (flushed) return true;  | 
 | 19 | +        if (typeof window.plausible !== 'function') return false;  | 
 | 20 | +        while (queue.length) {  | 
 | 21 | +            const [e, p] = queue.shift();  | 
 | 22 | +            window.plausible(e, { props: p });  | 
 | 23 | +        }  | 
 | 24 | +        flushed = true;  | 
 | 25 | +        return true;  | 
 | 26 | +    };  | 
 | 27 | + | 
 | 28 | +    const startPolling = () => {  | 
 | 29 | +        const start = Date.now();  | 
 | 30 | +        const tick = () => {  | 
 | 31 | +            if (flushQueueIfReady()) return;  | 
 | 32 | +            if (Date.now() - start >= MAX_WAIT_MS) return; // give up silently  | 
 | 33 | +            setTimeout(tick, POLL_INTERVAL_MS);  | 
 | 34 | +        };  | 
 | 35 | +        tick();  | 
 | 36 | +    };  | 
 | 37 | + | 
 | 38 | +    document.addEventListener('DOMContentLoaded', () => {  | 
 | 39 | +        const el = document.getElementById('search_no_results');  | 
 | 40 | +        if (!el) return;  | 
 | 41 | + | 
 | 42 | +        const query = el.dataset.query || '';  | 
 | 43 | + | 
 | 44 | +        // Inject UTM params (only if not already set)  | 
 | 45 | +        try {  | 
 | 46 | +            const url = new URL(window.location.href);  | 
 | 47 | +            const alreadyTagged = url.searchParams.get('utm_source') === 'internal_search'  | 
 | 48 | +                && url.searchParams.get('utm_medium') === 'no_results';  | 
 | 49 | +            if (!alreadyTagged) {  | 
 | 50 | +                url.searchParams.set('utm_source', 'internal_search');  | 
 | 51 | +                url.searchParams.set('utm_medium', 'no_results');  | 
 | 52 | +                url.searchParams.set('utm_campaign', 'search');  | 
 | 53 | +                url.searchParams.set('utm_term', query);  | 
 | 54 | +                window.history.replaceState({}, '', url);  | 
 | 55 | +            }  | 
 | 56 | +        } catch (_) {  | 
 | 57 | +            // Ignore URL manipulation errors  | 
 | 58 | +        }  | 
 | 59 | + | 
 | 60 | +        enqueueOrSend('Search no results', { query });  | 
 | 61 | +        flushQueueIfReady();  | 
 | 62 | +        if (!flushed) startPolling();  | 
 | 63 | +    });  | 
 | 64 | + | 
 | 65 | +    // Also attempt flush after full load as a fallback  | 
 | 66 | +    window.addEventListener('load', flushQueueIfReady);  | 
 | 67 | +})();  | 
0 commit comments