diff --git a/airtable_client.py b/airtable_client.py index dbdac3a..b0c164d 100644 --- a/airtable_client.py +++ b/airtable_client.py @@ -27,7 +27,7 @@ class AirtableClient: }) 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. - 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_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: - 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}) else: changes = {} @@ -71,9 +79,15 @@ class AirtableClient: "antes": at_record["fields"].get("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: 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 for i in range(0, len(to_create), 10): diff --git a/google_ads_client.py b/google_ads_client.py index 290c92e..b479b6f 100644 --- a/google_ads_client.py +++ b/google_ads_client.py @@ -41,6 +41,34 @@ class GoogleAdsClient: print(f" ❌ Error obteniendo campañas de Google Ads: {e}") 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: """Métricas del mes en curso para una campaña concreta.""" ga_service = self.client.get_service("GoogleAdsService") diff --git a/run.py b/run.py index 278dfb1..11793e7 100644 --- a/run.py +++ b/run.py @@ -53,7 +53,8 @@ def run(): # Sincronizar catálogo de campañas desde Google Ads → Airtable print("→ Sincronizando campañas desde Google Ads...") 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"]: print(f" ✅ Campañas nuevas importadas ({len(sync_result['created'])}):") for c in sync_result["created"]: