# How to connect Google Ads to Hermes Agent (no API keys)

> Connect Google Ads to Hermes Agent with hosted OAuth, then keep it working: the GAQL queries Google rejects, the mutate fields that vanish silently, and the 10 tools your agent gets.

Web version: https://claw-link.dev/hermes/google-ads

Most guides for giving Hermes Agent Google Ads access start with registering your own OAuth app or pasting API keys into env files, then leave the token refresh and tool wiring to you. ClawLink gives Hermes a more practical Google Ads setup: pair once in the browser and your always-on Hermes agent can act on Google Ads for you, reading and doing real work on your behalf with no auth, token refresh, or tool wiring to build yourself.

**Start here — paste this into Hermes to set up ClawLink:**

> Set up ClawLink for Hermes and tell me when it's ready.
> 1. Install the plugin: `hermes plugins install ClawLink-HQ/hermes-plugin --enable`
> 2. Start pairing with `hermes clawlink begin`. It prints an approval link, so show me the link and stop, don't wait.
> 3. I'll approve it in my browser, then reply "approved".
> 4. When I say approved, finish setup: `hermes clawlink finish`
> 5. Then run `hermes clawlink test` and tell me whether ClawLink is ready.

## Setup

It takes three steps to connect Hermes to Google Ads.

1. **Install ClawLink** — add the plugin to Hermes Agent once.
2. **Connect Google Ads** — one-click OAuth in the ClawLink dashboard.
3. **Use it from chat** — ask Hermes Agent in plain English.

**Alternative for any agent (no plugin needed):** if the Hermes Agent plugin route isn't available or doesn't work, any AI agent with shell access can use the ClawLink CLI instead:

```bash
npx -y @useclawlink/cli login          # sign in via browser — no API key to paste
npx -y @useclawlink/cli connect google-ads  # connect Google Ads (browser OAuth)
npx -y @useclawlink/cli actions google-ads  # list available actions
npx -y @useclawlink/cli run google-ads <action> --input '<json>'  # execute (add --confirm for writes)
```

### Install by command

The prompt above walks Hermes through this. By hand, it is four commands and a browser approval:

```bash
hermes plugins install ClawLink-HQ/hermes-plugin --enable
hermes clawlink begin    # prints an approval link — open it and approve
hermes clawlink finish   # after approving in the browser
hermes clawlink test
```

Then connect Google Ads in the [ClawLink dashboard](https://claw-link.dev/dashboard) — a one-click OAuth approval, no API keys.

Verify the connection by asking Hermes:

> Use Google Ads to run: SELECT campaign.name, campaign.status, metrics.cost_micros, metrics.clicks, metrics.conversions FROM campaign WHERE segments.date DURING YESTERDAY ORDER BY metrics.cost_micros DESC. Divide cost_micros by 1,000,000 for real currency and flag anything that spent with zero conversions.

### Using a different agent?

The Hermes plugin is one client of ClawLink's MCP server. Claude Code, Cursor, Codex, or any agent that can run a shell command pairs with the same ClawLink account through the CLI:

```bash
npx -y @useclawlink/cli login
```

`login` opens the same browser approval and stores a credential locally. Once Google Ads is connected in the dashboard, that agent calls the same 10 Google Ads tools over MCP. Full setup for MCP clients and shell agents: [connect apps to any AI agent](https://claw-link.dev/learn/connect-apps-to-any-ai-agent).

## Google Ads MCP for Hermes

Looking for a Google Ads MCP server for Hermes Agent? ClawLink connects Google Ads to Hermes Agent and exposes 10 Google Ads tools your agent can call over [MCP](https://claw-link.dev/learn/what-is-an-mcp-server), with [hosted auth](https://claw-link.dev/learn/oauth-for-ai-agents) and nothing to run or maintain yourself. Using OpenClaw instead? The [OpenClaw Google Ads integration](https://claw-link.dev/openclaw/google-ads) works the same way.

Hosted OAuth is where most Google Ads guides stop, and it is the easy half. Connecting takes a browser approval either way, and ClawLink's version means you never register an OAuth app or hold a Google Ads API developer token, which on its own is worth avoiding: the token Google issues at signup is Test Account Access level and cannot read a live account, and production access is capped at 2,880 operations a day until you apply for more and wait roughly ten business days. The half nobody writes about is what happens next. Google Ads rejects more agent-written queries than any other integration we run, almost always for the same handful of reasons, and because Hermes works unattended a query that fails at 6am fails quietly. The sections below are the failures we log in production, with the corrections.

## What the Hermes Agent Google Ads integration can do

10 Google Ads tools are ready for Hermes Agent once the account is connected.

### All 10 Google Ads tools for Hermes

| Tool | What it does |
|---|---|
| **Add or remove to customer list** `googleads_add_or_remove_to_customer_list` | Add or remove contacts from a Google Ads customer list |
| **Create customer list** `googleads_create_customer_list` | Create a customer list in Google Ads |
| **Get campaign by ID** `googleads_get_campaign_by_id` | Get a Google Ads campaign by ID |
| **Get campaign by name** `googleads_get_campaign_by_name` | Get a Google Ads campaign by name |
| **Get customer lists** `googleads_get_customer_lists` | Get customer lists in Google Ads |
| **List accessible customers** `googleads_list_accessible_customers` | List Google Ads customers accessible to the account |
| **Mutate ad group criteria** `googleads_mutate_ad_group_criteria` | Create, update, or remove keywords and other ad group criteria |
| **Mutate ad groups** `googleads_mutate_ad_groups` | Create, update, or remove Google Ads ad groups |
| **Mutate campaigns** `googleads_mutate_campaigns` | Create, update, or remove Google Ads campaigns |
| **Search stream gaql** `googleads_search_stream_gaql` | Run a GAQL query stream in Google Ads |

## Example prompts

**Check yesterday's spend**

> Use Google Ads to run: SELECT campaign.name, campaign.status, metrics.cost_micros, metrics.clicks, metrics.conversions FROM campaign WHERE segments.date DURING YESTERDAY ORDER BY metrics.cost_micros DESC. Divide cost_micros by 1,000,000 for real currency and flag anything that spent with zero conversions.

**Find keywords burning budget**

> Use Google Ads to run: SELECT campaign.name, ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type, metrics.cost_micros, metrics.conversions FROM keyword_view WHERE segments.date DURING LAST_30_DAYS AND metrics.conversions = 0 ORDER BY metrics.cost_micros DESC LIMIT 25. Use keyword_view, not ad_group_criterion, because that resource has no metrics.

**Audit campaign settings**

> Use Google Ads to list my accounts, then for the one I name run: SELECT campaign.name, campaign.status, campaign.advertising_channel_type, campaign.bidding_strategy_type, campaign_budget.amount_micros FROM campaign WHERE campaign.status != 'REMOVED'. Tell me which campaigns share a budget.

**Pause an overspending campaign**

> Use Google Ads to find the campaign named "Shopping - All Products" with googleads_get_campaign_by_name, then pause it. Send an update containing only resource_name and status, with no update_mask, and show me the operations array before you send it.

## What Google Ads rejects, and the argument shapes that work

Ranked by how often we see them fail in production. ClawLink checks each one before the request reaches Google and hands the agent a correction, so these usually cost a turn rather than a debugging session, but an unattended agent still does better when the prompt steers it right the first time.

- **GAQL has no report resources.** `FROM campaign_performance_report` and its siblings belong to the AdWords API that Google retired, and they are the single most common failure on this toolkit because a decade of tutorials still use them. Metrics come off the entity: `FROM campaign`, `FROM ad_group`, `FROM ad_group_ad`.
- **Keyword metrics live on `keyword_view`.** `ad_group_criterion` looks like the keyword resource and is the natural guess, but it exposes no metrics at all, so any `metrics.*` selected next to it fails. `keyword_view` carries `ad_group_criterion.keyword.text`, `ad_group_criterion.keyword.match_type` and `metrics.*` together.
- **Ids are INT64.** `campaign.id = '23996552320'` is rejected for the quotes alone; write the number bare.
- **`device` is a segment, not a resource.** Select `segments.device` from a real resource rather than writing `FROM device`.
- **There are no subqueries.** `WHERE campaign.id IN (SELECT ...)` fails. Filter on the attributed resource in the same query, or run two queries and join them yourself.
- **`metrics.conversion_rate` is not a field.** The real one is `metrics.conversions_from_interactions_rate`, or derive it from `metrics.conversions` and `metrics.interactions`.
- **The mutate tools derive their own field mask and silently drop anything they do not recognise.** Passing `update_mask` does nothing because a supplied mask is discarded, and an unrecognised field is stripped before Google sees the request, which is why the error that comes back is `FIELD_MASK_MISSING` rather than a complaint about the field you actually sent. Campaign operations accept `name`, `status`, `start_date`, `end_date`, `daily_budget`, `campaign_budget`, `bidding_strategy_type`, `manual_cpc`, `network_settings`, `targeted_locations` and a few more; ad group creates accept `name`, `type`, `status`, `campaign`, and ad group updates accept only `name`, `status`, `resource_name`.
- **Portfolio bidding sub-fields are not writable here.** `target_cpa.target_cpa_micros`, `target_roas.target_roas` and `target_spend.cpc_bid_ceiling_micros` cannot be set through these tools, so a request to change a target CPA should end in an explanation rather than a retry.
- **Budgets move through `daily_budget` on `googleads_mutate_campaigns`.** There is no dedicated budget tool, which is why agents reach for `googleads_create_campaign_budget` and get nothing.
- **Money is in micros.** `metrics.cost_micros` is millionths of the account currency, so 12,340,000 means 12.34. Ask for the conversion or the numbers in your morning summary will be off by six orders of magnitude.

## ClawLink vs. building it yourself

The alternative to ClawLink is usually manual OAuth app setup plus your own token handling, permission troubleshooting, and tool plumbing for Hermes Agent. That is fine if you want to build and maintain the integration yourself. Most teams just want Google Ads working from chat.

| | Manual | ClawLink |
|---|---|---|
| **Connection flow** | Register a Google Ads app, configure redirect URLs, manage consent details, and reconnect users when auth settings drift. | Users connect Google Ads through the hosted browser flow and ClawLink keeps the token lifecycle out of your app code. |
| **Ongoing maintenance** | You own refresh logic, permission debugging, environment config, and every provider-specific edge case for Google Ads. | ClawLink handles the repetitive integration plumbing so your team can focus on the workflow instead of the infrastructure. |
| **Agent usability** | You still need to expose the right Google Ads actions to the runtime in a format your agent can reliably use. | 10 tools for Google Ads are already exposed through ClawLink, so the agent can read and act from chat immediately. |

## ClawLink vs. Composio

Composio also exposes Google Ads to AI agents. It is developer infrastructure: Python and TypeScript SDKs, an MCP server, and a catalog past 1,000 apps, aimed at teams shipping agent products. ClawLink is built for Hermes Agent users instead. You install the plugin once, connect Google Ads in the browser, and the 10 tools above work from chat. There is no SDK, no config file, and no API key handling. Choosing between them? Read the full [Composio alternatives](https://claw-link.dev/hub/composio-alternatives) comparison.

### Hermes paired but still can't use Google Ads
Pairing is a two-step handshake: run `hermes clawlink begin`, approve the link in your browser, then run `hermes clawlink finish`. If you ran finish before approving, or the approval link expired, run `hermes clawlink begin` again to get a fresh link. Confirm the plugin was installed with `--enable`, then verify with `hermes clawlink test`.

### Connection succeeds but no tools appear
Reconnect Google Ads from the dashboard, then start a fresh chat if the runtime still has the old tool catalog loaded.

### "Tool schema not loaded yet" error when calling Google Ads tools
Google Ads tool schemas load on demand the first time a tool runs and are cached after that, so this error usually clears on its own: wait a few seconds and retry the same request. If every Google Ads call keeps failing with it in a fresh chat, reconnect from the dashboard, and contact support if it still persists — that pattern points to a configuration problem on our side, not something you can fix by reconnecting again.

### Google Ads returns 403 or "permission denied" on one action while others work
Two usual causes. The connected account may not have access to the specific workspace, inbox, store, or project in the request — check that first. If access looks right, the agent may have sent a placeholder value (like "YOUR_ID" or an example id from documentation) instead of a real one: ask it to run a list or search tool first, then retry the action with a real id from those results. Most failures at this stage are one of these two, not ClawLink bugs.

### arguments.query is invalid GAQL. `*_performance_report` resources are from the legacy AdWords API and do not exist in GAQL.
Hermes wrote a query against `campaign_performance_report`, `keyword_performance_report` or another `*_performance_report` name. None of them exist. They come from the legacy AdWords reporting API, and they are so thoroughly baked into older tutorials and Stack Overflow answers that a model reaching for training data reproduces them by default. GAQL selects metrics from the entity instead, so the same report becomes `SELECT campaign.name, metrics.impressions, metrics.clicks, metrics.cost_micros FROM campaign WHERE segments.date DURING LAST_30_DAYS`. Left alone an agent tends to retry the identical query, so the fix is to tell it the resource does not exist rather than to ask it to try again.

Ask the agent to diagnose it:

```text
That resource is from the retired AdWords API. Rewrite the query in current GAQL, selecting metrics.* from campaign, ad_group, or keyword_view with a segments.date filter. Print the query before running it.
```

### FIELD_MASK_MISSING
The update reached Google with nothing in it. The mutate tools accept a fixed set of fields and discard the rest before the request goes out, so a campaign update carrying `budget_amount_micros` or a nested bidding-strategy object arrives empty and Google objects that there is no field mask. Supplying `update_mask` yourself does not help, because the mask is derived and a passed one is thrown away. Retry with supported fields only: `name`, `status`, `start_date`, `end_date`, `daily_budget`, `campaign_budget`, `bidding_strategy_type` and related settings on campaigns, and `name`, `status`, `resource_name` on ad group updates. If the goal was a bid ceiling or a target CPA, no retry will work, because those sub-fields are not writable through this toolkit.

Ask the agent to diagnose it:

```text
Print the operations array you sent. Drop any update_mask and every field outside the supported set, then tell me whether what I asked for is writable at all before you retry.
```

### PROHIBITED_SEGMENT_IN_SELECT_OR_WHERE_CLAUSE
This one comes from mixing `FROM conversion_action` with `segments.conversion_action` or `segments.conversion_action_name`. Google treats those segments as incompatible with the `conversion_action` resource and rejects the query rather than ignoring the clash. Pick a shape: keep `FROM conversion_action` and read `conversion_action.id` and `conversion_action.name` as plain attributes, or keep the segment and move to `FROM customer` or `FROM campaign`, in which case only conversion metrics such as `metrics.conversions`, `metrics.all_conversions` and `metrics.conversions_value` may sit beside it.

Ask the agent to diagnose it:

```text
Give me two rewrites: one with FROM conversion_action selecting conversion_action.name as an attribute, one with FROM campaign using segments.conversion_action_name and only conversion metrics. Run whichever answers my question.
```

### Tool 'googleads_create_campaign_budget' not found
That tool does not exist, and neither do `googleads_mutate_campaign_budgets`, `googleads_search`, `googleads_mutate_ad_group_ads` or `googleads_mutate_campaign_criteria`. The guesses are reasonable, because the Google Ads API really does have separate budget and criterion services, but this toolkit exposes ten tools and those are not among them. Budgets change through `daily_budget` on `googleads_mutate_campaigns`, and reporting runs through `googleads_search_stream_gaql` rather than a plain `googleads_search`. Ask Hermes to read the catalog before it guesses a second time.

Ask the agent to diagnose it:

```text
Run clawlink_list_tools for google-ads and show me every tool name it returns. Redo my request using only those names.
```

### OAuth finished in the browser but the account is still missing
Try reconnecting Google Ads and complete the consent flow in the same browser session. Partial OAuth approvals or switching accounts mid-flow can leave the connection incomplete.

### Is there a Hermes Agent Google Ads integration?
Yes. ClawLink is the fastest way to connect Hermes to Google Ads: link your Google Ads account once in the browser and Hermes Agent can call the Google Ads API through 10 ready-made tools — no custom code or token handling.

### How do I connect Google Ads to Hermes with ClawLink?
Install the plugin with `hermes plugins install ClawLink-HQ/hermes-plugin --enable`, then pair once: run `hermes clawlink begin`, approve the link in your browser, and run `hermes clawlink finish`. Connect Google Ads in the dashboard and Hermes can use it from the next message — no config files or API keys to manage.

### How long does it take to connect Google Ads to Hermes Agent?
About two minutes. Sign in, click Connect next to Google Ads in the dashboard, authenticate, and Hermes Agent can use it from the next chat message.

### Why use ClawLink instead of wiring Google Ads up myself?
The alternative to ClawLink is usually manual OAuth app setup plus your own token handling, permission troubleshooting, and tool plumbing for Hermes Agent. That is fine if you want to build and maintain the integration yourself. Most teams just want Google Ads working from chat.

### Does Hermes need a Google Ads API developer token?
No, and the reason this matters more than it sounds is what a fresh token can reach. Sign up for the Google Ads API and you are issued a token at Test Account Access level, which works against test accounts only, so it cannot read the account you actually spend money on. Production reads need Explorer access, which Google grants automatically only in some cases and which caps you at 2,880 operations per day; lifting that cap means applying for Standard access and waiting around ten business days. Connecting Google Ads through ClawLink uses hosted OAuth on Google's own consent screen, so there is no developer token, client secret, or refresh token in your setup at all.

### Why do Hermes Google Ads reports fail when the connection is fine?
Because the query is wrong, not the auth, and six patterns cover most of it: legacy `*_performance_report` resources, `FROM device` when device is a segment, `IN (SELECT ...)` subqueries that GAQL does not support, quoted numeric ids, `metrics.*` selected from `ad_group_criterion` instead of `keyword_view`, and `metrics.conversion_rate`, which is not a real field. ClawLink checks all six before the query leaves and returns the corrected form, so Hermes can fix it on the next turn instead of retrying something Google will never accept.

### Can Hermes adjust Google Ads budgets and bids on its own?
Budgets yes, bidding mostly no. `googleads_mutate_campaigns` takes a `daily_budget` field and that is the only budget control in the toolkit, so there is nothing to call for creating a separate budget resource. On bidding you can set `bidding_strategy_type` and `manual_cpc`, but the values inside a portfolio strategy, meaning `target_cpa.target_cpa_micros`, `target_roas.target_roas` and `target_spend.cpc_bid_ceiling_micros`, cannot be written through these tools. Because Hermes runs unattended, it is worth saying in the prompt that an unsupported change should be reported rather than retried.

### Do I have to give Hermes my Google Ads customer ID?
Usually not. `customer_id` is optional on `googleads_search_stream_gaql`, and most successful queries in production leave it out, so a missing customer ID is rarely why a call failed. It earns its place when you manage several accounts: have the agent run `googleads_list_accessible_customers` first and name the account you mean, which is what removes the ambiguity.

### Hermes paired but still can't use Google Ads
Pairing is a two-step handshake: run `hermes clawlink begin`, approve the link in your browser, then run `hermes clawlink finish`. If you ran finish before approving, or the approval link expired, run `hermes clawlink begin` again to get a fresh link. Confirm the plugin was installed with `--enable`, then verify with `hermes clawlink test`.

## Related

- [Hermes Google Classroom integration](https://claw-link.dev/hermes/google-classroom) — Manage classes, coursework, and students
- [Hermes Google Calendar integration](https://claw-link.dev/hermes/google-calendar) — Create and manage calendar events
- [Hermes Google Sheets integration](https://claw-link.dev/hermes/google-sheets) — Read and write spreadsheet data
