leads-optimizer/backfill_leadform_jun8_10.py
José Manuel Gómez 170f0a3207 Add 5th lead attribution path: cursoid + Google-Ads-Notifications UserAgent
Leadform leads in Airtable now counted for PMX campaigns via
attr_cursoid + UserAgent='Google-Ads-Notifications', both for
monthly totals and daily MetricasDiarias.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-11 18:35:55 +02:00

98 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Recalcula leads_lake en MetricasDiarias para días 8-10 de junio 2026
añadiendo la atribución de leadforms via cursoid + UserAgent.
También actualiza ConvLeadsLakeMes, Leads Lake y ConvLeadsLakeMesFinal.
"""
import json
import re
from datetime import datetime
from airtable_client import AirtableClient
DAYS = ["2026-06-08", "2026-06-09", "2026-06-10"]
def _course_num(name: str) -> str | None:
m = re.search(r'fco_(?:search|pmx)_(\d+)', name, re.IGNORECASE)
return m.group(1) if m else None
def run():
at = AirtableClient()
campaigns = at.get_active_gacampaignmes()
print(f"{len(campaigns)} campañas activas este mes\n")
# Mapping cursoid → PMX campaign_id para leadforms diarios
cursoid_to_campaign: dict[str, str] = {}
for c in campaigns:
num = _course_num(c["curso"])
if num and "pmx" in c["curso"].lower() and "_leadform" not in c["curso"].lower():
cursoid_to_campaign[num] = c["google_campaign_id"]
print(f"→ Mapping cursoid→campaign: {len(cursoid_to_campaign)} entradas")
# Obtener leads por campaña para cada día (una llamada bulk por día)
daily_counts: dict[str, dict[str, int]] = {}
for date_str in DAYS:
daily_counts[date_str] = at.get_leads_by_campaign_on_date(date_str, cursoid_to_campaign)
total = sum(daily_counts[date_str].values())
print(f" {date_str}: {total} leads totales encontrados")
print()
# Actualizar MetricasDiarias para cada campaña
metricas_updates = []
for campaign in campaigns:
cid = campaign["google_campaign_id"]
try:
md = json.loads(campaign["metricas_diarias"])
except (json.JSONDecodeError, TypeError):
md = {}
changed = False
for date_str in DAYS:
day_key = date_str[8:10]
if day_key not in md:
continue
new_count = daily_counts[date_str].get(cid, 0)
old_count = md[day_key].get("leads_lake", 0)
if old_count != new_count:
print(f" {campaign['curso'][:45]} día {day_key}: leads_lake {old_count}{new_count}")
md[day_key]["leads_lake"] = new_count
# Recalcular ingreso_lxp para el día (leads_lake × PPL)
md[day_key]["ingreso"] = round(new_count * campaign["ppl"], 2)
changed = True
if changed:
metricas_updates.append({
"airtable_id": campaign["airtable_id"],
"metricas_json": json.dumps(md, ensure_ascii=False),
})
if metricas_updates:
print(f"\n→ Actualizando MetricasDiarias ({len(metricas_updates)} registros)...")
at.batch_update_metricas_diarias(metricas_updates)
print(" ✓ MetricasDiarias actualizado.")
else:
print(" ✓ MetricasDiarias sin cambios.")
# Recalcular totales mensuales con la nueva atribución
print("\n→ Recalculando totales mensuales (leads_lake acumulado del mes)...")
final_leads_data = []
for campaign in campaigns:
cid = campaign["google_campaign_id"]
leads, lead_ids = at.get_leads_this_month_gads(cid, campaign["curso"])
at.update_gacampaignmes_leads_lake(campaign["airtable_id"], lead_ids)
final_leads_data.append({
"airtable_id": campaign["airtable_id"],
"conv_leads_lake_mes": leads,
"conv_leads_lake_mes_grupo": leads,
})
if leads > 0:
print(f" {campaign['curso'][:45]}: {leads} leads")
at.batch_update_gacampaignmes_final_leads(final_leads_data)
print(" ✓ ConvLeadsLakeMesFinal actualizado.")
if __name__ == "__main__":
run()