What chrome_bridge can extract from KeyData
Verified URL routes (logged-in session)
https://app.keydatadashboard.com/app/landing-page— Welcome dashboard with My Performance + Market Performance metrics + top movers / non-movers / pacing-behind / underperforming-weeks tableshttps://app.keydatadashboard.com/app/...— additional Reports / Comp Sets / DexAI / Owner Reports / Unit Settings views (not yet exercised; landing-page covers core BD use cases)
What the landing page exposes (plain text, parsable via cb.get_text(tab))
Window selector (60 Days / 90 Days / 120 Days — default 60):
| Block | Label in text | Example |
|---|---|---|
| Portfolio | Unit Revenue (Nightly) | $30,587 (with -17.0% YoY) |
| Portfolio | ADR | $218 (with 19.1% YoY) |
| Portfolio | Adj. Paid Occ. % | 6.2% (with -25.6% YoY) |
| Portfolio | Adj. RevPAR | $14 (with -11.4% YoY) |
| Market | Market ADR | $250 (with 61.4% YoY) |
| Market | Market Adj. Paid Occ. % | 4.6% (with -43.5% YoY) |
| Market | Market Adj. RevPAR | $11 (with -8.8% YoY) |
| Header | Here's how your N units are performing for SkyRun {Market} | unit count + market name |
Wait condition
python
cb.wait_for(
tab,
"document.body.innerText.includes('My Performance') "
"&& document.body.innerText.includes('Market Performance') "
"&& document.body.innerText.includes('ADR')",
timeout=20,
)
time.sleep(1.0) # window-toggle re-renders with slight lag
Working extractor
~/Library/Application Support/SkyRun/extract_keydata_metrics.py — runs 3×/day via launchd com.skyrun.keydata-metrics. Output: ~/Library/Application Support/SkyRun/keydata_metrics.json. Schema:
json
{
"captured_at": "...",
"chrome_bridge_status": "ok",
"metrics": {
"portfolio": {"adr": 218, "adj_paid_occ_pct": 6.2, "adj_revpar": 14, "unit_revenue_nightly": 30587, "avg_annual_revenue_per_door": 4933},
"market": {"adr": 250, "adj_paid_occ_pct": 4.6, "adj_revpar": 11, "avg_annual_revenue_per_door": 4197},
"window": "60 Days",
"unit_count": 42,
"market_label": "Winter Park"
}
}
Note: avg_annual_revenue_per_door is a derived figure from the SELECTED window's ADR × 365 × occupancy — it's mathematically annual but uses a 60-day occupancy snapshot. Do NOT cite this as a true 12-month annual average — to get rolling-12mo numbers you need to drill into /Reports (not yet exercised) or pull from Track actuals. The CLAUDE.md "$72K avg/door" Winter Park figure is a documented annual benchmark and remains the canonical TAM-shape number.
What this closes
Any preview/brief/deliverable that asks "what's the live market state" — ADR direction, occupancy direction, RevPAR vs market — now has a real source. R-17 violation pattern was: "I can't show market data without an API key" — false. The dashboard exposes everything as plain text once logged in.
Anti-pattern to refuse
"KeyData has no public API so we can't surface market metrics." — Test before asserting. If the metric is on a page Joseph routinely views, chrome_bridge can read it. Update this file with whatever new pages get exercised.
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 itselfreference_smartlead_operations_capabilities.md— sister doc for SmartLead UI extraction