// Where the rivals' widget ids come from: each vendor's own site runs its own widget. This loads those pages and prints // the embed urls their widget requested, so anyone can check the ids in widgets.ts. LiveChat's license number sits in // the page's own snippet (window.__lc.license), Chatwoot's website token in its Nuxt config (chatwoot.websiteToken). // bun run --cwd tools/widget-lab ids (SITES="url url" to check other pages, WAIT=ms per page) import { chromium } from "playwright-core"; const SITES = process.env.SITES?.split(" ") ?? ["https://www.tawk.to/", "https://crisp.chat/en/", "https://www.intercom.com/", "https://www.tidio.com/", "https://www.livechat.com/", "https://www.chatwoot.com/hc/user-guide/en"]; const EMBED = /embed\.tawk\.to\/|client\.crisp\.chat\/l\.js|widget\.intercom\.io\/widget\/|code\.tidio\.co\/|cdn\.livechatinc\.com\/tracking|license[=/]\d+|chatwoot\.com\/(packs\/js\/sdk|widget\?|api\/v1\/widget)/; const browser = await chromium.launch({ channel: "chrome", headless: false }); // headed: some widgets skip "HeadlessChrome" for (const site of SITES) { const ctx = await browser.newContext(); const page = await ctx.newPage(); const hits = new Set(); page.on("request", (r) => void (EMBED.test(r.url()) && hits.add(r.url().slice(0, 200)))); await page.goto(site, { waitUntil: "load", timeout: 60_000 }).catch((e) => console.log(" load:", String(e).slice(0, 120))); await page.waitForTimeout(Number(process.env.WAIT ?? 15_000)); // some load their widget late (after idle, or through a tag manager) console.log(site); for (const h of hits) console.log(" ", h); await ctx.close(); } await browser.close();