Align field names with actual Airtable schema
- Campaigns: Status='Activa' filter (was Activa=TRUE), CPAMax (was CPAMaximo), add MargenObjetivo and CursoID Text per campaign - Leads: filter by attr_cursoid + creado (was GoogleCampaignID + Fecha) - analyzer: expose margen_objetivo and margen_ok per campaign - config: remove global MARGEN_MINIMO, now per-campaign via Airtable - sync: new campaigns created with Status='Pausada' https://claude.ai/code/session_01WEcdWPxGWZKk8FGwBRLGR2
This commit is contained in:
parent
d68f9f5659
commit
905ad3bcd2
@ -11,17 +11,19 @@ class AirtableClient:
|
||||
|
||||
def get_active_campaigns(self) -> list[dict]:
|
||||
"""Lee todas las campañas activas desde 'Google Ads Campaigns'."""
|
||||
records = self.campaigns.all(formula="{Activa}=TRUE()")
|
||||
records = self.campaigns.all(formula="{Status}='Activa'")
|
||||
result = []
|
||||
for r in records:
|
||||
f = r["fields"]
|
||||
result.append({
|
||||
"airtable_id": r["id"],
|
||||
"curso": f.get("Campaign Name", "Sin nombre"),
|
||||
"cursoid_text": str(f.get("CursoID Text", "")).strip(),
|
||||
"google_campaign_id": str(f.get("CampaignID", "")).strip(),
|
||||
"ppl": float(f.get("PPL", 0)),
|
||||
"capping_mensual": int(f.get("CapTotalMes", 0)),
|
||||
"cpa_maximo": float(f.get("CPAMaximo", 0)),
|
||||
"cpa_maximo": float(f.get("CPAMax", 0)),
|
||||
"margen_objetivo": float(f.get("MargenObjetivo", 0)),
|
||||
})
|
||||
return [c for c in result if c["google_campaign_id"]] # descartar sin ID
|
||||
|
||||
@ -50,7 +52,7 @@ class AirtableClient:
|
||||
self.campaigns.create({
|
||||
"Campaign Name": gc["name"],
|
||||
"CampaignID": int(gid),
|
||||
"Activa": False,
|
||||
"Status": "Pausada",
|
||||
})
|
||||
created.append(gc["name"])
|
||||
else:
|
||||
@ -63,18 +65,18 @@ class AirtableClient:
|
||||
|
||||
return {"created": created, "updated": updated}
|
||||
|
||||
def get_leads_this_month(self, google_campaign_id: str) -> int:
|
||||
def get_leads_this_month(self, cursoid_text: str) -> int:
|
||||
"""
|
||||
Cuenta todos los leads del mes actual para una campaña.
|
||||
Todos los leads en Airtable están validados, sin filtro de estado.
|
||||
Cuenta todos los leads validados del mes actual para un curso.
|
||||
Filtra por attr_cursoid (que coincide con CursoID Text de la campaña).
|
||||
"""
|
||||
now = datetime.now()
|
||||
mes_inicio = f"{now.year}-{now.month:02d}-01"
|
||||
|
||||
formula = (
|
||||
f"AND("
|
||||
f"{{GoogleCampaignID}}='{google_campaign_id}',"
|
||||
f"{{Fecha}}>='{mes_inicio}'"
|
||||
f"{{attr_cursoid}}='{cursoid_text}',"
|
||||
f"{{creado}}>='{mes_inicio}'"
|
||||
f")"
|
||||
)
|
||||
records = self.leads.all(formula=formula)
|
||||
|
||||
@ -11,6 +11,7 @@ def analyze(campaign_config: dict, leads_entregados: int, ads_metrics: dict) ->
|
||||
capping = campaign_config["capping_mensual"]
|
||||
ppl = campaign_config["ppl"]
|
||||
cpa_max = campaign_config["cpa_maximo"]
|
||||
margen_objetivo = campaign_config.get("margen_objetivo", 0)
|
||||
gasto = ads_metrics.get("cost", 0)
|
||||
conversiones_google = ads_metrics.get("conversions", 0)
|
||||
|
||||
@ -42,6 +43,8 @@ def analyze(campaign_config: dict, leads_entregados: int, ads_metrics: dict) ->
|
||||
"campaign_id": campaign_config["google_campaign_id"],
|
||||
"ppl": ppl,
|
||||
"cpa_maximo": cpa_max,
|
||||
"margen_objetivo": margen_objetivo,
|
||||
"margen_ok": margen >= margen_objetivo if margen_objetivo > 0 else True,
|
||||
"capping": capping,
|
||||
"leads_entregados": leads_entregados,
|
||||
"leads_restantes": leads_restantes,
|
||||
|
||||
@ -21,4 +21,3 @@ ANTHROPIC_API_KEY = os.environ["ANTHROPIC_API_KEY"]
|
||||
|
||||
# Operación
|
||||
DRY_RUN = True # True = solo sugiere, no aplica cambios en Google Ads
|
||||
MARGEN_MINIMO = 0.40 # 40% mínimo de margen sobre PPL
|
||||
|
||||
2
run.py
2
run.py
@ -53,7 +53,7 @@ def run():
|
||||
print(f" Campaign ID: {cid} | PPL: {campaign['ppl']}€ | Cap: {campaign['capping_mensual']} leads")
|
||||
|
||||
# 1. Leads reales desde Airtable
|
||||
leads = at.get_leads_this_month(cid)
|
||||
leads = at.get_leads_this_month(campaign["cursoid_text"])
|
||||
|
||||
# 2. Métricas de Google Ads
|
||||
metrics = gads.get_campaign_metrics(cid)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user