Google Ads API: configurazione, autenticazione, lettura e scrittura
Una guida tecnica per configurare l’accesso programmatico a Google Ads — dall’architettura alla prima chiamata API. Tratta la configurazione MCC, OAuth 2.0, i livelli del token sviluppatore, la libreria Python google-ads, le query GAQL in lettura e lo schema di scrittura validate_only.
Aggiornamento (ottobre 2026): Google ha dismesso i token sviluppatore il 9 settembre 2026. I livelli di accesso all’API sono ora assegnati per progetto Google Cloud e gestiti nella pagina Panoramica di Google Ads API nella Cloud Console; l’header developer-token è facoltativo e viene ignorato e il Centro API non gestisce più la registrazione o le modifiche di accesso. Google dichiara che il codice esistente continua a funzionare. I passaggi sui token sviluppatore e sul Centro API riportati di seguito descrivono la configurazione pubblicata a giugno 2026. La configurazione attuale è descritta nel nostro articolo di approfondimento, Accesso alla Google Ads API nel 2026: i progetti Cloud sostituiscono i Developer Token.
Architettura
Prima di poter eseguire anche una sola chiamata API, servono tre entità distinte:
| Entità | Scopo | Esempio |
|---|---|---|
| Account amministratore (MCC) | Rilascia il token sviluppatore | login_customer_id |
| Progetto Google Cloud | Client OAuth 2.0 per l’autenticazione | ID client + segreto client |
| Account Google Ads | Destinazione di tutte le operazioni API | customer_id |
Non si tratta dello stesso account. Un MCC può disporre di un token sviluppatore senza essere proprietario dell’account di destinazione: basta che sia collegato come amministratore. Il progetto Google Cloud può appartenere a un’identità Google diversa da quella dell’MCC. L’account di destinazione è l’account dell’inserzionista che contiene le campagne.
Questa separazione è importante perché il Centro API, dove vengono rilasciati i token sviluppatore, è disponibile solo negli account amministratore. Un account Google Ads autonomo non può accedervi, anche se dispone di utenti con privilegi amministrativi.
L’intestazione della chiamata API riunisce queste tre identità e un token Bearer OAuth:
developer-token: <da API Center dell'MCC>
login-customer-id: <ID numerico MCC, senza trattini>
customer-id: <ID numerico account target>
Authorization: Bearer <token di accesso OAuth 2.0>
Prerequisiti
- Un account amministratore Google Ads con la configurazione completata
- L’account pubblicitario di destinazione collegato all’account amministratore, con il collegamento accettato
- Un progetto Google Cloud con la Google Ads API abilitata
- Python 3.9+ con la libreria
google-ads(pip install google-ads) - Un browser per il flusso di consenso OAuth una tantum
Passo 1: account amministratore e token sviluppatore
Il Centro API si trova in Strumenti e impostazioni → Configurazione → Centro API all’interno di un account amministratore. Se non è presente, l’account non è un account amministratore oppure la sua configurazione è incompleta.
Dal Centro API, richiedi un token sviluppatore. Imposta il tipo di account su Inserzionista, non Agenzia o Terze parti, quando il token è destinato ai tuoi account. Il token viene rilasciato immediatamente al livello Accesso di test.
L’accesso di test consente:
- Operazioni di lettura solo su account di test
- Operazioni di scrittura solo su account di test
- Nessuna operazione di lettura o scrittura su account di produzione
Le richieste su account di produzione con accesso di test falliscono con DEVELOPER_TOKEN_NOT_APPROVED («The developer token is only approved for use with test accounts»). Dalla dismissione di settembre 2026, le versioni attuali dell’API restituiscono invece CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION (ACTION_NOT_PERMITTED nella v24 e precedenti).
Richiesta di accesso base
Per accedere ad account di produzione, richiedi l’accesso base dalla stessa pagina del Centro API. Il modulo di richiesta contiene 12 domande. Per uso interno sui propri account, le risposte pertinenti sono:
| Domanda | Risposta |
|---|---|
| Q4: Rapporto con un rappresentante Google | No |
| Q6: Modello di business | Descrivi il tuo caso d’uso (e-commerce, lead generation, reportistica interna) |
| Q8: Chi avrà accesso | Utenti interni — solo dipendenti |
| Q9: Strumento sviluppato da terze parti | No (script o agenti sviluppati internamente) |
| Q10: API per il monitoraggio delle conversioni e il remarketing | No (a meno che non le utilizzi effettivamente) |
| Q11: Tipi di campagne | Search, Performance Max, Shopping (a seconda dei casi) |
| Q12: Funzionalità | Creazione di campagne, gestione delle campagne, reportistica |
Per la Q7 è richiesto un documento di progettazione in PDF. Deve descrivere l’architettura dell’API, il flusso di autenticazione, la strategia di limitazione della frequenza delle richieste, la gestione degli errori e il caso d’uso esclusivamente interno. Attieniti ai fatti: il team di verifica della conformità controlla la coerenza con il caso d’uso dichiarato.
Tempo di elaborazione a giugno 2026: circa 3 giorni lavorativi, con una nota che segnala un volume di richieste superiore al normale.
Passo 2: OAuth 2.0
Configurazione del progetto Google Cloud
Nella Google Cloud Console, nel progetto pertinente:
- Abilita la Google Ads API (API e servizi → Libreria)
- Configura la schermata di consenso OAuth:
- Tipo di utente: Interno (solo gli utenti del tuo Google Workspace possono autorizzare l’accesso; evita la verifica prevista per le app esterne)
- Nome dell’app, email di assistenza ed email di contatto dello sviluppatore
- Aggiungi l’ambito di autorizzazione in Accesso ai dati:
https://www.googleapis.com/auth/adwords - Crea un ID client OAuth:
- Tipo di applicazione: App desktop
- Scarica il file JSON con il segreto client
Il tipo App desktop utilizza http://localhost come URI di reindirizzamento. È corretto: il flusso OAuth apre un browser, Google reindirizza a localhost con il codice di autorizzazione e un server HTTP locale lo riceve.
Generazione del token di aggiornamento
Uno script Python minimale (non verifica il parametro state restituito né imposta le autorizzazioni sul file dei token; aggiungi entrambe le misure prima di usarlo oltre una singola esecuzione locale) avvia un server HTTP locale su 127.0.0.1:0 (porta casuale), stampa l’URL di autorizzazione, attende una richiesta, estrae il parametro code e lo scambia con i token:
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())
Due parametri sono importanti:
access_type='offline'— restituisce un token di aggiornamento, non soltanto un token di accessoprompt='consent'— forza una nuova schermata di consenso anche se l’utente ha già autorizzato l’accesso; è necessario per ottenere un nuovo token di aggiornamento se gli ambiti di autorizzazione sono cambiati
Il token di aggiornamento non ha una durata fissa, ma smette di funzionare se l’utente revoca l’accesso, rimane inutilizzato per sei mesi, l’utente cambia la password (per i token con ambiti Gmail), l’account supera il limite di Google per i token di aggiornamento attivi oppure un amministratore Workspace limita l’ambito o impone una durata della sessione. Prevedi la necessità di una nuova autorizzazione.
Ambiti di autorizzazione: un’insidia con i client esistenti
Se l’URL di autorizzazione imposta include_granted_scopes=true e l’utente ha già concesso a questo client OAuth altri ambiti di autorizzazione (Gmail, Drive, Calendar), Google restituisce l’unione degli ambiti vecchi e nuovi. La libreria google-auth-oauthlib rifiuta questa discrepanza per impostazione predefinita. Imposta la variabile d’ambiente prima di caricare il flusso:
import os
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
In alternativa, ometti include_granted_scopes=true dall’URL di autorizzazione (lo script precedente non lo imposta), così il token copre solo l’ambito richiesto esplicitamente.
Passo 3: google-ads.yaml
La libreria legge la configurazione da un file YAML:
developer_token: <valore>
client_id: <valore>
client_secret: <valore>
refresh_token: <valore>
login_customer_id: 1911599764
use_proto_plus: true
Regole di sicurezza:
- Permessi del file:
0600(lettura e scrittura riservate al proprietario) - Non inserire mai il file nel controllo versione
- Conservare al di fuori di qualsiasi repository Git
- Per i team, distribuire tramite un gestore di segreti, non tramite un file condiviso
login_customer_id è l’ID numerico dell’MCC senza trattini. Indica all’API attraverso quale account amministratore l’utente autenticato accede all’account di destinazione ed è obbligatorio ogni volta che l’accesso avviene tramite un account amministratore. Il customer_id di destinazione viene passato al momento della chiamata, non nella configurazione.
use_proto_plus è una chiave di configurazione obbligatoria: true seleziona l’interfaccia dei messaggi proto-plus usata in questa guida, false seleziona i messaggi protobuf semplici, che Google raccomanda per le attività sensibili alle prestazioni.
Passo 4: inizializzazione del client 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')
Il parametro version seleziona esplicitamente la versione dell’API. La libreria google-ads include più versioni installate in parallelo; gli esempi qui usano v22. A ottobre 2026, le versioni attuali della libreria non includono più v22 (rimossa nella 33.0.0) e la 34.0.0 aggiunge v26, quindi sostituiscila con una versione attuale. Specifica sempre la versione: quella predefinita potrebbe essere meno recente o non supportare i nuovi campi.
Verifica la connettività:
cs = client.get_service('CustomerService')
customers = cs.list_accessible_customers()
ids = [r.split('/')[-1] for r in customers.resource_names]
# Output di esempio: ['1305475941', '3977581086', '1911599764']
Passo 5: operazioni di lettura (GAQL)
Google Ads utilizza GAQL (Google Ads Query Language), una sintassi simile a SQL. Tutte le operazioni di lettura passano attraverso GoogleAdsService.search_stream(), che evita la paginazione ed è preferito rispetto a search() per la maggior parte delle query.
Campagne con metriche di prestazione
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
Budget delle campagne
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
Gruppi di annunci
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
Parole chiave ordinate per impressioni
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
Annunci con stato di conformità alle norme
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
Azioni di conversione
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
Schema di esecuzione in 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
Passo 6: operazioni di scrittura con validate_only
Gli esempi seguenti usano oggetti di richiesta anziché argomenti con nome perché l’oggetto di richiesta contiene validate_only. Ogni servizio di modifica (CampaignService, AdGroupService, AdGroupCriterionService, CampaignBudgetService) segue lo stesso schema:
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 = 'Nome Campagna'
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(), non .add()
client.get_service('CampaignService').mutate_campaigns(request=req)
Punti chiave di questo schema (con use_proto_plus: true):
validate_onlyè un campo dell’oggetto di richiesta, non un argomento con nome del metodo di modifica- Le operazioni vengono aggiunte tramite
req.operations.append(op);.add()appartiene all’interfaccia protobuf semplice (use_proto_plus: false) - Qui i percorsi delle risorse sono scritti come stringhe esplicite (
'customers/1305475941/campaigns/22479990461'); i servizi forniscono anche metodi helper per i percorsi, comecampaign_service.campaign_path(customer_id, campaign_id), che Google raccomanda al posto dei nomi costruiti manualmente
Controllo delle modifiche in tre fasi
Per garantire la sicurezza in produzione, le operazioni di modifica passano attraverso tre controlli:
Controllo 1 — validate_only=True: l’API convalida la struttura della richiesta, i campi obbligatori e i riferimenti alle risorse. Non viene creato alcun oggetto. Esegui prima questo controllo per ogni operazione di modifica.
Controllo 2 — Creazione in stato di pausa: imposta validate_only=False e crea l’oggetto con status=PAUSED. Verifica il risultato con una query di lettura prima di procedere.
Controllo 3 — Attivazione in produzione: una chiamata API separata aggiorna solo il campo status a ENABLED. Dovrebbe richiedere un’approvazione esplicita anziché essere incorporata nella creazione.
# Gate 3: attivare una campagna precedentemente creata in pausa
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)
Aggiornamento del budget
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 al giorno
op.update_mask.CopyFrom(field_mask_pb2.FieldMask(paths=['amount_micros']))
req.operations.append(op)
client.get_service('CampaignBudgetService').mutate_campaign_budgets(request=req)
Aggiornamento dell’offerta del gruppo di annunci
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)
Creazione di una parola chiave
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 = 'parola chiave esempio'
op.create.keyword.match_type = client.enums.KeywordMatchTypeEnum.EXACT
req.operations.append(op)
client.get_service('AdGroupCriterionService').mutate_ad_group_criteria(request=req)
Gestione degli errori
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}')
Codici di errore comuni e loro significato:
| Codice di errore | Causa |
|---|---|
RESOURCE_NOT_FOUND | La risorsa indicata non esiste, è stata rimossa oppure ha un nome di risorsa non valido |
DEVELOPER_TOKEN_NOT_APPROVED | Token con accesso di test usato su un account di produzione (CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION dalla dismissione di settembre 2026) |
REQUIRED | Campo obbligatorio mancante (es. strategia di offerta nella creazione della campagna) |
UNRECOGNIZED_FIELD | Campo di una versione API diversa o nome di campo errato |
INVALID_ARGUMENT | Il valore del campo non supera la validazione (es. budget negativo) |
PERMISSION_DENIED | L’utente OAuth non ha accesso all’account di destinazione |
Livelli di accesso API
L’accesso alla Google Ads API è a livelli, non binario:
| Livello | Rilascio | Lettura (produzione) | Scrittura (produzione) | Scrittura (account di test) | Limite giornaliero di operazioni |
|---|---|---|---|---|---|
| Accesso di test | Immediato (dal Centro API dell’MCC fino a settembre 2026; ora automatico quando si abilita l’API nel progetto Cloud) | ❌ | ❌ | ✅ | 15.000 |
| Accesso Explorer (elencato a ottobre 2026) | Richiesta nella pagina Panoramica della Cloud Console | ✅ | ✅ (alcuni servizi limitati) | ✅ | 2.880 in produzione / 15.000 nei test |
| Accesso base | Richiesta + verifica della conformità | ✅ | ✅ | ✅ | 15.000 |
| Accesso standard | Richiesta dopo l’accesso base + verifica manuale | ✅ | ✅ | ✅ | Illimitato |
L’accesso di test è sufficiente per lo sviluppo sugli account di test Google Ads: autenticazione, query GAQL, test validate_only e lettura e scrittura complete. Il passaggio all’accesso base è subordinato alla verifica della conformità, non alla spesa.
L’accesso standard rimuove il limite giornaliero di operazioni (restano i limiti di frequenza delle richieste per singola funzionalità). Richiede una richiesta separata, disponibile solo dopo aver ottenuto l’accesso base, e una verifica manuale; la documentazione di Google sui livelli di accesso non indica soglie di spesa.
Account di test
Gli account di test sono account Google Ads gratuiti senza fatturazione che non pubblicano mai annunci. Gli account di test e quelli di produzione non possono interagire, quindi un account di test non può dipendere dal tuo MCC di produzione: crea un account amministratore di test separato accedendo con un Account Google non collegato al tuo MCC di produzione, crea al suo interno account cliente di test e usane uno come customer_id di destinazione (con l’amministratore di test come login_customer_id) durante lo sviluppo con accesso di test.
validate_only tra i livelli di accesso
validate_only=True funziona a tutti i livelli di accesso, ma l’accesso di test rifiuta comunque le operazioni di modifica validate_only su account di produzione con lo stesso errore di autorizzazione di qualsiasi altra richiesta. Non è una limitazione di validate_only: è lo stesso controllo di accesso applicato a tutte le operazioni di scrittura, indipendentemente dal flag validate_only.
Monitoraggio delle conversioni: lettura API e funzionamento effettivo
L’interfaccia Google Ads potrebbe mostrare "Configura il monitoraggio delle conversioni" come raccomandazione anche quando un’azione di conversione esiste ed è abilitata. L’API può confermare l’esistenza di un’azione di conversione (tipo WEBPAGE, categoria PURCHASE, stato ENABLED, include_in_conversions_metric: true), ma questo dimostra solo che l’oggetto azione esiste. Non dimostra che il sito web emetta l’evento AW-.../label corrispondente, che il tag Google sia caricato o che un segnale di conversione sia stato ricevuto.
Durante la verifica del monitoraggio delle conversioni, separa il controllo API (metadati dell’azione di conversione) dal controllo nel browser (scheda Rete, caricamento dei tag, attivazione degli eventi). L’API è la fonte di riferimento per la configurazione; il browser lo è per l’esecuzione.
Lo schema per l’attribuzione dei ricavi lato backend si applica qui: se gli eventi di conversione lato client non sono affidabili, pianifica il caricamento delle conversioni lato server o offline tramite il ConversionUploadService della Google Ads API come alternativa.
Versionamento API
La libreria Python google-ads include più versioni API. A ottobre 2026, l’ultima versione (34.0.0) aggiunge v26, mentre v22 e precedenti sono state rimosse dalla libreria. Ogni versione aggiunge campi GAQL e metodi di servizio, li dichiara obsoleti o li rimuove.
Regole per la selezione della versione:
- Specifica la versione esplicitamente in
load_from_storage(version='v22'). Quella predefinita potrebbe essere obsoleta. - Controlla le note di rilascio della Google Ads API per verificare quali campi sono stati dichiarati obsoleti prima di aggiornare.
- Il metodo
search_streamè disponibile in tutte le versioni attuali ed è il percorso di lettura raccomandato. use_proto_plusdeve essere impostato esplicitamente (trueofalse); seleziona l’interfaccia dei messaggi Python, non una versione dell’API.- Lo schema basato su oggetti di richiesta per le operazioni di modifica (
mutate_campaigns(request=req)) contiene campi a livello di richiesta comevalidate_only; gli esempi attuali di Google passano ancoracustomer_ideoperationscome argomenti con nome per le semplici operazioni di modifica.
Sicurezza locale
Tutti i file di credenziali devono rimanere fuori dal controllo versione:
~/.hermes/
google-ads.yaml # 0600 — dev token, client OAuth, refresh token
google_ads_token.json # 0600 — token OAuth, scope adwords
google_client_secret.json # 0600 — client ID + secret OAuth
Per il repository di lavoro, aggiungi un .gitignore:
google-ads.yaml
*_token*.json
*_secret*.json
Un file modello con valori segnaposto può essere inserito nel controllo versione per documentare la struttura prevista:
# google-ads.yaml.template — committa questo, compila localmente
developer_token: INSERISCI_DEV_TOKEN
client_id: INSERISCI_CLIENT_ID
client_secret: INSERISCI_CLIENT_SECRET
refresh_token: INSERISCI_REFRESH_TOKEN
login_customer_id: INSERISCI_MCC_ID
use_proto_plus: true
Campi obbligatori per le operazioni comuni
| Operazione | Campi obbligatori |
|---|---|
| Crea campagna (Search) | name, status, advertising_channel_type, campaign_budget, manual_cpc o strategia di offerta, contains_eu_political_advertising |
| Crea gruppo di annunci (Search) | name, status, type_, cpc_bid_micros, campaign |
| Crea parola chiave | ad_group, status, keyword.text, keyword.match_type |
| Aggiorna stato della campagna | resource_name, status, update_mask (paths: ['status']) |
| Aggiorna budget | resource_name, amount_micros, update_mask (paths: ['amount_micros']) |
Un campo obbligatorio mancante restituisce REQUIRED con il nome del campo. Un’operazione di aggiornamento priva di update_mask viene rifiutata con FieldMaskError.FIELD_MASK_MISSING.
Script di test abbreviato
Uno script abbreviato (gli elenchi dei campi e i filtri GAQL sono abbreviati con ... e gli ID sono segnaposto, quindi completali prima dell’esecuzione) che legge tutti i tipi di entità ed esegue test di scrittura validate_only:
# google_ads_api_test.py — legge tutte le entità + test di scrittura validate_only
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} righe')
# Legge tutte le entità
gaql("SELECT customer.id, customer.descriptive_name FROM customer WHERE customer.id = ...", "CUSTOMER")
gaql("SELECT campaign.id, campaign.name, campaign.status, ... FROM campaign", "CAMPAGNE")
gaql("SELECT campaign_budget.id, campaign_budget.name, ... FROM campaign_budget", "BUDGET")
gaql("SELECT ad_group.id, ad_group.name, ... FROM ad_group", "GRUPPI DI ANNUNCI")
gaql("SELECT ad_group_criterion.keyword.text, ... FROM keyword_view WHERE ...", "PAROLE CHIAVE")
gaql("SELECT ad_group_ad.ad.id, ... FROM ad_group_ad", "ANNUNCI")
gaql("SELECT conversion_action.id, ... FROM conversion_action", "CONVERSIONI")
# Test di scrittura
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_CAMPAGNA'
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('Crea Campagna (validate_only)', test_create_campaign)
print('\nFatto.')
Riferimenti
- Documentazione Google Ads API
- Libreria Python google-ads
- Riferimento GAQL
- OAuth 2.0 per app desktop
- Creare un assistente IA specifico per progetto tramite Telegram — lo stesso schema OAuth applicato a un diverso ambito di autorizzazione Google
- Architettura di riferimento per un livello operativo di IA basato su thread — il modello operativo in cui si integra l’automazione API
- Operazioni su larga scala con un piccolo team: gestire decine di progetti — perché l’automazione API sostituisce il lavoro manuale nell’interfaccia quando il volume cresce