Systems Library / Industry Applications / How to Create Automated Real Estate Email Drip Campaigns
Industry Applications real estate

How to Create Automated Real Estate Email Drip Campaigns

Nurture real estate leads with automated drip campaigns by buyer stage.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

Automating real estate email drip campaigns by buyer stage keeps leads warm until they are ready to move. Most agents blast the same newsletter to everyone. This system segments by buyer type and stage, then sends the right content at the right time. A first-time buyer gets different emails than a downsizing retiree.

What You Need Before Starting

Step 1: Define Drip Sequences by Buyer Type

DRIP_SEQUENCES = {
    "first_time_buyer": [
        {"day": 0, "subject": "Your homebuying journey starts here", "topic": "overview of buying process"},
        {"day": 3, "subject": "How much home can you afford?", "topic": "mortgage pre-approval guide"},
        {"day": 7, "subject": "The 5 things every first-time buyer misses", "topic": "common mistakes"},
        {"day": 14, "subject": "What to expect at a showing", "topic": "showing preparation"},
        {"day": 21, "subject": "Making an offer that wins", "topic": "offer strategy"},
        {"day": 30, "subject": "From offer to keys: the closing process", "topic": "closing guide"},
    ],
    "move_up_buyer": [
        {"day": 0, "subject": "Selling and buying at the same time", "topic": "simultaneous transactions"},
        {"day": 3, "subject": "What your current home is worth", "topic": "home valuation"},
        {"day": 7, "subject": "Bridge loans and contingencies explained", "topic": "financing options"},
        {"day": 14, "subject": "Timing your sale for maximum profit", "topic": "market timing"},
        {"day": 21, "subject": "Neighborhoods worth the upgrade", "topic": "area recommendations"},
    ],
    "investor": [
        {"day": 0, "subject": "Current rental yields in your market", "topic": "rental market data"},
        {"day": 3, "subject": "Cash flow analysis: what the numbers need to show", "topic": "investment analysis"},
        {"day": 7, "subject": "Off-market opportunities this month", "topic": "off-market deals"},
        {"day": 14, "subject": "Tax advantages of real estate investing", "topic": "tax strategy"},
        {"day": 21, "subject": "Property management: DIY vs outsource", "topic": "management options"},
    ]
}

Step 2: Generate Personalized Email Content

import anthropic
from dotenv import load_dotenv
load_dotenv()

def generate_drip_email(lead, step):
    client = anthropic.Anthropic()
    
    response = client.messages.create(
        model="claude-sonnet-4-20250514",
        max_tokens=1024,
        system="""You are a real estate agent writing educational email content.
Rules:
- Helpful and informative, not salesy
- Include one specific actionable tip
- End with a soft call to action (reply, call, or link)
- Under 200 words
- Conversational tone
- No ALL CAPS or excessive punctuation""",
        messages=[{
            "role": "user",
            "content": f"Write an email to {lead['name']} about: {step['topic']}. They are a {lead['buyer_type']} looking in {lead.get('preferred_area', 'the local market')}. Subject line: {step['subject']}"
        }]
    )
    
    return response.content[0].text

Step 3: Build the Drip Engine

import sqlite3
from datetime import datetime, timedelta

def init_drip_db(db_path="drip_campaigns.db"):
    conn = sqlite3.connect(db_path)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS drip_enrollments (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            lead_id INTEGER,
            lead_name TEXT,
            lead_email TEXT,
            buyer_type TEXT,
            preferred_area TEXT,
            current_step INTEGER DEFAULT 0,
            enrolled_at TEXT,
            status TEXT DEFAULT 'active'
        )
    """)
    conn.execute("""
        CREATE TABLE IF NOT EXISTS drip_sends (
            id INTEGER PRIMARY KEY AUTOINCREMENT,
            enrollment_id INTEGER,
            step_index INTEGER,
            subject TEXT,
            sent_at TEXT
        )
    """)
    conn.commit()
    conn.close()

def process_drip_sends(db_path="drip_campaigns.db"):
    conn = sqlite3.connect(db_path)
    active = conn.execute("""
        SELECT id, lead_id, lead_name, lead_email, buyer_type, preferred_area, current_step, enrolled_at
        FROM drip_enrollments WHERE status = 'active'
    """).fetchall()
    
    sent_count = 0
    for enrollment in active:
        eid, lid, name, email, btype, area, step_idx, enrolled = enrollment
        sequence = DRIP_SEQUENCES.get(btype, DRIP_SEQUENCES["first_time_buyer"])
        
        if step_idx >= len(sequence):
            conn.execute("UPDATE drip_enrollments SET status = 'completed' WHERE id = ?", (eid,))
            continue
        
        step = sequence[step_idx]
        enrolled_dt = datetime.fromisoformat(enrolled)
        send_date = enrolled_dt + timedelta(days=step["day"])
        
        if datetime.utcnow() >= send_date:
            lead = {"name": name, "buyer_type": btype, "preferred_area": area}
            body = generate_drip_email(lead, step)
            
            send_email(email, step["subject"], body)
            
            conn.execute("UPDATE drip_enrollments SET current_step = ? WHERE id = ?", (step_idx + 1, eid))
            conn.execute("INSERT INTO drip_sends (enrollment_id, step_index, subject, sent_at) VALUES (?,?,?,?)",
                        (eid, step_idx, step["subject"], datetime.utcnow().isoformat()))
            sent_count += 1
    
    conn.commit()
    conn.close()
    return sent_count

Step 4: Enroll New Leads

def enroll_lead(lead_id, name, email, buyer_type, preferred_area="", db_path="drip_campaigns.db"):
    conn = sqlite3.connect(db_path)
    existing = conn.execute(
        "SELECT id FROM drip_enrollments WHERE lead_email = ? AND status = 'active'",
        (email,)
    ).fetchone()
    
    if existing:
        print(f"{email} already enrolled in active drip")
        conn.close()
        return None
    
    conn.execute("""
        INSERT INTO drip_enrollments (lead_id, lead_name, lead_email, buyer_type, preferred_area, enrolled_at)
        VALUES (?,?,?,?,?,?)
    """, (lead_id, name, email, buyer_type, preferred_area, datetime.utcnow().isoformat()))
    conn.commit()
    conn.close()
    return True

Step 5: Schedule Daily Processing

0 9 * * * python3 /path/to/drip_engine.py
if __name__ == "__main__":
    init_drip_db()
    sent = process_drip_sends()
    print(f"Sent {sent} drip emails")

What to Build Next

Add engagement tracking. When a lead opens multiple emails or clicks links, auto-escalate them to the agent for a personal call. High engagement signals readiness to buy.

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