leads-optimizer/backfill_leadform_jun8_10.py
José Manuel Gómez 858755a6b8 Disable ambiguous attribution paths for cursoids with multiple PMX campaigns
When multiple PMX campaigns share the same cursoid (e.g. PMX + Reset),
paths 4 (cursoid+utm_source) and 5 (cursoid+UserAgent) are disabled for
all of them to prevent double-counting Airtable leads. Only direct paths
(GACampaignID, GoogleCampaignID, attr_referer) are used in those cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-13 09:41:52 +02:00

108 lines
4.2 KiB
Python
Raw Permalink 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", "2026-06-11"]
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.")
# Cursoids con múltiples campañas PMX activas (mismo criterio que run.py)
pmx_count_by_cursoid: dict[str, int] = {}
for c in campaigns:
num = _course_num(c["curso"])
if num and "pmx" in c["curso"].lower() and "_leadform" not in c["curso"].lower():
pmx_count_by_cursoid[num] = pmx_count_by_cursoid.get(num, 0) + 1
ambiguous_pmx_cursoids = {num for num, cnt in pmx_count_by_cursoid.items() if cnt > 1}
if ambiguous_pmx_cursoids:
print(f" ⚠️ Cursoids con múltiples PMX (paths 4/5 desactivados): {ambiguous_pmx_cursoids}")
# 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"], ambiguous_pmx_cursoids)
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()