Sync Google Ads campaigns to Airtable before analysis
Before each run, fetch all non-removed campaigns from Google Ads and upsert them into the Airtable campaigns table: new campaigns are created (Activa=False, pending manual PPL/Cap/CPA setup) and existing ones get their name updated if it changed. https://claude.ai/code/session_01WEcdWPxGWZKk8FGwBRLGR2
This commit is contained in:
parent
f0d7f65c1a
commit
d68f9f5659
@ -25,6 +25,44 @@ 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:
|
||||||
|
"""
|
||||||
|
Sincroniza campañas de Google Ads → Airtable.
|
||||||
|
- Crea las campañas nuevas (Activa=False, requiere configuración manual de PPL/Cap/CPA).
|
||||||
|
- Actualiza el nombre si ha cambiado.
|
||||||
|
Devuelve un resumen con listas de campañas creadas y actualizadas.
|
||||||
|
"""
|
||||||
|
all_records = self.campaigns.all()
|
||||||
|
at_by_gid = {
|
||||||
|
str(r["fields"].get("CampaignID", "")).strip(): r
|
||||||
|
for r in all_records
|
||||||
|
if r["fields"].get("CampaignID")
|
||||||
|
}
|
||||||
|
|
||||||
|
created = []
|
||||||
|
updated = []
|
||||||
|
|
||||||
|
for gc in google_campaigns:
|
||||||
|
gid = gc["id"]
|
||||||
|
at_record = at_by_gid.get(gid)
|
||||||
|
|
||||||
|
if at_record is None:
|
||||||
|
self.campaigns.create({
|
||||||
|
"Campaign Name": gc["name"],
|
||||||
|
"CampaignID": int(gid),
|
||||||
|
"Activa": False,
|
||||||
|
})
|
||||||
|
created.append(gc["name"])
|
||||||
|
else:
|
||||||
|
changes = {}
|
||||||
|
if at_record["fields"].get("Campaign Name") != gc["name"]:
|
||||||
|
changes["Campaign Name"] = gc["name"]
|
||||||
|
if changes:
|
||||||
|
self.campaigns.update(at_record["id"], changes)
|
||||||
|
updated.append(gc["name"])
|
||||||
|
|
||||||
|
return {"created": created, "updated": updated}
|
||||||
|
|
||||||
def get_leads_this_month(self, google_campaign_id: str) -> int:
|
def get_leads_this_month(self, google_campaign_id: str) -> int:
|
||||||
"""
|
"""
|
||||||
Cuenta todos los leads del mes actual para una campaña.
|
Cuenta todos los leads del mes actual para una campaña.
|
||||||
|
|||||||
@ -15,6 +15,32 @@ class GoogleAdsClient:
|
|||||||
})
|
})
|
||||||
self.customer_id = config.GOOGLE_ADS_LOGIN_CUSTOMER_ID
|
self.customer_id = config.GOOGLE_ADS_LOGIN_CUSTOMER_ID
|
||||||
|
|
||||||
|
def get_all_campaigns(self) -> list[dict]:
|
||||||
|
"""Obtiene todas las campañas no eliminadas de la cuenta."""
|
||||||
|
ga_service = self.client.get_service("GoogleAdsService")
|
||||||
|
query = """
|
||||||
|
SELECT
|
||||||
|
campaign.id,
|
||||||
|
campaign.name,
|
||||||
|
campaign.status
|
||||||
|
FROM campaign
|
||||||
|
WHERE campaign.status != 'REMOVED'
|
||||||
|
ORDER BY campaign.name
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
response = ga_service.search(customer_id=self.customer_id, query=query)
|
||||||
|
return [
|
||||||
|
{
|
||||||
|
"id": str(row.campaign.id),
|
||||||
|
"name": row.campaign.name,
|
||||||
|
"status": row.campaign.status.name,
|
||||||
|
}
|
||||||
|
for row in response
|
||||||
|
]
|
||||||
|
except GoogleAdsException as e:
|
||||||
|
print(f" ❌ Error obteniendo campañas de Google Ads: {e}")
|
||||||
|
return []
|
||||||
|
|
||||||
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")
|
||||||
|
|||||||
16
run.py
16
run.py
@ -25,6 +25,22 @@ def run():
|
|||||||
at = AirtableClient()
|
at = AirtableClient()
|
||||||
gads = GoogleAdsClient()
|
gads = GoogleAdsClient()
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
if sync_result["created"]:
|
||||||
|
print(f" ✅ Campañas nuevas importadas ({len(sync_result['created'])}):")
|
||||||
|
for name in sync_result["created"]:
|
||||||
|
print(f" + {name}")
|
||||||
|
if sync_result["updated"]:
|
||||||
|
print(f" 🔄 Campañas con nombre actualizado ({len(sync_result['updated'])}):")
|
||||||
|
for name in sync_result["updated"]:
|
||||||
|
print(f" ~ {name}")
|
||||||
|
if not sync_result["created"] and not sync_result["updated"]:
|
||||||
|
print(" ✓ Sin cambios en el catálogo.")
|
||||||
|
print()
|
||||||
|
|
||||||
campaigns = at.get_active_campaigns()
|
campaigns = at.get_active_campaigns()
|
||||||
print(f"→ {len(campaigns)} campañas activas encontradas\n")
|
print(f"→ {len(campaigns)} campañas activas encontradas\n")
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user