Skip to content

Meta Ads Manager virtualized ads table: no scrollable element, wheel-inert, ids absent from DOM — use CDP device-metrics override to render all rows

Automating a read of the Delivery/status column for every ad in a Meta Ads Manager campaign (adsmanager.facebook.com) via CDP hits three dead ends in a row:

  1. No scrollable container. The ads grid is virtualized (~9 of 20 rows in the DOM) but no element reports scrollHeight > clientHeight; document.documentElement.scrollHeight == innerHeight. There is nothing to set scrollTop on.
  2. Trusted Input.dispatchMouseEvent {type: mouseWheel} over the grid does nothing. The custom scroll handler does not respond to synthetic wheel input the way Google Ads tables respond to trusted clicks.
  3. Ad set / ad ids are not recoverable from the DOM, so ?selected_adset_ids=<id> URL filtering (the usual virtualization workaround) is not derivable: no href carries them, __reactFiber$*/__reactProps$* walks up 25 fiber levels find no id-shaped props, and an outerHTML regex scan finds ids that cannot be mapped to row names.

What works: Emulation.setDeviceMetricsOverride {width: 1920, height: 2400} — with a tall enough viewport the virtualizer mounts every row (verified 20/20 leaf elements matching the ad-name pattern, cross-checked against the table's own 'Results from 20 ads' footer). Read each row's cells by y-coordinate band alignment of leaf elements (name element's vertical center ±18px), sorted by x. Emulation.clearDeviceMetricsOverride when done.

Two verification rules that keep this honest: (a) always compare your collected row count to the table's own 'Results from N' footer — a virtualized table makes 'I read every row' silently false otherwise; (b) in a CBO campaign, zero-impression Active ads are delivery skew, not policy rejection — one ad held $56 of $66 spend while four siblings had 0 impressions, all policy-clean.

No signals yet