Systems Library / Marketing Automation / How to Set Up Automated Budget Alerts for Ad Campaigns
Marketing Automation paid advertising

How to Set Up Automated Budget Alerts for Ad Campaigns

Get instant alerts when ad campaigns overspend or underperform benchmarks.

Jay Banlasan

Jay Banlasan

The AI Systems Guy

Automated ad campaign budget alerts catch problems before they eat your monthly spend. I have seen accounts blow through a week of budget in a day because nobody checked. This system watches spend in real time and pings you when something is off.

Setup takes 30 minutes. It pays for itself the first time it catches a runaway campaign.

What You Need Before Starting

Step 1: Define Your Budget Rules

BUDGET_RULES = {
    "daily_overspend_threshold": 1.3,   # Alert if daily spend > 130% of daily budget
    "daily_underspend_threshold": 0.5,   # Alert if daily spend < 50% of daily budget
    "monthly_pace_warning": 0.85,        # Alert when 85% of monthly budget is spent
    "cpa_alert_multiplier": 1.5,         # Alert if CPA exceeds 150% of target
    "zero_spend_alert": True,            # Alert if campaign has $0 spend by noon
}

CAMPAIGN_BUDGETS = {
    "JB | Lead | UK | Assessment": {"daily": 20, "monthly": 600, "target_cpa": 25},
    "JB | Lead | US | Quiz": {"daily": 50, "monthly": 1500, "target_cpa": 15},
}

Step 2: Fetch Current Spend

import requests
import os
from datetime import datetime

def fetch_campaign_spend(account_id):
    token = os.getenv("META_ACCESS_TOKEN")
    today = datetime.now().strftime("%Y-%m-%d")
    
    url = f"https://graph.facebook.com/v19.0/{account_id}/insights"
    params = {
        "access_token": token,
        "fields": "campaign_name,spend,actions",
        "level": "campaign",
        "time_range": f'{{"since":"{today}","until":"{today}"}}',
        "filtering": '[{"field":"campaign.delivery_info","operator":"IN","value":["active"]}]',
    }
    
    resp = requests.get(url, params=params)
    campaigns = []
    for row in resp.json().get("data", []):
        conversions = 0
        for action in row.get("actions", []):
            if action["action_type"] in ["lead", "purchase"]:
                conversions += int(action["value"])
        
        campaigns.append({
            "name": row["campaign_name"],
            "spend": float(row.get("spend", 0)),
            "conversions": conversions,
        })
    return campaigns

Step 3: Check Against Budget Rules

def check_budgets(campaigns):
    alerts = []
    
    for campaign in campaigns:
        name = campaign["name"]
        budget = CAMPAIGN_BUDGETS.get(name)
        if not budget:
            continue
        
        spend = campaign["spend"]
        daily_budget = budget["daily"]
        
        # Overspend check
        if spend > daily_budget * BUDGET_RULES["daily_overspend_threshold"]:
            alerts.append({
                "level": "critical",
                "campaign": name,
                "message": f"Overspending: ${spend:.2f} vs ${daily_budget:.2f} daily budget"
            })
        
        # CPA check
        if campaign["conversions"] > 0:
            cpa = spend / campaign["conversions"]
            if cpa > budget["target_cpa"] * BUDGET_RULES["cpa_alert_multiplier"]:
                alerts.append({
                    "level": "warning",
                    "campaign": name,
                    "message": f"CPA too high: ${cpa:.2f} vs ${budget['target_cpa']:.2f} target"
                })
        
        # Zero spend check (only after noon)
        hour = datetime.now().hour
        if spend == 0 and hour >= 12 and BUDGET_RULES["zero_spend_alert"]:
            alerts.append({
                "level": "warning",
                "campaign": name,
                "message": "Zero spend detected after noon. Check delivery."
            })
    
    return alerts

Step 4: Send Alerts to Slack

def send_slack_alerts(alerts):
    webhook_url = os.getenv("SLACK_WEBHOOK_URL")
    
    for alert in alerts:
        icon = "🔴" if alert["level"] == "critical" else "🟡"
        text = f"{icon} *{alert['campaign']}*\n{alert['message']}"
        requests.post(webhook_url, json={"text": text})

Step 5: Run on a Schedule

# Check every 4 hours during business hours
0 8,12,16,20 * * * cd /path/to/project && python3 budget_alerts.py

Four checks per day is enough to catch problems without being noisy. The noon check catches zero-spend issues. The 4 PM check catches afternoon overspend before it compounds overnight.

What to Build Next

Add monthly pacing alerts that project whether you will hit or miss budget based on current run rate. Then add auto-pause for campaigns that exceed 150% of daily budget with zero conversions.

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