To bannerscored · Banner Speed
Time to banner
Elapsed time from navigation until a configured banner selector is detected as visible.
Why it matters. How long a visitor waits to be asked. It is the whole of Banner Speed, 30% of the score.
Reading the value. Lower is earlier. Scores 100 at 0 ms and 0 at 5 s or later.
How it is captured. A requestAnimationFrame probe checks visibility and non-zero bounds, then records performance.now(). Detection is not a separate pixel-paint measurement.
FCPscored · Page Impact
First Contentful Paint
First Contentful Paint: when the browser first paints text, an image or other content.
Why it matters. A consent script that loads synchronously holds up the page's first paint. It is the most independent cost in the score: it barely tracks any other measurement.
Reading the value. Scored as first-paint delay, the increase over the no-SDK control: 100 at no delay, 0 at 3 s — the Core Web Vitals poor line — or more.
How it is captured. The first first-contentful-paint entry from a buffered paint PerformanceObserver.
TBTscored · Page Impact
Total Blocking Time
Total observed long-task duration beyond the first 50 ms of each task.
Why it matters. Time the page cannot respond to a tap or a click because a script is busy.
Reading the value. Scored in Page Impact as the increase over the no-SDK control: 100 at none added, 0 at 600 ms — the Core Web Vitals poor line — or more.
How it is captured. A longtask observer sums max(0, duration − 50 ms) throughout collection, not just the Lighthouse FCP-to-TTI window. This is not INP.
Bytesscored · Network Cost
Bytes over the wire
Every byte that crossed the network for this page load, headers included, compressed as sent, recorded from outside the page over the DevTools protocol.
Why it matters. It is the figure Network Cost scores. The page's own view of the same load reports zero for cross-origin responses whose server withholds Timing-Allow-Origin, which is every vendor-script installation here — so on that view the vendors that disclose least would look lightest.
Reading the value. Scored as the increase over the no-SDK control: 100 at nothing added, 0 at 250 KB or more.
How it is captured. encodedDataLength from Network.loadingFinished, summed over completed http(s) requests. Redirects count as their own entries; failed and aborted requests are excluded rather than counted as zero; data: and blob: URLs never crossed a wire and are skipped. The navigation document is included, which Resource Timing excludes — both sides of the control comparison are counted the same way.
Requestsscored · Network Cost
Requests over the wire
Completed network requests the page made, as the protocol counted them.
Why it matters. Each request is at least a round trip and a slot in the browser's connection queue, whatever its size.
Reading the value. Scored as the increase over the no-SDK control: 100 at none added, 0 at 20 or more.
How it is captured. Count of the requests summed for wireBytes.
Coveragescored · Visitor Experience
Viewport coverage
Banner bounding-box area divided by the viewport area at detection.
Why it matters. How much of the page the question hides while it waits for an answer.
Reading the value. Scored in Visitor Experience: 100 at 0 %, 0 at half the screen or more. A smaller banner is not automatically a better consent interface; this measures only what it covers.
How it is captured. getBoundingClientRect() width × height divided by window.innerWidth × window.innerHeight. The bounding box is not clipped to the visible viewport.
To usablescored · Visitor Experience
Time to a usable banner
Elapsed time from navigation until the banner first has a control a click would reach: an enabled button or link whose own centre passes a hit test, with nothing in its ancestry still animating.
Why it matters. A banner can be on screen before it can be acted on. A control that is covered, set to pointer-events: none, or still sliding into place will not respond to the tap it invites.
Reading the value. Equal to time-to-banner means the banner was usable the moment it appeared. The gap between the two is scored in Visitor Experience: 100 at no gap, 0 at a second or more. It is never also counted in Banner Speed.
How it is captured. Per frame after detection: document.elementFromPoint at each candidate control's centre, descending through shadow roots, accepting the control or a descendant of it but not an ancestor. Accepted immediately when no ancestor reports a running animation, otherwise when the control's geometry is unchanged from the previous frame. Null if nothing becomes clickable within 5s of detection — unmeasured, not zero.
LCPreported, not scored
Largest Contentful Paint
Largest Contentful Paint: the latest observed timestamp for the largest eligible content element.
Why it matters. Reported, not scored. When the banner is the largest thing on screen it is the LCP element, so a fast banner makes LCP later and a slow one leaves it early — scoring it would reward arriving late.
Reading the value. The published Core Web Vitals good threshold is at most 2,500 ms. These are lab page loads, not field assessment.
How it is captured. A buffered largest-contentful-paint PerformanceObserver retains the largest startTime until collection ends.
Page LCPreported, not scored
The page's own LCP
Largest Contentful Paint with every entry belonging to the banner excluded.
Why it matters. The page's own largest paint — the cost the host pays — separated from the banner's. On this test page it lands on first paint, which is why first-paint delay is what the score uses.
Reading the value. Reported, not scored.
How it is captured. The same largest-contentful-paint observer as LCP, skipping an entry whose element sits inside the banner, climbing out of shadow roots. Decided when the entry is observed, while its element is still attached.
CLSreported, not scored
Cumulative Layout Shift
The collector’s accumulated layout-shift values during the measurement window.
Why it matters. Reported, not scored. Every banner here is a fixed overlay, so nothing below it moves: 0.000 for all but one installation. Scored, it would hand every row a free hundred.
Reading the value. The standard CLS good boundary is at most 0.1, but this collector sums the whole window rather than using the standard largest session window.
How it is captured. A layout-shift PerformanceObserver sums entries without recent user input. This lab accumulator must not be presented as a field CLS assessment.
TTIreported, not scored
Time to Interactive
A lab approximation of the time after the last observed long task.
Why it matters. Reported, not scored: it moves almost exactly with blocking time, which is scored, so scoring both would charge the same long tasks twice.
Reading the value. Lower is earlier, but this approximation has no validated good threshold.
How it is captured. The maximum of FCP, DOMContentLoaded end and last-long-task end. This is not the retired Lighthouse TTI algorithm.
Hostsreported, not scored
Third-party hosts contacted
Distinct hosts other than the page's own that the load contacted.
Why it matters. Reported, not scored. It was scored in a draft of this method and withdrawn: the time, bytes and requests those hosts cost are already scored, and what was left scored every self-hosted install a perfect hundred for being self-hosted.
Reading the value. No threshold. Zero means the consent layer was served from the page's own origin.
How it is captured. Distinct URL hosts among completed wire requests not on the page's origin.
Third-partyreported, not scored
Third-party bytes
Wire bytes that came from an origin other than the page's own.
Why it matters. On this page the only third party is the consent vendor, so this is a second, independent derivation of the bytes Network Cost already charges — which is why it is reported rather than scored twice.
Reading the value. Zero means the consent layer was served from the page's own origin.
How it is captured. wireBytes restricted to requests whose origin is not the page's.
Page-reportedreported, not scored
Bytes the page could see
Sum of resource sizes exposed to the collector, excluding the navigation document.
Why it matters. Reported beside the wire figure, which is what the score uses. The difference between the two is exactly what a vendor's host withheld from the page.
Reading the value. Not scored. Cross-origin restrictions mean this is not complete network traffic, which is why it was replaced.
How it is captured. Resource Timing entries contribute transferSize, falling back to encodedBodySize, then zero. Cache hits may therefore still contribute body bytes; unexposed cross-origin sizes can remain zero.
Banner shiftreported, not scored
Layout shift after banner
Layout-shift total accumulated after the banner is first detected.
Why it matters. Shows movement in the part of the measurement window after the banner arrives.
Reading the value. Zero means no recorded shift in that window; this metric has no separate standard threshold.
How it is captured. The collector subtracts the CLS total at banner detection from the final total. Other late content can contribute: this is a timing attribution, not proof of causation.