Sync ConvMes and CosteMes to Airtable on each run
- Add get_monthly_metrics_all() in GoogleAdsClient: fetches conversions and cost for all campaigns in one query - sync_campaigns_from_google_ads() now accepts monthly_metrics and updates ConvMes and CosteMes fields in Airtable - run.py fetches monthly metrics before sync and passes them Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e4362c6ad9
commit
952fabe4ca
@ -27,7 +27,7 @@ class AirtableClient:
|
|||||||
})
|
})
|
||||||
return [c for c in result if c["google_campaign_id"]] # descartar sin ID
|
return [c for c in result if c["google_campaign_id"]] # descartar sin ID
|
||||||
|
|
||||||
def sync_campaigns_from_google_ads(self, google_campaigns: list[dict]) -> dict:
|
def sync_campaigns_from_google_ads(self, google_campaigns: list[dict], monthly_metrics: dict = None) -> dict:
|
||||||
"""
|
"""
|
||||||
Sincroniza campañas de Google Ads → Airtable.
|
Sincroniza campañas de Google Ads → Airtable.
|
||||||
- Crea las campañas nuevas con el status real de Google Ads.
|
- Crea las campañas nuevas con el status real de Google Ads.
|
||||||
@ -53,8 +53,16 @@ class AirtableClient:
|
|||||||
at_status = STATUS_MAP.get(gc["status"], "Pausada")
|
at_status = STATUS_MAP.get(gc["status"], "Pausada")
|
||||||
at_record = at_by_gid.get(gid)
|
at_record = at_by_gid.get(gid)
|
||||||
|
|
||||||
|
metrics = (monthly_metrics or {}).get(gid, {})
|
||||||
|
conv = round(metrics.get("conversions", 0), 2)
|
||||||
|
cost = round(metrics.get("cost", 0), 2)
|
||||||
|
|
||||||
if at_record is None:
|
if at_record is None:
|
||||||
to_create.append({"Campaign Name": gc["name"], "CampaignID": gid, "Status": at_status})
|
fields = {"Campaign Name": gc["name"], "CampaignID": gid, "Status": at_status}
|
||||||
|
if monthly_metrics is not None:
|
||||||
|
fields["ConvMes"] = conv
|
||||||
|
fields["CosteMes"] = cost
|
||||||
|
to_create.append(fields)
|
||||||
created.append({"name": gc["name"], "id": gid, "status": at_status})
|
created.append({"name": gc["name"], "id": gid, "status": at_status})
|
||||||
else:
|
else:
|
||||||
changes = {}
|
changes = {}
|
||||||
@ -71,9 +79,15 @@ class AirtableClient:
|
|||||||
"antes": at_record["fields"].get("Status"),
|
"antes": at_record["fields"].get("Status"),
|
||||||
"ahora": at_status,
|
"ahora": at_status,
|
||||||
}
|
}
|
||||||
|
if monthly_metrics is not None:
|
||||||
|
if at_record["fields"].get("ConvMes") != conv:
|
||||||
|
changes["ConvMes"] = conv
|
||||||
|
if at_record["fields"].get("CosteMes") != cost:
|
||||||
|
changes["CosteMes"] = cost
|
||||||
if changes:
|
if changes:
|
||||||
to_update.append((at_record["id"], changes, gc["name"]))
|
to_update.append((at_record["id"], changes, gc["name"]))
|
||||||
updated.append({"name": gc["name"], "id": gid, "changes": change_detail})
|
if change_detail:
|
||||||
|
updated.append({"name": gc["name"], "id": gid, "changes": change_detail})
|
||||||
|
|
||||||
# Crear en lotes de 10
|
# Crear en lotes de 10
|
||||||
for i in range(0, len(to_create), 10):
|
for i in range(0, len(to_create), 10):
|
||||||
|
|||||||
@ -41,6 +41,34 @@ class GoogleAdsClient:
|
|||||||
print(f" ❌ Error obteniendo campañas de Google Ads: {e}")
|
print(f" ❌ Error obteniendo campañas de Google Ads: {e}")
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def get_monthly_metrics_all(self) -> dict:
|
||||||
|
"""
|
||||||
|
Devuelve métricas del mes actual para TODAS las campañas en una sola query.
|
||||||
|
Retorna dict {campaign_id: {conversions, cost}}.
|
||||||
|
"""
|
||||||
|
ga_service = self.client.get_service("GoogleAdsService")
|
||||||
|
query = """
|
||||||
|
SELECT
|
||||||
|
campaign.id,
|
||||||
|
metrics.conversions,
|
||||||
|
metrics.cost_micros
|
||||||
|
FROM campaign
|
||||||
|
WHERE campaign.status != 'REMOVED'
|
||||||
|
AND segments.date DURING THIS_MONTH
|
||||||
|
"""
|
||||||
|
result = {}
|
||||||
|
try:
|
||||||
|
response = ga_service.search(customer_id=self.customer_id, query=query)
|
||||||
|
for row in response:
|
||||||
|
cid = str(row.campaign.id)
|
||||||
|
result[cid] = {
|
||||||
|
"conversions": row.metrics.conversions,
|
||||||
|
"cost": row.metrics.cost_micros / 1_000_000,
|
||||||
|
}
|
||||||
|
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."""
|
"""Métricas del mes en curso para una campaña concreta."""
|
||||||
ga_service = self.client.get_service("GoogleAdsService")
|
ga_service = self.client.get_service("GoogleAdsService")
|
||||||
|
|||||||
3
run.py
3
run.py
@ -53,7 +53,8 @@ def run():
|
|||||||
# Sincronizar catálogo de campañas desde Google Ads → Airtable
|
# Sincronizar catálogo de campañas desde Google Ads → Airtable
|
||||||
print("→ Sincronizando campañas desde Google Ads...")
|
print("→ Sincronizando campañas desde Google Ads...")
|
||||||
google_campaigns = gads.get_all_campaigns()
|
google_campaigns = gads.get_all_campaigns()
|
||||||
sync_result = at.sync_campaigns_from_google_ads(google_campaigns)
|
monthly_metrics = gads.get_monthly_metrics_all()
|
||||||
|
sync_result = at.sync_campaigns_from_google_ads(google_campaigns, monthly_metrics)
|
||||||
if sync_result["created"]:
|
if sync_result["created"]:
|
||||||
print(f" ✅ Campañas nuevas importadas ({len(sync_result['created'])}):")
|
print(f" ✅ Campañas nuevas importadas ({len(sync_result['created'])}):")
|
||||||
for c in sync_result["created"]:
|
for c in sync_result["created"]:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user