agentleFS
pbc-ospbc-os/smb-starter-kit/skills/tier-4-growth/google-ads/SKILL.md

google-ads

Skill10 starsChanged 7 months agoMITView on GitHub

Create, query, audit, and optimize Google Ads campaigns via the Google Ads API (Python SDK). Use for campaign management, performance analysis, keyword optimization, and ad creation.

  • Installs packages

We split this skill into the rules it gives an agent

5 rules. 0 are common, 3 are distinctive, and 2 are very specific to this project.

  • 0

    Common

    Most of the 25 edited versions we read keep these.

  • 3

    Distinctive

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    If API is not configured, guide the user through references/api-setup.md.

    line 59
  2. Distinctive:

    Before writing any campaign creation code, document:

    line 82
  3. Very specific:

    If the API is truly unavailable (no developer token, client account without API access), browser automation can work for read-only checks.

    line 287
  4. Distinctive:

    Not suitable for mutations (pausing, budget changes) — too risky without confirmation loops

    line 294
  5. Distinctive:

    When reporting findings, use clear tables:

    line 302

“Common” is measured: kept by at least 6 in 10 of the 25 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Google Ads Management Skill

Comprehensive skill for managing Google Ads accounts via the Google Ads API.

Why This Skill Exists

The Problem:
Google Ads management requires precise, methodical work. Missed settings cause wasted spend. Forgotten fields cause API rejections. Small mistakes compound into big losses.

The Solution:
This skill provides battle-tested checklists, query templates, and workflows for common Google Ads operations. It captures lessons learned from real production use — the gotchas that aren't in the official docs.

What it prevents:

  • Campaign creation with broken landing pages ($$ wasted on 404s)
  • RSA text rejections (character limits are strict)
  • Missing required fields that cause API errors
  • Pausing the wrong campaigns
  • Forgetting to set end dates on promotional campaigns

When to Use This Skill

TaskUse This Skill
Check campaign performance✅ Yes
Create new campaigns/ads✅ Yes
Find wasted spend✅ Yes
Pause underperforming keywords✅ Yes
Adjust budgets✅ Yes
Audit account health✅ Yes
Billing/payment issues❌ No (use Google support)

Setup Verification

The agent should verify API access before proceeding:

# Check for API configuration
ls ~/.google-ads.yaml 2>/dev/null && echo "API config found" || echo "No API config — see references/api-setup.md"

# Check for SDK
python3 -c "from google.ads.googleads.client import GoogleAdsClient; print('SDK installed')" 2>/dev/null || echo "SDK not installed — run: pip install google-ads"

If API is not configured, guide the user through references/api-setup.md. The API approach is strongly recommended — it's reliable, automatable, and doesn't depend on UI changes.


Campaign Creation Checklist

⚠️ COMPLETE THIS BEFORE CREATING ANY CAMPAIGN

This checklist exists because every item has caused real-world failures:

1. Pre-Flight Verification

# ALWAYS verify landing page is live
curl -sI "https://your-landing-page.com/path" | head -2
# Must return: HTTP/2 200 or HTTP/1.1 200 OK

# Why? We've seen campaigns launch with 404 landing pages. 
# All ad spend went to a broken page. Verify FIRST.

2. Plan Structure Before Code

Before writing any campaign creation code, document:

ElementYour PlanCharacter Limit
Campaign name—
Campaign typeSearch / PMax / Display / etc.—
Daily budget—
Ad group names—
Keywords per group—
Headlines (3-15)≤30 chars each
Descriptions (2-4)≤90 chars each
Final URLMust return 200
Location targeting—
End date?(if promotional)

Why plan first? Iterating campaign structure via API is slow and error-prone. Get it right on paper first.

3. Required API Fields (Easy to Forget)

# EU Political Advertising field (REQUIRED even for non-political ads)
campaign.contains_eu_political_advertising = (
    client.enums.EuPoliticalAdvertisingStatusEnum.DOES_NOT_CONTAIN_EU_POLITICAL_ADVERTISING
)
# Why? Without this, the API rejects the campaign with a confusing error.

# RSA character limits (STRICT)
# Headlines: exactly ≤30 characters (not "about 30")
# Descriptions: exactly ≤90 characters (not "about 90")
# Why? The API rejects over-length text, doesn't truncate it.

4. Post-Creation Verification

  • Campaign status shows ENABLED (not PAUSED or ERROR)
  • Ads show "Eligible" or "Under review" (not "Disapproved")
  • Conversion tracking is connected
  • Location targeting is correct
  • Budget is what you intended
  • End date set (if time-limited)

Account Audit Checklist

Quick health check for any Google Ads account:

CheckWhere to LookRed Flags
Zero-conversion keywordsKeywords → Filter: Conv<1, Cost>$XHigh spend, no results
Empty ad groupsAd Groups → Filter: Ads=0Budget allocated, no creative
Policy violationsCampaigns → Status columnYellow warning icons
Optimization ScoreOverview page (top right)Below 70%
Conversion trackingTools → Conversions"Inactive" or no recent data
Wasted spendSearch Terms reportIrrelevant queries
Landing page statusAds → Final URL columnAny 404s or redirects

Common Queries (API Mode)

Campaign Performance (Last 30 Days)

query = """
    SELECT 
        campaign.id,
        campaign.name,
        campaign.status,
        campaign_budget.amount_micros,
        metrics.cost_micros,
        metrics.conversions,
        metrics.cost_per_conversion
    FROM campaign
    WHERE segments.date DURING LAST_30_DAYS
      AND campaign.status != 'REMOVED'
    ORDER BY metrics.cost_micros DESC
    LIMIT 50
"""

# Parse results
for row in response:
    cost = row.metrics.cost_micros / 1_000_000
    conv = row.metrics.conversions
    cpa = row.metrics.cost_per_conversion / 1_000_000 if conv > 0 else 0
    print(f"{row.campaign.name}: ${cost:.2f} | {conv:.1f} conv | ${cpa:.2f} CPA")

Find Wasted Spend (Zero-Conversion Keywords)

query = """
    SELECT 
        ad_group_criterion.keyword.text,
        ad_group_criterion.keyword.match_type,
        campaign.name,
        metrics.cost_micros,
        metrics.clicks,
        metrics.impressions
    FROM keyword_view
    WHERE metrics.conversions = 0
      AND metrics.cost_micros > 500000000  /* $500 in micros */
      AND segments.date DURING LAST_90_DAYS
      AND ad_group_criterion.status = 'ENABLED'
    ORDER BY metrics.cost_micros DESC
    LIMIT 100
"""

# Why 90 days? Short windows miss slow converters.
# Why $500 threshold? Adjust based on your CPA expectations.

Search Terms Report (Find Bad Matches)

query = """
    SELECT 
        search_term_view.search_term,
        campaign.name,
        metrics.cost_micros,
        metrics.conversions,
        metrics.clicks
    FROM search_term_view
    WHERE segments.date DURING LAST_30_DAYS
    ORDER BY metrics.cost_micros DESC
    LIMIT 200
"""

# Look for irrelevant searches eating budget.
# Add them as negative keywords.

Common Mutations (API Mode)

Mutations change live ad spend. Before running any mutation (pause, budget change, status flip, negative keyword), show the user the exact campaigns or keywords and the change you're about to make, and get explicit approval. Run a read query first to confirm you're targeting the right resources.

Pause Campaigns

from google.ads.googleads.client import GoogleAdsClient
from google.api_core import protobuf_helpers

def pause_campaigns(client, customer_id, campaign_ids):
    """Pause one or more campaigns."""
    campaign_service = client.get_service("CampaignService")
    operations = []

    for campaign_id in campaign_ids:
        operation = client.get_type("CampaignOperation")
        campaign = operation.update
        campaign.resource_name = campaign_service.campaign_path(
            customer_id, campaign_id
        )
        campaign.status = client.enums.CampaignStatusEnum.PAUSED

        # Set field mask so the API only updates the fields we changed
        client.copy_from(
            operation.update_mask,
            protobuf_helpers.field_mask(None, campaign._pb)
        )
        operations.append(operation)

    response = campaign_service.mutate_campaigns(
        customer_id=customer_id,
        operations=operations
    )
    return response

Pause Keywords

from google.api_core import protobuf_helpers

def pause_keywords(client, customer_id, keyword_resource_names):
    """Pause specific keywords by resource name."""
    service = client.get_service("AdGroupCriterionService")
    operations = []

    for resource_name in keyword_resource_names:
        operation = client.get_type("AdGroupCriterionOperation")
        criterion = operation.update
        criterion.resource_name = resource_name
        criterion.status = client.enums.AdGroupCriterionStatusEnum.PAUSED

        client.copy_from(
            operation.update_mask,
            protobuf_helpers.field_mask(None, criterion._pb)
        )
        operations.append(operation)

    return service.mutate_ad_group_criteria(
        customer_id=customer_id,
        operations=operations
    )

Browser Fallback (Not Recommended)

Stability Warning: Browser automation against ads.google.com is fragile. Google frequently changes their UI, which breaks selectors and workflows. Use the API whenever possible.

If the API is truly unavailable (no developer token, client account without API access), browser automation can work for read-only checks. See references/browser-workflows.md for details.

Limitations of browser mode:

  • UI selectors break without warning when Google updates the interface
  • Cannot be reliably scheduled or automated
  • Requires the user to be logged in with an active session
  • Slower and more error-prone than API calls
  • Not suitable for mutations (pausing, budget changes) — too risky without confirmation loops

Recommended path: Invest the 1-2 hours to set up API access (see references/api-setup.md). It pays off immediately.


Output Format

When reporting findings, use clear tables:

## Campaign Performance (Last 30 Days)
| Campaign | Cost | Conv | CPA | Status |
|----------|------|------|-----|--------|
| Branded  | $5K  | 50   | $100| ✅ Strong |
| Generic  | $10K | 5    | $2K | ⚠️ Review |
| Test     | $2K  | 0    | N/A | ❌ Pause |

## Recommended Actions
1. **PAUSE**: Test campaign ($2K spent, 0 conversions)
2. **REVIEW**: Generic campaign (CPA too high)
3. **INCREASE**: Branded budget (efficient performer)

Troubleshooting

API Issues

ErrorCauseFix
AuthenticationErrorBad credentialsRegenerate refresh token
DEVELOPER_TOKEN_NOT_APPROVEDUsing test token in prodApply for token approval
CUSTOMER_NOT_FOUNDWrong customer IDUse 10-digit ID, no dashes
proto-plus CopyFrom errorsWrong assignment syntaxUse direct assignment, not CopyFrom
INVALID_STRING_LENGTHText too longHeadlines ≤30, descriptions ≤90

Why This Belongs in Tier 4 (Growth)

This skill directly drives revenue growth:

  • Tier 1 = Foundation (secrets, setup)
  • Tier 2 = Communication (email, Slack)
  • Tier 3 = Business Ops (POS, accounting)
  • Tier 4 = Growth (advertising, marketing, SEO)

Google Ads is one of the primary paid growth channels for SMBs. This skill helps you manage it without the expensive mistakes that eat into margins.


Files Included

google-ads/
├── SKILL.md                    # This documentation
└── references/
    ├── api-setup.md            # Full API setup guide (start here)
    └── browser-workflows.md    # Browser fallback (unstable, last resort)

Download now (ZIP)

  • Other versions28 projects use a version of this.

    Word for word · 0

    None found.

    Edited · 1

    1. FelipeAngeli/skills★ 214% same

    Wrote their own version · 27

    1. superdesigndev/treg★ 7ksame name
    2. nowork-studio/toprank★ 4.1ksame name
    3. nowork-studio/notfair-plugin★ 4.1ksame name
    4. OpenClaudia/openclaudia-skills★ 724same name
    5. pedronauck/skills★ 641same name
    6. ivangfalco/ads-skills★ 267same name
    7. HybridAIOne/hybridclaw★ 159same name
    8. hyperfx-ai/marketing-skills★ 107same name
    9. AceDataCloud/Skills★ 17same name
    10. chanktb/claude-google-ads★ 11same name

    17 more not listed

    How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.

  • Used alongsideProjects with it also use gohighlevel, google-ads-assets and 5 more.

    Other files people use alongside this one.

    Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
    • windsor-aiSkill

      gohighlevel

      Analyze GoHighLevel CRM data through Windsor.ai. Use when the user asks about their GoHighLevel account — contacts, opportunities and pipeline stages, deal value, appointments, campaigns, lead sources, or conversion rates. It can also create or update a contact and create an invoice, always after the user confirms the exact change. It does not send emails or SMS, book or change appointments, or modify pipeline or campaign settings. Do not use for other CRMs (HubSpot, Salesforce), outbound messaging, or ad-platform performance data.

      Also in 3 projects that use this

    • chanktbSkill

      google-ads-assets

      Generates Google Ads creative assets shared across campaign types: responsive search ad headlines and descriptions, Performance Max asset-group copy and search themes, Demand Gen image/video briefs, and sitelinks/callouts. Enforces character limits, brand voice from account-context.yaml, and policy/ trademark safety. Use when the user says "ad copy", "headlines", "descriptions", "assets", "creative", "rsa", "asset group copy", "sitelinks", "callouts".

      Also in 3 projects that use this

    • hyperfx-aiSkill

      tiktok-ads

      Plan and create TikTok advertising campaigns end-to-end via the Hyper MCP, with strict parameter validation for objective-specific requirements. Use when the user wants to launch TikTok ads, set up TikTok traffic or reach campaigns, configure conversions or app-promotion campaigns, upload TikTok video creatives, or analyze TikTok ad performance. Also triggers on tiktok marketing, tiktok campaign, tiktok ppc, or tiktok ads manager.

      Also in 5 projects that use this

    • brainbytes-devSkill

      linkedin-ads

      LinkedIn advertising strategy for B2B lead generation, brand awareness, and recruitment. Use when running LinkedIn ad campaigns.

      Also in 5 projects that use this

    • isiahw1Skill

      google-search-console

      Query and analyze Google Search Console data for SEO insights. Use when users want to analyze search performance, find content optimization opportunities, check URL index status, manage sitemaps, or make data-driven content decisions. Supports multiple properties and covers keyword discovery, CTR analysis, position tracking, and technical SEO checks.

      Also in 3 projects that use this

    • itallstartedwithaideaSkill

      google-ads-audit

      Structured Google Ads account audit across 7 dimensions. Activate when the user asks to "audit my account", "check for problems", "find issues", "review my campaigns", or requests a comprehensive account health assessment. Delivers findings with severity ratings and prioritized action items.

      Also in 3 projects that use this

  • In this repository23 other files it gives its agents.

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.