PageSourceSearch

https://www.mhai.net/wp-content/plugins/modern-events-calendar-lit…/js/tracking.js?ver=7.36.4.1789671652

js mhai.net collected 2026-09-24 12:08:43 UTC 4,978 bytes, 125 lines download raw bytes

1/**
2 * MEC product analytics — front-end relay (events 2 and 5).
3 *
4 * Exposes window.mecRelayBeacon(event, props, dedupKey):
5 *   - sendBeacon to the admin-ajax relay endpoint (see Tracking\ClientRelay)
6 *   - hard client-side dedup via sessionStorage when a dedupKey is given
7 *
8 * Also listens for MEC search/filter completions (the "mec_search_init"
9 * document event every view triggers once results are shown) and relays
10 * mec_calendar_discovery_used. The search phrase itself is NEVER collected —
11 * only the action shape, the filter type, and a result-count bucket.
12 */
13(function () {
14    'use strict';
15
16    if (window.mecRelayBeacon) return; // double-enqueue guard
17
18    var ajaxUrl = (typeof mecdata !== 'undefined' && mecdata.ajax_url) ? mecdata.ajax_url : null;
19
20    function bucket(n) {
21        n = parseInt(n, 10) || 0;
22        if (n <= 0) return '0';
23        if (n <= 4) return '1_4';
24        if (n <= 20) return '5_20';
25        if (n <= 100) return '21_100';
26        return '101_plus';
27    }
28
29    window.mecRelayBeacon = function (event, props, dedupKey) {
30        if (!ajaxUrl || !navigator.sendBeacon) return;
31
32        if (dedupKey) {
33            try {
34                if (sessionStorage.getItem(dedupKey)) return;
35                sessionStorage.setItem(dedupKey, '1');
36            } catch (e) { /* private mode: fall through and send */ }
37        }
38
39        var body = new FormData();
40        body.append('action', 'mec_track_event');
41        body.append('event', event);
42        body.append('props', JSON.stringify(props || {}));
43
44        navigator.sendBeacon(ajaxUrl, body);
45    };
46
47    // ---- Event 5: mec_calendar_discovery_used -------------------------------
48
49    // Remember WHAT the visitor used, so that when the results arrive
50    // (mec_search_init) we can attach discovery_action and filter_type.
51    var pending = { action: null, filter_type: null };
52
53    // Search phrase field: mec_sf_s_{id}. Everything else in the search form
54    // is a filter (month, category, label, location, organizer, …).
55    var FILTER_BY_ID = [
56        ['mec_sf_s', 'text'],
57        ['mec_sf_address_s', 'text_address'],
58        ['mec_sf_month', 'month'],
59        ['mec_sf_year', 'year'],
60        ['mec_sf_category', 'category'],
61        ['mec_sf_label', 'label'],
62        ['mec_sf_location', 'location'],
63        ['mec_sf_organizer', 'organizer'],
64        ['mec_sf_speaker', 'speaker'],
65        ['mec_sf_sponsor', 'sponsor'],
66        ['mec_sf_event_type', 'event_type'],
67        ['mec_sf_event_cost', 'cost'],
68        ['mec_sf_timepicker', 'time'],
69        ['mec_sf_date', 'date']
70    ];
71
72    function filterTypeFromId(id) {
73        for (var i = 0; i < FILTER_BY_ID.length; i++) {
74            if (id && id.indexOf(FILTER_BY_ID[i][0]) === 0) return FILTER_BY_ID[i][1];
75        }
76        return 'other';
77    }
78
79    jQuery(function ($) {
80        if (!$ || !$.fn) return;
81
82        // Any change inside a MEC search form records the initiating action.
83        $(document).on('change', 'form[id^="mec_search_form_"] select, form[id^="mec_search_form_"] input', function () {
84            var id = (this.id || '');
85            pending.action = (id.indexOf('mec_sf_s') === 0) ? 'search' : 'filter';
86            pending.filter_type = filterTypeFromId(id);
87        });
88
89        // Explicit submit = search even if the phrase field id differed.
90        $(document).on('submit', 'form[id^="mec_search_form_"]', function () {
91            if (!pending.action) {
92                pending.action = 'search';
93                pending.filter_type = 'text';
94            }
95        });
96
97        // Results shown — every view triggers this with (event, view, settings).
98        $(document).on('mec_search_init', function (event, view, viewSettings) {
99            if (!pending.action) return; // initial page render, not a discovery
100
101            var resultCount = 0;
102            if (viewSettings && viewSettings.id) {
103                resultCount = $('#mec_skin_' + viewSettings.id + ' .mec-event, #mec_skin_' + viewSettings.id + ' article').length
104                    || $('.mec-wrap .mec-event, .mec-wrap article.mec-event-article').length;
105            } else {
106                resultCount = $('.mec-wrap .mec-event, .mec-wrap article.mec-event-article').length;
107            }
108
109            var props = {
110                discovery_action: pending.action,
111                filter_type: pending.filter_type,
112                selected_count: 1,
113                result_count_bucket: bucket(resultCount),
114                view_type: view || null,
115                calendar_url: location.origin + location.pathname
116            };
117
118            // Consume: one beacon per completed discovery.
119            pending.action = null;
120            pending.filter_type = null;
121
122            window.mecRelayBeacon('mec_calendar_discovery_used', props);
123        });
124    });
125})();

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.