Google Ads API: Einrichtung, Authentifizierung, Lese- und Schreiboperationen
Eine technische Anleitung für den programmatischen Zugriff auf Google Ads — von der Architektur bis zum ersten API-Aufruf. Behandelt MCC-Konfiguration, OAuth 2.0, Developer-Token-Stufen, die google-ads-Python-Bibliothek, GAQL-Leseabfragen und das validate_only-Schreibmuster.
Architektur
Drei separate Entitäten sind erforderlich, bevor ein einzelner API-Aufruf funktioniert:
| Entität | Zweck | Beispiel |
|---|---|---|
| **Manager-Konto (MCC)** | Stellt das Developer Token aus | `login_customer_id` |
| **Google Cloud-Projekt** | OAuth 2.0-Client für die Authentifizierung | Client-ID + Secret |
| **Google Ads-Konto** | Ziel aller API-Operationen | `customer_id` |
Es handelt sich nicht um dasselbe Konto. Ein MCC kann ein Developer Token besitzen, ohne das Zielkonto zu besitzen — es muss lediglich als Manager verknüpft sein. Das Google Cloud-Projekt kann unter einer anderen Google-Identität als das MCC laufen. Das Zielkonto ist das Werbetreibendenkonto, in dem die Kampagnen liegen.
Diese Trennung ist wichtig, weil das API Center (wo Developer Tokens bereitgestellt werden) nur innerhalb von Manager-Konten verfügbar ist. Ein eigenständiges Google Ads-Konto kann nicht auf das API Center zugreifen, selbst wenn es über administrative Nutzer verfügt.
Der API-Aufruf-Header setzt diese drei Identitäten plus ein OAuth-Bearer-Token zusammen:
developer-token: <aus dem MCC API Center>
login-customer-id: <numerische MCC-ID, ohne Bindestriche>
customer-id: <numerische ID des Zielkontos>
Authorization: Bearer <OAuth 2.0 Access Token>
Voraussetzungen
- Ein Google Ads Manager-Konto mit abgeschlossener Einrichtung
- Das Ziel-Werbekonto ist mit dem Manager-Konto verknüpft und die Verknüpfung wurde akzeptiert
- Ein Google Cloud-Projekt mit aktivierter Google Ads API
- Python 3.9+ mit der
google-ads-Bibliothek (pip install google-ads) - Ein Browser für den einmaligen OAuth-Consent-Flow
Schritt 1: Manager-Konto und Developer Token
Das API Center befindet sich unter Tools & Settings → Setup → API Center innerhalb eines Manager-Kontos. Wenn das API Center fehlt, ist das Konto entweder kein Manager-Konto oder seine Einrichtung ist unvollständig.
Im API Center ein Developer Token beantragen. Den Kontotyp auf Advertiser (nicht Agency oder Third-Party) setzen, wenn das Token für die eigenen Konten bestimmt ist. Das Token wird sofort auf der Stufe Test Access ausgestellt.
Test Access erlaubt:
- Leseoperationen für jedes verknüpfte Konto
- Schreiboperationen nur für Testkonten
- Keine Schreiboperationen für Produktionskonten
Der Fehler bei Schreibvorgängen auf Produktionskonten mit Test Access lautet RESOURCE_NOT_FOUND — nicht PERMISSION_DENIED. Das ist irreführend, da die Ressource tatsächlich existiert und lesbar ist. Der Fehler bedeutet, dass die API die Mutation unter der aktuellen Zugriffsstufe ablehnt.
Basic Access-Antrag
Um auf Produktionskonten schreiben zu können, muss Basic Access über dieselbe API Center-Seite beantragt werden. Das Antragsformular stellt 12 Fragen. Für die interne Nutzung auf eigenen Konten lauten die relevanten Antworten:
| Frage | Antwort |
|---|---|
| Q4: Beziehung zu einem Google-Vertreter | Nein |
| Q6: Geschäftsmodell | Eigener Anwendungsfall beschreiben (E-Commerce, Lead-Generierung, internes Reporting) |
| Q8: Wer wird Zugriff haben | Interne Nutzer — nur Mitarbeiter |
| Q9: Von Drittanbietern entwickeltes Tool | Nein (eigene Skripte/Agenten) |
| Q10: Conversion Tracking & Remarketing API | Nein (es sei denn, sie wird tatsächlich genutzt) |
| Q11: Kampagnentypen | Search, Performance Max, Shopping (je nach Anwendungsfall) |
| Q12: Fähigkeiten | Kampagnenerstellung, Kampagnenverwaltung, Reporting |
Für Q7 ist ein Design-Dokument (PDF) erforderlich. Es sollte die API-Architektur, den Authentifizierungsablauf, die Rate-Limiting-Strategie, die Fehlerbehandlung und den rein internen Anwendungsfall beschreiben. Sachlich halten — das Compliance-Team prüft auf Konsistenz mit dem deklarierten Anwendungsfall.
Bearbeitungszeit Stand Juni 2026: etwa 3 Werktage, mit einem Hinweis auf ein überdurchschnittlich hohes Antragsvolumen.
Schritt 2: OAuth 2.0
Google Cloud-Projekt einrichten
In der Google Cloud Console unter dem entsprechenden Projekt:
- Die Google Ads API aktivieren (APIs & Services → Bibliothek)
- Den OAuth-Zustimmungsbildschirm konfigurieren:
- Nutzertyp: Internal (nur Nutzer der eigenen Google Workspace können autorisieren — umgeht die externe App-Verifizierung)
- App-Name, Support-E-Mail, Entwickler-Kontakt-E-Mail
- Den Scope unter Data Access hinzufügen:
https://www.googleapis.com/auth/adwords - Eine OAuth-Client-ID erstellen:
- Anwendungstyp: Desktop app
- Die Client-Secret-JSON herunterladen
Der Desktop-App-Typ verwendet http://localhost als Redirect-URI. Das ist korrekt — der OAuth-Flow öffnet einen Browser, Google leitet mit dem Authorization Code an localhost weiter, und ein lokaler HTTP-Server fängt ihn ab.
Refresh Token generieren
Ein Python-Skript, das einen lokalen HTTP-Server auf 127.0.0.1:0 (zufälliger Port) startet, die Autorisierungs-URL ausgibt, auf eine Anfrage wartet, den code-Parameter extrahiert und gegen Tokens eintauscht:
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())
Zwei Parameter sind entscheidend:
access_type='offline'— liefert ein Refresh Token, nicht nur ein Access Tokenprompt='consent'— erzwingt einen neuen Zustimmungsbildschirm, selbst wenn der Nutzer zuvor autorisiert hat; erforderlich, um ein neues Refresh Token zu erhalten, wenn sich die Scopes geändert haben
Das Refresh Token ist dauerhaft gültig, es sei denn, es wird widerrufen, der Nutzer ändert sein Passwort oder das Token wird 6 Monate lang nicht verwendet.
Scope-Fallstrick bei bestehenden Clients
Wenn der OAuth-Client zuvor für andere Scopes autorisiert wurde (Gmail, Drive, Calendar), gibt Google die Vereinigungsmenge aus alten und neuen Scopes zurück. Die google-auth-oauthlib-Bibliothek lehnt diese Scope-Abweichung standardmäßig ab. Die Umgebungsvariable vor dem Laden des Flows setzen:
import os
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'
Alternativ include_granted_scopes=true aus der Autorisierungs-URL weglassen, was Google anweist, nur den explizit übergebenen Scope anzufordern.
Schritt 3: `google-ads.yaml`
Die Bibliothek liest die Konfiguration aus einer YAML-Datei:
developer_token: <value>
client_id: <value>
client_secret: <value>
refresh_token: <value>
login_customer_id: 1911599764
use_proto_plus: true
Sicherheitsregeln:
- Dateiberechtigungen:
0600(nur Besitzer lesen/schreiben) - Niemals in die Versionskontrolle einchecken
- Außerhalb jedes Git-Repositories speichern
- Für Team-Setups über einen Secrets-Manager verteilen, nicht als geteilte Datei
login_customer_id ist die numerische MCC-ID ohne Bindestriche. Sie teilt der API mit, welches Developer Token des Manager-Kontos verwendet werden soll. Die Ziel-customer_id wird beim Aufruf übergeben, nicht in der Konfiguration.
use_proto_plus: true aktiviert die Protobuf-Plus-Schnittstelle, die für aktuelle API-Versionen erforderlich ist.
Schritt 4: Python-Client-Initialisierung
from google.ads.googleads.client import GoogleAdsClient
client = GoogleAdsClient.load_from_storage(
'/path/to/google-ads.yaml',
version='v22'
)
gs = client.get_service('GoogleAdsService')
Der version-Parameter wählt explizit die API-Version aus. Die google-ads-Bibliothek wird mit mehreren parallel installierten Versionen ausgeliefert (v19 bis v22 Stand Juni 2026). Immer die Version angeben — der Standardwert kann veraltet sein oder neuere Felder nicht unterstützen.
Konnektivität prüfen:
cs = client.get_service('CustomerService')
customers = cs.list_accessible_customers()
ids = [r.split('/')[-1] for r in customers.resource_names]
# Beispielausgabe: ['1305475941', '3977581086', '1911599764']
Schritt 5: Leseoperationen (GAQL)
Google Ads verwendet GAQL (Google Ads Query Language), eine SQL-ähnliche Syntax. Alle Leseoperationen laufen über GoogleAdsService.search_stream(), das Paginierung vermeidet und für die meisten Abfragen gegenüber search() bevorzugt wird.
Kampagnen mit Leistungskennzahlen
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
Kampagnenbudgets
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
Anzeigengruppen
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
Keywords (nach Impressionen)
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
Anzeigen mit Richtlinienstatus
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
Conversion-Aktionen
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
Python-Ausführungsmuster
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
Schritt 6: Schreiboperationen mit `validate_only`
Die v22-API erfordert Request-Objekte, keine Keyword-Argumente. Jeder Mutationsdienst (CampaignService, AdGroupService, AdGroupCriterionService, CampaignBudgetService) folgt demselben Muster:
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(), nicht .add()
client.get_service('CampaignService').mutate_campaigns(request=req)
Wesentliche Unterschiede zu älteren API-Versionen:
validate_onlyist ein Feld des Request-Objekts, kein Keyword-Argument der Mutate-Methode- Operationen werden über
req.operations.append(op)angehängt, nicht überreq.operations.add(op) - Ressourcenpfade sind explizite Strings (
'customers/1305475941/campaigns/22479990461'), keine Rückgabewerte von Hilfsmethoden
Drei-Phasen-Mutations-Gate
Zur Produktionssicherheit durchlaufen Mutationen drei Gates:
Gate 1 — validate_only=True: Die API validiert die Request-Struktur, Pflichtfelder und Ressourcenreferenzen. Es wird kein Objekt erstellt. Dieses Gate zuerst für jede Mutation ausführen.
Gate 2 — Pausierte Erstellung: validate_only=False setzen und das Objekt mit status=PAUSED erstellen. Das Ergebnis mit einer Leseabfrage prüfen, bevor fortgefahren wird.
Gate 3 — Live-Aktivierung: Ein separater API-Aufruf, der nur das status-Feld auf ENABLED aktualisiert. Dies sollte eine explizite Genehmigung erfordern und nicht in die Erstellung integriert werden.
# Gate 3: eine zuvor erstellte pausierte Kampagne aktivieren
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)
Budget-Update
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 pro Tag
op.update_mask.CopyFrom(field_mask_pb2.FieldMask(paths=['amount_micros']))
req.operations.append(op)
client.get_service('CampaignBudgetService').mutate_campaign_budgets(request=req)
Anzeigengruppen-Gebot aktualisieren
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)
Keyword-Erstellung
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)
Fehlerbehandlung
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}')
Häufige Fehlercodes und ihre Bedeutung:
| Fehlercode | Ursache |
|---|---|
| `RESOURCE_NOT_FOUND` | Test Access Token auf einem Produktionskonto (erwartet) oder tatsächlich fehlende Ressource |
| `REQUIRED` | Fehlendes Pflichtfeld (z. B. Gebotsstrategie bei Kampagnenerstellung) |
| `UNRECOGNIZED_FIELD` | Feld aus einer anderen API-Version oder falscher Feldname |
| `INVALID_ARGUMENT` | Feldwert scheitert an der Validierung (z. B. negatives Budget) |
| `PERMISSION_DENIED` | OAuth-Nutzer hat keinen Zugriff auf das Zielkonto |
API-Zugriffsstufen
Der Google Ads API-Zugriff ist gestuft, nicht binär:
| Stufe | Bereitstellung | Lesen (Produktion) | Schreiben (Produktion) | Schreiben (Testkonten) | Tägliches Ops-Limit |
|---|---|---|---|---|---|
| **Test Access** | Sofort aus dem MCC API Center | ✅ | ❌ | ✅ | 15.000 |
| **Basic Access** | Antrag + Compliance-Prüfung | ✅ | ✅ | ✅ | 15.000 |
| **Standard Access** | Ausgabenschwelle + Prüfung | ✅ | ✅ | ✅ | Unbegrenzt |
Test Access ist für die Entwicklung ausreichend: Authentifizierung, GAQL-Abfragen, validate_only-Tests und vollständiges Lesen/Schreiben auf Google Ads-Testkonten. Der Sprung zu Basic Access wird durch die Compliance-Prüfung gesteuert, nicht durch Ausgaben.
Standard Access entfernt die tägliche Operationsobergrenze. Es erfordert entweder eine nachgewiesene Historie von über das Token verwalteten Ausgaben oder einen separaten Antrag.
Testkonten
Testkonten sind kostenlose Google Ads-Konten ohne Abrechnung. Sie akzeptieren jede Mutation. Um eines zu erstellen: im MCC zu Accounts → + → Create new account → Test account gehen. Es mit dem MCC verknüpfen und als Ziel-customer_id während der Test-Access-Entwicklung verwenden.
`validate_only` über Zugriffsstufen hinweg
validate_only=True funktioniert auf allen Zugriffsstufen, aber Test Access lehnt validate_only-Mutationen auf Produktionskonten weiterhin mit RESOURCE_NOT_FOUND ab. Dies ist keine Einschränkung von validate_only — es ist dieselbe Zugriffskontrolle, die auf alle Schreiboperationen angewendet wird, unabhängig vom validate_only-Flag.
Conversion Tracking: API-Lesestatus vs. funktionaler Status
Die Google Ads-Benutzeroberfläche zeigt möglicherweise „Conversion-Tracking einrichten" als Empfehlung an, selbst wenn eine Conversion-Aktion existiert und aktiviert ist. Die API kann die Existenz einer Conversion-Aktion bestätigen (Typ WEBPAGE, Kategorie PURCHASE, Status ENABLED, include_in_conversions_metric: true), aber dies beweist nur, dass das Aktionsobjekt existiert. Es beweist nicht, dass die Website das entsprechende AW-.../label-Ereignis auslöst, dass das Google-Tag geladen ist oder dass ein Conversion-Signal empfangen wurde.
Bei der Prüfung des Conversion-Trackings die API-Prüfung (Conversion-Action-Metadaten) von der Browser-Prüfung (Netzwerk-Tab, Tag-Ladung, Ereignisauslösung) trennen. Die API ist die Quelle der Wahrheit für die Konfiguration; der Browser ist die Quelle der Wahrheit für die Ausführung.
Das Muster für Backend-Umsatzzuordnung gilt auch hier: Wenn clientseitige Conversion-Ereignisse unzuverlässig sind, serverseitige oder Offline-Conversion-Uploads über den Google Ads API ConversionUploadService als Fallback einplanen.
API-Versionierung
Die google-ads-Python-Bibliothek wird mit mehreren API-Versionen ausgeliefert. Stand Juni 2026 sind v19 bis v22 verfügbar. Jede Version fügt GAQL-Felder und Dienstmethoden hinzu, kennzeichnet sie als veraltet oder entfernt sie.
Regeln für die Versionsauswahl:
- Die Version explizit in
load_from_storage(version='v22')angeben. Der Standardwert kann veraltet sein. - Die Google Ads API-Versionshinweise auf Feld-Verwerfungen prüfen, bevor ein Upgrade durchgeführt wird.
- Die
search_stream-Methode ist ab v6+ verfügbar und der empfohlene Lesepfad. - Protobuf-plus (
use_proto_plus: true) ist für v12+ erforderlich. - Das Request-Objekt-Muster für Mutationen (
mutate_campaigns(request=req)) hat den Keyword-Argument-Stil in v17+ abgelöst.
Lokale Sicherheit
Alle Anmeldedatendateien müssen außerhalb der Versionskontrolle bleiben:
~/.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
Für das Arbeits-Repository eine .gitignore hinzufügen:
google-ads.yaml
*_token*.json
*_secret*.json
Eine Vorlagendatei mit Platzhalterwerten kann eingecheckt werden, um die erwartete Struktur zu dokumentieren:
# google-ads.yaml.template — diese Datei einchecken, lokal ausfüllen
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
Pflichtfelder für häufige Operationen
| Operation | Pflichtfelder |
|---|---|
| Kampagne erstellen (Search) | `name`, `status`, `advertising_channel_type`, `campaign_budget`, `manual_cpc` oder Gebotsstrategie |
| Anzeigengruppe erstellen (Search) | `name`, `status`, `type_`, `cpc_bid_micros`, `campaign` |
| Keyword erstellen | `ad_group`, `status`, `keyword.text`, `keyword.match_type` |
| Kampagnenstatus aktualisieren | `resource_name`, `status`, `update_mask` (paths: `['status']`) |
| Budget aktualisieren | `resource_name`, `amount_micros`, `update_mask` (paths: `['amount_micros']`) |
Ein fehlendes Pflichtfeld gibt REQUIRED mit dem Feldnamen zurück. Eine fehlende update_mask bei einer Update-Operation wird stillschweigend ignoriert — das Feld wird nicht aktualisiert und es wird kein Fehler zurückgegeben.
Vollständiges Testskript
Ein einzelnes Skript, das alle Entitätstypen liest und validate_only-Schreibtests ausführt:
# google_ads_api_test.py — alle Entitäten lesen + validate_only-Schreibtests
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')
# Alle Entitäten lesen
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")
# Schreibtests
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.')
Vollständige ausführbare Version im Google Ads API operations skill im Advertising-Operations-Repository.
Referenzen
- Google Ads API-Dokumentation
- google-ads Python-Bibliothek
- GAQL-Referenz
- OAuth 2.0 für Desktop-Apps
- Building a Project-Specific AI Assistant via Telegram — gleiches OAuth-Muster, angewendet auf einen anderen Google-Scope
- Reference Architecture for a Thread-Based AI Operations Layer — das Betriebsmodell, in das sich die API-Automatisierung einfügt
- Solo Operations at Scale: Managing Dozens of Projects with a Small Team — warum API-Automatisierung manuelle UI-Arbeit in großem Maßstab ersetzt