← Windsor.ai Google AdsCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Windsor.ai Google Ads
Snapshot Sep 30, 2026 · 22:47 UTC · version 1.0.0
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"description": "Analyze and manage Google Ads through Windsor.ai. Use when the user asks about their Google Ads performance — pulling live campaign, ad group, or keyword metrics (cost, impressions, clicks, conversions, CPA, ROAS), comparing date ranges, or finding top or underperforming campaigns — or when they want to pause or enable a campaign or change a campaign budget. Do not use for other ad platforms (Meta/Facebook, TikTok, LinkedIn, Microsoft Ads), organic social, or GA4/website analytics.",
"included_files": [
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 496
}
],
"name": "google-ads",
"skill_md_contents": "---\nname: google-ads\ndescription: Analyze and manage Google Ads through Windsor.ai. Use when the user asks about their Google Ads performance — pulling live campaign, ad group, or keyword metrics (cost, impressions, clicks, conversions, CPA, ROAS), comparing date ranges, or finding top or underperforming campaigns — or when they want to pause or enable a campaign or change a campaign budget. Do not use for other ad platforms (Meta/Facebook, TikTok, LinkedIn, Microsoft Ads), organic social, or GA4/website analytics.\n---\n\n# Google Ads via Windsor.ai\n\nWindsor.ai exposes live Google Ads data (read) and a small set of campaign\nmanagement actions (write) through MCP tools. The connector id is\n`google_ads`. On the Google Ads app the connector is already scoped, so you\nusually do not need to pass it — but when a tool asks for a connector, use\n`google_ads`.\n\nGolden rules:\n\n- **Never guess field, account, action, or option names.** They come from\n `get_fields`, `get_connectors`, `list_actions`, and `get_options`. Call those\n first; do not invent identifiers.\n- **Reads are safe; writes change live ad spend.** Only call `execute_action`\n after the user has confirmed the specific change.\n- Report numbers the user asked for, concisely. Don't dump raw rows unless asked.\n\n## 1. Ground yourself first\n\nCall `get_connectors` to see which Google Ads accounts are connected (each has\nan id and, usually, a name). If none are connected, help the user connect one:\ncall `get_connector_authorization_url` (or `get_connector_connect_info` for the\nauth type and steps) and give them the setup link — do not describe manual\ndashboard navigation.\n\nIf the user names an account, match it to a connected account id. If several are\nconnected and the request is ambiguous, ask which account.\n\n## 2. Reading performance data\n\n1. Call `get_fields` for `google_ads` to get valid field ids (e.g. campaign,\n ad_group, date, cost/spend, impressions, clicks, conversions, conversion\n value — use the exact ids returned, not these examples).\n2. If the analysis needs attribution or segmentation controls, call\n `get_options` to see the connector's options and valid values.\n3. Call `get_data` with:\n - `fields`: the ids you actually need (keep the set small).\n - `accounts`: the target account id(s); omit for all connected accounts.\n - A date range: either `date_from`/`date_to` (`\"2026-02-01\"`), or\n `date_preset` — `last_7d`, `last_30d`, `last_Xd`/`last_Xw`/`last_Xm`,\n `this_month`, `this_year`, `last_year`. Append `T` to include today\n (e.g. `last_7dT`, `this_monthT`).\n - `options`: only if get_options showed relevant ones.\n - `filters`: optional conditions, e.g. `[[\"cost\", \"gt\", 100]]`; combine with\n `\"and\"`/`\"or\"` and nest as needed.\n\nCommon requests → recipe:\n\n- **Overview / trend:** fields `date` + the metrics, over a preset range.\n- **By campaign:** fields `campaign` + metrics; sort/aggregate in your answer.\n- **Best / worst campaign:** pull campaign + the metric, then rank; return only\n what was asked (e.g. just the campaign name) if the user constrained the\n output format.\n- **Efficiency:** cost per conversion = cost ÷ conversions; ROAS = conversion\n value ÷ cost. Compute from returned fields; note if conversions are zero.\n\nWatch out: Google Ads money fields are in the account currency (state it if\nknown). Conversions can be fractional. If a field the user wants isn't in\n`get_fields`, say so rather than substituting a different metric.\n\n## 3. Managing campaigns (write actions)\n\nGoogle Ads exposes exactly **three** write actions via `list_actions` /\n`execute_action`. Always call `list_actions` first to confirm the exact action\nids and parameter schemas — treat the list below as guidance, not gospel:\n\n- **`pause_campaign`** — params: `campaign_id`.\n- **`enable_campaign`** — params: `campaign_id`.\n- **`set_campaign_budget`** — params: `campaign_id`, `budget_type`\n (`daily` or `lifetime`), `amount_micros`, and `apply_to_shared_budget`\n (default false — set true only to change a budget shared by several\n campaigns). There is **no** ad-group budget action; Google ad groups have no\n budgets.\n\nThere is no create-campaign, no bid adjustment, and no offline-conversion\nupload — do not claim these exist.\n\nBudget mechanics:\n\n- `amount_micros` is in **micros**: 1,000,000 micros = 1 unit of the account\n currency, so `50000000` = 50.00. Convert the user's amount to micros.\n- `set_campaign_budget` sets an **absolute** budget, not a delta. To \"raise by\n 20%\", first read the current budget, compute the new absolute value, and set\n that.\n\nWrite workflow — every time:\n\n1. Resolve the campaign to its `campaign_id` (via a `get_data` read on\n `campaign` + id fields if the user gave a name).\n2. Build the exact params from the `list_actions` schema.\n3. **Show the user the concrete change and ask them to confirm** — e.g.\n \"Pause campaign 'Summer Sale' (id 123…) on account 456…?\" or \"Set daily\n budget for campaign X to €50.00 (50000000 micros)?\".\n4. Only after an explicit yes, call `execute_action` and report the result.\n\nIf the user says \"pause the worst campaign\", first do the read + ranking, then\nname the specific campaign and confirm before pausing — don't pause on the\nstrength of the aggregate alone.\n\n## 4. Reference the user's data, don't fabricate\n\nIf a tool returns an error (unknown field/connector/account), call the relevant\ndiscovery tool (`get_fields`, `get_connectors`, `list_actions`) and retry with\ncorrect ids. Never fill gaps with made-up numbers or campaign names.\n"
}SHA-256 of public snapshot: eb3ad24820398d30efa05638ce9458d2a1571933b9eda975e13f0df1c74d6700