Keywords
Synced Search keyword criteria and the Keyword Planner
Keywords
Two different jobs: reading the keywords your campaigns already run (synced, free to query) and researching keywords you don't run yet (Keyword Planner, live against Google).
Synced keyword criteria
GET /v1/ads/keywords returns the Google Search keyword criteria (positive and negative) synced from connected accounts, one row per ad-group keyword.
const { data } = await zernio.adcampaigns.listAdKeywords({
query: {
accountId: 'ACCOUNT_ID',
adAccountId: '1234567890',
matchType: 'EXACT',
negative: false,
search: 'platform',
limit: 100,
},
});data = client.ad_campaigns.list_ad_keywords(
account_id="ACCOUNT_ID",
ad_account_id="1234567890",
match_type="EXACT",
negative=False,
search="platform",
limit=100,
)curl "https://zernio.com/api/v1/ads/keywords?accountId=ACCOUNT_ID&adAccountId=1234567890&matchType=EXACT&negative=false&search=platform&limit=100" \
-H "Authorization: Bearer YOUR_API_KEY"Filters: campaignId, adSetId (the Google ad group), status, matchType, negative (true = negative keywords only), and search (case-insensitive substring on the keyword text).
Refreshed about once a week per Google Ads customer. The keyword sweep rides the ads discovery pass on a slower slot to stay inside Google's shared daily API quota, so keywords added on Google can take several days to appear here. A newly connected account is populated on its first discovery pass, and a manual sync refreshes immediately. Campaign-level negative keywords are not included, only ad-group-level criteria.
For live, current-state keyword data (or campaign-level negatives), query GAQL directly: see Insights & GAQL.
Keyword Planner: ideas
POST /v1/ads/keywords/ideas runs Keyword Planner's idea generation from seed keywords, a seed URL, or both:
const { data } = await zernio.adinsights.generateKeywordIdeas({
body: {
accountId: 'ACCOUNT_ID',
seedKeywords: ['platform engineering tools'],
seedUrl: 'https://example.com/platform',
countries: ['US', 'GB'],
pageSize: 50,
},
});
// rows: { text, avgMonthlySearches, competition, competitionIndex,
// lowTopOfPageBidMicros, highTopOfPageBidMicros, monthlySearchVolumes[] }data = client.ad_insights.generate_keyword_ideas(
account_id="ACCOUNT_ID",
seed_keywords=["platform engineering tools"],
seed_url="https://example.com/platform",
countries=["US", "GB"],
page_size=50,
)curl -X POST "https://zernio.com/api/v1/ads/keywords/ideas" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "ACCOUNT_ID",
"seedKeywords": ["platform engineering tools"],
"seedUrl": "https://example.com/platform",
"countries": ["US", "GB"],
"pageSize": 50
}'Keyword Planner: historical metrics
POST /v1/ads/keywords/historical-metrics looks up exact keywords you already have (up to 1,000 per call): historical search volume, competition, top-of-page bid ranges, and averageCpcMicros when includeAverageCpc is set.
{
"accountId": "ACCOUNT_ID",
"keywords": ["internal developer platform", "platform engineering tools"],
"countries": ["US"],
"includeAverageCpc": true
}Shared rules
- Rows come back verbatim from Google: counters are int64s encoded as strings (parse before doing math), and every bid/CPC value is in micros of the account currency (divide by 1,000,000).
countriesomitted = worldwide.languageConstantIdpicks the language (1000 = English).customerIdis only needed when the connection has several Google Ads accounts.- Paging:
pageSize+pageTokenfrompaging.nextPageToken(ideas only; historical metrics is a single batch). - These run live against Google and count toward the per-user ops budget, see quotas.