Gentic Google Ads — Documentation
Connect any AI agent to manage Google Search campaigns — keyword research, campaign creation, bid management, and performance analysis — all through the Model Context Protocol. OAuth connects in one click, and every mutating tool defaults to PAUSED for safe review.
1. Getting Started
Sign Up & Get Your API Key
Before you can use Gentic Google Ads, you need an API key to authenticate your requests.
- Go to gentic.co/google-ads and create an account.
- Create an organization from your dashboard. API keys and billing are scoped to the organization.
- Generate an API key and use it as a Bearer token in your MCP client.
2. Connecting to the MCP Server
The server is available at https://mcp.gentic.co/google-ads. For Claude Code:
claude mcp add gentic-google-ads \
--transport http \
https://mcp.gentic.co/google-ads \
--header "Authorization: Bearer YOUR_API_KEY"For Claude Web and ChatGPT you can also connect via OAuth — no API key needed. See the connect section on the landing page for other MCP clients (n8n, OpenClaw).
3. Agent Skill
For the best results, pair the MCP server with the Gentic Google Ads agent skill. The MCP server gives your agent tool access; the skill teaches it the optimal workflow order. Both the raw SKILL.md and a ready-to-upload .skill bundle are generated on demand from the live manifest, so they always reflect the current tools and pricing.
Add the skill directly via URL:
https://gentic.co/google-ads/SKILL.mdOr upload a .skill bundle to Claude Managed Agents:
https://gentic.co/google-ads/gentic-google-ads.skillDownload this file and upload it wherever Claude Managed Agents asks for a .skill file. It's a zip bundle generated on demand from the latest SKILL.md.
4. When to Apply
- User wants to create, manage, or optimize Google Search campaigns.
- User wants to research keywords with search volume, competition, and bid estimates.
- User wants to analyze Google Ads performance (spend, clicks, conversions, CTR, CPA, ROAS).
- User wants to create responsive search ads with headlines and descriptions.
- User wants to see which search terms are triggering their ads.
- User wants to run arbitrary GAQL queries against their Google Ads data.
- User wants to adjust campaign budgets, ad group CPC bids, or toggle campaign status (pause/enable).
- User wants to pause, enable, or remove individual ad groups or ads.
- User wants to add negative keywords to stop ads from showing on irrelevant queries.
- User wants to switch which Google Ads account (or MCC login account) the agent operates against.
5. Workflow
1. Check connection with `google_ads_connection_status`
Free call — returns whether the org has connected a Google Ads account, plus the selected customer ID. If not connected, direct the user to the Gentic dashboard Integrations section to authorize via OAuth. Use `list_accessible_customers` (also free) to see all accounts the credentials can access, keep only the ones where status is ENABLED and manager is false (manager accounts can't serve campaigns), then switch with `select_google_ads_account` — pass `loginCustomerId` to the MCC if the account is accessed via a manager. `select_google_ads_account` runs a smoke GAQL query and returns `verified: true/false` so you catch a bad combination before making real calls.
2. Research keywords with `generate_keyword_ideas` (25¢/call)
Provide seed `keywords`, a `pageUrl`, or both. Returns per-keyword average monthly searches, competition level (LOW/MEDIUM/HIGH), and top-of-page bid range in micros. Filter by `language` (default "en"), `geoTargetLocations` (default ["US"]), and `network`. Paginate with `pageSize` and `pageToken` for large result sets.
3. Create the campaign structure (25¢ per mutating call)
Build bottom-up: `create_campaign_budget` (daily amount in micros — 1 USD = 1,000,000) → `create_search_campaign` (references the budget, choose MANUAL_CPC or TARGET_CPA) → `create_ad_group` (set default CPC bid) → `add_keywords` (1-200 keywords with BROAD/PHRASE/EXACT match types) → `create_responsive_search_ad` (3-15 headlines ≤30 chars, 2-4 descriptions ≤90 chars). **Everything defaults to PAUSED.** To create ENABLED campaigns that spend immediately, pass `status="ENABLED"` AND `confirmEnableSpend=true`.
4. Pull structured performance with `get_campaign_performance` (15¢/call)
Returns impressions, clicks, cost, conversions, CTR, CPA, and ROAS grouped by campaign. Use `dateRange` with a preset (`LAST_7_DAYS`, `LAST_30_DAYS`, etc.) or custom `startDate`/`endDate`. Drill down with `get_ad_group_performance` and `get_keyword_performance` (both 15¢). Filter by `campaignId` or `adGroupId` to narrow results.
5. Get AI-narrated analysis with `analyze_campaign` (50¢/call)
Pulls performance for the requested period and the prior equivalent period, then returns a ranked narrative comparing the two with winners, losers, and concrete recommendations. Use this when the user wants strategic insights rather than raw numbers. Filter to specific campaigns with `campaignIds`.
6. Investigate search terms with `get_search_terms_report` (15¢/call)
Shows the actual user queries that triggered ads — critical for finding negative keyword candidates and wasted spend. Filter by `campaignId`, `adGroupId`, and `minImpressions`. Present results as a ranked table by impressions or cost, highlighting irrelevant queries the user should add as negatives.
7. Exclude irrelevant queries with `add_negative_keywords` (25¢/call)
Once you've identified wasted spend in the search terms report, use `add_negative_keywords` to stop ads from serving on those queries. Pass `level: "campaign"` with `campaignResourceName` to exclude across the whole campaign (most common), or `level: "adGroup"` with `adGroupResourceName` for narrower exclusion. 1–200 keywords per call, each with a `matchType` of BROAD, PHRASE, or EXACT.
8. Run arbitrary queries with `run_gaql_query` (15¢/call)
Execute any Google Ads Query Language query when the built-in tools don't cover a specific metric or dimension. Capped at 1,000 rows per call — paginate with `pageSize` and `pageToken`. Use this for edge cases like segmenting by device, hour of day, or custom attribute combinations.
9. Adjust budgets, bids, and status after launch (25¢ per mutating call)
Once campaigns are live, use `update_campaign_budget` to change the daily amount (in micros) on an existing budget resource, `update_ad_group_bid` to change an ad group's default CPC (also in micros — sanity-check the digit count), and `update_campaign_status` / `update_ad_group_status` / `update_ad_status` to pause, enable, or remove a campaign, ad group, or individual ad. Status accepts `ENABLED`, `PAUSED`, or `REMOVED`. Note that `update_ad_status` takes the `AdGroupAd` resource name, not a raw ad ID; transitioning anything to `ENABLED` is gated by `confirmEnableSpend: true`, and transitioning to `REMOVED` is gated by `confirmRemove: true` — see Notes for all three.
10. Present results clearly
For performance: lead with the headline metric (spend, CTR, top performer), show a ranked table, and call out outliers or period-over-period changes. For campaign creation: echo back the resource names, budget (in dollars, not micros), bidding strategy, and the fact that everything is **PAUSED — needs manual activation**. For keyword research: rank by search volume, highlight low-competition/high-volume opportunities.
6. Tool Reference
21 tools, rendered live from the Gentic MCP manifest. Parameter tables come directly from each tool's JSON Schema.
add_keywords
Bulk-add keywords to an ad group. Each keyword has a text and a match type (BROAD, PHRASE, or EXACT). 1–200 keywords per call.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
adGroupResourceNamerequired | string | — |
keywordsrequired | object[] | — |
add_negative_keywords
Bulk-add negative keywords at either the campaign or ad-group level. Set level="campaign" with campaignResourceName to exclude across the whole campaign (most common), or level="adGroup" with adGroupResourceName for narrower exclusion. Each keyword has a text and a match type (BROAD, PHRASE, or EXACT). 1–200 keywords per call.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
levelrequired | string | — enum: campaign, adGroup |
campaignResourceName | string | Required when level="campaign". |
adGroupResourceName | string | Required when level="adGroup". |
keywordsrequired | object[] | — |
analyze_campaign
AI-narrated campaign analysis: pulls performance for the requested period and the prior equivalent period, then returns a ranked narrative comparing the two with winners, losers, and concrete recommendations.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
dateRangerequired | any | — |
campaignIds | string[] | — |
create_ad_group
Create a SEARCH_STANDARD ad group inside a campaign with a default CPC bid. Defaults to PAUSED.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
campaignResourceNamerequired | string | — |
namerequired | string | — |
cpcBidMicrosrequired | string | — |
status | string | — enum: PAUSED, ENABLED |
create_campaign_budget
Create a Google Ads campaign budget. amountMicros is the daily budget in micros (1 USD = 1,000,000). ⚠️ Double-check the digit count before submitting — values ≥ 100,000,000 ($100/day) are typo-prone (an extra zero turns $10/day into $100/day). Confirm the intended dollar amount with the user when amountMicros exceeds 100,000,000.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
namerequired | string | — |
amountMicrosrequired | string | — |
deliveryMethod | string | — enum: STANDARD, ACCELERATED |
create_responsive_search_ad
Create a responsive search ad inside an ad group. Requires 3–15 headlines (≤30 chars each) and 2–4 descriptions (≤90 chars each). Defaults to PAUSED. ⚠️ path1/path2 render in the ad's DISPLAYED URL (e.g. example.com/path1/path2) — they're cosmetic breadcrumbs that should describe the landing page's content ("hydration", "sale") and do NOT need to match a real route on finalUrls. Don't fabricate paths that imply a section that doesn't exist; omit them entirely to show only the bare domain.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
adGroupResourceNamerequired | string | — |
finalUrlsrequired | string[] | — |
headlinesrequired | object[] | — |
descriptionsrequired | object[] | — |
path1 | string | Cosmetic display-URL segment (≤15 chars). Renders as example.com/{path1} in the ad — does NOT need to exist as a real route on finalUrls. Use to describe content (e.g. "hydration"), not to imply non-existent sections. Omit to show only the bare domain. |
path2 | string | Cosmetic display-URL second segment (≤15 chars). Renders as example.com/{path1}/{path2}. Same rules as path1: cosmetic only, not a real route. |
status | string | — enum: PAUSED, ENABLED |
create_search_campaign
Create a SEARCH-channel Google Ads campaign referencing a budget. Defaults to PAUSED — to create an ENABLED campaign that spends immediately, you MUST pass status="ENABLED" AND confirmEnableSpend=true. Bidding is either manual CPC or target CPA. Defaults `containsEuPoliticalAdvertising` to DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING (required by EU TTPA regulation on every new campaign); pass CONTAINS_EU_POLITICAL_ADVERTISING only if the campaign actually runs EU political ads. STRONGLY recommended to pass `geoTargetLocations` (e.g. ["US"]) and `language` (e.g. "en") — if omitted, the campaign serves globally in all languages, which usually wastes budget. These are written as separate CampaignCriterion records after the campaign is created.
| Parameter | Type | Description |
|---|---|---|
customerId | string | — |
namerequired | string | — |
budgetResourceNamerequired | string | — |
biddingStrategyrequired | any | — |
networkSettings | object | — |
startDate | string | — |
endDate | string | — |
status | string | — enum: PAUSED, ENABLED |
confirmEnableSpend | boolean | — |
containsEuPoliticalAdvertising | string | — enum: DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING, CONTAINS_EU_POLITICAL_ADVERTISING |
geoTargetLocations | string[] | — |
language | string | — |
generate_keyword_ideas
Discover new keyword ideas relevant to a business using Google's Keyword Planner data (KeywordPlanIdeaService). Provide seed keywords, a landing-page URL, or both. Returns per-keyword average monthly searches, competition level, and top-of-page bid range.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
keywords | string[] | — |
pageUrl | string | — |
language | string | ISO language code (e.g. "en") or raw languageConstants/{id}. Default "en". |
geoTargetLocations | string[] | 2-letter country codes (e.g. ["US","CA"]) or raw geoTargetConstants/{id}. Default ["US"]. |
network | string | — enum: GOOGLE_SEARCH, GOOGLE_SEARCH_AND_PARTNERS |
includeAdultKeywords | boolean | — |
pageSize | integer | — 1 – 1000 |
pageToken | string | — |
get_ad_group_performance
Structured ad-group performance metrics for a date range. Optionally filter to a single campaign.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
dateRangerequired | any | — |
campaignId | string | — |
get_campaign_performance
Structured campaign performance: impressions, clicks, cost, conversions, CTR, CPA, ROAS for a date range, grouped by campaign and sorted by spend.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
dateRangerequired | any | — |
campaignIds | string[] | — |
get_keyword_performance
Structured keyword-level performance including quality score, for a date range.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
dateRangerequired | any | — |
campaignId | string | — |
adGroupId | string | — |
get_search_terms_report
Search-terms report — the actual user queries that triggered ads. Useful for identifying negative-keyword candidates. Filter by campaign, ad group, and/or minimum impressions.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
dateRangerequired | any | — |
campaignId | string | — |
adGroupId | string | — |
minImpressions | integer | — 0 – 9007199254740991 |
google_ads_connection_status
Check whether this organization has connected a Google Ads account. Returns the connection status plus stored customer IDs. Does not call Google.
This tool takes no parameters.
list_accessible_customers
List all Google Ads customer accounts the connected credentials can access, enriched with account name, currency, time zone, manager flag, and status (ENABLED / CANCELED / SUSPENDED / CLOSED). Only ENABLED non-manager accounts can serve campaigns — agents should filter to status=='ENABLED' && manager==false when picking a target customer, and use select_google_ads_account to set it.
This tool takes no parameters.
run_gaql_query
Execute an arbitrary Google Ads Query Language (GAQL) query via GoogleAdsService.search. Paginated; capped at GOOGLE_ADS_MAX_ROWS_PER_QUERY (default 1000) per call.
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
queryrequired | string | Raw GAQL query string |
pageSize | integer | — 1 – 1000 |
pageToken | string | — |
select_google_ads_account
Update which Google Ads account this org operates against. Set `selectedCustomerId` to change the default customer used by other tools when no customerId is passed. Set `loginCustomerId` to the manager (MCC) ID that contains that customer — required when the account is accessed via an MCC. Pass `loginCustomerId: null` to clear it (use only for direct-access non-managed accounts). Run `list_accessible_customers` first to see valid IDs and identify which one is a manager. After saving, runs a smoke GAQL query against the new combination and returns `verified: true` on success or `verified: false` plus `verificationError` when the credentials don't actually work — check this before making real API calls.
| Parameter | Type | Description |
|---|---|---|
selectedCustomerId | string | 10-digit customer ID (or customers/{id} resource name) to set as the default customer for subsequent tool calls. |
loginCustomerId | any | 10-digit manager (MCC) ID to send as the login-customer-id header. Pass null to clear. Required when the selected customer is accessed via an MCC. |
update_ad_group_bid
Update an ad group's default CPC bid (cpcBidMicros). ⚠️ cpcBidMicros is in micros (1 USD = 1,000,000; e.g. $3.50 = 3500000) — double-check the digit count before submitting. Confirm the intended dollar amount with the user when cpcBidMicros exceeds 20,000,000 ($20/click).
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
adGroupResourceNamerequired | string | — |
cpcBidMicrosrequired | string | — |
update_ad_group_status
Change an ad group's status to ENABLED, PAUSED, or REMOVED. status="ENABLED" requires confirmEnableSpend=true (explicit opt-in to start serving ads). status="REMOVED" requires confirmRemove=true (irreversible — Google Ads cannot restore a removed ad group; prefer PAUSED if you only want to stop serving).
| Parameter | Type | Description |
|---|---|---|
customerId | string | — |
adGroupResourceNamerequired | string | — |
statusrequired | string | — enum: ENABLED, PAUSED, REMOVED |
confirmEnableSpend | boolean | — |
confirmRemove | boolean | — |
update_ad_status
Change an ad's status to ENABLED, PAUSED, or REMOVED. Operates on the AdGroupAd resource (resource name format: customers/{cid}/adGroupAds/{adGroupId}~{adId}), which is what `create_responsive_search_ad` returns. status="ENABLED" requires confirmEnableSpend=true. status="REMOVED" requires confirmRemove=true (irreversible — Google Ads cannot restore a removed ad; prefer PAUSED if you only want to stop serving).
| Parameter | Type | Description |
|---|---|---|
customerId | string | — |
adGroupAdResourceNamerequired | string | — |
statusrequired | string | — enum: ENABLED, PAUSED, REMOVED |
confirmEnableSpend | boolean | — |
confirmRemove | boolean | — |
update_campaign_budget
Update the daily amount (in micros) of a campaign budget. ⚠️ amountMicros is in micros (1 USD = 1,000,000) — double-check the digit count before submitting. Confirm the intended dollar amount with the user when amountMicros exceeds 100,000,000 ($100/day).
| Parameter | Type | Description |
|---|---|---|
customerId | string | Google Ads customer ID (10-digit numeric, or a full resource name like customers/1234567890). If omitted, uses the selected_customer_id stored on the connection. |
budgetResourceNamerequired | string | — |
amountMicrosrequired | string | — |
update_campaign_status
Change a campaign's status to ENABLED, PAUSED, or REMOVED. status="ENABLED" requires confirmEnableSpend=true (explicit opt-in to start spending). status="REMOVED" requires confirmRemove=true (irreversible — Google Ads cannot restore a removed campaign; prefer PAUSED if you only want to stop spending).
| Parameter | Type | Description |
|---|---|---|
customerId | string | — |
campaignResourceNamerequired | string | — |
statusrequired | string | — enum: ENABLED, PAUSED, REMOVED |
confirmEnableSpend | boolean | — |
confirmRemove | boolean | — |
7. Pricing
Pricing is pulled live from the Gentic MCP manifest. All prices are per call and deducted from your Gentic credits.
| Tool | Cost |
|---|---|
| add_keywords | 25¢ / call |
| add_negative_keywords | 25¢ / call |
| analyze_campaign | 50¢ / call |
| create_ad_group | 25¢ / call |
| create_campaign_budget | 25¢ / call |
| create_responsive_search_ad | 25¢ / call |
| create_search_campaign | 25¢ / call |
| generate_keyword_ideas | 25¢ / call |
| get_ad_group_performance | 15¢ / call |
| get_campaign_performance | 15¢ / call |
| get_keyword_performance | 15¢ / call |
| get_search_terms_report | 15¢ / call |
| google_ads_connection_status | Free |
| list_accessible_customers | Free |
| run_gaql_query | 15¢ / call |
| select_google_ads_account | Free |
| update_ad_group_bid | 25¢ / call |
| update_ad_group_status | 25¢ / call |
| update_ad_status | 25¢ / call |
| update_campaign_budget | 25¢ / call |
| update_campaign_status | 25¢ / call |
8. Notes
- **OAuth required.** Users must connect their Google Ads account via the Gentic dashboard before the agent can access any tools (except `google_ads_connection_status`, `list_accessible_customers`, and `select_google_ads_account` — all free).
- `customerId` is optional on most tools — if omitted, it uses the `selected_customer_id` stored on the connection. Change the default with `select_google_ads_account`, or pass `customerId` explicitly on a single call to operate on a different account.
- **MCC accounts:** if the target customer is accessed via a manager account, set `loginCustomerId` on `select_google_ads_account` to that manager's 10-digit ID. Pass `loginCustomerId: null` only for direct-access, non-managed accounts. `select_google_ads_account` verifies the combination with a smoke GAQL query and returns `verified: false` + `verificationError` if the credentials don't actually work — check this before making real calls.
- **Budgets and bids are in micros** — 1 USD = 1,000,000 micros. `amountMicros: "5000000"` = $5/day.
- All campaigns, ad groups, and ads are created in **PAUSED** status by default. Enabling spend — at creation OR via `update_campaign_status` / `update_ad_group_status` / `update_ad_status` — requires `status: "ENABLED"` AND `confirmEnableSpend: true`.
- Removing a campaign, ad group, or ad via `update_*_status` with `status: "REMOVED"` requires `confirmRemove: true` and is **irreversible** — Google Ads cannot restore a removed entity. Prefer `PAUSED` if you only want to stop serving.
- `update_ad_status` operates on the `AdGroupAd` resource. Use the `adGroupAdResourceName` returned by `create_responsive_search_ad` (format `customers/{cid}/adGroupAds/{adGroupId}~{adId}`), not the raw ad ID.
- `update_ad_group_bid` takes `cpcBidMicros` in micros (1 USD = 1,000,000). Double-check the digit count before submitting and confirm the dollar amount with the user when it exceeds 20,000,000 ($20/click).
- Responsive search ads require **3-15 headlines** (≤30 chars each) and **2-4 descriptions** (≤90 chars each). Use `pinnedField` to lock a headline or description to a specific position.
- `path1` / `path2` on responsive search ads are cosmetic breadcrumbs on the displayed URL — they don't need to match a real route on `finalUrls`. Omit them entirely to show only the bare domain.
- `create_search_campaign` defaults `containsEuPoliticalAdvertising` to `DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING` — required by EU TTPA on every new campaign. Pass `CONTAINS_EU_POLITICAL_ADVERTISING` only when the campaign actually runs EU political ads.
- Strongly recommended to pass `geoTargetLocations` (e.g. `["US"]`) and `language` (e.g. `"en"`) on `create_search_campaign` — if omitted, the campaign serves globally in all languages, which usually wastes budget.
- `generate_keyword_ideas` needs at least one of `keywords` or `pageUrl`. Provide both for the best results.
- `run_gaql_query` is capped at 1,000 rows per call. Use `pageSize` and `pageToken` for pagination.
- Performance tools cost 15¢/call, mutating tools cost 25¢/call, and `analyze_campaign` costs 50¢/call. Connection, account listing, and account selection are free.
- All tools are organization-scoped — users only see their own Google Ads accounts.