Claude Skill जो मेरे Google Ads कॉपी लिखती है
मैंने एक Claude skill बनाई जो GAQL के ज़रिए सीधे Google Ads API क्वेरी करती है, कमज़ोर CTR या ज़्यादा CPA वाले responsive search ads पहचानती है, और हेडलाइन व डिस्क्रिप्शन को Google की सटीक character सीमा (30 और 90) के भीतर फिर से लिखती है। नया ad PAUSED स्टेटस में बनता है — मैं खुद रिव्यू करके इसे एक्टिवेट करता हूं। जो बात असल में मायने रखती है: Google की character सीमा ही असली constraint है, कॉपी नहीं। जो मॉडल characters को सही से count नहीं करता, वह ऐसे ads बना देता है जिन्हें Google चुपचाप truncate या reject कर देता है।
हर बुधवार। 28,400+ पाठक। बिना फालतू बात।
✓ अपना इनबॉक्स देखें — साइन-अप पूरा करने के लिए पुष्टि लिंक पर क्लिक करें।
✓ आपकी सदस्यता हो गई!
✓ आप पहले से सूची में हैं।
[ऑपरेटर की नज़र से] मेरे पास पहले से एक Claude skill है जो मेरे Facebook ads मैनेज करती है — वह बिल्ड यहां है। Google Ads इससे ज़्यादा मुश्किल सीक्वल था, इसलिए नहीं कि API खराब है, बल्कि इसलिए कि responsive search ads में सख्त character सीमाएं होती हैं जो Facebook में नहीं होती: हर हेडलाइन में 30 characters, हर डिस्क्रिप्शन में 90। एक rewrite जो पढ़ने में ठीक लगती है लेकिन serve होते वक्त reject या truncate हो जाती है, वह rewrite नहीं, बग है। इस skill के ज़्यादातर काम में मॉडल को उस constraint का पालन करने के लिए मजबूर करना शामिल था — उस पर भरोसा करने के बजाय कि वह खुद कर लेगा।
Table of contents
Open Table of contents
Google Ads को Facebook से अलग बिल्ड क्यों चाहिए थी
Facebook skill परफॉर्मेंस डेटा पढ़ती है, कॉपी फिर से लिखती है, और नया ad set पब्लिश करती है। Google Ads भी वही तीन काम करती है, लेकिन दो चीज़ें बदल जाती हैं:
- क्वेरी भाषा GAQL है, REST filters नहीं। Google Ads API v18, Google Ads Query Language पर चलता है — SQL जैसा, सिर्फ पढ़ने के लिए, ठीक इस तरह की रिपोर्टिंग pull के लिए बनाया गया।
- Responsive search ads में सख्त सीमाएं हैं। हर ad में 15 हेडलाइन (हर एक 30 characters) और 4 डिस्क्रिप्शन (हर एक 90 characters) तक। Google धीरे से warn नहीं करता — या तो submission पर asset reject कर देता है, या उससे भी बुरा, एक truncated वर्शन serve करता है जो किसी असली customer को गलत दिखता है।
पॉइंट 2 वही है जो naive implementations को तोड़ देता है। मॉडल से कहो “ज़्यादा punchy हेडलाइन लिखो” और वह खुशी-खुशी 34 characters दे देगा। Google Ads उस asset को reject कर देगा या उसे बीच शब्द से कटा हुआ दिखाएगा। मुझे यह तब पता चलता है जब मैं एक live ad देखता हूं जो “अभी बुक कर—” पर खत्म होता है।
API access लेना (वह हिस्सा जिसे सब कम आंकते हैं)
तीन चीज़ें, और तीसरी वही है जो प्लान न करने पर एक हफ्ता ले लेती है:
- OAuth2 credentials के साथ एक Google Cloud प्रोजेक्ट — client ID, client secret, और
https://www.googleapis.com/auth/adwordsscope वाला refresh token। refresh token एक बार जेनरेट करो, OAuth playground या छोटी local स्क्रिप्ट से; उसके बाद यह सिर्फ एक stored credential है, login flow नहीं। - एक developer token, जो अपने Google Ads manager (MCC) अकाउंट से, Admin → API Center के ज़रिए रिक्वेस्ट करते हैं।
- Access level। हर नया developer token Test Account access से शुरू होता है — यह सिर्फ Google Ads test accounts के खिलाफ काम करता है, आपके असली अकाउंट के खिलाफ नहीं। आप Basic Access (15,000 operations/day तक, इसके लिए काफी) एक फॉर्म के ज़रिए रिक्वेस्ट करते हैं जिसे Google मैन्युअली रिव्यू करता है। असली अकाउंट पर जाने से पहले approval के लिए कुछ बिज़नेस दिन रखो।
GOOGLE_ADS_CLIENT_ID, GOOGLE_ADS_CLIENT_SECRET, GOOGLE_ADS_REFRESH_TOKEN, GOOGLE_ADS_DEVELOPER_TOKEN, और GOOGLE_ADS_CUSTOMER_ID (10-digit account ID, बिना dashes के) अपने .env में स्टोर करो। अगर आप अकाउंट MCC के ज़रिए मैनेज करते हो, तो आपको GOOGLE_ADS_LOGIN_CUSTOMER_ID भी चाहिए manager account ID के साथ — इसके बिना क्वेरीज़ permissions error के साथ reject हो जाती हैं, और error message यह नहीं बताता कि क्यों।
Skill की फाइल स्ट्रक्चर
.claude/skills/google-ads/
SKILL.md ← instructions जो Claude पढ़ता है
index.ts ← असली tool implementation
limits.ts ← character-limit validationSKILL.md:
# Google Ads Manager Skill
Use this skill when the user says "check my Google Ads", "run ads
report", or "rewrite underperforming RSAs". Never run this without
explicit user instruction — it touches live ad spend.
## What it can do
- Pull campaign and ad group performance via GAQL (last 7 or 30 days)
- Flag responsive search ads with CTR < 3% or CPA above the stored
target as underperformers
- Rewrite headlines (≤30 chars) and descriptions (≤90 chars) for
flagged ads in Ale's voice
- Create new ad variations as PAUSED — never enabled automatically
## What it will NOT do
- Change budgets or bids without explicit confirmation
- Enable a paused ad
- Submit any headline or description that fails the character check“What it will NOT do” की आखिरी लाइन वह है जो मैंने तब जोड़ी जब skill ने पहले हफ्ते में 32-character वाली हेडलाइन पब्लिश कर दी। मॉडल का अपना count दो characters से गलत था — इतना करीब कि एक नज़र में pass हो जाए, इतना दूर कि asset reject हो जाए। उसके बाद से सब कुछ एक सख्त validator से गुज़रता है, मॉडल की self-report से नहीं।
मुख्य TypeScript कोड
// .claude/skills/google-ads/index.ts
import { GoogleAdsApi } from "google-ads-api";
import Anthropic from "@anthropic-ai/sdk";
const client = new GoogleAdsApi({
client_id: process.env.GOOGLE_ADS_CLIENT_ID!,
client_secret: process.env.GOOGLE_ADS_CLIENT_SECRET!,
developer_token: process.env.GOOGLE_ADS_DEVELOPER_TOKEN!,
});
const customer = client.Customer({
customer_id: process.env.GOOGLE_ADS_CUSTOMER_ID!,
login_customer_id: process.env.GOOGLE_ADS_LOGIN_CUSTOMER_ID,
refresh_token: process.env.GOOGLE_ADS_REFRESH_TOKEN!,
});
interface AdPerformance {
adGroupAdId: string;
campaignName: string;
headlines: string[];
descriptions: string[];
impressions: number;
clicks: number;
costMicros: number;
conversions: number;
ctr: number;
cpa: number;
}
async function getAdPerformance(days = 7): Promise<AdPerformance[]> {
const rows = await customer.query(`
SELECT
ad_group_ad.ad.id,
campaign.name,
ad_group_ad.ad.responsive_search_ad.headlines,
ad_group_ad.ad.responsive_search_ad.descriptions,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions
FROM ad_group_ad
WHERE segments.date DURING LAST_${days === 30 ? "30" : "7"}_DAYS
AND ad_group_ad.status = 'ENABLED'
`);
return rows.map((r: any) => {
const impressions = Number(r.metrics.impressions ?? 0);
const clicks = Number(r.metrics.clicks ?? 0);
const cost = Number(r.metrics.cost_micros ?? 0) / 1_000_000;
const conversions = Number(r.metrics.conversions ?? 0);
return {
adGroupAdId: r.ad_group_ad.ad.id,
campaignName: r.campaign.name,
headlines: (r.ad_group_ad.ad.responsive_search_ad?.headlines ?? []).map((h: any) => h.text),
descriptions: (r.ad_group_ad.ad.responsive_search_ad?.descriptions ?? []).map((d: any) => d.text),
impressions,
clicks,
costMicros: Number(r.metrics.cost_micros ?? 0),
conversions,
ctr: impressions > 0 ? (clicks / impressions) * 100 : 0,
cpa: conversions > 0 ? cost / conversions : Infinity,
};
});
}
const HEADLINE_MAX = 30;
const DESCRIPTION_MAX = 90;
function validateAsset(text: string, max: number): boolean {
return text.length <= max;
}
async function rewriteRsa(
ad: AdPerformance,
targetCpa: number,
): Promise<{ headlines: string[]; descriptions: string[] }> {
const anthropic = new Anthropic();
const msg = await anthropic.messages.create({
model: "claude-sonnet-4-6",
max_tokens: 1024,
messages: [{
role: "user",
content: `Rewrite this Google Ads responsive search ad in Alejandro Rioja's voice: direct, operator-focused, specific. It's underperforming — CTR ${ad.ctr.toFixed(2)}%, CPA $${ad.cpa.toFixed(2)} vs a $${targetCpa} target.
Current headlines: ${JSON.stringify(ad.headlines)}
Current descriptions: ${JSON.stringify(ad.descriptions)}
Rules, non-negotiable:
- Each headline: 30 characters MAXIMUM, including spaces and punctuation
- Each description: 90 characters MAXIMUM, including spaces and punctuation
- Return 5 headlines and 4 descriptions
- Return JSON only: {"headlines": ["...", ...], "descriptions": ["...", ...]}`,
}],
});
const text = (msg.content[0] as any).text.replace(/```json\n?/, "").replace(/```/, "").trim();
const parsed = JSON.parse(text);
const headlines = parsed.headlines.filter((h: string) => validateAsset(h, HEADLINE_MAX));
const descriptions = parsed.descriptions.filter((d: string) => validateAsset(d, DESCRIPTION_MAX));
if (headlines.length < 3 || descriptions.length < 2) {
throw new Error("Model returned too many over-limit assets — rerun or revise manually.");
}
return { headlines, descriptions };
}हर हेडलाइन और डिस्क्रिप्शन जेनरेट होने के बाद, API को छूने से पहले, कोड में सीमा के खिलाफ वैलिडेट होती है। मॉडल की rewrite एक draft है। Validator ही gate है।
मैं इसे रोज़ कैसे इस्तेमाल करता हूं
> पिछले 7 दिनों का मेरा Google Ads चेक करोClaude GAQL क्वेरी चलाता है, 3% से कम CTR या मेरे stored CPA target से ज़्यादा कुछ भी flag करता है, और rewrite करने से पहले पुष्टि मांगता है। मैं पुष्टि करता हूं। यह नई हेडलाइन और डिस्क्रिप्शन जेनरेट करता है, उन्हें character validator से गुज़ारता है, जो fail होती हैं उन्हें हटाता है, और Google Ads API के mutate operation के ज़रिए PAUSED स्टेटस में एक नया ad बनाता है। मैं नई कॉपी को पुरानी से Google Ads के भीतर compare करता हूं, जो सच में इस्तेमाल करूंगा उन्हें activate करता हूं, और बाकी को paused छोड़ देता हूं।
Facebook वर्शन जैसी ही सीमा: UI में पूरे दिन की बजाय लगभग 20 मिनट, क्योंकि mechanical हिस्सा — डेटा निकालना, सख्त constraint के भीतर लिखना, बदलाव तैयार करना — ठीक वही है जो मॉडल को मेरी जगह करना चाहिए।
जो validator पकड़ नहीं पाता
Character count mechanical है। Relevance नहीं है। कोई हेडलाइन 28 characters की हो सकती है, हर check pass कर सकती है, और फिर भी उस search term के लिए गलत message हो सकती है जिससे वह जुड़ी है। Skill यह नहीं जान सकती कि कमज़ोर परफॉर्म करने वाले ad group में खराब offer है, landing page का mismatch है, या genuinely weak कॉपी है — यह मुझे सिर्फ यह बता सकती है कि कॉपी आस-पास के ads के मुकाबले कमज़ोर है। अगर किसी campaign के सारे ads का CTR कम है, तो यह targeting या landing page की समस्या है, और गलत matched search intent पर skill को ज़्यादा rewrite cycles देने से सिर्फ ज़्यादा compliant, लेकिन वैसी ही ignored कॉपी मिलती है।
मैं खुद GAQL output पढ़ता हूं rewrite batch approve करने से पहले, जैसे Facebook साइड पर करता हूं। Skill typing और character counting हटा देती है। यह यह judgment नहीं हटाती कि असल में क्या टूटा है।
इसके लिए मैं जो tools इस्तेमाल करता हूं
Claude दोनों ad skills का base है — Facebook वाली और यह — दोनों एक ही rewrite-and-validate पैटर्न शेयर करती हैं, सिर्फ अलग API और tighter character budget के खिलाफ।
Google Ads API (npm package google-ads-api) — raw gRPC/REST API के चारों ओर TypeScript wrapper। यह OAuth refresh और GAQL query building हैंडल करता है ताकि आपको protobuf हाथ से न बनाना पड़े।
अक्सर पूछे जाने वाले सवाल
क्या मुझे Basic Access चाहिए, या Test Account access से काम चल जाएगा?
Test Account access सिर्फ Google Ads test accounts के खिलाफ काम करता है — development के लिए useful, असली खर्च वाले असली अकाउंट के लिए बेकार। इस skill के किसी live campaign को छूने से पहले आपको Basic Access (अपने manager account के API Center से request करें) चाहिए। Approval मैन्युअल रिव्यू है, instant नहीं, इसलिए इसे ज़रूरत से पहले request करो, जिस हफ्ते launch करना है तब नहीं।
15 और 4 के maximum की बजाय 5 हेडलाइन और 4 डिस्क्रिप्शन क्यों?
Google 15 हेडलाइन तक allow करता है, लेकिन Ad Strength और real-world testing दोनों बताते हैं कि genuinely अलग 8-10 angles के बाद diminishing returns आ जाते हैं — ज़्यादातर अकाउंट कुछ near-duplicate हेडलाइन के साथ खत्म होते हैं जो सिर्फ count भरते हैं। मैं मॉडल के output को हर rewrite batch में 5 नई हेडलाइन तक सीमित करता हूं ताकि मैं distinct options रिव्यू करूं, एक ही sentence के नौ variations filter न करूं।
अगर मॉडल की rewrite हर attempt में character check fail कर जाए तो क्या होता है?
Validator silently truncate या over-limit asset submit करने की बजाय error throw करता है। व्यावहारिक रूप से इसका मतलब है कि मैं prompt को एक बार फिर चलाता हूं, और अगर यह दो बार fail हो जाए तो मैं वह specific हेडलाइन हाथ से लिखता हूं। यह descriptions में ज़्यादा होता है — 90 characters एक पूरे sentence के लिए दिखने से ज़्यादा tight space है।
संबंधित: GA4, Search Console, Bing, Ahrefs, और Core Web Vitals पर read-only रिपोर्टिंग के लिए, हर platform के लिए अलग skill बनाने की बजाय, मैं एक ही Claude connector में SiteWide MCP इस्तेमाल करता हूं — Claude को असली marketing डेटा से जोड़ने का वही idea, लेकिन एक single ad platform से कहीं ज़्यादा wide surface।
ऑपरेटर का फैसला
अगर आप हाथ से responsive search ad variations लिख रहे हो और खुद characters count कर रहे हो, तो यह ठीक वही mechanical, rule-bound काम है जो मॉडल को लेना चाहिए। जिस हिस्से में असली judgment चाहिए — यह कॉपी की समस्या है या targeting की — वह आपका ही रहता है। Skill बनाओ, उसे Google की सीमाओं के खिलाफ लिखने और validate करने दो, और diagnosis अपने पास रखो।
हर बुधवार। 28,400+ पाठक। बिना फालतू बात।
✓ अपना इनबॉक्स देखें — साइन-अप पूरा करने के लिए पुष्टि लिंक पर क्लिक करें।
✓ आपकी सदस्यता हो गई!
✓ आप पहले से सूची में हैं।
संबंधित पोस्ट
Claude Cowork शेड्यूल्ड टास्क: सेटअप गाइड
Claude Cowork के शेड्यूल्ड टास्क एक बार के प्रॉम्प्ट को बिना कोड-सर्वर के अपने-आप चलने वाले काम में बदल देते हैं। इसे सेट करने का तरीका यहाँ है।
AI Agents2026 में एजेंसियां बेच सकने वाली AI एजेंट सेवाएं
मेरे अपने बिज़नेस से छह AI एजेंट ऑटोमेशन, जिन्हें सर्विस लाइन आइटम के रूप में दोबारा तैयार किया गया है जिन्हें एजेंसी स्कोप, प्राइस और क्लाइंट को बेच सके।
AI AgentsSaaS के लिए AI एजेंट्स: पहले क्या ऑटोमेट करें
AI एजेंट फैसलों का टियर और ROI फ्रेमवर्क, उन SaaS वर्कफ़्लो पर लागू किया गया जिन्हें वाकई सबसे पहले ऑटोमेट करना फायदेमंद है।
AI प्लेबुक अपने इनबॉक्स में पाएं
हर बुधवार। 28,400+ पाठक। बिना फालतू बात।
अपना इनबॉक्स देखें।
हमने आपको एक पुष्टिकरण ईमेल भेजा है — सदस्यता पूरी करने के लिए लिंक पर क्लिक करें। यदि एक मिनट में न दिखे तो स्पैम देखें।
आपकी सदस्यता हो गई।
स्वागत है — अगला संस्करण जल्द ही आपके इनबॉक्स में आएगा।
आप पहले से सूची में हैं — हर बुधवार इसका इंतज़ार करें।