← back to Ventura Corridor

scripts/probe_adst.ts

128 lines

/**
 * One-off DOM probe for Google Ads Transparency Center.
 * Run: npx tsx scripts/probe_adst.ts
 */
import { chromium } from 'playwright';

const DOMAIN = 'clearchoice.com';
const URL = `https://adstransparency.google.com/?domain=${DOMAIN}&region=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();

console.log('Navigating to', URL);
await page.goto(URL, { waitUntil: 'domcontentloaded', timeout: 30_000 });

// Wait longer for React/Angular hydration
await page.waitForTimeout(4000);

const dump = await page.evaluate(() => {
  const out: Record<string, any> = {};

  // --- Dump all text visible at top of page (first 2000 chars) ---
  out.body_text_head = document.body.innerText.slice(0, 2000);

  // --- Find any element that contains the advertiser name area ---
  // Try known Angular custom-element tags
  const tags = [
    'advertiser-name', 'advertiser-header', 'advertiser-info',
    'creative-grid', 'creative-card', 'creative-preview',
    'at-creative-card', 'at-creative-preview',
    'search-header', 'results-header', 'results-count',
  ];
  out.custom_elements = {};
  for (const tag of tags) {
    const els = document.querySelectorAll(tag);
    if (els.length) {
      out.custom_elements[tag] = Array.from(els).slice(0, 3).map((e) => ({
        outerHTML_snippet: (e as HTMLElement).outerHTML.slice(0, 300),
        innerText: (e as HTMLElement).innerText.slice(0, 200),
      }));
    }
  }

  // --- Dump all unique tag names on the page ---
  out.all_tags = [...new Set(Array.from(document.querySelectorAll('*')).map((e) => e.tagName.toLowerCase()))].sort();

  // --- Look for elements whose text includes "ads" or "results" + a number ---
  const adCountCandidates: string[] = [];
  document.querySelectorAll('*').forEach((el) => {
    if (el.children.length === 0) {
      const t = (el as HTMLElement).innerText?.trim();
      if (t && /\d/.test(t) && t.length < 100 && /(ad|result|showing|total)/i.test(t)) {
        adCountCandidates.push(`<${el.tagName.toLowerCase()} class="${el.className}"> ${t}`);
      }
    }
  });
  out.ad_count_candidates = [...new Set(adCountCandidates)].slice(0, 20);

  // --- Find "See more results" element and its surroundings ---
  const allText = Array.from(document.querySelectorAll('*'));
  const seeMore = allText.filter((el) => (el as HTMLElement).innerText?.trim() === 'See more results');
  out.see_more_elements = seeMore.slice(0, 3).map((e) => ({
    tag: e.tagName,
    className: e.className,
    parentTag: e.parentElement?.tagName,
    parentClass: e.parentElement?.className,
    outerHTML: (e as HTMLElement).outerHTML.slice(0, 400),
  }));

  // --- Find elements with class containing "advertiser" ---
  const advEls = document.querySelectorAll('[class*="advertiser"], [data-test-id*="advertiser"]');
  out.advertiser_class_els = Array.from(advEls).slice(0, 10).map((e) => ({
    tag: e.tagName,
    className: e.className,
    innerText: (e as HTMLElement).innerText.slice(0, 200),
    outerHTML: (e as HTMLElement).outerHTML.slice(0, 400),
  }));

  // --- Creative cards ---
  const cardSelectors = [
    'creative-card', 'creative-preview', 'at-creative-card',
    '[class*="creative-card"]', '[class*="ad-card"]',
  ];
  out.creative_cards = {};
  for (const sel of cardSelectors) {
    const els = document.querySelectorAll(sel);
    if (els.length) {
      out.creative_cards[sel] = {
        count: els.length,
        first3: Array.from(els).slice(0, 3).map((e) => ({
          innerText: (e as HTMLElement).innerText.slice(0, 300),
          imgs: Array.from(e.querySelectorAll('img')).map((i) => i.src).slice(0, 2),
        })),
      };
    }
  }

  return out;
});

console.log('\n=== BODY TEXT HEAD ===');
console.log(dump.body_text_head);

console.log('\n=== ALL TAGS ===');
console.log(dump.all_tags.join(', '));

console.log('\n=== CUSTOM ELEMENTS ===');
console.log(JSON.stringify(dump.custom_elements, null, 2));

console.log('\n=== AD COUNT CANDIDATES ===');
console.log(dump.ad_count_candidates.join('\n'));

console.log('\n=== SEE MORE ELEMENTS ===');
console.log(JSON.stringify(dump.see_more_elements, null, 2));

console.log('\n=== ADVERTISER CLASS ELS ===');
console.log(JSON.stringify(dump.advertiser_class_els, null, 2));

console.log('\n=== CREATIVE CARDS ===');
console.log(JSON.stringify(dump.creative_cards, null, 2));

await ctx.close();
await browser.close();