PageSourceSearch

https://kashkavalgarden.com/js/rt.js?v=96218582b9af

js kashkavalgarden.com collected 2026-10-04 19:54:28 UTC 6,974 bytes, 170 lines download raw bytes

1/**
2 * Global Page View + Click Tracker
3 * Fires a /track-impression pixel on page load, then tracks all clicks
4 * on the page (with special handling for Resy buttons as conversions).
5 * Usage: Include this script on any page to track user interactions.
6 * Version: 2.3.0
7 */
8(function() {
9    'use strict';
10
11    // Prevent double initialization (e.g., in iframes)
12    if (window.rtTrackerInitialized) {
13        return;
14    }
15    window.rtTrackerInitialized = true;
16    // An internal reporting label does not change the public/SEO document title.
17    var titleOverride = document.querySelector('meta[name="tracking-page-title"]');
18    var trackingTitle = titleOverride ? titleOverride.content : document.title;
19
20    // Don't track the password-protected reporting dashboard itself
21    var isDashboard = window.location.pathname.indexOf('/click-report') === 0;
22
23    // Fire an impression pixel on page load with UTM params, referrer, and title
24    if (!isDashboard) {
25        try {
26            var impParams = new URLSearchParams(window.location.search);
27            if (document.referrer) {
28                impParams.set('ref', document.referrer);
29            }
30            if (document.title) {
31                impParams.set('page_title', trackingTitle);
32            }
33            var impImg = new Image();
34            impImg.src = '/track-impression?' + impParams.toString();
35        } catch (e) {
36            // Tracking must never break the page
37        }
38    }
39
40    // Track a conversion (Resy button click)
41    function trackResyConversion(clickData) {
42        var params = new URLSearchParams(window.location.search);
43        if (document.referrer) {
44            params.set('ref', document.referrer);
45        }
46        params.set('url', window.location.href);
47        params.set('page_title', trackingTitle);
48        params.set('click_target', clickData.target);
49        params.set('click_text', clickData.text);
50        params.set('click_href', clickData.href);
51
52        // Use sendBeacon for reliability
53        if (navigator.sendBeacon) {
54            navigator.sendBeacon('/track-conversion?' + params.toString());
55        } else {
56            var img = new Image();
57            img.src = '/track-conversion?' + params.toString();
58        }
59    }
60
61    // Get useful info about a clicked element
62    function getElementInfo(element) {
63        if (!element) {
64            return {
65                tag: '',
66                id: '',
67                className: '',
68                text: '',
69                href: '',
70                type: ''
71            };
72        }
73
74        var label = element.getAttribute('data-track-label') || element.getAttribute('aria-label') || element.title || (element.textContent || '').trim();
75        if (element.matches('a[href="#kg-menu-dialog"]')) {
76            label = 'Open ' + (element.dataset.menuKey || 'dinner') + ' menu';
77        }
78        var menuDialog = element.closest('#kg-menu-dialog');
79        if (menuDialog && !element.matches('[role="tab"]')) {
80            var selectedMenu = menuDialog.querySelector('[role="tab"][aria-selected="true"]');
81            var pageCount = menuDialog.querySelector('.kg-menu-page-count');
82            if (selectedMenu) label += ' — ' + selectedMenu.textContent.trim();
83            if (pageCount && /(?:Next|Previous) menu page/.test(label)) label += ' (from ' + pageCount.textContent.trim() + ')';
84        }
85        if (element.matches('[role="tab"][data-menu]')) label = 'View ' + element.textContent.trim() + ' menu';
86        var info = {
87            tag: element.tagName || '',
88            id: element.id || '',
89            className: element.className || '',
90            text: label.substring(0, 120),
91            href: element.href || '',
92            type: element.type || '',
93            ariaLabel: (element.getAttribute && element.getAttribute('aria-label')) || '',
94            title: element.title || ''
95        };
96        return info;
97    }
98
99    // A Resy click is a click on something that actually opens Resy: a link to
100    // resy.com, the Resy widget (embed.js swaps the resyButton-* link for a
101    // role="button" span labelled "Resy - Book Now"), or an element tagged
102    // data-reserve / data-track="resy". Ancestors are matched
103    // by these attributes only, never by their text, so a "View Our Menus" button
104    // that merely sits next to "Book on Resy" is not counted as a reservation.
105    var RESY_SELECTOR = 'a[href*="resy.com"],a[href*="kashkaval.com/reservations"],[id^="resyButton"],' +
106        '[aria-label*="Resy"],[class*="resy"],[data-reserve],[data-track="resy"]';
107
108    function findResyElement(element) {
109        return element && element.closest ? element.closest(RESY_SELECTOR) : null;
110    }
111
112    // Track a general click (any clickable element)
113    function trackGeneralClick(clickData) {
114        var params = new URLSearchParams(window.location.search);
115        if (document.referrer) {
116            params.set('ref', document.referrer);
117        }
118        params.set('url', window.location.href);
119        params.set('page_title', trackingTitle);
120        params.set('click_target', clickData.target);
121        params.set('click_text', clickData.text);
122        params.set('click_href', clickData.href);
123
124        // Use sendBeacon for reliability
125        if (navigator.sendBeacon) {
126            navigator.sendBeacon('/track-click?' + params.toString());
127        } else {
128            var img = new Image();
129            img.src = '/track-click?' + params.toString();
130        }
131    }
132
133    function describeTarget(info) {
134        return info.tag + (info.id ? '#' + info.id : '') + (info.className ? '.' + String(info.className).split(' ')[0] : '');
135    }
136
137    // Global click handler
138    document.addEventListener('click', function(e) {
139        var target = e.target && e.target.closest && e.target.closest('a,button,input,[role="button"],[role="tab"],[oncl
139ick]');
140        if (!target) return;
141
142        var info = getElementInfo(target);
143
144        // A Resy click is logged once, as a conversion, and not again as a general click
145        var resyElement = findResyElement(target);
146        if (resyElement) {
147            var resyInfo = getElementInfo(resyElement);
148            trackResyConversion({
149                target: describeTarget(resyInfo),
150                text: resyInfo.text,
151                href: resyInfo.href
152            });
153            return;
154        }
155
156        // Track all clicks on links, buttons, and interactive elements
157        if (info.tag === 'A' || info.tag === 'BUTTON' ||
158            info.tag === 'INPUT' || info.href ||
159            String(info.className).indexOf('btn') >= 0 ||
160            target.onclick || target.getAttribute('onclick')) {
161
162            trackGeneralClick({
163                target: describeTarget(info),
164                text: (info.text || info.ariaLabel || info.title || '').substring(0, 120),
165                href: info.href
166            });
167        }
168    }, true); // Use capture phase to catch clicks early
169
170})();

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.