diff --git a/agents/junior-ae/junior-ae-v4.py b/agents/junior-ae/junior-ae-v4.py index 6ac028b..34830f2 100755 --- a/agents/junior-ae/junior-ae-v4.py +++ b/agents/junior-ae/junior-ae-v4.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 """ -JAE v4 - Process HOA Ledger IQ leads -Fetches from ROI Calculator and Interest Form APIs -Detects temperature and elevates HOT/WARM leads +Junior AE v4 - Process ALL leads, auto-detect temperature +- Processes notes with or without temperature prefixes +- Auto-detects temperature from content if not in title +- Elevates HOT/WARM leads, skips COLD """ import json, re, time, urllib.request, urllib.error from datetime import datetime, timedelta from pathlib import Path +import ssl SCRIPT_DIR = Path(__file__).parent for d in [SCRIPT_DIR / "state", SCRIPT_DIR / "logs"]: @@ -14,11 +16,8 @@ for d in [SCRIPT_DIR / "state", SCRIPT_DIR / "logs"]: STATE_FILE = SCRIPT_DIR / "state" / "jae-v4-state.json" LOG_FILE = SCRIPT_DIR / "logs" / f"jae-v4-{datetime.now().strftime('%Y%m%d')}.log" - -# HOA Ledger IQ API endpoints -CALC_API = "https://www.hoaledgeriq.com/api/calc-submissions" -LEADS_API = "https://hoaledgeriq.com/api/leads" -ADMIN_KEY = "K9mP2vL8x4qR7nZ" +CRM_URL = "https://salesforce.hoaledgeriq.com/rest" +CRM_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5M2FmNGFmNS0zZWQ0LTQ1ZDMtOWE5Zi01MDMzZjc3YTY3MjMiLCJ0eXBlIjoiQVBJX0tFWSIsIndvcmtzcGFjZUlkIjoiOTNhZjRhZjUtM2VkNC00NWQzLTlhOWYtNTAzM2Y3N2E2NzIzIiwiaWF0IjoxNzczMzI4NDQzLCJleHAiOjE4MDQ3ODE2NDIsImp0aSI6IjIwZjEyYzkwLTRkMDctNGJmNi1iMzk3LTZjNmU3MzlmMThjOCJ9.zeM5NvwCSGEcz99m2LYtgb0sVD6WUXcCF7SwonFg930" def log(msg): ts = datetime.now().strftime('%H:%M:%S') @@ -35,50 +34,16 @@ def save_state(s): STATE_FILE.write_text(json.dumps(s, indent=2)) def fetch_notes(): - """Fetch leads from HOA Ledger IQ API (both calc submissions and interest form)""" - all_leads = [] - - # Fetch ROI Calculator submissions try: req = urllib.request.Request( - CALC_API, - headers={"x-admin-key": ADMIN_KEY, "Accept": "application/json"} + f"{CRM_URL}/notes?limit=200&order[createdAt]=desc", + headers={"Authorization": f"Bearer {CRM_TOKEN}", "Accept": "application/json"} ) with urllib.request.urlopen(req, timeout=15) as r: - data = json.loads(r.read().decode()) - submissions = data.get('submissions', []) if data else [] - for sub in submissions: - all_leads.append({ - 'id': f"calc_{sub['id']}", - 'title': f"ROI Calc: {sub.get('email', 'Unknown')}", - 'body': f"Email: {sub.get('email', '')}\nHomesites: {sub.get('homesites', 0)}\nProperty Type: {sub.get('property_type', '')}\nAnnual Income: ${sub.get('annual_income', 0):,}\nReserve Funds: ${sub.get('reserve_funds', 0):,}\nAI Rec: {sub.get('ai_recommendation', 'None')[:200]}", - 'created_at': sub.get('created_at', ''), - 'source': 'roi_calculator' - }) + return json.loads(r.read().decode()).get('data', {}).get('notes', []) except Exception as e: - log(f"Calc API error: {e}") - - # Fetch Interest Form leads - try: - req = urllib.request.Request( - LEADS_API, - headers={"x-admin-key": ADMIN_KEY, "Accept": "application/json"} - ) - with urllib.request.urlopen(req, timeout=15) as r: - data = json.loads(r.read().decode()) - leads = data.get('leads', []) - for lead in leads: - all_leads.append({ - 'id': f"lead_{lead['id']}", - 'title': f"Interest: {lead.get('first_name', '')} {lead.get('last_name', '')}", - 'body': f"Email: {lead.get('email', '')}\nOrg: {lead.get('org_name', '')}\nState: {lead.get('state', '')}\nRole: {lead.get('role', '')}\nUnits: {lead.get('unit_count', '')}\nBeta Interest: {lead.get('beta_interest', 0)}", - 'created_at': lead.get('created_at', ''), - 'source': 'interest_form' - }) - except Exception as e: - log(f"Leads API error: {e}") - - return all_leads + log(f"Fetch error: {e}") + return [] def detect_temp(title, body=""): """Detect temperature from title or content""" @@ -93,12 +58,12 @@ def detect_temp(title, body=""): return 'COLD' # Auto-detect from engagement signals - hot_signals = ['READY', 'INTERESTED', 'WANTS', 'NEEDS', 'BUDGET', 'TIMELINE', 'SOON', 'QUICK', 'BETA', 'TEST'] + hot_signals = ['READY', 'INTERESTED', 'WANTS', 'NEEDS', 'BUDGET', 'TIMELINE', 'SOON', 'QUICK'] warm_signals = ['CONSIDERING', 'THINKING', 'MAYBE', 'LATER', 'RESEARCH', 'COMPARE'] for signal in hot_signals: if signal in text: - return 'HOT' + return 'WARM' # Default to WARM if unsure for signal in warm_signals: if signal in text: @@ -107,50 +72,119 @@ def detect_temp(title, body=""): # Default to WARM for unclassified leads (better to over-qualify) return 'WARM' +def update_note_temp(note_id, new_temp): + """Update note title with temperature""" + try: + # Get current note + req = urllib.request.Request( + f"{CRM_URL}/notes/{note_id}", + headers={"Authorization": f"Bearer {CRM_TOKEN}", "Accept": "application/json"} + ) + with urllib.request.urlopen(req, timeout=10) as r: + note = json.loads(r.read().decode()).get('data', {}) + + # Update title + old_title = note.get('title', '') + new_title = re.sub(r'^(HOT|WARM|COLD):\s*', '', old_title) # Remove old temp + new_title = f"{new_temp}: {new_title}" + + # Patch the note + patch_data = json.dumps({"title": new_title}).encode() + req = urllib.request.Request( + f"{CRM_URL}/notes/{note_id}", + data=patch_data, + headers={"Authorization": f"Bearer {CRM_TOKEN}", "Content-Type": "application/json"}, + method='PATCH' + ) + with urllib.request.urlopen(req, timeout=10) as r: + return True + except Exception as e: + log(f"Update error: {e}") + return False + +def create_opportunity(note, temp): + """Create opportunity for HOT/WARM leads""" + try: + person_id = note.get('personId') + if not person_id: + log(f" Skip: No person ID") + return False + + # Check if opportunity already exists + opp_name = f"Lead: {note.get('title', '')}" + + opp_data = { + "name": opp_name[:100], + "stage": "NEW", + "pointOfContactId": person_id, + "ownerId": "ecf52aad-4827-40c9-9475-b68f3ca9a924" + } + + req = urllib.request.Request( + f"{CRM_URL}/opportunities", + data=json.dumps(opp_data).encode(), + headers={"Authorization": f"Bearer {CRM_TOKEN}", "Content-Type": "application/json"} + ) + with urllib.request.urlopen(req, timeout=15) as r: + opp = json.loads(r.read().decode()) + log(f" ✓ UPGRADED to Opportunity: {opp.get('id', 'N/A')}") + return True + except Exception as e: + log(f" ✗ Create opp error: {e}") + return False + def main(): - log("=== JAE v4 Starting - HOA Ledger IQ Integration ===") + log("=== JAE v4 Starting - Auto-Temperature Detection ===") state = load_state() + processed_ids = state.get('processed_ids', []) + notes = fetch_notes() + log(f"Fetched {len(notes)} notes") - log(f"Fetched {len(notes)} leads from HOA Ledger IQ APIs") - - processed_count = 0 - upgraded_count = 0 + upgraded = 0 + processed = 0 for note in notes: - note_id = note['id'] + note_id = note.get('id') + title = note.get('title', '') # Skip if already processed - if note_id in state.get('processed_ids', []): + if note_id in processed_ids: continue + processed += 1 + processed_ids.append(note_id) + # Detect temperature - temp = detect_temp(note.get('title', ''), note.get('body', '')) + body = note.get('body', '') + temp = detect_temp(title, body) - # Process based on temperature + log(f"Processing: {title[:60]}... -> {temp}") + + # Update title with temperature + if not title.startswith(f"{temp}:"): + update_note_temp(note_id, temp) + + # Create opportunity for HOT/WARM if temp in ['HOT', 'WARM']: - log(f"🔥 {temp} lead: {note['title'][:60]}") - upgraded_count += 1 + if create_opportunity(note, temp): + upgraded += 1 else: - log(f"❄️ COLD lead: {note['title'][:60]}") + log(f" Skipped: COLD lead") - processed_count += 1 - state['processed_ids'].append(note_id) - - # Keep only last 1000 processed IDs - if len(state['processed_ids']) > 1000: - state['processed_ids'] = state['processed_ids'][-1000:] + # Rate limit + time.sleep(0.5) + # Save state + state['processed'] = processed + state['upgraded'] = state.get('upgraded', 0) + upgraded + state['processed_ids'] = processed_ids[-1000:] # Keep last 1000 state['last_check'] = datetime.now().isoformat() - state['processed'] += processed_count - state['upgraded'] += upgraded_count - save_state(state) - log(f"=== Done: {processed_count} processed, {upgraded_count} upgraded ===") + + log(f"=== Done: {processed} processed, {upgraded} upgraded ===") log("Waiting 3 hours...") if __name__ == "__main__": - while True: - main() - time.sleep(3 * 60 * 60) # 3 hours + main() diff --git a/hoa-leads-data/data/HOA_Leads.xlsx b/hoa-leads-data/data/HOA_Leads.xlsx new file mode 100644 index 0000000..5056112 Binary files /dev/null and b/hoa-leads-data/data/HOA_Leads.xlsx differ diff --git a/hoa-leads-data/data/crm_push_results_latest.json b/hoa-leads-data/data/crm_push_results_latest.json new file mode 100644 index 0000000..facb6fb --- /dev/null +++ b/hoa-leads-data/data/crm_push_results_latest.json @@ -0,0 +1,319 @@ +[ + { + "name": "Waterfall Community Association", + "status": "ok", + "companyId": "11b7cda9-1669-48ac-9d50-31f45f159380", + "noteId": "389a2771-4a62-4c6e-90aa-a1401f607b8b" + }, + { + "name": "Trilogy at Redmond Ridge Community Association", + "status": "ok", + "companyId": "61e4475b-a01a-433b-81b5-093c69de14b5", + "noteId": "90e432a6-78a9-4f5f-827a-06650f67ca4a" + }, + { + "name": "Sommerset Highlands HOA", + "status": "ok", + "companyId": "0f15db30-3345-451c-8215-58107c87013f", + "noteId": "5a36b35c-66ff-45c4-ab0c-cf896d92a2e5" + }, + { + "name": "Maple Valley HOA", + "status": "ok", + "companyId": "43fbd8a1-f4dd-4ec6-9ed8-87b6368a9232", + "noteId": "8ca3dbd5-d69a-4e93-ae3a-e146e1fde74c" + }, + { + "name": "Woodcreek Community Association", + "status": "ok", + "companyId": "e4e78d49-a4eb-4e85-b50e-0255380d4c7c", + "noteId": "378eb892-744d-4241-ac61-b72043dc18d4" + }, + { + "name": "Hazel Dell Community HOA", + "status": "ok", + "companyId": "7b16f229-d2ff-4ab2-b4c4-e1f90a708f5a", + "noteId": "9efc3372-0d4c-4f4b-8b82-f0df40e11d88" + }, + { + "name": "South Cooper Mountain Community Association", + "status": "ok", + "companyId": "c7e64f15-3e54-4e67-bdc4-f702bed147fd", + "noteId": "ef80e61e-20fa-4d77-b8df-fe399922d6de" + }, + { + "name": "Stafford Hills Community HOA", + "status": "error", + "error": "Company error: [{'message': 'A duplicate entry was detected', 'extensions': {'userFriendlyMessage': 'This Domain Name value is already in use. Please check your data and try again.', 'conflictingRecordId': 'df27cb65-51e3-4b84-b401-461b43cd7f65', 'conflictingObjectNameSingular': 'company', 'code': 'BAD_USER_INPUT'}}]" + }, + { + "name": "Centennial Farm Community Association", + "status": "ok", + "companyId": "f8e90e6a-d110-4f6c-a974-d3d2017a284c", + "noteId": "8104ed70-6872-44a0-8665-a2894cdd60b9" + }, + { + "name": "Hartland Glen HOA", + "status": "ok", + "companyId": "c1826164-132f-4642-b110-e8bdad1ad5fd", + "noteId": "64456018-0f9d-4069-bbf3-b450acadd572" + }, + { + "name": "Heritage Meadows Community Association", + "status": "ok", + "companyId": "0a410e4d-be40-44c4-86c5-841f2704b906", + "noteId": "1123c3f2-880b-4c4d-9077-16a3af7af5ef" + }, + { + "name": "Stonewater Community Association", + "status": "ok", + "companyId": "954a9651-a87b-4517-a37a-b915ce88efcf", + "noteId": "296e4bd3-b74b-483e-bed1-21fbcb23c2a8" + }, + { + "name": "Hartland Township HOA", + "status": "ok", + "companyId": "627149c3-f929-4231-8f17-cbfa96715089", + "noteId": "ee49805f-ca1e-405c-840f-eee593b9678d" + }, + { + "name": "New Albany Links HOA", + "status": "ok", + "companyId": "23b07e7f-9c5f-4850-849f-3552b209de4d", + "noteId": "4f8f0869-a185-4c0b-9975-8230652763d1" + }, + { + "name": "Olentangy Falls Community Association", + "status": "ok", + "companyId": "78c2325a-fe63-4dac-9116-f8a467ae37c3", + "noteId": "19e5f987-fb12-4302-a7a8-ae6dd1fbeb6f" + }, + { + "name": "Easton Estates HOA", + "status": "ok", + "companyId": "09420471-3455-455e-8917-657d7e6ff523", + "noteId": "077c1f88-0f00-45a1-9900-5f2052f5571b" + }, + { + "name": "Westridge at South Elgin HOA", + "status": "ok", + "companyId": "eab84d7c-c99e-4394-81a7-ade02737f4f4", + "noteId": "197d64aa-a521-4bd1-8492-ed084fe09835" + }, + { + "name": "Spring Lakes Community Association", + "status": "ok", + "companyId": "8f0107a0-c201-43ba-bbb3-1b9fff6cdebb", + "noteId": "a98fffbd-d180-40d9-bb01-9798ad7a00c5" + }, + { + "name": "Lakewood Falls HOA", + "status": "ok", + "companyId": "cbf8ad47-f5de-49e1-a6fc-d3f6db30f575", + "noteId": "afd6a269-8f47-499a-a927-342b155ac750" + }, + { + "name": "Carriage Greens Community Association", + "status": "ok", + "companyId": "3b5400e5-6882-40f1-b7fb-12a81284a49f", + "noteId": "73703a23-5181-42b5-bcd3-d28c1078e692" + }, + { + "name": "Kennecott Copperton Community Association", + "status": "ok", + "companyId": "74b2691d-6bcf-4e2c-a570-f9be093e5239", + "noteId": "3ba6f3d9-82cb-49fd-a136-7c2747575872" + }, + { + "name": "Meridian Hills Community Association", + "status": "ok", + "companyId": "28cd5c42-62a6-4cb3-8104-99226c631bac", + "noteId": "54fe7201-2c0e-4f1f-983d-656ed5bfc672" + }, + { + "name": "Tuscany HOA Boise", + "status": "ok", + "companyId": "794081d8-629e-48ed-8d40-4043a1ac7528", + "noteId": "e6a9a1a3-ffe5-4f21-b318-a85d91e75e1b" + }, + { + "name": "Treeline Commons HOA", + "status": "ok", + "companyId": "707d41ec-f72f-4f5a-8641-75aacd98dc6d", + "noteId": "4c8a2b82-cdd2-4ddc-b71a-bccafa66cbf0" + }, + { + "name": "Brandywine at Thornbury HOA", + "status": "ok", + "companyId": "f70848d0-1ba9-466a-9bbb-2106762bf279", + "noteId": "7786a226-355e-4d88-9955-0fe72c290c8e" + }, + { + "name": "Toll Brothers at Traditions HOA", + "status": "ok", + "companyId": "38d679dc-79b7-479e-a4e5-60056fb320da", + "noteId": "2e1c12a9-e0b3-4c24-8d11-6763bf491f20" + }, + { + "name": "Meadowbrook Manor Community Association", + "status": "ok", + "companyId": "5d7919b2-084f-49e5-a86e-435887b61f25", + "noteId": "ff6170da-6ddb-4ffa-95d1-0f5cac076454" + }, + { + "name": "The Grove at Metairie HOA", + "status": "ok", + "companyId": "1c96cd6e-6e7f-43cf-9dbf-6f229557a093", + "noteId": "bd5723fc-d66c-480d-a964-a5272326c3da" + }, + { + "name": "Beau Chene Homeowners Association", + "status": "ok", + "companyId": "e8767f33-e664-406e-929a-efcf5bd518cf", + "noteId": "c82f6e45-d633-412b-aa6e-c44fc663122d" + }, + { + "name": "Woodlake at Covington HOA", + "status": "ok", + "companyId": "c35f8f1d-d128-4c85-8159-88b7473ee49d", + "noteId": "947e883a-3432-4741-b3f7-7e4a7195c34d" + }, + { + "name": "Whisper Creek Community Association", + "status": "ok", + "companyId": "bb57f5dc-6ccd-4aea-aae8-0e0e6e635b09", + "noteId": "62621594-fb20-4b0b-8029-34d9d956a4db" + }, + { + "name": "Waterford Pointe HOA", + "status": "ok", + "companyId": "8960e541-ecf7-4ed8-888b-9b6b4d82ad7d", + "noteId": "cfe519e7-6889-4ff3-8c54-fb437318b5fe" + }, + { + "name": "Stonebridge Community Association", + "status": "ok", + "companyId": "611cd487-ff54-40c4-b521-788709942d6c", + "noteId": "9dc48099-3c7f-4070-b9b9-e9edbd8790aa" + }, + { + "name": "Meadows of Wildwood Community Association", + "status": "ok", + "companyId": "23f3c1f7-2b1e-41cd-82b0-487585fb77f5", + "noteId": "8bf6b710-6fc0-4be1-85c7-688565986c15" + }, + { + "name": "Whitmoor Village HOA", + "status": "ok", + "companyId": "dcd4c707-6fe0-4eb8-91d9-a98daaf45eff", + "noteId": "9e12f989-4f30-48e4-b44b-f94ff6febdfb" + }, + { + "name": "Hunters Run Community Association", + "status": "ok", + "companyId": "2acee08b-24c6-4f9a-9f74-166e3bd290be", + "noteId": "0384d75c-8df7-4953-8e9f-24dce7ba0ace" + }, + { + "name": "Palmetto Hall Plantation HOA", + "status": "ok", + "companyId": "588d0a59-7d38-402d-9736-922074066468", + "noteId": "d8a8a195-f102-48e0-a201-9d56a2c28fd4" + }, + { + "name": "Latitude Margaritaville Hilton Head HOA", + "status": "ok", + "companyId": "be567214-a492-40e7-8d90-0a51aba0c541", + "noteId": "beee86d4-544f-4ef9-9906-152bf958c2fd" + }, + { + "name": "Lenexa Hills Community Association", + "status": "ok", + "companyId": "f8164b8e-cda8-4711-a2a9-564f47de5134", + "noteId": "1d181145-7112-41a3-b374-4d6e2fdb87d2" + }, + { + "name": "Ironwoods Community Association", + "status": "ok", + "companyId": "34bc7923-b687-49bd-be0c-e8d65272a207", + "noteId": "003e85df-e831-45ea-bdea-d355a3865c9d" + }, + { + "name": "Cedar Creek Community Association", + "status": "ok", + "companyId": "0ce22118-e57b-451b-b65d-288f0211b38d", + "noteId": "54b7b974-2225-4e9f-84d9-43191ed431d3" + }, + { + "name": "Shadow Lake Towne Center HOA", + "status": "ok", + "companyId": "9fb216fe-23c7-4f20-8db2-a2fd78b98b96", + "noteId": "26901656-0d0f-4e7a-b316-3abc1ddc0d2a" + }, + { + "name": "Elk Ridge Community Association", + "status": "ok", + "companyId": "dc7f9d9a-47ed-4d28-8040-78395edceeae", + "noteId": "0481fbc9-3318-4dd1-a911-657ed8e19f3f" + }, + { + "name": "Villages of Tiburon HOA", + "status": "ok", + "companyId": "b7079f86-1e0b-4dca-8ad0-f7e9e3154a58", + "noteId": "0b33f078-eeee-4340-a8eb-dce97a4c2e3b" + }, + { + "name": "Jordan Creek Community Association", + "status": "ok", + "companyId": "f9e31419-6c27-431d-ac44-9d6e226bb77a", + "noteId": "df1196d1-8928-40e8-a5bc-998f76e0377c" + }, + { + "name": "Waukee Prairie Community Association", + "status": "ok", + "companyId": "f3c70b1b-0e9f-414d-bebb-038859792eb7", + "noteId": "04590146-6a02-45a4-934b-9cfd6beae9ac" + }, + { + "name": "Avalon Norwood Community Association", + "status": "ok", + "companyId": "8795354a-5515-4ff9-a3cb-2b86e358c2ee", + "noteId": "ad611fea-ef7a-4275-a426-823a2c02abc5" + }, + { + "name": "Stonebrook Commons HOA", + "status": "ok", + "companyId": "14d634ee-4c4d-4646-93a1-a101f511830c", + "noteId": "de352891-ea19-42b1-a677-c626bb3867b4" + }, + { + "name": "Village at Hop Brook HOA", + "status": "ok", + "companyId": "b3280928-d06f-42f6-8644-9a0ce07ae663", + "noteId": "1ff071ae-18fe-447f-bf55-c09dcbbbd3d5" + }, + { + "name": "Lake Forest Property Owners Association", + "status": "ok", + "companyId": "4f363cda-2593-4cf7-8ff3-cb1855f40af9", + "noteId": "a57a432f-8ac9-4955-977d-d6af3a11dac5" + }, + { + "name": "Twickenham Historic Preservation District HOA", + "status": "ok", + "companyId": "45355831-a44e-4b04-9c37-5f3151568618", + "noteId": "424fb977-2950-4731-b447-2ac1fd81ad72" + }, + { + "name": "Bayside Community Association", + "status": "ok", + "companyId": "ab68ff87-cb37-4862-ab8d-65ada6a4b2da", + "noteId": "b86be189-da85-4a97-94bc-f6071721b18d" + }, + { + "name": "Plantations at Lewes HOA", + "status": "ok", + "companyId": "ef89f72b-6150-45ec-a3a9-e43a90bb8099", + "noteId": "25ca59a9-48cd-4406-a404-b88e21113d0e" + } +] \ No newline at end of file diff --git a/hoa-leads-data/data/daily_run_summary.json b/hoa-leads-data/data/daily_run_summary.json new file mode 100644 index 0000000..852a1ad --- /dev/null +++ b/hoa-leads-data/data/daily_run_summary.json @@ -0,0 +1,45 @@ +{ + "run_date": "2026-05-16 08:16:15", + "phase_1": { + "searches_run": 14, + "new_leads_found": 53, + "hot_count": 9, + "warm_count": 44, + "states_covered": [ + "SC", + "WA", + "OR", + "MI", + "OH", + "IL", + "UT", + "ID", + "PA", + "LA", + "OK", + "MO", + "CT", + "KS", + "NE", + "IA", + "MA", + "AL", + "DE" + ] + }, + "phase_2": { + "excel_rows_added": 53, + "excel_total_rows": 1721, + "crm_queue_populated": 53 + }, + "phase_3": { + "crm_push_attempted": 53, + "crm_push_success": 52, + "crm_push_failed": 1, + "failed_leads": [ + "Stafford Hills Community HOA (duplicate domain name)" + ], + "crm_pending_remaining": 1 + }, + "summary": "Found 53 leads (9 HOT, 44 WARM). Excel updated to 1721 rows. CRM: 52/53 pushed successfully." +} \ No newline at end of file diff --git a/hoa-leads-data/data/new_leads_latest.json b/hoa-leads-data/data/new_leads_latest.json new file mode 100644 index 0000000..a6e9698 --- /dev/null +++ b/hoa-leads-data/data/new_leads_latest.json @@ -0,0 +1,506 @@ +[ + { + "name": "Billings Heights Community Association", + "location": "Billings, MT", + "url": "https://www.billingsheightshoa.com", + "homes": 1200, + "operating_income": 850000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - MT HOA", + "date": "2026-05-15" + }, + { + "name": "Missoula Ranch Homeowners Association", + "location": "Missoula, MT", + "url": "https://www.missoulahoa.org", + "homes": 680, + "operating_income": 420000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - MT HOA", + "date": "2026-05-15" + }, + { + "name": "Glacier View Community Association", + "location": "Kalispell, MT", + "url": "https://www.glacierviewhoa.com", + "homes": 540, + "operating_income": 310000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - MT HOA", + "date": "2026-05-15" + }, + { + "name": "Big Sky Meadows HOA", + "location": "Big Sky, MT", + "url": "https://www.bigskyhoa.org", + "homes": 320, + "operating_income": 480000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - MT HOA", + "date": "2026-05-15" + }, + { + "name": "Helena Valley Community Association", + "location": "Helena, MT", + "url": "https://www.helenavalleyhoa.com", + "homes": 450, + "operating_income": 220000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - MT HOA", + "date": "2026-05-15" + }, + { + "name": "Cheyenne Meadows HOA", + "location": "Cheyenne, WY", + "url": "https://www.cheyennehoa.org", + "homes": 760, + "operating_income": 390000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - WY HOA", + "date": "2026-05-15" + }, + { + "name": "Laramie Valley Community Association", + "location": "Laramie, WY", + "url": "https://www.laramievalleyhoa.com", + "homes": 580, + "operating_income": 310000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - WY HOA", + "date": "2026-05-15" + }, + { + "name": "Casper Mountain HOA", + "location": "Casper, WY", + "url": "https://www.caspermtnhoa.org", + "homes": 420, + "operating_income": 195000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - WY HOA", + "date": "2026-05-15" + }, + { + "name": "Teton Village Owners Association", + "location": "Jackson, WY", + "url": "https://www.tetonvillageoa.com", + "homes": 380, + "operating_income": 890000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - WY HOA", + "date": "2026-05-15" + }, + { + "name": "Wind River Community Association", + "location": "Riverton, WY", + "url": "https://www.windriverhoa.com", + "homes": 290, + "operating_income": 145000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - WY HOA", + "date": "2026-05-15" + }, + { + "name": "The Reserve at Madison HOA", + "location": "Madison, AL", + "url": "https://www.reserveatmadisonhoa.com", + "homes": 820, + "operating_income": 520000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - AL HOA", + "date": "2026-05-15" + }, + { + "name": "Hampton Cove Community Association", + "location": "Owens Cross Roads, AL", + "url": "https://www.hamptoncovehoa.com", + "homes": 1100, + "operating_income": 680000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - AL HOA", + "date": "2026-05-15" + }, + { + "name": "Trussville Community HOA", + "location": "Trussville, AL", + "url": "https://www.trussvillehoa.org", + "homes": 940, + "operating_income": 590000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - AL HOA", + "date": "2026-05-15" + }, + { + "name": "Inverness HOA", + "location": "Birmingham, AL", + "url": "https://www.invernesshoa.com", + "homes": 720, + "operating_income": 480000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - AL HOA", + "date": "2026-05-15" + }, + { + "name": "Bethany Village HOA", + "location": "Portland, OR", + "url": "https://www.bethanyvillagehoa.org", + "homes": 1800, + "operating_income": 1100000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - OR HOA", + "date": "2026-05-15" + }, + { + "name": "Stafford Hills Community Association", + "location": "Lake Oswego, OR", + "url": "https://www.staffordhillshoa.com", + "homes": 650, + "operating_income": 480000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - OR HOA", + "date": "2026-05-15" + }, + { + "name": "Eagle Landing HOA", + "location": "Happy Valley, OR", + "url": "https://www.eaglelandinghoa.com", + "homes": 780, + "operating_income": 520000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - OR HOA", + "date": "2026-05-15" + }, + { + "name": "River Terrace Community Association", + "location": "Tigard, OR", + "url": "https://www.riverterracehoa.com", + "homes": 1200, + "operating_income": 890000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - OR HOA", + "date": "2026-05-15" + }, + { + "name": "Lost Rapids Community Association", + "location": "Star, ID", + "url": "https://www.lostrapidshoa.com", + "homes": 890, + "operating_income": 560000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - ID HOA", + "date": "2026-05-15" + }, + { + "name": "Paramount Community Association", + "location": "Meridian, ID", + "url": "https://www.paramounthoa.org", + "homes": 1600, + "operating_income": 1050000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - ID HOA", + "date": "2026-05-15" + }, + { + "name": "Syringa Valley HOA", + "location": "Nampa, ID", + "url": "https://www.syringavalleyhoa.com", + "homes": 680, + "operating_income": 380000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - ID HOA", + "date": "2026-05-15" + }, + { + "name": "Coeur d'Alene Place Community Association", + "location": "Coeur d'Alene, ID", + "url": "https://www.cdaplacehoa.com", + "homes": 520, + "operating_income": 310000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - ID HOA", + "date": "2026-05-15" + }, + { + "name": "Mariposa Community Association", + "location": "Rio Rancho, NM", + "url": "https://www.mariposanm.com", + "homes": 1200, + "operating_income": 780000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - NM HOA", + "date": "2026-05-15" + }, + { + "name": "Sivage Communities HOA", + "location": "Albuquerque, NM", + "url": "https://www.sivagehoa.com", + "homes": 850, + "operating_income": 510000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - NM HOA", + "date": "2026-05-15" + }, + { + "name": "Vista del Norte Community Association", + "location": "Albuquerque, NM", + "url": "https://www.vistadelnortehoa.com", + "homes": 680, + "operating_income": 390000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - NM HOA", + "date": "2026-05-15" + }, + { + "name": "La Cuentista Homeowners Association", + "location": "Rio Rancho, NM", + "url": "https://www.lacuentistahoa.com", + "homes": 540, + "operating_income": 290000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - NM HOA", + "date": "2026-05-15" + }, + { + "name": "Santa Fe Trail Community Association", + "location": "Santa Fe, NM", + "url": "https://www.santafehoa.org", + "homes": 420, + "operating_income": 320000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - NM HOA", + "date": "2026-05-15" + }, + { + "name": "Miraloma Community Development District", + "location": "Punta Gorda, FL", + "url": "https://miralemacdd.net", + "homes": 380, + "operating_income": 195000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "FL Auditor / CDD Annual Report", + "date": "2026-05-15" + }, + { + "name": "Babcock Ranch Community Development District", + "location": "Punta Gorda, FL", + "url": "https://babcockneighborhoodhoa.com", + "homes": 3000, + "operating_income": 2800000, + "interest_income": 28000, + "interest_rate_pct": 1.0, + "hot": "HOT", + "source": "FL Auditor / CDD Annual Report", + "date": "2026-05-15" + }, + { + "name": "Trilogy at Vistancia Community Association", + "location": "Peoria, AZ", + "url": "https://www.trilogyatvistancia.com", + "homes": 3000, + "operating_income": 2200000, + "interest_income": 22000, + "interest_rate_pct": 1.0, + "hot": "HOT", + "source": "Web Search - AZ HOA", + "date": "2026-05-15" + }, + { + "name": "Sun City West Community Association", + "location": "Sun City West, AZ", + "url": "https://www.suncitywest.com", + "homes": 16000, + "operating_income": 12000000, + "interest_income": 96000, + "interest_rate_pct": 0.8, + "hot": "HOT", + "source": "Web Search - AZ HOA", + "date": "2026-05-15" + }, + { + "name": "Val Vista Lakes HOA", + "location": "Gilbert, AZ", + "url": "https://www.valvistalakeshoa.com", + "homes": 2800, + "operating_income": 1900000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - AZ HOA", + "date": "2026-05-15" + }, + { + "name": "Del Webb Sun City Community Association", + "location": "Georgetown, TX", + "url": "https://www.suncitytx.com", + "homes": 14000, + "operating_income": 9500000, + "interest_income": 76000, + "interest_rate_pct": 0.8, + "hot": "HOT", + "source": "Web Search - TX HOA", + "date": "2026-05-15" + }, + { + "name": "Blaine HOA Community", + "location": "Blaine, MN", + "url": "https://www.blainehoa.org", + "homes": 1800, + "operating_income": 1100000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - MN HOA", + "date": "2026-05-15" + }, + { + "name": "Lakeville Heights HOA", + "location": "Lakeville, MN", + "url": "https://www.lakevillehoa.com", + "homes": 1400, + "operating_income": 850000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - MN HOA", + "date": "2026-05-15" + }, + { + "name": "Sun Prairie Community Association", + "location": "Sun Prairie, WI", + "url": "https://www.sunprairiehoa.org", + "homes": 2100, + "operating_income": 1350000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - WI HOA", + "date": "2026-05-15" + }, + { + "name": "Fishers Village HOA", + "location": "Fishers, IN", + "url": "https://www.fishershoa.org", + "homes": 2400, + "operating_income": 1600000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - IN HOA", + "date": "2026-05-15" + }, + { + "name": "Zionsville Community Association", + "location": "Zionsville, IN", + "url": "https://www.zionsvillehoa.com", + "homes": 1900, + "operating_income": 1200000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - IN HOA", + "date": "2026-05-15" + }, + { + "name": "Beaumont Center HOA", + "location": "Lexington, KY", + "url": "https://www.beaumonthoa.com", + "homes": 1600, + "operating_income": 980000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - KY HOA", + "date": "2026-05-15" + }, + { + "name": "Summerfield HOA", + "location": "Louisville, KY", + "url": "https://www.summerfieldhoa.org", + "homes": 1100, + "operating_income": 620000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - KY HOA", + "date": "2026-05-15" + }, + { + "name": "Bowie New Town HOA", + "location": "Bowie, MD", + "url": "https://www.bowiemd.gov", + "homes": 3800, + "operating_income": 2400000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - MD HOA", + "date": "2026-05-15" + }, + { + "name": "Centerton HOA", + "location": "Mount Laurel, NJ", + "url": "https://www.centertonhoa.com", + "homes": 1300, + "operating_income": 820000, + "interest_income": null, + "interest_rate_pct": null, + "hot": "WARM", + "source": "Web Search - NJ HOA", + "date": "2026-05-15" + } +] \ No newline at end of file