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>
This commit is contained in:
parent
4d03ddf271
commit
858755a6b8
@ -336,7 +336,7 @@ class AirtableClient:
|
|||||||
for i in range(0, len(cat_batch), 10):
|
for i in range(0, len(cat_batch), 10):
|
||||||
self.campaigns.batch_update(cat_batch[i:i+10])
|
self.campaigns.batch_update(cat_batch[i:i+10])
|
||||||
|
|
||||||
def get_leads_this_month_gads(self, campaign_id: str, campaign_name: str = "") -> tuple[int, list[str]]:
|
def get_leads_this_month_gads(self, campaign_id: str, campaign_name: str = "", ambiguous_cursoids: set = None) -> tuple[int, list[str]]:
|
||||||
"""
|
"""
|
||||||
Leads del mes actual para una campaña de Google Ads.
|
Leads del mes actual para una campaña de Google Ads.
|
||||||
Cubre cinco vías de atribución:
|
Cubre cinco vías de atribución:
|
||||||
@ -362,7 +362,9 @@ class AirtableClient:
|
|||||||
is_pmx_non_leadform = (
|
is_pmx_non_leadform = (
|
||||||
"pmx" in campaign_name.lower() and "_leadform" not in campaign_name.lower()
|
"pmx" in campaign_name.lower() and "_leadform" not in campaign_name.lower()
|
||||||
)
|
)
|
||||||
if is_pmx_non_leadform:
|
# Paths 4 y 5 se desactivan para PMX cuando hay múltiples PMX del mismo curso
|
||||||
|
is_ambiguous_pmx = is_pmx_non_leadform and bool(ambiguous_cursoids and course_num in ambiguous_cursoids)
|
||||||
|
if is_pmx_non_leadform and not is_ambiguous_pmx:
|
||||||
utm_source = "pmx"
|
utm_source = "pmx"
|
||||||
elif "search" in campaign_name.lower():
|
elif "search" in campaign_name.lower():
|
||||||
utm_source = "google"
|
utm_source = "google"
|
||||||
@ -373,8 +375,8 @@ class AirtableClient:
|
|||||||
f"AND({{attr_cursoid}}='{course_num}',"
|
f"AND({{attr_cursoid}}='{course_num}',"
|
||||||
f"{{attr_utm_source}}='{utm_source}')"
|
f"{{attr_utm_source}}='{utm_source}')"
|
||||||
)
|
)
|
||||||
# Path 5: leadform leads en Airtable, solo para PMX (no search, no _leadform)
|
# Path 5: leadform leads en Airtable, solo para PMX único (no search, no _leadform, no ambiguo)
|
||||||
if is_pmx_non_leadform:
|
if is_pmx_non_leadform and not is_ambiguous_pmx:
|
||||||
leadform_cursoid_clause = (
|
leadform_cursoid_clause = (
|
||||||
f"AND({{attr_cursoid}}='{course_num}',"
|
f"AND({{attr_cursoid}}='{course_num}',"
|
||||||
f"{{UserAgent del visitante}}='Google-Ads-Notifications')"
|
f"{{UserAgent del visitante}}='Google-Ads-Notifications')"
|
||||||
|
|||||||
@ -74,12 +74,22 @@ def run():
|
|||||||
else:
|
else:
|
||||||
print(" ✓ MetricasDiarias sin cambios.")
|
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
|
# Recalcular totales mensuales con la nueva atribución
|
||||||
print("\n→ Recalculando totales mensuales (leads_lake acumulado del mes)...")
|
print("\n→ Recalculando totales mensuales (leads_lake acumulado del mes)...")
|
||||||
final_leads_data = []
|
final_leads_data = []
|
||||||
for campaign in campaigns:
|
for campaign in campaigns:
|
||||||
cid = campaign["google_campaign_id"]
|
cid = campaign["google_campaign_id"]
|
||||||
leads, lead_ids = at.get_leads_this_month_gads(cid, campaign["curso"])
|
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)
|
at.update_gacampaignmes_leads_lake(campaign["airtable_id"], lead_ids)
|
||||||
final_leads_data.append({
|
final_leads_data.append({
|
||||||
"airtable_id": campaign["airtable_id"],
|
"airtable_id": campaign["airtable_id"],
|
||||||
|
|||||||
12
run.py
12
run.py
@ -155,6 +155,16 @@ def run():
|
|||||||
if "_leadform" in c["curso"].lower() and _course_num(c["curso"])
|
if "_leadform" in c["curso"].lower() and _course_num(c["curso"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Cursoids con múltiples campañas PMX activas → paths 4/5 ambiguos, desactivar para evitar doble conteo
|
||||||
|
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}")
|
||||||
|
|
||||||
# Precomputar conversiones Google de cada campaña leadform por número de curso
|
# Precomputar conversiones Google de cada campaña leadform por número de curso
|
||||||
leadform_conv_by_course: dict[str, int] = {}
|
leadform_conv_by_course: dict[str, int] = {}
|
||||||
for c in campaigns:
|
for c in campaigns:
|
||||||
@ -183,7 +193,7 @@ def run():
|
|||||||
for campaign in campaigns:
|
for campaign in campaigns:
|
||||||
cid = campaign["google_campaign_id"]
|
cid = campaign["google_campaign_id"]
|
||||||
|
|
||||||
leads, lead_ids = at.get_leads_this_month_gads(cid, campaign["curso"])
|
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)
|
at.update_gacampaignmes_leads_lake(campaign["airtable_id"], lead_ids)
|
||||||
|
|
||||||
metrics = monthly_metrics.get(cid)
|
metrics = monthly_metrics.get(cid)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user