Add PMX attribution detection and ConvLeadsLakeMesGrupo field
- Detect Search+PMX companion campaigns by course number - Add PMX attribution warning to Log field for Search campaigns with active PMX - Add ConvLeadsLakeMesGrupo: for PMX with Search companion uses Search leads count Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a1aef8f58e
commit
9edd74b9ad
@ -360,12 +360,18 @@ class AirtableClient:
|
||||
|
||||
def batch_update_gacampaignmes_final_leads(self, gcm_records: list[dict]) -> None:
|
||||
"""
|
||||
Copia ConvLeadsLakeMes → ConvLeadsLakeMesFinal en GACampaignMes.
|
||||
Se llama una vez por ejecución diaria.
|
||||
gcm_records: lista de dicts con 'airtable_id' y 'conv_leads_lake_mes'
|
||||
Actualiza ConvLeadsLakeMesFinal y ConvLeadsLakeMesGrupo en GACampaignMes.
|
||||
gcm_records: lista de dicts con:
|
||||
- 'airtable_id'
|
||||
- 'conv_leads_lake_mes' → valor para ConvLeadsLakeMesFinal
|
||||
- 'conv_leads_lake_mes_grupo' → valor para ConvLeadsLakeMesGrupo
|
||||
(igual al anterior salvo en PMX con Search companion: usa leads del Search)
|
||||
"""
|
||||
batch = [
|
||||
{"id": r["airtable_id"], "fields": {"ConvLeadsLakeMesFinal": r["conv_leads_lake_mes"]}}
|
||||
{"id": r["airtable_id"], "fields": {
|
||||
"ConvLeadsLakeMesFinal": r["conv_leads_lake_mes"],
|
||||
"ConvLeadsLakeMesGrupo": r["conv_leads_lake_mes_grupo"],
|
||||
}}
|
||||
for r in gcm_records
|
||||
]
|
||||
for i in range(0, len(batch), 10):
|
||||
|
||||
48
run.py
48
run.py
@ -1,6 +1,7 @@
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import re
|
||||
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8", line_buffering=True)
|
||||
|
||||
from airtable_client import AirtableClient
|
||||
@ -173,6 +174,23 @@ def run():
|
||||
# Ordenar: 0=críticas → 1=no críticas → 2=mantener
|
||||
collected.sort(key=_priority)
|
||||
|
||||
# Detectar cursos con campaña Search Y PMX simultáneas (posible reatribución PMX)
|
||||
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
|
||||
|
||||
course_types: dict[str, set] = {}
|
||||
for item in collected:
|
||||
name = item["campaign"]["curso"]
|
||||
num = _course_num(name)
|
||||
if num:
|
||||
course_types.setdefault(num, set())
|
||||
if "pmx" in name.lower():
|
||||
course_types[num].add("pmx")
|
||||
elif "search" in name.lower():
|
||||
course_types[num].add("search")
|
||||
courses_with_both = {num for num, types in course_types.items() if "pmx" in types and "search" in types}
|
||||
|
||||
# === SEGUNDA PASADA: imprimir en orden + aplicar decisiones ===
|
||||
resumen = []
|
||||
advice_updates = [] # (gcm_record_id, consejo, criticidad) para batch update final
|
||||
@ -235,6 +253,11 @@ def run():
|
||||
else:
|
||||
log_text = f"OK: {leads} leads Airtable | {conv_google} conv Google Ads"
|
||||
|
||||
# Nota de reatribución PMX para campañas Search con companion PMX del mismo curso
|
||||
course_num = _course_num(campaign["curso"])
|
||||
if "search" in campaign["curso"].lower() and course_num in courses_with_both:
|
||||
log_text += " | ⚠️ PMX ATTRIBUTION: campaña Search con companion PMX activo — parte de las conversiones de Google pueden estar reatribuidas a la campaña PMX"
|
||||
|
||||
advice_updates.append((
|
||||
campaign["airtable_id"],
|
||||
decision.get("consejo", ""),
|
||||
@ -262,12 +285,27 @@ def run():
|
||||
at.batch_update_gacampaignmes_advice(advice_updates)
|
||||
print(" ✓ Consejos y criticidad guardados.")
|
||||
|
||||
# Copiar ConvLeadsLakeMes → ConvLeadsLakeMesFinal (snapshot diario)
|
||||
final_leads_data = [
|
||||
{"airtable_id": item["campaign"]["airtable_id"],
|
||||
"conv_leads_lake_mes": item["leads"]}
|
||||
# Snapshot diario: ConvLeadsLakeMesFinal + ConvLeadsLakeMesGrupo
|
||||
# Para PMX con Search companion del mismo curso, Grupo = leads del Search
|
||||
course_search_leads = {
|
||||
_course_num(item["campaign"]["curso"]): item["leads"]
|
||||
for item in collected
|
||||
]
|
||||
if "search" in item["campaign"]["curso"].lower()
|
||||
and _course_num(item["campaign"]["curso"])
|
||||
}
|
||||
final_leads_data = []
|
||||
for item in collected:
|
||||
name = item["campaign"]["curso"]
|
||||
num = _course_num(name)
|
||||
if num and "pmx" in name.lower() and num in courses_with_both:
|
||||
grupo = course_search_leads.get(num, item["leads"])
|
||||
else:
|
||||
grupo = item["leads"]
|
||||
final_leads_data.append({
|
||||
"airtable_id": item["campaign"]["airtable_id"],
|
||||
"conv_leads_lake_mes": item["leads"],
|
||||
"conv_leads_lake_mes_grupo": grupo,
|
||||
})
|
||||
if final_leads_data:
|
||||
print(f"→ Actualizando ConvLeadsLakeMesFinal ({len(final_leads_data)} registros)...")
|
||||
at.batch_update_gacampaignmes_final_leads(final_leads_data)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user