Signal · signalsVersion 5

content_blockers

Which of eight off-screen bait elements with ad-like names a content blocker hid. No request is made and everything is removed. Not in either id.

content_blockers at a glance (from the library code, signalsVersion 5)
Component namecontent_blockers
In the visitorIdno (reported, kept out of both ids)
structuredId groupnone
Hashingplain value; a digest only when longer than 128 characters or not printable ASCII
Excluded underno browser class
Inner timeout1000 ms
Added insignalsVersion 3
In plain words

Ad blockers hide page elements whose names look like ads. WhiskerJS puts eight tiny, invisible test boxes with ad-like names on the page for a moment and checks which ones were hidden. That shows whether a blocker is active here, without loading anything. Users switch blockers on and off, so the result is reported but kept out of the identifiers.

What it reads

Whether each bait element has an offsetParent after 50 ms. The baits are 1x1 div elements with these selectors: classes ad-banner, adsbox, ad-slot, banner-ad, sponsored-ad, textAd, and ids ad-unit, ad_leaderboard. They are reported by the keys ad_banner, ad_box, ad_slot, banner_ad, sponsored, text_ad, ad_unit, ad_leaderboard.

How the technique works

  1. It needs a document.body; otherwise unavailable / no_document.
  2. An off-screen container (position: absolute; left: -9999px) gets the eight baits and is appended to the body.
  3. After 50 ms (time for cosmetic filters to apply), a bait whose offsetParent is null counts as hidden.
  4. If all eight look hidden and the container itself has no offsetParent, the page is not laid out (for example display: none on the body): unavailable / no_layout.
  5. The value is the keys of the hidden baits, comma-separated, or none.
  6. The container is removed in a finally block, so it leaves nothing behind.

Why it helps

It tells your server whether cosmetic filtering is active on this page, and roughly which kind of filter list: different blockers and lists hide different subsets of the baits. It also helps explain other values, such as missing page elements.

Stability

Low to medium: users enable and disable blockers per site, and filter lists update. Outside both ids for that reason.

Browser support and what blocks it

Works in any browser with a laid-out page: Chrome, Firefox, Safari, iOS browsers, Edge. Brave has a built-in blocker, so baits may be hidden there by default. Pages that are hidden or not laid out give no_layout. On slow or emulated setups the 50 ms wait plus layout can exceed the 1000 ms inner timeout.

Privacy

It reveals whether an ad blocker hides these names on this page. No ad or filter list is loaded, nothing is requested, and the elements are removed before collect() resolves. Leave it out with collect({ exclude: ['content_blockers'] }) if you do not need it; no id changes.

How WhiskerJS handles noise and failures

Status ruleId When
ok none or a list of hidden bait keys
unavailable no_document no document.body
unavailable no_layout the container itself is not laid out
blocked threw, security_error adding the elements throws
excluded caller_excluded you excluded it
timed_out timeout, aborted budget or abort

Example value

In the container test, headless Chromium and Firefox reported none; headless WebKit reported timed_out / timeout (the run was slow under emulation). With a common ad blocker you might see something like ad_banner,ad_box,banner_ad.

Questions and answers

Does WhiskerJS load ads or test URLs to detect blockers?

No. It only adds eight small elements with ad-like class names and ids to the page, waits 50 ms and checks which were hidden. No request is made, and the names are WhiskerJS's own, not copied from any filter list.

What does none mean?

No bait was hidden: either no content blocker is active on this page, or the blocker does not hide these names. It is not proof that no blocker is installed.

Why is it not in the visitorId?

Users turn blockers on and off per site and filter lists update often, so the value changes too easily.