Systems Library / Industry Applications / How to Automate Real Estate Lead Follow-Up
Industry Applications real estate

How to Automate Real Estate Lead Follow-Up

Follow up with property leads automatically across email and text.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

Automating real estate lead follow-up is where agents stop losing deals. The National Association of Realtors says 80% of sales happen after the fifth follow-up, but most agents stop after one. I build follow-up systems that handle the first five touches automatically, so agents only spend time on leads that respond.

What You Need Before Starting

Step 1: Set Up the Lead Database

import sqlite3
from datetime import datetime

def init_lead_db(db_path="real_estate_leads.db"):
    conn = sqlite3.connect(db_path)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS leads (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            name TEXT,
            email TEXT,
            phone TEXT,
            source TEXT,
            property_interest TEXT,
            lead_type TEXT,
            status TEXT DEFAULT 'new',
            follow_up_count INTEGER DEFAULT 0,
            created_at TEXT,
            last_contact TEXT
        )
    """)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS follow_ups (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            lead_id INTEGER,
            channel TEXT,
            message TEXT,
            sent_at TEXT,
            opened INTEGER DEFAULT 0
        )
    """)
    conn.commit()
    conn.close()

Step 2: Define the Follow-Up Sequence

FOLLOW_UP_SEQUENCE = [
    {
        "delay_hours": 0,
        "channel": "email",
        "subject": "Thanks for your inquiry about {property}",
        "template": "quick_response"
    },
    {
        "delay_hours": 24,
        "channel": "email",
        "subject": "More details on {property}",
        "template": "property_details"
    },
    {
        "delay_hours": 72,
        "channel": "email",
        "subject": "Similar properties you might like",
        "template": "similar_listings"
    },
    {
        "delay_hours": 168,
        "channel": "email",
        "subject": "Market update for {neighborhood}",
        "template": "market_update"
    },
    {
        "delay_hours": 336,
        "channel": "email",
        "subject": "Still looking in {neighborhood}?",
        "template": "check_in"
    }
]

Step 3: Build the Message Generator

import anthropic
from dotenv import load_dotenv

load_dotenv()

def generate_follow_up(lead, template_type):
    client = anthropic.Anthropic()
    
    prompts = {
        "quick_response": f"Write a brief, warm follow-up email to {lead['name']} who inquired about {lead['property_interest']}. Thank them, confirm you received their inquiry, and ask what their timeline looks like. Under 100 words.",
        "property_details": f"Write a follow-up email to {lead['name']} with additional details about {lead['property_interest']}. Mention neighborhood highlights and suggest scheduling a showing. Under 120 words.",
        "similar_listings": f"Write an email to {lead['name']} suggesting they might also like similar properties near {lead['property_interest']}. Keep it helpful, not salesy. Under 100 words.",
        "market_update": f"Write a brief market update email for the area around {lead['property_interest']}. Include a note about timing and invite questions. Under 100 words.",
        "check_in": f"Write a casual check-in email to {lead['name']} asking if they are still looking for properties. Offer to help with no pressure. Under 80 words."
    }
    
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=512,
        system="You are a friendly real estate agent. Write natural, conversational emails. No ALL CAPS. No exclamation marks overuse. Sound human, not automated.",
        messages=[{"role": "user", "content": prompts.get(template_type, prompts["check_in"])}]
    )
    
    return response.content[0].text

Step 4: Build the Follow-Up Engine

from datetime import datetime, timedelta
import smtplib
from email.mime.text import MIMEText

def send_email(to_email, subject, body):
    msg = MIMEText(body)
    msg["Subject"] = subject
    msg["From"] = "[email protected]"
    msg["To"] = to_email
    
    with smtplib.SMTP("smtp.gmail.com", 587) as server:
        server.starttls()
        server.login("[email protected]", "YOUR_APP_PASSWORD")
        server.send_message(msg)

def process_follow_ups(db_path="real_estate_leads.db"):
    conn = sqlite3.connect(db_path)
    leads = conn.execute("""
        SELECT id, name, email, property_interest, follow_up_count, created_at
        FROM leads WHERE status = 'new' OR status = 'following_up'
    """).fetchall()
    
    for lead_row in leads:
        lead_id, name, email, property, count, created = lead_row
        
        if count >= len(FOLLOW_UP_SEQUENCE):
            conn.execute("UPDATE leads SET status = 'nurture' WHERE id = ?", (lead_id,))
            continue
        
        step = FOLLOW_UP_SEQUENCE[count]
        created_dt = datetime.fromisoformat(created)
        send_after = created_dt + timedelta(hours=step["delay_hours"])
        
        if datetime.utcnow() >= send_after:
            lead_data = {"name": name, "property_interest": property}
            body = generate_follow_up(lead_data, step["template"])
            subject = step["subject"].replace("{property}", property or "your inquiry")
            
            send_email(email, subject, body)
            
            conn.execute("UPDATE leads SET follow_up_count = ?, last_contact = ?, status = 'following_up' WHERE id = ?",
                        (count + 1, datetime.utcnow().isoformat(), lead_id))
            conn.execute("INSERT INTO follow_ups (lead_id, channel, message, sent_at) VALUES (?,?,?,?)",
                        (lead_id, "email", body[:500], datetime.utcnow().isoformat()))
    
    conn.commit()
    conn.close()

Step 5: Schedule Hourly Processing

0 * * * * python3 /path/to/follow_up_engine.py

What to Build Next

Add reply detection. Monitor your inbox for responses and automatically pause the sequence when a lead replies. That prevents the awkward automated email that arrives after they already responded.

Related Reading

Want this system built for your business?

Get a free assessment. We will map every system your business needs and show you the ROI.

Get Your Free Assessment

Related Systems