// ==UserScript==
// @name Advanced Ad Tracker Logger
// @namespace elite.scan.logger.v2
// @version 2.0
// @description Logs and exports all ad/tracker URLs (.js, links, redirects, fetch) with download support even on redirecting pages
// @author Abdelali
// @match *://*/*
// @grant GM_download
// ==/UserScript==
(function () {
'use strict';
const findings = {
scripts: [],
adLinks: [],
externalLinks: [],
redirects: [],
};
const adKeywords = ['ads', 'adserver', 'doubleclick', 'tracker', 'analytics', 'revbid', 'coinzilla', 'adskeeper', 'banner', 'prebid', 'rtb'];
function isAdOrTracker(url) {
return adKeywords.some(kw => url.toLowerCase().includes(kw));
}
function logFinding(type, url, context = '') {
if (!findings[type].some(entry => entry.url === url)) {
findings[type].push({ url, context });
}
}
// Watch script injections
const scanDOM = () => {
try {
document.querySelectorAll('script[src]').forEach(script => {
const src = script.src;
if (isAdOrTracker(src)) {
logFinding('scripts', src, 'script tag');
}
});
document.querySelectorAll('a[href]').forEach(link => {
const href = link.href;
if (isAdOrTracker(href)) {
logFinding('adLinks', href, 'anchor');
} else if (href.startsWith('http') && new URL(href).hostname !== location.hostname) {
logFinding('externalLinks', href, 'external anchor');
}
});
// Try to inspect iframes
document.querySelectorAll('iframe').forEach(iframe => {
try {
const doc = iframe.contentDocument;
if (doc) {
doc.querySelectorAll('script[src]').forEach(script => {
if (isAdOrTracker(script.src)) {
logFinding('scripts', script.src, 'iframe script');
}
});
}
} catch (e) {
// cross-origin, skip silently
}
});
} catch (e) {}
};
const observer = new MutationObserver(scanDOM);
observer.observe(document, { childList: true, subtree: true });
setInterval(scanDOM, 3000); // Catch delayed loads
// Hook fetch & XHR
const origFetch = window.fetch;
window.fetch = function () {
const url = arguments[0];
if (typeof url === 'string' && isAdOrTracker(url)) {
logFinding('scripts', url, 'fetch');
}
return origFetch.apply(this, arguments);
};
const origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function (method, url) {
if (isAdOrTracker(url)) {
logFinding('scripts', url, 'XHR');
}
return origOpen.apply(this, arguments);
};
// Catch redirections
['pushState', 'replaceState'].forEach(fn => {
const orig = history[fn];
history[fn] = function () {
const url = arguments[2];
if (typeof url === 'string' && isAdOrTracker(url)) {
logFinding('redirects', url, `history.${fn}`);
}
return orig.apply(this, arguments);
};
});
window.addEventListener('hashchange', () => {
const url = location.href;
if (isAdOrTracker(url)) {
logFinding('redirects', url, 'hashchange');
}
});
// Export function with force download using Blob
function forceDownload(content, filename = 'ad_scan.json') {
const blob = new Blob([content], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.style.display = 'none';
document.body.appendChild(a);
a.click();
setTimeout(() => {
URL.revokeObjectURL(url);
a.remove();
}, 1000);
}
// Button
window.addEventListener('load', () => {
const btn = document.createElement('button');
btn.textContent = '📦 Export Ads Log';
Object.assign(btn.style, {
position: 'fixed',
bottom: '20px',
right: '20px',
zIndex: 999999,
padding: '10px',
background: '#111',
color: '#fff',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
});
btn.onclick = () => {
const data = JSON.stringify(findings, null, 2);
forceDownload(data, `ad_scan_${location.hostname}.json`);
};
document.body.appendChild(btn);
});
})();