← back to Ventura Corridor
scripts/verify_adst_patch.ts
95 lines
/**
* Verify the patched ads_transparency selectors on 3 known-active domains.
* Run: npx tsx scripts/verify_adst_patch.ts
*/
import { chromium, Browser } from 'playwright';
const DOMAINS = ['clearchoice.com', 'discounttirecenters.com', 'paymentcloud.com'];
async function scrapeOne(browser: Browser, domain: string) {
const url = `https://adstransparency.google.com/?domain=${encodeURIComponent(domain)}®ion=US`;
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();
try {
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 25_000 });
await page.waitForFunction(
() => document.querySelector('creative-preview, .ads-count') !== null
|| document.body.innerText.includes('No ads to show')
|| document.body.innerText.includes('No advertisers'),
{ timeout: 20_000 }
).catch(() => {});
await page.waitForTimeout(1500);
return await page.evaluate(() => {
const out: any = { domain: window.location.href };
const advEl = document.querySelector(
'creative-preview .advertiser-name, .thumbnail-container .advertiser-name'
);
out.advertiser_name = advEl ? (advEl as HTMLElement).innerText.trim() : null;
const adsCountEl = document.querySelector('.ads-count');
if (adsCountEl) {
const raw = (adsCountEl as HTMLElement).innerText.trim();
const m = raw.match(/([\d,]+)/);
out.ad_count_raw = raw;
out.ad_count = m ? parseInt(m[1].replace(/,/g, ''), 10) : null;
} else {
const cardCount = document.querySelectorAll('creative-preview').length;
out.ad_count_raw = `${cardCount} (card count fallback)`;
out.ad_count = cardCount > 0 ? cardCount : null;
}
const cards = Array.from(document.querySelectorAll('creative-preview'));
out.creatives_count = cards.length;
out.creatives = cards.slice(0, 3).map((c) => {
const a = c.querySelector('a');
const img = c.querySelector('html-renderer img, img');
const nameEl = c.querySelector('.advertiser-name');
const ariaLabel = a?.getAttribute('aria-label') || undefined;
const href = a?.getAttribute('href') || undefined;
const creativeIdMatch = href ? href.match(/creative\/(CR\w+)/) : null;
return {
headline: ariaLabel,
body: nameEl ? (nameEl as HTMLElement).innerText.trim() : undefined,
thumb: (img && (img as HTMLImageElement).src) || undefined,
creative_id: creativeIdMatch ? creativeIdMatch[1] : undefined,
};
});
const txt = document.body.innerText;
out.no_results = /No ads to show|No advertisers|We didn't find any/i.test(txt);
return out;
});
} finally {
await ctx.close().catch(() => {});
}
}
const browser = await chromium.launch({ headless: true });
for (const domain of DOMAINS) {
process.stdout.write(`\n=== ${domain} ===\n`);
try {
const r = await scrapeOne(browser, domain);
console.log(` advertiser_name : ${r.advertiser_name}`);
console.log(` ad_count_raw : ${r.ad_count_raw}`);
console.log(` ad_count : ${r.ad_count}`);
console.log(` creatives_count : ${r.creatives_count}`);
console.log(` no_results : ${r.no_results}`);
r.creatives.forEach((c: any, i: number) => {
console.log(` creative[${i}]:`);
console.log(` headline : ${c.headline}`);
console.log(` body : ${c.body}`);
console.log(` thumb : ${c.thumb?.slice(0, 80)}`);
console.log(` creative_id: ${c.creative_id}`);
});
} catch (e: any) {
console.log(` ERROR: ${e.message}`);
}
}
await browser.close();
console.log('\nDone.');