meta-optimizer/meta_ads_client.py
José Manuel Gómez 92786e94a8 Initial structure: Meta Optimizer
- 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>
2026-05-22 12:22:11 +02:00

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