AnswerixAI Docs AnswerixAI Docs AI Search Visibility, GEO & AEO platform

Google Ads API setup

Obtain the free Google Ads API credentials that power prompt volume analysis.

On this page 8

Google Ads API — Operational Setup Guide

The prompt search-volume feature (app/Services/Volumes/GoogleAdsClient.php) pulls keyword volumes straight from Google Ads Keyword Planner via the generateKeywordHistoricalMetrics REST endpoint. This replaced the paid DataForSEO subscription — DataForSEO resold this exact data, so numbers and location codes are identical. The API itself is free; you only need the credentials below.

Credentials you'll end up with

Env variable What it is Where it comes from
GOOGLE_ADS_DEVELOPER_TOKEN API access token for your Ads organization Google Ads manager account → API Center
GOOGLE_ADS_CLIENT_ID / GOOGLE_ADS_CLIENT_SECRET OAuth2 app identity Google Cloud Console → Credentials
GOOGLE_ADS_REFRESH_TOKEN Long-lived token for your Google login One-time OAuth consent flow
GOOGLE_ADS_CUSTOMER_ID The Ads account queried for metrics (10 digits, no dashes) Google Ads UI, top-right
GOOGLE_ADS_LOGIN_CUSTOMER_ID Manager (MCC) account ID — only if the account above sits under one Manager account, top-right

Step 1 — Create a Google Ads manager account (MCC) and get the developer token

Developer tokens are only issued to manager accounts, not regular Ads accounts.

  1. Create a manager account at https://ads.google.com/home/tools/manager-accounts/ (use the company Google account, e.g. the one behind [email protected]).
  2. If you have a regular Google Ads account already, link it under the manager account (Accounts → Sub-account settings → Link existing account).
  3. In the manager account: Admin (Tools & Settings) → API Center.
  4. Accept the terms → your developer token appears. Copy it.
  5. The token starts at Test Account access level — it can only query test accounts and returns dummy data. On the same API Center page, apply for Basic access (short form: describe the use case as "internal SEO tool fetching keyword search volumes via KeywordPlanIdeaService"). Approval typically takes 1–3 business days. Basic access allows 15,000 operations/day — far more than we need.

The token string itself never changes when access is upgraded; only its permission level does.

Step 2 — Google Cloud project + OAuth client

  1. Go to https://console.cloud.google.com/ → create a project (e.g. answerix-ads-api).
  2. APIs & Services → Library → search "Google Ads API" → Enable.
  3. APIs & Services → OAuth consent screen:
    • User type: External → Create.
    • Fill app name + support email; no scopes need to be added on the form itself.
    • Add the Google account that owns the Ads manager account as a test user.
  4. APIs & Services → Credentials → Create Credentials → OAuth client ID:
    • Application type: Desktop app.
    • Copy the Client ID and Client Secret.
  5. Important: while the consent screen is in Testing status, refresh tokens expire after 7 days. Once everything works, go back to the OAuth consent screen and click Publish app (no verification is needed for the adwords scope used by your own account) — refresh tokens then stop expiring.

Step 3 — Generate the refresh token (one-time)

Easiest path — OAuth Playground:

  1. Open https://developers.google.com/oauthplayground.
  2. Click the ⚙️ gear (top right) → check "Use your own OAuth credentials" → paste your Client ID and Client Secret.
  3. In "Step 1" on the left, enter the scope manually: https://www.googleapis.com/auth/adwordsAuthorize APIs.
  4. Sign in with the Google account that owns the Ads manager account and consent.
  5. In "Step 2", click Exchange authorization code for tokens.
  6. Copy the Refresh token.
Alternative: curl-only flow (no Playground)
bash
# 1. Open this URL in a browser, consent, and copy the code Google shows you:
open "https://accounts.google.com/o/oauth2/v2/auth?client_id=CLIENT_ID&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/adwords&access_type=offline&prompt=consent"

# 2. Exchange the code:
curl -s https://oauth2.googleapis.com/token \
  -d client_id=CLIENT_ID -d client_secret=CLIENT_SECRET \
  -d code=THE_CODE -d grant_type=authorization_code \
  -d redirect_uri=urn:ietf:wg:oauth:2.0:oob

The JSON response contains refresh_token.

Step 4 — Customer IDs

  • GOOGLE_ADS_CUSTOMER_ID: the ID of the (non-manager) Ads account metrics are requested against. Shown top-right in the Ads UI as 123-456-7890 → enter as 1234567890 (strip dashes).
  • GOOGLE_ADS_LOGIN_CUSTOMER_ID: the manager account's ID — required whenever the customer account is accessed through the MCC (which is the normal setup here, since the developer token lives on the MCC). Same format, no dashes.

Step 5 — Configure and verify

Fill the block in .env:

dotenv
GOOGLE_ADS_DEVELOPER_TOKEN=xxxxxxxxxxxxxxxxxxxxxx
GOOGLE_ADS_CLIENT_ID=xxxxxxxx.apps.googleusercontent.com
GOOGLE_ADS_CLIENT_SECRET=GOCSPX-xxxxxxxx
GOOGLE_ADS_REFRESH_TOKEN=1//xxxxxxxx
GOOGLE_ADS_CUSTOMER_ID=1234567890
GOOGLE_ADS_LOGIN_CUSTOMER_ID=9876543210

Verify end-to-end (should print a real volume map):

bash
php artisan tinker --execute 'print_r(app(App\Services\Volumes\GoogleAdsClient::class)->getSearchVolumes(["crm software"], ["locationCode" => 2840, "languageCode" => "en"]));'

Expected shape:

php
["crm software" => ["volume" => 74000, "competitionIndex" => 89, "competition" => "HIGH"]]

Troubleshooting

Error Cause / fix
DEVELOPER_TOKEN_NOT_APPROVED Token still at Test Account level — wait for Basic access approval (Step 1.5).
invalid_grant on token refresh Refresh token expired (consent screen still in Testing → publish the app, Step 2.5) or was revoked — redo Step 3.
USER_PERMISSION_DENIED The OAuth Google account can't access GOOGLE_ADS_CUSTOMER_ID, or GOOGLE_ADS_LOGIN_CUSTOMER_ID is missing/wrong for an MCC-linked account.
CUSTOMER_NOT_FOUND Customer ID has dashes or is the MCC ID instead of the client account ID.
Metrics all zero Brand-new Ads accounts with no billing history get bucketed/limited Keyword Planner data. Add billing info to the customer account (no spend required).

Operational notes

  • Quota: Basic access = 15,000 operations/day. One volume analysis ≈ 1 operation (up to 10,000 keywords per request), so quota is a non-issue.
  • Token caching: the app caches the OAuth access token (~1 h) in the Laravel cache; the refresh token itself is what lives in .env.
  • Location/language codes: stored location_code values (2840 = US, …) are Google's own geoTargetConstants IDs — unchanged from the DataForSEO era. Mapping lives in app/Support/GoogleAdsCodes.php.
  • API version: the client pins v21 in GoogleAdsClient::API_BASE. Google sunsets versions roughly yearly; bump the constant when deprecation emails arrive.