API de Google Ads: configuración, autenticación, lectura y escritura
Guía técnica para configurar el acceso programático a Google Ads, desde la arquitectura hasta la primera llamada a la API. Cubre la configuración del MCC, OAuth 2.0, los niveles de acceso del token de desarrollador, la biblioteca de Python google-ads, las consultas de lectura GAQL y el patrón de escritura validate_only.
Actualización (octubre de 2026): Google retiró los tokens de desarrollador el 9 de septiembre de 2026. Los niveles de acceso a la API ahora se asignan por proyecto de Google Cloud y se gestionan en la página de descripción general de Google Ads API en Cloud Console; el encabezado developer-token es opcional y se ignora, y API Center ya no gestiona el registro ni los cambios de acceso. Google indica que el código existente sigue funcionando. Los pasos sobre tokens de desarrollador y API Center que aparecen a continuación describen la configuración publicada en junio de 2026. La configuración actual se explica en nuestro artículo de seguimiento, Acceso a la API de Google Ads en 2026: los proyectos de Cloud sustituyen a los Developer Tokens.
Arquitectura
Se requieren tres entidades distintas antes de poder realizar una llamada a la API:
| Entidad | Propósito | Ejemplo |
|---|---|---|
| Cuenta de administrador (MCC) | Emite el token de desarrollador | login_customer_id |
| Proyecto de Google Cloud | Cliente OAuth 2.0 para autenticación | ID de cliente + secreto |
| Cuenta de Google Ads | Destino de todas las operaciones de la API | customer_id |
No son la misma cuenta. Un MCC puede tener un token de desarrollador sin ser propietario de la cuenta de destino; solo necesita estar vinculado como administrador. El proyecto de Google Cloud puede pertenecer a una identidad de Google distinta de la del MCC. La cuenta de destino es la cuenta del anunciante donde se encuentran las campañas.
Esta separación es importante porque API Center (donde se aprovisionan los tokens de desarrollador) solo está disponible dentro de cuentas de administrador. Una cuenta de Google Ads independiente no puede acceder a API Center, incluso si tiene usuarios con permisos de administrador.
El encabezado de la llamada a la API combina estas tres identidades con un token Bearer de OAuth:
developer-token: <from MCC API Center>
login-customer-id: <MCC numeric ID, no dashes>
customer-id: <target account numeric ID>
Authorization: Bearer <OAuth 2.0 access token>
Requisitos previos
- Una cuenta de administrador de Google Ads con la configuración completa
- La cuenta publicitaria de destino vinculada a la cuenta de administrador y el vínculo aceptado
- Un proyecto de Google Cloud con la API de Google Ads habilitada
- Python 3.9+ con la biblioteca
google-ads(pip install google-ads) - Un navegador para el flujo de consentimiento OAuth que se realiza una sola vez
Paso 1: cuenta de administrador y token de desarrollador
API Center se encuentra en Herramientas y configuración → Configuración → API Center dentro de una cuenta de administrador. Si API Center no aparece, la cuenta o bien no es una cuenta de administrador o su configuración está incompleta.
Desde API Center, solicite un token de desarrollador. Establezca el tipo de cuenta como Anunciante (no Agencia ni Terceros) cuando el token es para sus propias cuentas. El token se emite inmediatamente con nivel de acceso de prueba.
El acceso de prueba permite:
- Operaciones de lectura solo en cuentas de prueba
- Operaciones de escritura solo en cuentas de prueba
- Ninguna operación de lectura ni escritura en cuentas de producción
Las solicitudes a cuentas de producción con acceso de prueba fallan con DEVELOPER_TOKEN_NOT_APPROVED («The developer token is only approved for use with test accounts»). Desde la retirada de septiembre de 2026, las versiones actuales de la API devuelven CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION en su lugar (ACTION_NOT_PERMITTED en v24 y anteriores).
Solicitud de acceso básico
Para acceder a cuentas de producción, solicite acceso básico desde la misma página de API Center. El formulario de solicitud contiene 12 preguntas. Para uso interno en sus propias cuentas, las respuestas relevantes son:
| Pregunta | Respuesta |
|---|---|
| Q4: Relación con un representante de Google | No |
| Q6: Modelo de negocio | Describa su caso de uso (comercio electrónico, captación de clientes potenciales, informes internos) |
| Q8: Quién tendrá acceso | Usuarios internos — solo empleados |
| Q9: Herramienta desarrollada por terceros | No (scripts/agentes propios) |
| Q10: API de seguimiento de conversiones y remarketing | No (a menos que realmente la use) |
| Q11: Tipos de campaña | Search, Performance Max, Shopping (según corresponda) |
| Q12: Capacidades | Creación de campañas, gestión de campañas, generación de informes |
Se requiere un documento de diseño (PDF) para Q7. Debe describir la arquitectura de la API, el flujo de autenticación, la estrategia de limitación de solicitudes, el manejo de errores y el caso de uso exclusivamente interno. Describa los hechos con precisión: el equipo de cumplimiento revisa la coherencia con el caso de uso declarado.
Tiempo de procesamiento a junio de 2026: aproximadamente 3 días hábiles, con una nota sobre un volumen de solicitudes superior al habitual.
Paso 2: OAuth 2.0
Configuración del proyecto en Google Cloud
En la Consola de Google Cloud, dentro del proyecto correspondiente:
- Habilite la API de Google Ads (API y servicios → Biblioteca)
- Configure la pantalla de consentimiento OAuth:
- Tipo de usuario: Interno (solo usuarios de su Google Workspace pueden autorizar — omite la verificación externa de la app)
- Nombre de la app, correo electrónico de soporte, correo electrónico de contacto del desarrollador
- Añada el ámbito de autorización en Acceso a datos:
https://www.googleapis.com/auth/adwords - Cree un ID de cliente OAuth:
- Tipo de aplicación: Aplicación de escritorio
- Descargue el JSON del secreto de cliente
El tipo de aplicación de escritorio usa http://localhost como URI de redirección. Esto es correcto — el flujo de OAuth abre un navegador, Google redirige a localhost con el código de autorización, y un servidor HTTP local lo captura.
Generación del token de actualización
Un script mínimo de Python (no verifica el parámetro state devuelto ni establece los permisos del archivo de tokens; añada ambas medidas antes de usarlo más allá de una ejecución local puntual) que ejecuta un servidor HTTP local en 127.0.0.1:0 (puerto aleatorio), imprime la URL de autorización, espera una solicitud, extrae el parámetro code y lo intercambia por tokens:
from pathlib import Path
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
from google_auth_oauthlib.flow import Flow
class CallbackHandler(BaseHTTPRequestHandler):
code_value = None
def do_GET(self):
qs = parse_qs(urlparse(self.path).query)
CallbackHandler.code_value = (qs.get('code') or [None])[0]
self.send_response(200)
self.end_headers()
self.wfile.write(b'OAuth complete.')
def log_message(self, format, *args):
return
server = HTTPServer(('127.0.0.1', 0), CallbackHandler)
redirect_uri = f'http://127.0.0.1:{server.server_port}/'
flow = Flow.from_client_secrets_file(
'client_secret.json',
scopes=['https://www.googleapis.com/auth/adwords'],
redirect_uri=redirect_uri
)
auth_url, _ = flow.authorization_url(
access_type='offline',
prompt='consent'
)
print(auth_url)
server.handle_request()
flow.fetch_token(code=CallbackHandler.code_value)
Path('google_ads_token.json').write_text(flow.credentials.to_json())
Dos parámetros son importantes:
access_type='offline'— devuelve un token de actualización, no solo un token de accesoprompt='consent'— fuerza una nueva pantalla de consentimiento incluso si el usuario autorizó previamente; necesario para obtener un nuevo token de actualización si los ámbitos de autorización cambiaron
El token de actualización no tiene una duración fija, pero deja de funcionar si el usuario revoca el acceso, no se usa durante seis meses, el usuario cambia su contraseña (para tokens con ámbitos de Gmail), la cuenta supera el límite de Google de tokens de actualización activos o un administrador de Workspace restringe el ámbito o impone una duración de sesión. Prevea que será necesario volver a autorizar.
Problemas con los ámbitos de autorización de clientes existentes
Si la URL de autorización establece include_granted_scopes=true y el usuario ya había concedido a este cliente OAuth otros ámbitos de autorización (Gmail, Drive, Calendar), Google devuelve la unión de los ámbitos de autorización antiguos y nuevos. La biblioteca google-auth-oauthlib rechaza esta discrepancia de ámbitos de autorización por defecto. Establezca la variable de entorno antes de cargar el flujo:
import os
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
Como alternativa, omita include_granted_scopes=true de la URL de autorización (el script anterior no lo establece), de modo que el token cubra solo el ámbito de autorización solicitado explícitamente.
Paso 3: google-ads.yaml
La biblioteca lee la configuración de un archivo YAML:
developer_token: <value>
client_id: <value>
client_secret: <value>
refresh_token: <value>
login_customer_id: 1911599764
use_proto_plus: true
Reglas de seguridad:
- Permisos del archivo:
0600(solo el propietario puede leerlo y escribir en él) - Nunca incluir en control de versiones
- Almacenar fuera de cualquier repositorio Git
- Para configuraciones de equipo, distribuir mediante un gestor de secretos, no un archivo compartido
login_customer_id es el identificador numérico del MCC sin guiones. Le indica a la API a través de qué cuenta de administrador accede el usuario autenticado a la cuenta de destino, y es obligatorio siempre que el acceso se realice a través de una cuenta de administrador. El customer_id de destino se pasa en el momento de la llamada, no en la configuración.
use_proto_plus es una clave de configuración obligatoria: true selecciona la interfaz de mensajes proto-plus usada en esta guía; false selecciona los mensajes protobuf simples, que Google recomienda para tareas sensibles al rendimiento.
Paso 4: inicialización del cliente Python
from google.ads.googleads.client import GoogleAdsClient
client = GoogleAdsClient.load_from_storage(
'/path/to/google-ads.yaml',
version='v22'
)
gs = client.get_service('GoogleAdsService')
El parámetro version selecciona explícitamente la versión de la API. La biblioteca google-ads incluye múltiples versiones instaladas en paralelo; los ejemplos aquí usan v22. A octubre de 2026, las versiones actuales de la biblioteca ya no incluyen v22 (eliminada en 33.0.0) y la versión 34.0.0 añade v26, por lo que debe sustituirla por una versión actual. Especifique siempre la versión — la predeterminada puede estar desactualizada o no admitir campos más recientes.
Verifique la conectividad:
cs = client.get_service('CustomerService')
customers = cs.list_accessible_customers()
ids = [r.split('/')[-1] for r in customers.resource_names]
# Example output: ['1305475941', '3977581086', '1911599764']
Paso 5: operaciones de lectura (GAQL)
Google Ads usa GAQL (Google Ads Query Language), una sintaxis similar a SQL. Todas las operaciones de lectura pasan por GoogleAdsService.search_stream(), que evita la paginación y es preferible a search() para la mayoría de las consultas.
Campañas con métricas de rendimiento
SELECT
campaign.id,
campaign.name,
campaign.status,
campaign.advertising_channel_type,
campaign.serving_status,
campaign.bidding_strategy_type,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions,
metrics.conversions_value,
metrics.ctr,
metrics.average_cpc
FROM campaign
ORDER BY campaign.id
Presupuestos de campaña
SELECT
campaign_budget.id,
campaign_budget.name,
campaign_budget.amount_micros,
campaign_budget.delivery_method,
campaign_budget.status,
campaign.id,
campaign.name
FROM campaign_budget
Grupos de anuncios
SELECT
ad_group.id,
ad_group.name,
ad_group.status,
ad_group.cpc_bid_micros,
campaign.id,
campaign.name
FROM ad_group
ORDER BY campaign.id, ad_group.id
Palabras clave (por impresiones)
SELECT
ad_group_criterion.keyword.text,
ad_group_criterion.keyword.match_type,
ad_group_criterion.status,
ad_group_criterion.criterion_id,
ad_group.id,
ad_group.name,
campaign.id,
campaign.name,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions
FROM keyword_view
WHERE ad_group_criterion.type = 'KEYWORD'
ORDER BY metrics.impressions DESC
LIMIT 100
Anuncios y su estado de cumplimiento de políticas
SELECT
ad_group_ad.ad.id,
ad_group_ad.ad.name,
ad_group_ad.ad.type,
ad_group_ad.status,
ad_group_ad.policy_summary.approval_status,
ad_group.id,
ad_group.name,
campaign.id,
campaign.name
FROM ad_group_ad
Acciones de conversión
SELECT
conversion_action.id,
conversion_action.name,
conversion_action.status,
conversion_action.type,
conversion_action.category,
conversion_action.include_in_conversions_metric,
conversion_action.counting_type
FROM conversion_action
Patrón de ejecución en Python
def gaql_query(client, customer_id, query):
gs = client.get_service('GoogleAdsService')
results = []
for batch in gs.search_stream(customer_id=customer_id, query=query):
for row in batch.results:
results.append(row)
return results
Paso 6: operaciones de escritura con validate_only
Los ejemplos siguientes usan objetos de solicitud en lugar de argumentos con nombre porque el objeto de solicitud contiene validate_only. Cada servicio de modificación (CampaignService, AdGroupService, AdGroupCriterionService, CampaignBudgetService) sigue el mismo patrón:
from google.protobuf import field_mask_pb2
req = client.get_type('MutateCampaignsRequest')
req.customer_id = '1305475941'
req.validate_only = True
op = client.get_type('CampaignOperation')
op.create.name = 'Campaign Name'
op.create.status = client.enums.CampaignStatusEnum.PAUSED
op.create.advertising_channel_type = client.enums.AdvertisingChannelTypeEnum.SEARCH
op.create.campaign_budget = 'customers/1305475941/campaignBudgets/123456789'
op.create.manual_cpc.enhanced_cpc_enabled = False
req.operations.append(op) # .append(), not .add()
client.get_service('CampaignService').mutate_campaigns(request=req)
Puntos clave de este patrón (con use_proto_plus: true):
validate_onlyes un campo en el objeto de solicitud, no un argumento con nombre del método de modificación- Las operaciones se añaden mediante
req.operations.append(op);.add()pertenece a la interfaz protobuf simple (use_proto_plus: false) - Aquí las rutas de recursos se escriben como cadenas explícitas (
'customers/1305475941/campaigns/22479990461'); los servicios también proporcionan métodos auxiliares para rutas comocampaign_service.campaign_path(customer_id, campaign_id), que Google recomienda en lugar de construir los nombres manualmente
Control de modificaciones en tres fases
Por seguridad en producción, las modificaciones pasan por tres controles:
Control 1 — validate_only=True: La API valida la estructura de la solicitud, los campos obligatorios y las referencias a recursos. No se crea ningún objeto. Ejecute esto primero para cada modificación.
Control 2 — Creación en pausa: Establezca validate_only=False y cree el objeto con status=PAUSED. Verifique el resultado con una consulta de lectura antes de continuar.
Control 3 — Activación en producción: Una llamada separada a la API que actualiza solo el campo status a ENABLED. Esto debe requerir aprobación explícita, no integrarse en la creación.
# Gate 3: enable a previously created paused campaign
req = client.get_type('MutateCampaignsRequest')
req.customer_id = '1305475941'
req.validate_only = False
op = client.get_type('CampaignOperation')
op.update.resource_name = 'customers/1305475941/campaigns/22479990461'
op.update.status = client.enums.CampaignStatusEnum.ENABLED
op.update_mask.CopyFrom(field_mask_pb2.FieldMask(paths=['status']))
req.operations.append(op)
client.get_service('CampaignService').mutate_campaigns(request=req)
Actualización de presupuesto
req = client.get_type('MutateCampaignBudgetsRequest')
req.customer_id = '1305475941'
req.validate_only = True
op = client.get_type('CampaignBudgetOperation')
op.update.resource_name = 'customers/1305475941/campaignBudgets/123456789'
op.update.amount_micros = 1_000_000 # $1.00 per day
op.update_mask.CopyFrom(field_mask_pb2.FieldMask(paths=['amount_micros']))
req.operations.append(op)
client.get_service('CampaignBudgetService').mutate_campaign_budgets(request=req)
Actualización de la puja de un grupo de anuncios
req = client.get_type('MutateAdGroupsRequest')
req.customer_id = '1305475941'
req.validate_only = True
op = client.get_type('AdGroupOperation')
op.update.resource_name = 'customers/1305475941/adGroups/165827073530'
op.update.cpc_bid_micros = 250_000 # $0.25
op.update_mask.CopyFrom(field_mask_pb2.FieldMask(paths=['cpc_bid_micros']))
req.operations.append(op)
client.get_service('AdGroupService').mutate_ad_groups(request=req)
Creación de palabra clave
req = client.get_type('MutateAdGroupCriteriaRequest')
req.customer_id = '1305475941'
req.validate_only = True
op = client.get_type('AdGroupCriterionOperation')
op.create.ad_group = 'customers/1305475941/adGroups/165827073530'
op.create.status = client.enums.AdGroupCriterionStatusEnum.PAUSED
op.create.keyword.text = 'example keyword'
op.create.keyword.match_type = client.enums.KeywordMatchTypeEnum.EXACT
req.operations.append(op)
client.get_service('AdGroupCriterionService').mutate_ad_group_criteria(request=req)
Manejo de errores
from google.ads.googleads.errors import GoogleAdsException
try:
response = service.mutate_campaigns(request=req)
except GoogleAdsException as ex:
for error in ex.failure.errors:
print(f'{error.error_code}: {error.message}')
Códigos de error comunes y su significado:
| Código de error | Causa |
|---|---|
RESOURCE_NOT_FOUND | El recurso referenciado no existe, se eliminó o tiene un nombre de recurso mal formado |
DEVELOPER_TOKEN_NOT_APPROVED | Token con acceso de prueba utilizado con una cuenta de producción (CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION desde la retirada de septiembre de 2026) |
REQUIRED | Falta un campo obligatorio (p. ej., estrategia de puja en la creación de campaña) |
UNRECOGNIZED_FIELD | Campo de una versión de API diferente o nombre de campo incorrecto |
INVALID_ARGUMENT | El valor del campo no supera la validación (p. ej., presupuesto negativo) |
PERMISSION_DENIED | El usuario OAuth no tiene acceso a la cuenta de destino |
Niveles de acceso a la API
El acceso a la API de Google Ads es escalonado, no binario:
| Nivel | Aprovisionamiento | Lectura (producción) | Escritura (producción) | Escritura (cuentas de prueba) | Límite diario de operaciones |
|---|---|---|---|---|---|
| acceso de prueba | Inmediato (desde API Center del MCC hasta septiembre de 2026; ahora automático al habilitar la API en el proyecto de Cloud) | ❌ | ❌ | ✅ | 15.000 |
| acceso de explorador (incluido a octubre de 2026) | Solicitud en la página de descripción general de Cloud Console | ✅ | ✅ (algunos servicios restringidos) | ✅ | 2.880 en producción / 15.000 en pruebas |
| acceso básico | Solicitud + revisión de cumplimiento | ✅ | ✅ | ✅ | 15.000 |
| acceso estándar | Solicitud tras obtener acceso básico + auditoría manual | ✅ | ✅ | ✅ | Ilimitado |
El acceso de prueba es suficiente para el desarrollo con cuentas de prueba de Google Ads: autenticación, consultas GAQL, pruebas validate_only y lectura/escritura completa. El salto al acceso básico depende de la revisión de cumplimiento, no del gasto.
El acceso estándar elimina el límite diario de operaciones (siguen aplicándose los límites de frecuencia de solicitudes por función). Requiere una solicitud por separado, disponible solo después de obtener acceso básico, y una auditoría manual; la documentación de Google sobre los niveles de acceso no indica ningún umbral de gasto.
Cuentas de prueba
Las cuentas de prueba son cuentas gratuitas de Google Ads sin facturación que nunca publican anuncios. Las cuentas de prueba y de producción no pueden interactuar, por lo que una cuenta de prueba no puede depender de su MCC de producción: cree una cuenta de administrador de prueba independiente tras iniciar sesión con una cuenta de Google que no esté vinculada a su MCC de producción, cree cuentas de cliente de prueba bajo ella y use una como customer_id de destino (con el administrador de prueba como login_customer_id) durante el desarrollo con acceso de prueba.
validate_only en los distintos niveles de acceso
validate_only=True funciona en todos los niveles de acceso, pero el acceso de prueba sigue rechazando modificaciones validate_only en cuentas de producción con el mismo error de autorización que cualquier otra solicitud. Esto no es una limitación de validate_only — es el mismo control de acceso aplicado a todas las operaciones de escritura independientemente de la opción validate_only.
Seguimiento de conversiones: lectura de la API frente al estado funcional
La interfaz de Google Ads puede mostrar «Configurar seguimiento de conversiones» como recomendación incluso cuando existe una acción de conversión habilitada. La API puede confirmar la existencia de una acción de conversión (tipo WEBPAGE, categoría PURCHASE, estado ENABLED, include_in_conversions_metric: true), pero esto solo demuestra que el objeto de acción existe. No demuestra que el sitio web emita el evento AW-.../label correspondiente, que la etiqueta de Google esté cargada o que se haya recibido una señal de conversión.
Al auditar el seguimiento de conversiones, separe la verificación por API (metadatos de la acción de conversión) de la verificación por navegador (pestaña de red, carga de etiquetas, emisión de eventos). La API es la fuente de referencia para la configuración; el navegador es la fuente de referencia para la ejecución.
El patrón de atribución de ingresos en el backend se aplica aquí: si los eventos de conversión del lado del cliente no son fiables, planifique la carga de conversiones desde el servidor o sin conexión mediante el ConversionUploadService de la API de Google Ads como alternativa de respaldo.
Versionado de la API
La biblioteca de Python google-ads incluye múltiples versiones de la API. A octubre de 2026, la última versión (34.0.0) añade v26, y v22 y anteriores se han eliminado de la biblioteca. Cada versión añade, declara obsoletos o elimina campos GAQL y métodos de servicio.
Reglas para la selección de versión:
- Especifique la versión explícitamente en
load_from_storage(version='v22'). La predeterminada puede estar obsoleta. - Consulte las notas de versión de la API de Google Ads para conocer los campos declarados obsoletos antes de actualizar.
- El método
search_streamestá disponible en todas las versiones actuales y es la ruta de lectura recomendada. use_proto_plusdebe establecerse explícitamente (trueofalse); selecciona la interfaz de mensajes de Python, no una versión de la API.- El patrón de objeto de solicitud para modificaciones (
mutate_campaigns(request=req)) contiene campos de la solicitud comovalidate_only; los ejemplos actuales de Google siguen pasandocustomer_idyoperationscomo argumentos con nombre para las modificaciones simples.
Seguridad local
Todos los archivos de credenciales deben permanecer fuera del control de versiones:
~/.hermes/
google-ads.yaml # 0600 — dev token, OAuth client, refresh token
google_ads_token.json # 0600 — OAuth tokens, adwords scope
google_client_secret.json # 0600 — OAuth client ID + secret
Para el repositorio de trabajo, añada un .gitignore:
google-ads.yaml
*_token*.json
*_secret*.json
Un archivo de plantilla con valores de ejemplo puede incluirse en el repositorio para documentar la estructura esperada:
# google-ads.yaml.template — commit this, fill locally
developer_token: INSERT_DEV_TOKEN
client_id: INSERT_CLIENT_ID
client_secret: INSERT_CLIENT_SECRET
refresh_token: INSERT_REFRESH_TOKEN
login_customer_id: INSERT_MCC_ID
use_proto_plus: true
Campos obligatorios para operaciones comunes
| Operación | Campos obligatorios |
|---|---|
| Crear campaña (Search) | name, status, advertising_channel_type, campaign_budget, manual_cpc o estrategia de puja, contains_eu_political_advertising |
| Crear grupo de anuncios (Search) | name, status, type_, cpc_bid_micros, campaign |
| Crear palabra clave | ad_group, status, keyword.text, keyword.match_type |
| Actualizar estado de campaña | resource_name, status, update_mask (rutas: ['status']) |
| Actualizar presupuesto | resource_name, amount_micros, update_mask (rutas: ['amount_micros']) |
La ausencia de un campo obligatorio devuelve REQUIRED con el nombre del campo. La ausencia de update_mask en una operación de actualización se rechaza con FieldMaskError.FIELD_MASK_MISSING.
Script de prueba abreviado
Un script abreviado (las listas de campos y los filtros GAQL están abreviados con ... y los identificadores son marcadores de posición, por lo que debe completarlos antes de ejecutarlo) que lee todos los tipos de entidad y ejecuta pruebas de escritura validate_only:
# google_ads_api_test.py — read all entities + validate_only write tests
import warnings
warnings.filterwarnings('ignore')
from google.ads.googleads.client import GoogleAdsClient
from google.ads.googleads.errors import GoogleAdsException
from google.protobuf import field_mask_pb2
CFG = '/path/to/google-ads.yaml'
CID = '1305475941'
c = GoogleAdsClient.load_from_storage(CFG, version='v22')
gs = c.get_service('GoogleAdsService')
def gaql(query, label):
print(f'\n=== {label} ===')
n = 0
for batch in gs.search_stream(customer_id=CID, query=query):
for row in batch.results:
n += 1
print(f'{n} rows')
# Read all entities
gaql("SELECT customer.id, customer.descriptive_name FROM customer WHERE customer.id = ...", "CUSTOMER")
gaql("SELECT campaign.id, campaign.name, campaign.status, ... FROM campaign", "CAMPAIGNS")
gaql("SELECT campaign_budget.id, campaign_budget.name, ... FROM campaign_budget", "BUDGETS")
gaql("SELECT ad_group.id, ad_group.name, ... FROM ad_group", "AD GROUPS")
gaql("SELECT ad_group_criterion.keyword.text, ... FROM keyword_view WHERE ...", "KEYWORDS")
gaql("SELECT ad_group_ad.ad.id, ... FROM ad_group_ad", "ADS")
gaql("SELECT conversion_action.id, ... FROM conversion_action", "CONVERSIONS")
# Write tests
def test_write(name, fn):
print(f'\n--- {name} ---')
try:
fn()
print('PASS')
except GoogleAdsException as e:
for err in e.failure.errors:
print(f'{err.error_code}: {err.message}')
def test_create_campaign():
req = c.get_type('MutateCampaignsRequest')
req.customer_id = CID
req.validate_only = True
op = c.get_type('CampaignOperation')
op.create.name = 'TEST_CAMPAIGN'
op.create.status = c.enums.CampaignStatusEnum.PAUSED
op.create.advertising_channel_type = c.enums.AdvertisingChannelTypeEnum.SEARCH
op.create.campaign_budget = f'customers/{CID}/campaignBudgets/123456789'
op.create.manual_cpc.enhanced_cpc_enabled = False
req.operations.append(op)
c.get_service('CampaignService').mutate_campaigns(request=req)
test_write('Create Campaign (validate_only)', test_create_campaign)
print('\nDone.')
Referencias
- Documentación de la API de Google Ads
- Biblioteca de Python google-ads
- Referencia GAQL
- OAuth 2.0 para aplicaciones de escritorio
- Crear un asistente de IA específico de un proyecto mediante Telegram — mismo patrón OAuth aplicado a un ámbito de autorización diferente de Google
- Arquitectura de referencia para una capa de operaciones de IA basada en hilos — el modelo operativo al que se conecta la automatización de API
- Operaciones en solitario a escala: gestionar decenas de proyectos con un equipo pequeño — por qué la automatización de API reemplaza el trabajo manual en la interfaz a escala