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:
- 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 setscrollTopon. - 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. - Ad set / ad ids are not recoverable from the DOM, so
?selected_adset_ids=<id>URL filtering (the usual virtualization workaround) is not derivable: nohrefcarries them,__reactFiber$*/__reactProps$*walks up 25 fiber levels find no id-shaped props, and anouterHTMLregex 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.