Google Ads
Your agents forecast your terms, build exact-match search campaigns on your Google Ads account, cut wasted search terms daily, and stop by your rule.
- Connect
- Sign in once, 1 grant
- Runs through
- Your account
- First run
- Forecast clicks and cost for 10 exact terms, about 90¢
- Sites
- Google Search, Google Display, YouTube
Which search terms spent over $20 last week with no signup? Show me what to add as negatives.
curl -X POST "https: //api.sb/ leaseline.app/ metrics/ query? mode= try" \
-H "Authorization: Bearer $SB_TOKEN" \
-H "Content-Type: application/ json" \
-d '{"metric": "ad-spend", "shape": "trend", "breakdown": "search-term", "window": "7d", "where": "signups = 0 and spend > 20"}'
npx startup-builder do Metric.query --try --data '{"metric": "ad-spend", "shape": "trend", "breakdown": "search-term", "window": "7d", "where": "signups = 0 and spend > 20"}'
{
"name": "do",
"arguments": {
"mode": "try",
"code": "return await $.Metric.query({ metric: 'ad-spend', shape: 'trend', breakdown: 'search-term', window: '7d', where: 'signups = 0 and spend > 20' })"
}
}
import { $ } from 'startup-builder'
const result = await $.try.Metric.query({ metric: 'ad-spend', shape: 'trend', breakdown: 'search-term', window: '7d', where: 'signups = 0 and spend > 20' })
{
"$type": "Metric",
"mode": "try",
"stored": false,
"metric": "ad-spend",
"window": "7d",
"rows": [
{
"searchTerm": "free rent receipt template",
"spend": 64.2,
"clicks": 31,
"signups": 0,
"action": "add as a negative"
},
{
"searchTerm": "property management software enterprise",
"spend": 48.9,
"clicks": 9,
"signups": 0,
"action": "add as a negative"
}
]
}
Connect once
- Call
Integration.connectwithsystem:and'ads' venue:, then open the'google-search' connectUrlit returns and sign in as a Google account with access to your Google Ads account. - Pick the Google Ads account, then link it to your Google Analytics property so signups count as conversions.
- Set the spend on your standing approval with
Mandate.authorize; Google bills your account, never the platform.
| Grant | What it unlocks | Scope |
|---|---|---|
| Manage your Google Ads account | Reports, campaigns, ad groups, keywords, ads, budgets and audiences; Google offers no read-only grant, so your standing approval holds what changes | https:/ |
| To | Do this |
|---|---|
| Pause | Integration.pause stops every call through Google at once and keeps the token; Integration.resume picks up from the same cursor. |
| Reconnect | Integration.reconnect returns a fresh connectUrl that lasts one hour, and keeps the Integration's id and cursor, so nothing imports twice. |
| Disconnect | Integration.revoke revokes the token with Google; every record it brought in stays in your records. |
What your agents do
| Ask | Verb | Runs through | Price |
|---|---|---|---|
| Build the search campaign: 4 ad groups of exact terms, two ads each, and my negatives. | Campaign.create | Your account | Free |
| Add an ad to the best ad group with the winning headline. | Ad.create | Your account | Free |
| Add the search terms that wasted money as negatives, and lower the budget to $30 a day. | Campaign.update | Your account | Free |
| Which search terms spent over $20 last week with no signup? | Metric.query | Your account | Free |
| Build a remarketing list from pricing-page visitors. | Audience.create | Your account | Free |
Calls on your own account are free; Google bills your spend directly.
Reading this site’s public data needs no account: Keyword.forecast, Ad.find are Data calls (the three ways a call runs).
What it holds
| Noun | The account’s object | When | Which side leads |
|---|---|---|---|
| Campaign | campaign and campaign_budget | Your agent builds it | Your records |
| Ad | ad_group_ad | Your agent builds it; Google’s review sets its status | Your records |
| Keyword | search_term_view | A search triggers your ad | The account |
| Audience | user_list | Your agent builds one | Your records |
| Entry | metrics.cost_micros | Each day’s spend settles | The account |
Events and webhooks
| Direction | Event |
|---|---|
| Emits | Campaign.created, Campaign.updated, Ad.created, Audience.created, Keyword.measured, Entry.posted |
Any Event can wake a Workflow, and a Watch delivers it to your endpoint, signed (Events and webhooks).
Limits
| What | Limit | Call |
|---|---|---|
| A day’s spend | Google may spend up to twice the daily budget on one day and holds the month to about 30.4 days of it, so your standing approval’s cap is set on the month | Campaign.update |
| Ad review | Google reviews every ad; a disapproval comes back as venue-rejected with the policy it names | Ad.create |
| Smart Bidding | Learns from your conversion volume, and a new account has none, so a first test runs on manual CPC or maximize clicks on exact terms | Campaign.create |
| Spend | Your standing approval holds the cap; a budget change past it waits with over-mandate | Campaign.update |
Start here
| Move | The rule |
|---|---|
| Structure | One search campaign, 3 to 5 ad groups of tightly themed exact terms, two responsive search ads per group, and the negatives in place on day 0. |
| Budget | Spend what 500 clicks cost at your terms’ cost per click, on manual CPC or maximize clicks, and only on terms whose cost per click sits under your break-even. |
| Creative | The search term in headline 1, the outcome in headline 2, and a landing page whose H1 repeats the term with one call to action. |
| Kill rule | At 500 clicks: stop if cost per signup at the interval’s upper bound still fails break-even, hold and rewrite for 300 more if only the lower bound fails, and scale one tier only when the lower bound passes. |
| Benchmark | Source |
|---|---|
| CTR 6.66%, cost per click $5.26, conversion 7.52%, cost per lead $70.11 | Study of 16,000+ advertisers, 2025 |
| Judge a bidding change over 2 conversion cycles or 2 weeks, whichever is longer | Google Ads help |
| 10 signups in 500 clicks reads as 2%, with an interval of 1.1% to 3.6% | Our calculation (Wilson interval) |
| No signup in 150 clicks stops the test: a 2% rate would show one 95% of the time | Our calculation |
Field map
| Our field | Google Ads’s field | Notes | Calls |
|---|---|---|---|
Campaign.objective | campaign.advertising_channel_type | With a conversion goal; leads runs a SEARCH campaign bidding toward your signup conversion | Campaign.create, Campaign.update, Ad.create |
Campaign.budget | campaign_budget.amount_micros | A daily amount in millionths: $40 is 40000000 | Campaign.create, Campaign.update, Ad.create |
Campaign.startsAt | campaign.start_date | None. | Campaign.create |
Campaign.endsAt | campaign.end_date | None. | Campaign.create |
Campaign.keywords | ad_group_criterion.keyword | match_type EXACT for a test | Campaign.create, Campaign.update |
Campaign.negatives | campaign_criterion.negative | With the wasted search term as its keyword | Campaign.create, Campaign.update |
Ad.headline | ad_group_ad.ad.responsive_search_ad.headlines | 3 to 15, each 30 characters | Ad.create |
Ad.body | ad_group_ad.ad.responsive_search_ad.descriptions | 2 to 4, each 90 characters | Ad.create |
Ad.landingUrl | ad_group_ad.ad.final_urls | None. | Ad.create |
What try does here
Sends every change with validate_only set: Google Ads checks the whole build and returns any error, and creates nothing.
How long a connection lasts
A connection lasts until you revoke it in your Google Account; Google also ends a grant left unused for six months, and every call your agents make counts as use.
The platform asks you to reconnect 7 days before it runs out; until you do, a call that needs it refuses with needs-reauth.
Formats
| Site | Format | Size | Limits |
|---|---|---|---|
| Google Search | Responsive search ad | None. | 3 to 15 headlines of 30 characters; 2 to 4 descriptions of 90; two paths of 15 |
| YouTube | Video | None. | Title 100 characters; description 5,000 bytes; tags 500 characters in all |
Plays and strategies
| Kind | Where |
|---|---|
| Plays | Paid search, Retargeting, Promote winners, Positioning tournament |
| Strategies | Paid |
Used by
- Workflows: Search readout · Ad test setup
- Agent tasks: Message test
Reference
5 calls, each with its path and price
| Call | Path | Price |
|---|---|---|
Campaign.create | POST / | Free |
Ad.create | POST / | Free |
Campaign.update | POST / | Free |
Metric.query | POST / | Free |
Audience.create | POST / | Free |