1(function () { 2 'use strict'; 3 4 var options = {trackEvents: true, reportingClickId: true, serverClickLog: true, clickLogUrl: ''}; 5 6 if (window.Joomla && typeof window.Joomla.getOptions === 'function') { 7 var configured = window.Joomla.getOptions('plg_content_tiqets', {}); 8 options.trackEvents = configured.trackEvents !== false && configured.trackEvents !== 0; 9 options.reportingClickId = configured.reportingClickId !== false && configured.reportingClickId !== 0; 10 options.serverClickLog = configured.serverClickLog !== false && configured.serverClickLog !== 0; 11 options.clickLogUrl = typeof configured.clickLogUrl === 'string' ? configured.clickLogUrl : ''; 12 } 13 14 function sendEvent(name, params) { 15 if (!options.trackEvents) { 16 return; 17 } 18 19 if (typeof window.gtag === 'function') { 20 window.gtag('event', name, params); 21 return; 22 } 23 24 if (Array.isArray(window.dataLayer)) { 25 window.dataLayer.push(Object.assign({event: name}, params)); 26 } 27 } 28 29 function normaliseValue(value) { 30 if (value === null || typeof value === 'undefined') { 31 return null; 32 } 33 if (typeof value === 'number' || typeof value === 'string') { 34 return value; 35 } 36 return String(value); 37 } 38 39 function cleanClickId(value) { 40 value = String(value || '').trim(); 41 return value.length > 255 ? value.substring(0, 255) : value; 42 } 43 44 function getAdvertisingClickId() { 45 var params; 46 try { 47 params = new URL(window.location.href).searchParams; 48 } catch (_) { 49 return null; 50 } 51 52 var names = ['gclid', 'gbraid', 'wbraid', 'msclkid']; 53 for (var i = 0; i < names.length; i++) { 54 var value = cleanClickId(params.get(names[i])); 55 if (value) { 56 return {id: value, source: names[i]}; 57 } 58 } 59 60 return null; 61 } 62 63 function generateClickId() { 64 if (window.crypto && typeof window.crypto.randomUUID === 'function') { 65 return window.crypto.randomUUID(); 66 } 67 68 if (window.crypto && typeof window.crypto.getRandomValues === 'function') { 69 var bytes = new Uint8Array(16); 70 window.crypto.getRandomValues(bytes); 71 bytes[6] = (bytes[6] & 0x0f) | 0x40; 72 bytes[8] = (bytes[8] & 0x3f) | 0x80; 73 var hex = Array.prototype.map.call(bytes, function (b) { 74 return b.toString(16).padStart(2, '0'); 75 }).join(''); 76 return hex.substring(0, 8) + '-' + hex.substring(8, 12) + '-' + hex.substring(12, 16) 77 + '-' + hex.substring(16, 20) + '-' + hex.substring(20); 78 } 79 80 return 'tq-' + Date.now().toString(36) + '-' + Math.random().toString(36).substring(2, 14); 81 } 82 83 function applyReportingClickId(link) { 84 if (!options.reportingClickId) { 85 return {id: null, source: null}; 86 } 87 88 var adClick = getAdvertisingClickId(); 89 var clickId = adClick ? adClick.id : generateClickId(); 90 var source = adClick ? adClick.source : 'generated'; 91 92 try { 93 var url = new URL(link.href, window.location.href); 94 url.searchParams.set('tq_click_id', clickId); 95 link.href = url.toString(); 96 } catch (_) { 97 return {id: null, source: null}; 98 } 99 100 return {id: clickId, source: source}; 101 } 102 103 function logClickOnServer(link, click) { 104 if (!options.serverClickLog || !options.clickLogUrl || !click || !click.id) { 105 return; 106 } 107 108 var payload = new FormData(); 109 payload.append('click_id', click.id); 110 payload.append('campaign', link.getAttribute('data-tiqets-campaign') || ''); 111 payload.append('page_url', window.location.origin + window.location.pathname); 112 113 if (navigator.sendBeacon) { 114 try { 115 if (navigator.sendBeacon(options.clickLogUrl, payload)) { 116 return; 117 } 118 } catch (_) { 119 // Fall back to fetch below. 120 } 121 } 122 123 if (typeof window.fetch === 'function') { 124 try { 125 window.fetch(options.clickLogUrl, { 126 method: 'POST', 127 body: payload, 128 credentials: 'same-origin', 129 keepalive: true, 130 headers: {'X-Requested-With': 'XMLHttpRequest'} 131 }).catch(function () {}); 132 } catch (_) { 133 // Logging must never block navigation to Tiqets. 134 } 135 } 136 } 137 138 function handleTiqetsWidgetEvent(event) { 139 if (!options.trackEvents || event.origin !== 'https://www.tiqets.com') { 140 return; 141 } 142 143 var data = event.data; 144 145 if (typeof data === 'string') { 146 try { 147 data = JSON.parse(data); 148 } catch (_) { 149 return; 150 } 151 } 152 153 if (!data || typeof data !== 'object') { 154 return; 155 } 156 157 if (data.event !== 'tiqetsWidgetClickThrough' && data.event !== 'tiqetsWidgetInteraction') { 158 return; 159 } 160 161 var detail = data.detail && typeof data.detail === 'object' ? data.detail : {}; 162 var eventName = data.event === 'tiqetsWidgetClickThrough' 163 ? 'tiqets_widget_clickthrough' 164 : 'tiqets_widget_interaction'; 165 166 sendEvent(eventName, { 167 widget_type: normaliseValue(data.widget_type), 168 widget_campaign: normaliseValue(data.widget_campaign), 169 entity_name: normaliseValue(data.entity_name), 170 detail_name: normaliseValue(detail.name),
171 detail_value: normaliseValue(detail.value) 172 }); 173 } 174 175 window.addEventListener('message', handleTiqetsWidgetEvent); 176 177 document.addEventListener('click', function (event) { 178 var target = event.target; 179 if (!target || typeof target.closest !== 'function') { 180 return; 181 } 182 183 var link = target.closest('.tiqets-cta-button-v1, .tiqets-tracked-link-v1'); 184 if (!link) { 185 return; 186 } 187 188 var click = applyReportingClickId(link); 189 logClickOnServer(link, click); 190 191 sendEvent('tiqets_affiliate_click', { 192 widget_type: 'link', 193 widget_campaign: link.getAttribute('data-tiqets-campaign') || null, 194 product_id: link.getAttribute('data-tiqets-product') || null, 195 tiqets_click_id: click.id, 196 click_id_source: click.source, 197 link_url: link.href || null 198 }); 199 }, false); 200}());
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.