The fix, in one snippet
curl -s https://example.com | grep -oE 'src="https?://[^"/]+' | sort -u
Illustrative values. Change the paths, hostnames and options to match your own site before using it.
The sections below explain what is tested, why it matters and the alternatives.
What we test
Every third-party host named in the HTML the server delivered is matched against the same two filter lists most ad blockers are built on: EasyList, which names advertising endpoints, and EasyPrivacy, which names tracking, analytics and telemetry endpoints. Only whole-domain entries are used — a list rule covering one file on a shared CDN says nothing about the CDN itself, so it is ignored rather than counted. A host matches if it or any parent domain is named, so pagead2.googlesyndication.com matches a rule written for googlesyndication.com. The check reports the matching hosts; it does not judge whether you should have them.
Why it matters
This is the list of companies that receive your visitors' IP address, user agent and the page they were reading, on every page view, whether or not anyone consented. Two separate problems follow from it. The first is legal: under GDPR and the ePrivacy Directive, advertising and analytics endpoints are precisely the ones that require consent before they load, and a tag that fires on page load has already sent the data by the time a banner appears. The second is performance and supply chain: each of these hosts is a script with full access to the page, an extra DNS lookup and connection, and a third party whose outage or compromise becomes yours. The tracking guide explains what these endpoints collect and how.
A match is not an accusation. Plenty of sites run analytics deliberately and lawfully. The value of the list is that it makes the set explicit, which is the thing most teams have never actually seen written down.
One limit worth knowing: this reads the HTML your server sent, so it sees the tags that are in the page. A tag manager that injects further scripts after the page loads is counted once, as the tag manager — what it goes on to load is not in the HTML and is not counted here. On a site whose advertising is loaded entirely by script, expect this list to be shorter than what a browser's network panel shows.
How to fix it
Start by naming an owner for each host. Anything nobody claims should go — abandoned tags outlive the campaigns that added them by years.
For what stays, load it after consent rather than before. A tag manager that fires on page load defeats the consent banner in front of it:
<!-- not loaded until consent is recorded -->
<script>
window.addEventListener("consent:analytics", function () {
var s = document.createElement("script");
s.src = "https://www.googletagmanager.com/gtag/js?id=G-XXXX";
s.async = true;
document.head.appendChild(s);
});
</script>
Then stop the rest from being possible at all with a Content-Security-Policy that lists the hosts you meant to allow, so a tag added by someone else next quarter fails visibly instead of quietly shipping data:
Content-Security-Policy: script-src 'self' https://www.googletagmanager.com; connect-src 'self' https://region1.google-analytics.com
Server-side tagging (Cloudflare Zaraz, a self-hosted GTM container, Plausible or Matomo on your own domain) removes these hosts from the page entirely, which is the only fix that also makes the page faster. Whatever you keep, name it in your privacy policy: the list above is what a regulator would compile.
Where this fits
Advertising and tracking endpoints is check 4 of 10 that the website vulnerability scanner runs under page content and javascript, ordered the way they are worth fixing. That ordering is the point: Fixing this one while the check above it still fails buys less than it looks like.
Fix this one first
Above it in the same category sits Mixed content (HTTP resources on an HTTPS page) (high), where the HTTPS page loads scripts, styles, frames or media over plain HTTP. An attacker who has that does not need this, so it is the better use of the same hour.
What fixing this still leaves open
Advertising and tracking endpoints closes one route in. Immediately below it: CMS / generator version disclosure, where the page announces the CMS or static-site generator it was built with, usually including the version, in a meta tag, header or comment banner; Sensitive information in HTML comments, where hTML comments in the page source contain material that looks internal: Credentials, TODO notes, internal hostnames or IP addresses, file paths, or links to unpublished areas of the site; Third-party scripts without Subresource Integrity, where scripts or stylesheets are loaded from third-party hosts without an integrity attribute.
Found in the same scan
The website vulnerability scanner reports this alongside checks from other categories that are at least as serious, including Certificate chain and hostname validation, where the certificate presented for this hostname did not validate: The chain does not reach a trusted root, an intermediate is missing, the name does not match, or the certificate is self-signed or expired, and Exposed .env configuration file, where a .env configuration file is served from the web root. A single run of website vulnerability scanner answers all of them at once.
The first few lines
You are a senior web engineer. I ran a security and SEO scanner against my site and it reported the finding below. Fix it properly rather than suppressing the symptom.
Finding: Advertising and tracking endpoints (low severity)
Scanner check id: tracking-endpoints
The rest of this prompt names the pages and line numbers we found the problem on, the configuration to change, and the constraints a good answer has to respect. It is free, it just needs an account so the work is not scraped wholesale.
Sign in with GoogleSigning in is free and takes one click. We store your email address and nothing else.