Backfill Google Ads daily leads for May in MetricasDiarias
- Add get_daily_conversions_for_month() to GoogleAdsClient - Add backfill_leads_google_mayo.py: populates 'leads' (Google conv) for all May days - 147 day-entries updated across 49 GACampaignMes records Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f65f793c95
commit
523e04d61f
62
backfill_leads_google_mayo.py
Normal file
62
backfill_leads_google_mayo.py
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
"""
|
||||||
|
Script one-off: rellena el campo 'leads' (conversiones Google Ads) en MetricasDiarias
|
||||||
|
para cada dia de mayo ya registrado en GACampaignMes.
|
||||||
|
|
||||||
|
Ejecutar una sola vez:
|
||||||
|
python backfill_leads_google_mayo.py
|
||||||
|
"""
|
||||||
|
import json
|
||||||
|
from airtable_client import AirtableClient
|
||||||
|
from google_ads_client import GoogleAdsClient
|
||||||
|
at = AirtableClient()
|
||||||
|
gads = GoogleAdsClient()
|
||||||
|
|
||||||
|
print("Obteniendo conversiones diarias de Google Ads para mayo 2026...")
|
||||||
|
daily_conv = gads.get_daily_conversions_for_month(2026, 5)
|
||||||
|
print(f" > {len(daily_conv)} dias con datos en Google Ads")
|
||||||
|
|
||||||
|
print("Cargando registros GACampaignMes de mayo...")
|
||||||
|
records = at.gacampaignmes.all(
|
||||||
|
formula="AND({Mes}='5',{Año}='2026')",
|
||||||
|
fields=["CampaignID", "MetricasDiarias", "Campaign Name (from CampaignID)"],
|
||||||
|
)
|
||||||
|
|
||||||
|
campaigns_records = at.campaigns.all(fields=["CampaignID"])
|
||||||
|
at_id_to_gid = {r["id"]: str(r["fields"].get("CampaignID", "")).strip() for r in campaigns_records}
|
||||||
|
|
||||||
|
gid_to_gcm: dict[str, tuple[str, dict]] = {}
|
||||||
|
for r in records:
|
||||||
|
at_cids = r["fields"].get("CampaignID", [])
|
||||||
|
if not at_cids:
|
||||||
|
continue
|
||||||
|
gid = at_id_to_gid.get(at_cids[0], "")
|
||||||
|
if not gid:
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
md = json.loads(r["fields"].get("MetricasDiarias") or "{}")
|
||||||
|
except (json.JSONDecodeError, TypeError):
|
||||||
|
md = {}
|
||||||
|
gid_to_gcm[gid] = (r["id"], md)
|
||||||
|
|
||||||
|
total_updated = 0
|
||||||
|
for date_str, conv_by_cid in sorted(daily_conv.items()):
|
||||||
|
day_str = date_str[8:10] # "YYYY-MM-DD" -> "DD"
|
||||||
|
for gid, (gcm_id, md) in gid_to_gcm.items():
|
||||||
|
if day_str in md and "leads" not in md[day_str]:
|
||||||
|
md[day_str]["leads"] = int(conv_by_cid.get(gid, 0))
|
||||||
|
total_updated += 1
|
||||||
|
|
||||||
|
print(f"Entradas actualizadas en memoria: {total_updated}")
|
||||||
|
|
||||||
|
batch = [
|
||||||
|
{"id": gcm_id, "fields": {"MetricasDiarias": json.dumps(md, ensure_ascii=False)}}
|
||||||
|
for _, (gcm_id, md) in gid_to_gcm.items()
|
||||||
|
if any("leads" in v for v in md.values())
|
||||||
|
]
|
||||||
|
|
||||||
|
print(f"Guardando {len(batch)} registros en Airtable...")
|
||||||
|
for i in range(0, len(batch), 10):
|
||||||
|
at.gacampaignmes.batch_update(batch[i:i+10])
|
||||||
|
print(f" > {min(i+10, len(batch))}/{len(batch)} guardados")
|
||||||
|
|
||||||
|
print(f"OK Backfill completado: {len(batch)} registros, {total_updated} entradas de dia actualizadas.")
|
||||||
@ -100,6 +100,39 @@ class GoogleAdsClient:
|
|||||||
print(f" ❌ Error obteniendo métricas de hoy: {e}")
|
print(f" ❌ Error obteniendo métricas de hoy: {e}")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def get_daily_conversions_for_month(self, year: int, month: int) -> dict:
|
||||||
|
"""
|
||||||
|
Devuelve conversiones diarias de todas las campañas para un mes completo.
|
||||||
|
Retorna dict {date_str ('YYYY-MM-DD'): {campaign_id: conversions}}.
|
||||||
|
"""
|
||||||
|
start = f"{year}-{month:02d}-01"
|
||||||
|
# último día del mes
|
||||||
|
if month == 12:
|
||||||
|
end = f"{year + 1}-01-01"
|
||||||
|
else:
|
||||||
|
end = f"{year}-{month + 1:02d}-01"
|
||||||
|
ga_service = self.client.get_service("GoogleAdsService")
|
||||||
|
query = f"""
|
||||||
|
SELECT
|
||||||
|
campaign.id,
|
||||||
|
segments.date,
|
||||||
|
metrics.conversions
|
||||||
|
FROM campaign
|
||||||
|
WHERE campaign.status != 'REMOVED'
|
||||||
|
AND segments.date >= '{start}'
|
||||||
|
AND segments.date < '{end}'
|
||||||
|
"""
|
||||||
|
result: dict = {}
|
||||||
|
try:
|
||||||
|
response = ga_service.search(customer_id=self.customer_id, query=query)
|
||||||
|
for row in response:
|
||||||
|
date_str = row.segments.date
|
||||||
|
cid = str(row.campaign.id)
|
||||||
|
result.setdefault(date_str, {})[cid] = row.metrics.conversions
|
||||||
|
except GoogleAdsException as e:
|
||||||
|
print(f" ❌ Error obteniendo métricas mensuales: {e}")
|
||||||
|
return result
|
||||||
|
|
||||||
def get_campaign_metrics(self, campaign_id: str) -> dict:
|
def get_campaign_metrics(self, campaign_id: str) -> dict:
|
||||||
"""Métricas del mes en curso para una campaña concreta (acumulado mensual)."""
|
"""Métricas del mes en curso para una campaña concreta (acumulado mensual)."""
|
||||||
ga_service = self.client.get_service("GoogleAdsService")
|
ga_service = self.client.get_service("GoogleAdsService")
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user