PageSourceSearch

https://www.wprssaggregator.com/wp-content/plugins/vireo-analytics…/js/outbound-tracker.js?ver=1781022487

js wprssaggregator.com collected 2026-10-02 05:08:59 UTC 4,295 bytes, 125 lines download raw bytes

1(function () {
2	'use strict';
3
4	if (typeof window.laOutbound !== 'object' || !window.laOutbound.url) return;
5
6	// Respect Do-Not-Track — keeps us consent-free.
7	if (navigator.doNotTrack === '1' || window.doNotTrack === '1') return;
8
9	var endpoint = window.laOutbound.url;
10	var siteHost = (window.laOutbound.siteHost || location.hostname || '').toLowerCase();
11	var patterns = Array.isArray(window.laOutbound.affiliatePatterns) ? window.laOutbound.affiliatePatterns : [];
12	var dlExts = Array.isArray(window.laOutbound.downloadExtensions) ? window.laOutbound.downloadExtensions : [];
13
14	// Lowercase, strip leading dots, build a Set for O(1) lookup.
15	var dlSet = (function () {
16		var s = Object.create(null);
17		for (var i = 0; i < dlExts.length; i++) {
18			var e = String(dlExts[i] || '').toLowerCase().replace(/^\./, '');
19			if (e) s[e] = true;
20		}
21		return s;
22	})();
23
24	// Glob -> RegExp. `*` matches any char except `/`, `**` matches any char.
25	// Anchored. Same semantics as the server-side va_path_matches_rules().
26	function globToRegex(pattern) {
27		var rx = '^';
28		var parts = pattern.split(/(\*\*|\*)/);
29		for (var i = 0; i < parts.length; i++) {
30			var seg = parts[i];
31			if (seg === '**') rx += '.*';
32			else if (seg === '*') rx += '[^/]*';
33			else rx += seg.replace(/[.+?^${}()|[\]\\]/g, '\\$&');
34		}
35		rx += '$';
36		return new RegExp(rx, 'i');
37	}
38	var compiledPatterns = patterns.map(globToRegex);
39
40	function matchesAffiliate(pathname) {
41		if (!compiledPatterns.length) return false;
42		for (var i = 0; i < compiledPatterns.length; i++) {
43			if (compiledPatterns[i].test(pathname)) return true;
44		}
45		return false;
46	}
47
48	function pathExtension(pathname) {
49		// Strip query / fragment defensively (URL.pathname already does this,
50		// but be conservative since some callers pass raw hrefs).
51		var p = pathname.split('?')[0].split('#')[0];
52		var slash = p.lastIndexOf('/');
53		var name  = slash >= 0 ? p.slice(slash + 1) : p;
54		var dot   = name.lastIndexOf('.');
55		if (dot < 0 || dot === name.length - 1) return '';
56		return name.slice(dot + 1).toLowerCase();
57	}
58
59	function isDownload(pathname) {
60		var ext = pathExtension(pathname);
61		return ext !== '' && dlSet[ext] === true;
62	}
63
64	function fire(url, type) {
65		try {
66			var body = new URLSearchParams();
67			body.set('action', 'va_outbound_click');
68			body.set('url', url);
69			if (type) body.set('type', type);
70			fetch(endpoint, {
71				method: 'POST',
72				credentials: 'omit',
73				headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
74				body: body.toString(),
75				keepalive: true,
76			});
77		} catch (e) { /* ignore */ }
78	}
79
80	function onClick(e) {
81		// Only plain left clicks. Middle-click / cmd-click still navigate but
82		// we can't reliably catch them without blocking navigation.
83		if (e.defaultPrevented) return;
84		if (e.button !== 0) return;
85		if (e.metaKey || e.ctrlKey || e.shiftKey || e.altKey) return;
86
87		var a = e.target.closest ? e.target.closest('a[href]') : null;
88		if (!a) return;
89		var href = a.getAttribute('href');
90		if (!href) return;
91		if (href.startsWith('#') || href.startsWith('javascript:') || href.startsWith('mailto:') || href.startsWith('tel:')) return;
92
93		var url;
94		try { url = new URL(a.href, location.href); } catch (err) { return; }
95		if (url.protocol !== 'http:' && url.protocol !== 'https:') return;
96
97		var host        = url.hostname.toLowerCase();
98		var pathname    = url.pathname || '/';
99		var isExternal  = host !== '' && host !== siteHost;
100		var isAffiliate = !isExternal && matchesAffiliate(pathname);
101		var isDl        = isDownload(pathname);
102
103		// Three categories, two writes:
104		//   - external link  → type=link
105		//   - external download → type=download
106		//   - same-host affiliate (e.g. /go/foo) → type=link
107		//   - same-host download (e.g. /wp-content/uploads/foo.pdf) → type=download
108		// Anything else (regular internal navigation) is dropped.
109		if (!isExternal && !isAffiliate && !isDl) return;
110
111		fire(url.href, isDl ? 'download' : 'link');
112	}
113
114	function start() {
115		// Capture phase so we run before most in-page handlers. We never
116		// preventDefault — navigation proceeds normally.
117		document.addEventListener('click', onClick, true);
118	}
119
120	if (document.readyState === 'loading') {
121		document.addEventListener('DOMContentLoaded', start);
122	} else {
123		start();
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.