1. Crawling
We launch a headless Chromium browser (via Playwright) with a desktop User-Agent and a 1366×800 viewport. We then load the URL you provided and wait for the page to reach networkidle for up to six seconds.
To improve coverage we also try to scan one additional internal page. We pick the most “interesting” same-domain link we can find, typically checkout, contact, pricing, signup or login, because those pages often load payment, support and conversion-tracking scripts that the front page does not.
Free scans load the page once and record what the browser does without any interaction — no logins, no form submissions, no consent-banner clicks. Paid plans automatically run consent-aware scanning: we re-open the site in a clean browser context, click an “Accept all” button on the consent banner, then revisit the entry page plus up to four of the baseline subpages in the same context (so the consent cookies and localStorage flags persist). The report shows a side-by-side delta of vendors, cookies and third-party domains that only load after consent.
The consent clicker searches both the main page and likely CMP iframes (Sourcepoint, OneTrust, Cookiebot, Didomi, TrustArc, Quantcast, Usercentrics, Iubenda, Klaro, Osano, Borlabs, Complianz) using a curated list of vendor selectors and accept-all button labels in ~15 languages. When deterministic selectors miss, an optional LLM fallback (gpt-4o-mini, cached per host) identifies the accept button from a pruned list of visible elements. Only button metadata from the scanned site (label text, tag, CSS classes, IDs, ARIA labels) is sent to the model — never personal data, the scan URL, cookies or page content (see our privacy policy). Against an 18-site smoke test of major European publishers, the current hit rate is around 89%.
2. Recording requests
For every network request the browser makes we record the URL, the host and the resource type. A request is classified as third-party when its registrable domain is different from the registrable domain of the scanned site.
To determine the registrable domain we use the Public Suffix List — the same list browsers use to decide where one organisation’s domain ends and a shared registry begins. This correctly handles multi-part suffixes like .co.uk, .com.au and .co.jp, so shop.example.co.uk collapses to example.co.uk rather than the registry co.uk.
On paid plans we also tag each third-party request with the page it fired on and whether it ran before or after consent. This provenance powers the “Found on” section under each vendor in the report, so you can point to the exact subpage a tracker loaded on — and whether it fired without consent — instead of just knowing it exists somewhere on the site.
3. Vendor matching
We maintain a curated database of 766 third-party vendors: browse the directory. Each vendor entry contains one or more domain patterns.
A request matches a vendor when:
- its hostname equals the pattern, or
- its hostname ends with
.+ pattern (suffix match), or - for the few non-domain patterns we use, the full URL contains the pattern.
When a request matches multiple patterns we pick the most specific (longest) one. Domains that don’t match any vendor are listed as unmatched.
4. Region classification
Each vendor is classified by ownership region. The classification is based on where the parent company is incorporated, not where data physically resides. A US-owned vendor with EU data centres is still classified as US because data-access requests (FISA 702, Cloud Act) are governed by ownership.
5. Loaded before consent and transfer review
Beyond the score, two parts of the report answer the questions a DPO actually asks: what fires before the visitor consents, and where does the data go. Both are derived directly from the recorded requests — they describe what we observed, not whether it is lawful.
Loaded before consent
The no-interaction load is our baseline: the vendors that fire on the very first page load, before any consent banner is clicked. We take that baseline, keep only genuine tracking-relevant categories (advertising, analytics, tag management, error tracking and similar), and separate first-party services from third-party ones. The headline count reflects only third-party trackers, because a site loading its own subdomain is not the concern.
This is a technical observation of what loaded on a single no-interaction page load on the scan date — not a legal conclusion about consent validity.
Observed external services and transfer review worksheet
Technical observations that can support updates to processing records and vendor registers. Legal and organisational fields require customer verification. We group each observed external service by ownership and DPF signals, not by a concluded processing location or legal mechanism:
Each service is also tagged with whether it fired before or after consent. The exposure matrix counts observed services per signal bucket and phase. It helps prioritise review, but it is not a GDPR risk rating. Paid plans list a possible mechanism or review prompt and export a CSV worksheet with customer-owned fields left empty.
How we verify DPF status: we don’t guess. A US-owned service only receives a DPF match signal when its legal entity is matched against the official participant list published by the U.S. Department of Commerce at dataprivacyframework.gov and that entity holds an active EU–US certification. When it matches, the report shows the exact certified entity and the date we last checked it (e.g. “Verified 8 Jul 2026 · Stripe, LLC”), so you can see how fresh the finding is. An automated job re-checks the full list every week: new certifications are picked up, and if a vendor’s certification lapses we’re alerted and the status is downgraded. Vendors we can’t match to an active certification are left as “status unknown” rather than implying a negative.
6. The EU Independence Score
The score is an experimental signal, not a compliance rating. It starts at 100 and four penalty components are subtracted:
Score = 100 − P_vendor − P_mix − P_unknown − P_infra
The formula above applies to sites owned by an EU/EEA company. If the scanned site itself is owned by a US, Chinese or Russian company, that ownership takes precedence over the vendor maths: the score is capped and relabelled (for example US-owned site), because the third-party stack is then mostly the owner’s own first-party assets. In that case the score reflects the site’s ownership, not the EU-friendliness of its embedded vendors. This override is why an EU-independence figure and an ownership caveat can appear together on the same report.
When significantly non-EU vendors (US, China, Global) make up a large share of the classified vendor stack, an additional penalty applies — up to −20. The penalty is scaled by sample size so a single finding on a short scan does not over-fire.
Example: 3 US vendors, 1 EU vendor = 75% non-EU ratio → P_mix ≈ 15
A site can run its trackers from the EU yet still host itself, its email or its DNS on a non-EU-owned provider. That is a first-order sovereignty concern (CLOUD Act / FISA 702) independent of the third-party stack, so we resolve the origin hosting, email (MX) and authoritative DNS (NS) providers and classify each by ownership region.
Only significantly non-EU providers (US, China, Global, Unknown) count. When infrastructure can’t be resolved, P_infra is 0 — it never penalises a scan for missing data.
Label guardrails
Labels are not derived purely from the numeric score. Hard rules prevent misleading labels even when the score is numerically high. For example, Mostly EU independent is blocked if non-EU vendors outnumber EU/EEA vendors, regardless of the score.
The score card in your report shows a full breakdown so you can see exactly how each component contributed, along with a confidence indicator.
7. Monitoring, history & policy tracking
Paid plans re-scan each monitored site on a weekly schedule and turn the results into a durable history rather than a single snapshot. Every scan is diffed against the last one, and three things are recorded.
Vendor timeline
For each vendor we keep a first-seen and last-seendate, whether it is currently active, and whether it loaded before or after consent. A change timeline logs every vendor added, vendor removed and score change between scans, so you can point to the exact date a tracker appeared — useful evidence at an audit. The full history is browsable per site and exportable to CSV or JSON.
Reject-all resolution proof
Every weekly scan re-runs the reject-all verdict, so monitoring doesn’t just tell you a tracker appeared — it tells you whether your cookie banner still stops the trackers it’s supposed to. When a tracker starts firing after “Reject all”, we log a timestamped consent-violation eventon the timeline and email you. When that same tracker later stops firing, we log the fix — giving you dated, before-and-after proof of exactly when the problem started and when it was resolved. It’s a technical observation, not a legal ruling, but it’s the kind of evidence that turns “we fixed it” into something you can show.
Legal-document tracking
On the same run we discover the site’s privacy policy, cookie policy, DPA, terms and GDPR pages. Links are classified from both the URL and the anchor text across multiple languages, and we deliberately follow the very common case where a site hosts these documents on a parent-company or group domain (for example a newspaper whose privacy policy lives on the publisher’s domain), while excluding social-network and search-engine platform policies. This crawl runs with a lightweight, size- and time-bounded fetch outside the page budget, so it never costs you a vendor-scan page.
For each document we normalise the text, take a SHA-256 content fingerprint, and extract the date the page statesit was last updated (cue-based, multilingual, rejecting impossible or future dates). On the next scan we compare fingerprints to detect when the content actually changed — independently of whatever date the page claims.
Documentation-gap flag
The signal we find most useful: when your vendor stack changes but the privacy (or cookie/DPA) document stays frozen, the alert flags a possible documentation gap. It is a prompt to review, not a legal finding — a policy can be correct without changing, and a change does not prove anything. You decide what needs updating.
Disclosure gap (Consent Assurance)
We go one step further than tracking when a document changed: we compare what the document says against what the page actually loads. While each policy is fetched, we read its text and match it against our vendor catalogue — a vendor counts as disclosed when one of its own domains (for example hotjar.com) appears verbatim, or when a distinctive vendor name appears as a whole word. Any vendor observed loading on the site but absent from every document we could read is surfaced as a possible disclosure gap.
We are deliberately biased toward treating a vendor as disclosed: short or ambiguous names (“Segment”, “Forms”) and shared infrastructure domains (amazonaws.com, googleapis.com) are ignored, because a missed disclosure would wrongly accuse a site of hiding a vendor. This is text matching, not a legal parse of a consent-management configuration — a vendor named only inside a linked sub-processor PDF can be missed, so “not found” means “worth checking”, never proof of non-disclosure. Confidence scales with how many policy documents we could read (one document is medium, several is high). Free scans show only the count of possible gaps; the paid report names each vendor.
If auto-discovery misses a document, you can pin exact policy URLs per monitored site and we track those instead.
Reject-all verdict (Consent Assurance)
Disclosure asks whether a vendor is named; the reject-all verdict asks whether the banner works. On paid plans we open the site in a fresh browser context, click a “Reject all” (or “Only necessary”) control, then revisit the entry page plus up to four baseline subpages and record every third-party request that fires afterthe rejection. The reject clicker mirrors the accept clicker — the same vendor selectors, multilingual labels, iframe traversal and optional LLM fallback — but is biased toward the most restrictive choice and never picks Accept or Settings.
We only count genuinely non-essential trackers against the banner: advertising, analytics, product analytics, session replay, A/B testing, customer-data platforms, marketing automation, email marketing, affiliate and social embeds. Functional, infrastructure and tag-management services are deliberately excluded so a green or red verdict stays defensible. A tracker that fired on the very first load, before the visitor could reject, is notcounted here — that belongs to the “loaded before consent” finding. Only requests observed after the reject click count as a violation.
The verdict has three honest outcomes. Respected: no non-essential vendor kept firing after rejection. Not respected: one or more did, and the paid report names each one. Reject not confirmed: we found a banner but could not confirm a working reject control — shown as an amber “could not verify”, never as a pass or fail. This is a technical observation of network activity, not a legal ruling, and some banners hide their reject option behind a settings panel we may not reach automatically.
8. What we don't do
- We don’t determine GDPR or DSA compliance.
- We don’t click consent banners on free scans (paid plans run an automatic post-consent pass).
- We don’t crawl the entire site by default (front page + one internal link on free, up to 5 pages on Pro, up to 20 on Agency).
- We don’t log in to authenticated areas or fill out forms.
- We don’t store IP addresses in plaintext; they are salted-hashed daily.
9. Limitations
Geographic bias also matters: some vendors serve different scripts based on the visitor’s country. We currently scan from a European IP, so results approximate what European visitors see.
The methodology evolves as we improve coverage. If you find a wrong classification, please let us know.