Server side tracking checker
In questa pagina puoi trovare un codice JS utile per controllare la presenza di una installazione server side.
È da incollare nella console del browser dopo che hai caricato una pagina web.
Lo script restituirà in console il risultato del controllo sotto la voce “verdetto”.
(() => {
// --------- Utility
const now = new Date().toISOString();
const url = new URL(location.href);
// Grezza eTLD+1: sufficiente per molti casi (acme.it, example.co.uk, ecc.)
const getETLD1 = (host) => {
const parts = host.split('.').filter(Boolean);
if (parts.length <= 2) return host; const two = parts.slice(-2).join('.'); const three = parts.slice(-3).join('.'); const common2lvl = /(\.co\.uk|\.ac\.uk|\.gov\.uk|\.com\.au|\.com\.br|\.com\.mx|\.com\.ar|\.com\.sg|\.com\.tr|\.com\.cn)$/i; return common2lvl.test(three) ? three : two; }; const baseDomain = getETLD1(url.hostname); const isFirstParty = (u) => {
try { return new URL(u, location.href).hostname.endsWith(baseDomain); }
catch { return false; }
};
const getHostname = (u) => {
try { return new URL(u, location.href).hostname || ''; }
catch { return ''; }
};
// Pattern noti per “proxy/GTM-SS endpoints”
const FIRST_PARTY_COLLECT_PATTERNS = [
/\/g\/collect/i, // GA4 proxata/SS
/\/collect(\?|$)/i, // GA collect generico
/\/r\/collect/i, // GA legacy
/\/j\/collect/i, // GA legacy
/\/analytics\/collect/i, // varianti custom
/\/capi/i, // endpoint custom per Meta CAPI
/\/event(s)?\/collect/i, // varianti custom
];
// Vendor terze parti
const GA_THIRD = /(^|\.)google-analytics\.com$/i;
const GTM_THIRD = /(^|\.)googletagmanager\.com$/i;
const FB_THIRD = /(^|\.)facebook\.com$|(^|\.)connect\.facebook\.net$/i;
// Indicatori di "loader proxato"
const PROXIED_LOADER_PATTERNS = [
/\/gtm\.js\?id=GTM-/i, // gtm.js servito in first-party
/\/tag\/js\/g\?id=G-/i, // gtag.js servito in first-party
];
// --------- Network-based evidences (Performance API)
const entries = performance.getEntriesByType('resource')
.map(e => e.name)
.filter(Boolean);
const urls = [...new Set(entries)];
const parsed = urls.map(u => {
try {
const p = new URL(u);
return { url: u, host: p.hostname, path: p.pathname + (p.search || '') };
} catch { return { url: u, host: '', path: '' }; }
});
const firstPartyCollect = parsed.filter(r =>
isFirstParty(r.url) && FIRST_PARTY_COLLECT_PATTERNS.some(rx => rx.test(r.path))
);
const proxiedLoaders = parsed.filter(r =>
isFirstParty(r.url) && PROXIED_LOADER_PATTERNS.some(rx => rx.test(r.path))
);
const gaThirdCollect = parsed.filter(r =>
/\/(g|j|r)?\/collect/i.test(r.path) && GA_THIRD.test(r.host)
);
const gtmThirdLoader = parsed.filter(r =>
/\/gtm\.js/i.test(r.path) && GTM_THIRD.test(r.host)
);
const fbThirdPixel = parsed.filter(r =>
/\/fbevents\.js|\/tr\/?/i.test(r.path) && FB_THIRD.test(r.host)
);
const gaLoaderPresent = parsed.some(r =>
/gtag\/js|\/tag\/js\/g\?id=G-/i.test(r.path) || /G-[A-Z0-9]{6,}/.test(r.url)
);
// --------- NEW: DOM-based scan for GTM loaders (script + noscript iframe)
const domScripts = Array.from(document.querySelectorAll('script[src]'));
const domIframes = Array.from(document.querySelectorAll('iframe[src]'));
// Individua script GTM (gtm.js) e iframe noscript (ns.html?id=GTM-XXXX)
const domGtmScripts = domScripts
.filter(s => /(^|\/)gtm\.js(\?|$)/i.test(s.getAttribute('src') || ''))
.map(s => {
const src = s.getAttribute('src') || '';
const host = getHostname(src);
return {
tipo: 'script',
src,
host,
posizione: s.closest('head') ? 'head' : 'body'
};
});
const domGtmIframes = domIframes
.filter(f => /\/ns\.html\?id=GTM-/i.test(f.getAttribute('src') || ''))
.map(f => {
const src = f.getAttribute('src') || '';
const host = getHostname(src);
return {
tipo: 'iframe',
src,
host,
posizione: f.closest('body') ? 'body' : 'altro'
};
});
const domGtmAll = [...domGtmScripts, ...domGtmIframes];
const domOfficial = domGtmAll.filter(x => GTM_THIRD.test(x.host));
const domNonOfficial = domGtmAll.filter(x => x.host && !GTM_THIRD.test(x.host));
// --------- Heuristics / punteggio semplice
let score = 0;
if (firstPartyCollect.length) score += 2; // forte indizio SS/proxy
if (proxiedLoaders.length) score += 1; // loader proxati
if (!gaThirdCollect.length && gtmThirdLoader.length) score += 1; // GA presente ma collect non diretto
if (gaLoaderPresent && !gaThirdCollect.length && !firstPartyCollect.length) score += 1;
// NUOVO segnale: GTM caricato da host diverso da googletagmanager.com
if (domNonOfficial.length) score += 2;
const verdict =
score >= 3 ? 'PROBABILE tracking server-side/proxy su first-party'
: score === 2 ? 'POSSIBILE tracking server-side/proxy'
: 'IMPROBABILE (dai segnali disponibili)';
// --------- Output
console.group('🔎 Server-side/Proxy Tracking Check');
console.log('Data/ora:', now);
console.log('Dominio base rilevato (eTLD+1):', baseDomain);
console.group('Riepilogo segnali');
console.table([
{ metrica: 'First-party collect endpoints (network)', riscontri: firstPartyCollect.length },
{ metrica: 'Loader proxati (gtm.js/gtag.js in first-party, network)', riscontri: proxiedLoaders.length },
{ metrica: 'Collect GA verso google-analytics.com (network)', riscontri: gaThirdCollect.length },
{ metrica: 'Loader GTM da googletagmanager.com (network)', riscontri: gtmThirdLoader.length },
{ metrica: 'Pixel/JS Facebook terza parte (network)', riscontri: fbThirdPixel.length },
{ metrica: 'GTM ufficiale (DOM: host = googletagmanager.com)', riscontri: domOfficial.length },
{ metrica: 'GTM NON ufficiale (DOM: host ≠ googletagmanager.com)', riscontri: domNonOfficial.length }
]);
console.groupEnd();
console.log('➤ Verdict:', verdict);
if (domGtmAll.length) {
console.group('Dettagli GTM trovati nel DOM');
console.table(domGtmAll.map(x => ({
tipo: x.tipo,
host: x.host || '(relativo / non risolvibile)',
posizione: x.posizione,
src: x.src
})));
if (domNonOfficial.length) {
console.warn('⚠️ GTM caricato da host non ufficiale -> indizio di proxy/Server-Side (es. sGTM). Verificare configurazione.');
}
console.groupEnd();
} else {
console.info('ℹ️ Nessun riferimento GTM trovato nella DOM (script gtm.js / iframe ns.html).');
}
if (firstPartyCollect.length) {
console.group('Dettagli first-party collect endpoints sospetti (network)');
console.table(firstPartyCollect.map(x => ({ host: x.host, path: x.path })));
console.groupEnd();
}
if (proxiedLoaders.length) {
console.group('Dettagli loader proxati (gtm.js/gtag.js in first-party, network)');
console.table(proxiedLoaders.map(x => ({ host: x.host, path: x.path })));
console.groupEnd();
}
if (!firstPartyCollect.length && !domNonOfficial.length && score <= 2) {
console.info('ℹ️ Nota: l’assenza di collect “visibili” o di loader GTM non ufficiali non esclude un modello server-to-server puro (invisibile dal browser).');
}
// Suggerimento operativo leggibile
if (domNonOfficial.length) {
console.log('→ Azione consigliata: ispezionare l’host indicato (es. /ns.html o /gtm.js first-party) e verificare presenza di un container sGTM o di un reverse proxy.');
} else if (firstPartyCollect.length || proxiedLoaders.length) {
console.log('→ Azione consigliata: verificare regole proxy/rewriting e configurazioni di server-side tagging per GA/Meta.');
} else {
console.log('→ Azione consigliata: nessun indizio forte. Controllare comunque lato server/cordate CDN se si sospetta traffico SS.');
}
console.groupEnd();
})();

