- meta_ads_client.py: Meta Marketing API client (facebook-business SDK) - agent.py: Claude-powered campaign decision engine - run.py: main orchestration script - config.py: environment variables - .github/workflows/daily.yml: GitHub Actions cron (8am CEST) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
79 lines
2.9 KiB
Python
79 lines
2.9 KiB
Python
"""
|
|
Cliente para Meta Marketing API.
|
|
Documentación: https://developers.facebook.com/docs/marketing-api
|
|
SDK: facebook-business
|
|
"""
|
|
from facebook_business.api import FacebookAdsApi
|
|
from facebook_business.adobjects.adaccount import AdAccount
|
|
from facebook_business.adobjects.campaign import Campaign
|
|
import config
|
|
from datetime import datetime
|
|
|
|
|
|
class MetaAdsClient:
|
|
def __init__(self):
|
|
FacebookAdsApi.init(
|
|
app_id=config.META_APP_ID,
|
|
app_secret=config.META_APP_SECRET,
|
|
access_token=config.META_ACCESS_TOKEN,
|
|
)
|
|
self.account = AdAccount(config.META_AD_ACCOUNT_ID)
|
|
|
|
def get_monthly_metrics_all(self) -> dict:
|
|
"""
|
|
Métricas del mes en curso para todas las campañas activas.
|
|
Retorna dict {campaign_id: {spend, impressions, clicks, ctr, cpm, leads, cpl, status, name}}.
|
|
"""
|
|
now = datetime.now()
|
|
date_start = f"{now.year}-{now.month:02d}-01"
|
|
date_end = now.strftime("%Y-%m-%d")
|
|
|
|
campaigns = self.account.get_campaigns(fields=[
|
|
Campaign.Field.id,
|
|
Campaign.Field.name,
|
|
Campaign.Field.status,
|
|
Campaign.Field.effective_status,
|
|
], params={"effective_status": ["ACTIVE", "PAUSED"]})
|
|
|
|
result = {}
|
|
for c in campaigns:
|
|
cid = c["id"]
|
|
name = c["name"]
|
|
status = c.get("effective_status", "UNKNOWN")
|
|
|
|
insights = c.get_insights(fields=[
|
|
"spend", "impressions", "clicks", "ctr", "cpm",
|
|
"actions", # conversiones por tipo (lead, purchase, etc.)
|
|
"cost_per_action_type",
|
|
], params={
|
|
"time_range": {"since": date_start, "until": date_end},
|
|
"level": "campaign",
|
|
})
|
|
|
|
spend = impressions = clicks = ctr = cpm = leads = 0.0
|
|
if insights:
|
|
row = insights[0]
|
|
spend = float(row.get("spend", 0))
|
|
impressions = int(row.get("impressions", 0))
|
|
clicks = int(row.get("clicks", 0))
|
|
ctr = float(row.get("ctr", 0))
|
|
cpm = float(row.get("cpm", 0))
|
|
for action in row.get("actions", []):
|
|
if action["action_type"] in ("lead", "onsite_conversion.lead_grouped"):
|
|
leads += float(action["value"])
|
|
|
|
cpl = round(spend / leads, 2) if leads > 0 else 0.0
|
|
result[cid] = {
|
|
"campaign_id": cid,
|
|
"name": name,
|
|
"status": status,
|
|
"spend": round(spend, 2),
|
|
"impressions": impressions,
|
|
"clicks": clicks,
|
|
"ctr": round(ctr, 4),
|
|
"cpm": round(cpm, 2),
|
|
"leads": int(leads),
|
|
"cpl": cpl,
|
|
}
|
|
return result
|