What chrome_bridge can DO in SmartLead
This file is the persistent inventory. If an operation is listed here, it WORKS — do not re-fabricate "I'm blocked" without first attempting it. If you discover a new capability, append to this file in the same task.
Verified URL routes (active campaigns)
These all work in chrome_bridge — python3 chrome_bridge.py nav <tab> <url>:
https://app.smartlead.ai/app/email-campaign/all— campaigns list with Sent/Open/Bounce statshttps://app.smartlead.ai/app/email-campaign/{id}/analytics— per-campaign analytics + sequence breakdownhttps://app.smartlead.ai/app/email-campaign/{id}/performance— sender accounts table + sending efficiency scorehttps://app.smartlead.ai/app/email-campaign/{id}/inbox— campaign inboxhttps://app.smartlead.ai/app/email-campaign/{id}/lead-list— leads in this campaignhttps://app.smartlead.ai/app/email-campaign/{id}/subsequence— conditional follow-upshttps://app.smartlead.ai/app/email-campaign/{id}/trigger-logs— send-trigger audit loghttps://app.smartlead.ai/app/email-accounts— all sender accounts listhttps://app.smartlead.ai/app/email-account/{account_id}/general— per-sender-account config including SMTP/IMAP/Signature/BCC to CRM Settingshttps://app.smartlead.ai/app/master-inbox— master inbox
Verified DOM operations
Set per-sender BCC to HS dropbox (proven 2026-05-04)
- Navigate to
/app/email-account/{id}/general - Find the BCC input by anchoring on the
BCC to CRM Settingslabel and walking the DOM:
js
const bccLabel = Array.from(document.querySelectorAll("*"))
.find(e => (e.innerText||"").trim() === "BCC to CRM Settings");
let target = bccLabel.parentElement;
let bccInput = null;
for (let i = 0; i < 10 && target; i++) {
const inps = Array.from(target.querySelectorAll("input[type=text]"));
const cands = inps.filter(inp => (inp.value||"").includes("@bcc") || (inp.value||"") === "");
if (cands.length > 0) { bccInput = cands[cands.length-1]; break; }
target = target.parentElement;
}
- Set value with proper Vue reactivity:
js
bccInput.focus();
const setter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
setter.call(bccInput, "23273108@bcc.hubspot.com");
bccInput.dispatchEvent(new InputEvent("input", {bubbles:true, cancelable:true, data:"23273108@bcc.hubspot.com", inputType:"insertText"}));
bccInput.dispatchEvent(new Event("change", {bubbles:true}));
bccInput.blur();
- Click Save:
document.querySelector('button[data-sa="email-account-save-btn"]').click() - Verify success: wait 3-4s, look for
.q-notificationtoast saying"Saved successfully!!" - Verify persistence: navigate to
/app/email-accountsthen back to/app/email-account/{id}/general, re-read input value - Working script:
/tmp/sl_bcc_robust.py(canonical reference for the save sequence)
Open campaign edit wizard (proven 2026-05-04)
- Navigate to
/app/email-campaign/{id}/analytics - Click
button[data-sa="campaigns-old-detail-edit-btn"](pencil icon top-right) - Wizard opens with tabs: Import Leads / Sequences / Setup / Final Review
- "Setup" tab → "Modify Settings" button opens campaign-level settings panel (General / Email Accounts / Webhooks)
Read campaign analytics
- After navigating to
/email-campaign/{id}/analytics, body innerText contains:
Read all-campaign aggregate stats from list page (proven 2026-05-07)
- Navigate to
/app/email-campaign/all— the list page renders all 3 campaigns with Sent/Opened/Replied/Bounced counts AND percentages in plain text. cb.get_text(tab)returns each campaign as a labeled block (one block per campaign). Each has these labels in order: campaign-name → Active|Created → Sent count → Opened count+pct → Replied w/OOO count+pct → Bounced count+pct.- Wait condition:
body.innerText.includes('GC —') && includes('Sent') && includes('Opened'). Page has skeleton DOM before data lands. Add ~1s settle — percentages render slightly after counts. - Working extractor:
~/Library/Application Support/SkyRun/extract_smartlead_metrics.pyruns hourly via launchdcom.skyrun.smartlead-metrics. Output:~/Library/Application Support/SkyRun/smartlead_metrics.json. - Closes the "no API key" blocker — anything that needs sent/replies/opens/bounces uses this UI extraction. The REST API at
server.smartlead.ai/api/v1/*is gated; the UI is not.
Read sender accounts on campaign
/email-campaign/{id}/performanceshows the 6 sender accounts with daily limits used, warmup reputation, time gap
Known limitations
- The campaign-level More (••• 3-dots) button does not open its dropdown menu via synthetic
.click()— Quasar gates it on real user-event flow. Pause/Stop campaign actions live in this menu and are not yet automatable. https://app.smartlead.ai/app/api-keyand similar URLs return 404 — Joseph's plan tier may not expose API key management; **the public REST API atserver.smartlead.ai/api/v1/*requires an API key that doesn't exist in keychain, so per-campaign PATCH via API is currently unavailable.- Sequence editor inside the wizard's Sequences tab shows a loading spinner that never resolves while a campaign is ACTIVE — sequence-level email body / BCC config requires the campaign be paused first (which itself requires the gated More menu).
Why these limitations don't matter for the BCC fix
Per-sender-account BCC config (proven above) is sufficient to make every SL send create a properly-associated HS Email engagement, regardless of which campaign it's part of. Configure once per sender account → all 3 campaigns benefit.
Anti-pattern catalogued
"I can't do X in SmartLead because [reason from documentation/intuition]"** — REFUSE this assertion in your own output. Run the actual chrome_bridge nav + chrome_bridge js against the relevant URL/selector. The error or result is the truth. Update this file with whatever you learn.
Related
- R-17 in
RULES.md— no fabricated capability blockers - R-18 in
RULES.md— capability inventory must persist ~/Library/Application Support/SkyRun/chrome_bridge.py— the bridge itself~/Library/Application Support/SkyRun/engagement_reconciler.py— measures the gap this BCC config closes