tva
← Approfondimenti

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àScopoEsempio
Account amministratore (MCC)Rilascia il token sviluppatorelogin_customer_id
Progetto Google CloudClient OAuth 2.0 per l’autenticazioneID client + segreto client
Account Google AdsDestinazione di tutte le operazioni APIcustomer_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:

DomandaRisposta
Q4: Rapporto con un rappresentante GoogleNo
Q6: Modello di businessDescrivi il tuo caso d’uso (e-commerce, lead generation, reportistica interna)
Q8: Chi avrà accessoUtenti interni — solo dipendenti
Q9: Strumento sviluppato da terze partiNo (script o agenti sviluppati internamente)
Q10: API per il monitoraggio delle conversioni e il remarketingNo (a meno che non le utilizzi effettivamente)
Q11: Tipi di campagneSearch, 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:

  1. Abilita la Google Ads API (API e servizi → Libreria)
  2. 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
  1. Aggiungi l’ambito di autorizzazione in Accesso ai dati: https://www.googleapis.com/auth/adwords
  2. 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 accesso
  • prompt='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, come campaign_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 erroreCausa
RESOURCE_NOT_FOUNDLa risorsa indicata non esiste, è stata rimossa oppure ha un nome di risorsa non valido
DEVELOPER_TOKEN_NOT_APPROVEDToken con accesso di test usato su un account di produzione (CLOUD_PROJECT_NOT_APPROVED_FOR_PRODUCTION dalla dismissione di settembre 2026)
REQUIREDCampo obbligatorio mancante (es. strategia di offerta nella creazione della campagna)
UNRECOGNIZED_FIELDCampo di una versione API diversa o nome di campo errato
INVALID_ARGUMENTIl valore del campo non supera la validazione (es. budget negativo)
PERMISSION_DENIEDL’utente OAuth non ha accesso all’account di destinazione

Livelli di accesso API

L’accesso alla Google Ads API è a livelli, non binario:

LivelloRilascioLettura (produzione)Scrittura (produzione)Scrittura (account di test)Limite giornaliero di operazioni
Accesso di testImmediato (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 baseRichiesta + verifica della conformità✅✅✅15.000
Accesso standardRichiesta 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_plus deve essere impostato esplicitamente (true o false); 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 come validate_only; gli esempi attuali di Google passano ancora customer_id e operations come 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

OperazioneCampi 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 chiavead_group, status, keyword.text, keyword.match_type
Aggiorna stato della campagnaresource_name, status, update_mask (paths: ['status'])
Aggiorna budgetresource_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

Per approfondire