The Coalition for Better Ads (CBA) is an industry group that identified the ad experiences most likely to drive consumers to install ad blockers. Their research, conducted with over 66,000 consumers across North America and Europe, established the Better Ads Standards — a set of ad experiences that fall beneath a threshold of consumer acceptability.
These standards are enforced by major browsers. Google Chrome filters ads on sites that repeatedly violate them. Our monitoring system tests all CNC sites against every applicable standard.
View official standards at betterads.org
Our Playwright-based monitor runs automated tests against all 19 standards. Each test loads real site pages, handles cookie consent, waits for ads to render, then measures specific ad behaviors against the official thresholds. Results are indexed to OpenSearch and visualized in Grafana dashboards.
Daily sentinel: ~183 risk-weighted tests covering the 4 highest-risk standards across all sites. Weekly audit: Full 789 tests covering all standards on all URLs.
AdDetector.findPopupAds() scans for overlay elements that appear after page load, checking z-index, position:fixed/absolute, and viewport coverage. Also uses consent handler integration to distinguish CMP modals from ad pop-ups.
VideoDetector.findAutoplayingVideosWithSound() monitors all <video> and <audio> elements for 5 seconds, checking muted and autoplay attributes plus actual playback state via media events.
AdDetector.findPopupAds() + timing analysis. Detects full-page overlays present before DOMContentLoaded, then checks for countdown text patterns (e.g., "3s", "close in") and dismiss button delay.
AdDetector.findStickyAds() scrolls the page and identifies elements with position:fixed or position:sticky that remain visible, then calculates their viewport height percentage.
DensityCalculator.measureViewportDensity() uses AdDetector.findAllAds() + findBrandingAds() to sum all ad heights within the main content region and compute the ratio.
DensityCalculator first checks for sticky video ads via AdDetector.findStickyAds(), then applies the stricter 30% threshold if any are found. Uses the same density measurement pipeline as D5.
AdDetector.findPopupAds() — same detector as desktop, running on mobile viewport (iPhone 14, 390×844).
AdDetector.findPopupAds() + page load timing analysis. Detects overlays present before DOMContentLoaded on mobile viewport.
DensityCalculator.measureViewportDensity() with mobile thresholds. Same pipeline as desktop density but with 30% critical threshold.
VideoDetector.findAutoplayingVideosWithSound() — same as desktop, running on mobile viewport.
AdDetector.findStickyAds() — same as desktop D4, running on mobile viewport. Scrolls page and checks for fixed-position ad elements exceeding 30% viewport height.
position:fixed video elements at the bottom of the screen. Correlates with previously-visible inline video ads.
AdDetector.findAllAds() size filtering. Checks if a large inline ad (≥300×600) is visible while a sticky video ad is present.
| Threshold | Desktop | Mobile | Video |
|---|---|---|---|
>50% ad density |
D5 | — | — |
>30% ad density |
D6 (with sticky video) | M3 | — |
>30% of screen (sticky) |
D4 | M7 M8 | — |
>20% of video player |
— | — | V3 |
>31s + no skip in 6s |
— | — | V1 |
| Absolute ban (any instance) | D1 D2 D3 | M1 M2 M4 M5 M6 M9 M10 | V2 |
| Standard | Official Threshold | Our Warning | Our Critical |
|---|---|---|---|
| D5. Desktop Ad Density | >50% |
45% | 50% |
| D6. Desktop Density + Sticky Video | >30% |
— | 30% |
| M3. Mobile Ad Density | >30% |
25% | 30% |
| D4 / M8. Large Sticky Ads | >30% of viewport |
— | 30% |
| M7. Full-screen Scrollover | >30% of viewport |
— | 30% |
| M4. Flashing Animated Ads | Rapid flashing | — | >3 flashes/sec |
| D2 / M5. Autoplay Video with Sound | Any autoplay with sound | — | 5000ms detection window |
| V1. Long Pre-Roll | >31s + no skip in 6s |
— | 31s / 6s |
| V3. Large Display Overlay | >20% of player |
— | 20% |
Shared rules across D5, D6, and M3 density standards: