Fix tracking discrepancy direction, improve daily metrics table, increase max_tokens
Some checks failed
Weekly Strategic Report / run (push) Has been cancelled
Some checks failed
Weekly Strategic Report / run (push) Has been cancelled
- analyzer.py: use abs() for tracking discrepancy so both directions alert - slack_reporter.py: daily table adds L.AT/L.GA/Coste/€.AT/€.GA columns; margin uses Google Ads conversions × PPL; split monthly rankings into separate blocks; fix stale margen field - run.py: leads_grupo always uses Google Ads conversions; tracking alert shows direction (over/under attribution) - agent.py: increase decide() max_tokens 700→750 to fix JSON truncation for long campaign names Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
a024508062
commit
d23cb6b9c2
2
agent.py
2
agent.py
@ -228,7 +228,7 @@ def weekly_strategic_analysis(games_md_this: dict, games_md_prev_week: dict,
|
||||
def decide(analysis: dict) -> dict:
|
||||
response = client.messages.create(
|
||||
model="claude-sonnet-4-6",
|
||||
max_tokens=700,
|
||||
max_tokens=750,
|
||||
system=SYSTEM_PROMPT,
|
||||
messages=[{
|
||||
"role": "user",
|
||||
|
||||
@ -35,7 +35,7 @@ def analyze(campaign_config: dict, leads_entregados: int, ads_metrics: dict) ->
|
||||
else:
|
||||
urgencia = "EN_RITMO"
|
||||
|
||||
# Discrepancia entre leads Airtable (ConvLeadsLakeMes) y conversiones Google
|
||||
# Discrepancia en ambas direcciones: Google > Airtable puede indicar conversiones falsas
|
||||
conv_leads_lake_mes = campaign_config.get("conv_leads_lake_mes", leads_entregados)
|
||||
discrepancia = abs(conversiones_google - conv_leads_lake_mes)
|
||||
|
||||
|
||||
11
run.py
11
run.py
@ -220,10 +220,8 @@ def run():
|
||||
|
||||
if is_pmx_with_leadform:
|
||||
leads_grupo = int(metrics.get("conversions", 0)) + leadform_conv_by_course.get(course_num, 0)
|
||||
elif is_pmx_with_companion:
|
||||
leads_grupo = int(metrics.get("conversions", 0))
|
||||
else:
|
||||
leads_grupo = leads
|
||||
leads_grupo = int(metrics.get("conversions", 0))
|
||||
|
||||
analysis = analyze(campaign, leads_grupo, metrics)
|
||||
decision = decide(analysis)
|
||||
@ -296,8 +294,11 @@ def run():
|
||||
f"Rentable: {'✅' if analysis['rentable'] else '❌'}")
|
||||
|
||||
if analysis["alerta_tracking"]:
|
||||
print(f" 🚨 ALERTA TRACKING: {analysis['discrepancia_tracking']} leads de diferencia "
|
||||
f"entre Airtable ({campaign['conv_leads_lake_mes']}) y Google Ads ({int(analysis['conversiones_google'])})")
|
||||
at_leads = campaign['conv_leads_lake_mes']
|
||||
ga_leads = int(analysis['conversiones_google'])
|
||||
direction = "Airtable > Google (sobre-atribución?)" if at_leads > ga_leads else "Google > Airtable (conversiones falsas?)"
|
||||
print(f" 🚨 ALERTA TRACKING: {analysis['discrepancia_tracking']:.0f} leads de diferencia "
|
||||
f"— Airtable {at_leads} vs Google Ads {ga_leads} — {direction}")
|
||||
|
||||
print(f" Decisión: {accion_icono} {decision['accion']} "
|
||||
f"(confianza: {decision['confianza']*100:.0f}%)")
|
||||
|
||||
@ -185,35 +185,56 @@ def build_and_send(collected: list, dry_run: bool, prev_month_metricas: dict = N
|
||||
except ValueError:
|
||||
continue
|
||||
if d not in daily_totals:
|
||||
daily_totals[d] = {"coste": 0.0, "ingreso_sum": 0.0}
|
||||
daily_totals[d]["coste"] += vals.get("coste", 0)
|
||||
daily_totals[d]["ingreso_sum"] += vals.get("ingreso", 0)
|
||||
daily_totals[d] = {"coste": 0.0, "ing_gads": 0.0, "ing_at": 0.0, "leads_gads": 0, "leads_at": 0}
|
||||
daily_totals[d]["coste"] += vals.get("coste", 0)
|
||||
daily_totals[d]["ing_gads"] += vals.get("ingreso", 0) # conv_hoy × PPL
|
||||
daily_totals[d]["ing_at"] += vals.get("leads_lake", 0) * ppl # leads_lake × PPL
|
||||
daily_totals[d]["leads_gads"] += int(vals.get("leads", 0))
|
||||
daily_totals[d]["leads_at"] += int(vals.get("leads_lake", 0))
|
||||
|
||||
def _eur(v: float) -> str:
|
||||
return f"{v:,.0f}€".replace(",", ".")
|
||||
|
||||
def _marg(v: float) -> str:
|
||||
return ("+" if v >= 0 else "") + f"{v:,.0f}€".replace(",", ".")
|
||||
|
||||
def _pct(v: float) -> str:
|
||||
return ("+" if v >= 0 else "") + f"{v:.1f}%"
|
||||
|
||||
margin_table_block = None
|
||||
if daily_totals and not primer_dia_mes:
|
||||
rows = ["Día Margen € %"]
|
||||
total_coste = total_ing = 0.0
|
||||
hdr = f"{'Día':>3} {'L.AT':>5} {'L.GA':>5} {'Coste':>7} {'€.AT':>7} {'€.GA':>7} {'Margen':>9} {'%':>7}"
|
||||
sep = "─" * len(hdr)
|
||||
rows = [hdr, sep]
|
||||
tot = {"coste": 0.0, "ing_gads": 0.0, "ing_at": 0.0, "leads_gads": 0, "leads_at": 0}
|
||||
for d in sorted(daily_totals):
|
||||
coste = daily_totals[d]["coste"]
|
||||
ing_sum = daily_totals[d]["ingreso_sum"]
|
||||
margen = ing_sum - coste
|
||||
pct = round(margen / ing_sum * 100, 1) if ing_sum > 0 else 0.0
|
||||
total_coste += coste
|
||||
total_ing += ing_sum
|
||||
s_eur = ("+" if margen >= 0 else "") + f"{margen:,.0f}€".replace(",", ".")
|
||||
s_pct = ("+" if pct >= 0 else "") + f"{pct:.1f}%"
|
||||
rows.append(f"{d:02d} {s_eur:>9} {s_pct:>7}")
|
||||
total_margen = total_ing - total_coste
|
||||
total_pct = round(total_margen / total_ing * 100, 1) if total_ing > 0 else 0.0
|
||||
s_tot_eur = ("+" if total_margen >= 0 else "") + f"{total_margen:,.0f}€".replace(",", ".")
|
||||
s_tot_pct = ("+" if total_pct >= 0 else "") + f"{total_pct:.1f}%"
|
||||
rows.append("─" * 24)
|
||||
rows.append(f"TOT {s_tot_eur:>9} {s_tot_pct:>7}")
|
||||
v = daily_totals[d]
|
||||
ing = v["ing_gads"] # margen: conv Google Ads × PPL
|
||||
marg = ing - v["coste"]
|
||||
pct_v = round(marg / ing * 100, 1) if ing > 0 else 0.0
|
||||
for k in tot:
|
||||
tot[k] += v[k]
|
||||
rows.append(
|
||||
f"{d:02d} {v['leads_at']:>5} {v['leads_gads']:>5}"
|
||||
f" {_eur(v['coste']):>7}"
|
||||
f" {_eur(v['ing_at']):>7} {_eur(v['ing_gads']):>7}"
|
||||
f" {_marg(marg):>9} {_pct(pct_v):>7}"
|
||||
)
|
||||
tot_ing = tot["ing_gads"]
|
||||
tot_marg = tot_ing - tot["coste"]
|
||||
tot_pct = round(tot_marg / tot_ing * 100, 1) if tot_ing > 0 else 0.0
|
||||
rows.append(sep)
|
||||
rows.append(
|
||||
f"{'TOT':>3} {tot['leads_at']:>5} {tot['leads_gads']:>5}"
|
||||
f" {_eur(tot['coste']):>7}"
|
||||
f" {_eur(tot['ing_at']):>7} {_eur(tot['ing_gads']):>7}"
|
||||
f" {_marg(tot_marg):>9} {_pct(tot_pct):>7}"
|
||||
)
|
||||
margin_table_block = {
|
||||
"type": "section",
|
||||
"text": {
|
||||
"type": "mrkdwn",
|
||||
"text": _trunc(f"📅 *MÁRGENES POR DÍA — {MESES_ES[now.month].upper()}*\n```\n" + "\n".join(rows) + "\n```"),
|
||||
"text": _trunc(f"📅 *MÉTRICAS POR DÍA — {MESES_ES[now.month].upper()}* _(L.AT=leads Airtable · L.GA=conv Google Ads · €.AT=fact×PPL Airtable · €.GA=fact×PPL Google Ads)_\n```\n" + "\n".join(rows) + "\n```"),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user