← back to Ventura Corridor
scripts/probe_adst2.ts
125 lines
/**
* Deep dive into creative-preview structure and priority-creative-grid.
*/
import { chromium } from 'playwright';
const DOMAIN = 'clearchoice.com';
const URL = `https://adstransparency.google.com/?domain=${DOMAIN}®ion=US`;
const browser = await chromium.launch({ headless: true });
const ctx = await browser.newContext({
viewport: { width: 1280, height: 1600 },
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36',
});
const page = await ctx.newPage();
await page.goto(URL, { waitUntil: 'domcontentloaded', timeout: 30_000 });
await page.waitForTimeout(4000);
const dump = await page.evaluate(() => {
const out: Record<string, any> = {};
// Full outerHTML of first creative-preview (truncated to 2000 chars)
const cp = document.querySelectorAll('creative-preview');
out.creative_preview_full_html = Array.from(cp).slice(0, 3).map((e) => (e as HTMLElement).outerHTML.slice(0, 2000));
// priority-creative-grid
const pcg = document.querySelector('priority-creative-grid');
out.priority_creative_grid_html = pcg ? (pcg as HTMLElement).outerHTML.slice(0, 3000) : null;
// ads-count div
const adsCount = document.querySelector('.ads-count, [class*="ads-count"]');
out.ads_count_el = adsCount ? {
tag: adsCount.tagName,
className: adsCount.className,
innerText: (adsCount as HTMLElement).innerText,
outerHTML: (adsCount as HTMLElement).outerHTML,
} : null;
// domain-title
const domainTitle = document.querySelector('.domain-title, [class*="domain-title"]');
out.domain_title = domainTitle ? (domainTitle as HTMLElement).innerText : null;
// All aria-labels on creative-preview links
out.creative_aria_labels = Array.from(cp).slice(0, 5).map((e) => {
const a = e.querySelector('a');
return {
aria_label: a?.getAttribute('aria-label'),
href: a?.getAttribute('href'),
img_src: e.querySelector('img')?.src,
// Try to find any text not "Verified"
all_text_nodes: Array.from(e.querySelectorAll('*'))
.filter((el) => el.children.length === 0)
.map((el) => (el as HTMLElement).innerText?.trim())
.filter((t) => t && t.length > 0 && t !== 'Verified')
.slice(0, 10),
};
});
// iframes inside creative-preview
out.iframes_count = document.querySelectorAll('creative-preview iframe').length;
// scrollable-cards
const sc = document.querySelector('scrollable-cards');
out.scrollable_cards_text = sc ? (sc as HTMLElement).innerText.slice(0, 500) : null;
// html-renderer (used for ad creative HTML)
const hr = document.querySelectorAll('html-renderer');
out.html_renderer_count = hr.length;
out.html_renderer_first = hr.length ? (hr[0] as HTMLElement).outerHTML.slice(0, 1000) : null;
// image elements
const imgs = document.querySelectorAll('creative-preview img, creative-preview image');
out.creative_imgs = Array.from(imgs).slice(0, 5).map((i) => ({
src: (i as HTMLImageElement).src,
alt: (i as HTMLImageElement).alt,
tag: i.tagName,
}));
// date elements
const allEls = Array.from(document.querySelectorAll('*'));
const dateTexts = allEls.filter((el) => {
if (el.children.length > 0) return false;
const t = (el as HTMLElement).innerText?.trim();
return t && /\b(jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec|\d{4})\b/i.test(t) && t.length < 60;
}).slice(0, 10).map((el) => ({
tag: el.tagName,
className: el.className,
text: (el as HTMLElement).innerText,
}));
out.date_texts = dateTexts;
return out;
});
console.log('=== CREATIVE PREVIEW FULL HTML (first 3) ===');
dump.creative_preview_full_html.forEach((h: string, i: number) => {
console.log(`\n--- creative-preview[${i}] ---`);
console.log(h);
});
console.log('\n=== PRIORITY CREATIVE GRID ===');
console.log(dump.priority_creative_grid_html);
console.log('\n=== ADS COUNT EL ===');
console.log(JSON.stringify(dump.ads_count_el, null, 2));
console.log('\n=== DOMAIN TITLE ===');
console.log(dump.domain_title);
console.log('\n=== CREATIVE ARIA LABELS ===');
console.log(JSON.stringify(dump.creative_aria_labels, null, 2));
console.log('\n=== IFRAMES IN creative-preview ===', dump.iframes_count);
console.log('\n=== HTML RENDERER COUNT ===', dump.html_renderer_count);
console.log('\n=== HTML RENDERER FIRST ===');
console.log(dump.html_renderer_first);
console.log('\n=== CREATIVE IMGS ===');
console.log(JSON.stringify(dump.creative_imgs, null, 2));
console.log('\n=== DATE TEXTS ===');
console.log(JSON.stringify(dump.date_texts, null, 2));
await ctx.close();
await browser.close();