AI Agents Marketing

مهارة Claude التي تكتب إعلانات Google Ads الخاصة بي

Alejandro Rioja
Alejandro Rioja
7 د قراءة
TL;DR

بنيت مهارة Claude تستعلم مباشرة عن واجهة برمجة Google Ads باستخدام GAQL، وتكشف الإعلانات الإرشادية في البحث التي تعاني من نسبة نقر ضعيفة أو تكلفة تحويل مرتفعة، وتعيد كتابة العناوين والأوصاف ضمن حدود الأحرف الدقيقة لدى Google (30 و90). يُنشأ الإعلان الجديد بحالة متوقف مؤقتًا — وأنا من يراجعه ويفعّله. النقطة التي تهم فعلًا: حدود الأحرف لدى Google هي القيد الحقيقي، لا النص نفسه. أي نموذج لا يحسب الأحرف بدقة ينتج إعلانات يقطعها Google أو يرفضها بصمت.

نشرة بريدية مجانية

كل أربعاء. أكثر من 28,400 مشترك. بدون حشو.

[قراءة من منظور تشغيلي] لدي بالفعل مهارة Claude تدير إعلاناتي على Facebook — ذلك البناء موجود هنا. كانت Google Ads الجزء الأصعب، ليس لأن واجهتها البرمجية أسوأ، بل لأن الإعلانات الإرشادية في البحث تفرض حدود أحرف صارمة لا توجد في Facebook: 30 حرفًا لكل عنوان، و90 حرفًا لكل وصف. إعادة كتابة تُقرأ جيدًا لكنها تُرفض أو تُقطع عند العرض ليست إعادة كتابة، بل خلل برمجي. معظم العمل في هذه المهارة انصبّ على إجبار النموذج على احترام هذا القيد، بدل الوثوق بأنه سيفعل ذلك من تلقاء نفسه.

Table of contents

Open Table of contents

لماذا احتاجت Google Ads إلى بناء مختلف عن Facebook

مهارة Facebook تقرأ بيانات الأداء، تعيد كتابة النص، وتنشر مجموعة إعلانات جديدة. تؤدي Google Ads نفس المهام الثلاث، لكن يختلف أمران:

  1. لغة الاستعلام هي GAQL، لا فلاتر REST. تعمل واجهة Google Ads API الإصدار 18 بلغة Google Ads Query Language — بصيغة شبيهة بـSQL، للقراءة فقط، مصممة تحديدًا لهذا النوع من استخراج التقارير.
  2. الإعلانات الإرشادية في البحث لها حدود صارمة. حتى 15 عنوانًا (30 حرفًا لكل منها) و4 أوصاف (90 حرفًا لكل منها) لكل إعلان. لا تحذّر Google بلطف — فهي إما ترفض العنصر عند التقديم، أو الأسوأ، تعرض نسخة مقطوعة تبدو خاطئة لعميل حقيقي.

النقطة الثانية هي ما يكسر التطبيقات الساذجة. اطلب من النموذج “كتابة عنوان أكثر تأثيرًا” وسيعيد لك بسرور 34 حرفًا. سترفض Google Ads ذلك العنصر أو تعرضه مقطوعًا في منتصف كلمة. لا أكتشف ذلك إلا عندما أرى إعلانًا مباشرًا ينتهي بـ”احجز موعد—”.

الحصول على صلاحية الوصول إلى الواجهة البرمجية (الجزء الذي يستهين به الجميع)

ثلاثة أمور، والثالث هو ما يكلّفك أسبوعًا إن لم تخطط له:

  1. مشروع Google Cloud ببيانات اعتماد OAuth2 — معرّف العميل، وسرّ العميل، ورمز تحديث بصلاحية https://www.googleapis.com/auth/adwords. أنشئ رمز التحديث مرة واحدة، عبر OAuth playground أو سكربت محلي قصير؛ بعد ذلك يصبح بيانات اعتماد محفوظة، لا تدفق تسجيل دخول.
  2. رمز مطوّر، يُطلب من حساب إدارة Google Ads (MCC) الخاص بك، عبر الإدارة ← مركز الواجهة البرمجية.
  3. مستوى الوصول. يبدأ كل رمز مطوّر جديد بصلاحية حساب تجريبي — يعمل فقط مع حسابات Google Ads التجريبية، لا حسابك الحقيقي. تطلب Basic Access (حتى 15,000 عملية يوميًا، وهذا يكفي) عبر نموذج تراجعه Google يدويًا. خصّص بضعة أيام عمل للموافقة قبل التخطيط للعمل على حساب حقيقي.

خزّن GOOGLE_ADS_CLIENT_ID وGOOGLE_ADS_CLIENT_SECRET وGOOGLE_ADS_REFRESH_TOKEN وGOOGLE_ADS_DEVELOPER_TOKEN وGOOGLE_ADS_CUSTOMER_ID (معرّف الحساب المكوّن من 10 أرقام، دون شرطات) في ملف .env. إذا كنت تدير الحساب عبر MCC، فستحتاج أيضًا إلى GOOGLE_ADS_LOGIN_CUSTOMER_ID مضبوطًا على معرّف حساب الإدارة — بدونه تُرفض الاستعلامات بخطأ صلاحيات، ولا تخبرك رسالة الخطأ بالسبب.

بنية ملفات المهارة

code
.claude/skills/google-ads/
  SKILL.md          ← التعليمات التي يقرأها Claude
  index.ts          ← التنفيذ الفعلي للأداة
  limits.ts         ← التحقق من حدود الأحرف

SKILL.md:

markdown
# 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” هو ما أضفته بعد أن نشرت المهارة عنوانًا من 32 حرفًا في الأسبوع الأول. كان عدّ النموذج نفسه خاطئًا بحرفين — قريب كفاية ليمرّ عند نظرة سريعة، وبعيد كفاية ليُرفض العنصر. منذ ذلك الحين، يمرّ كل شيء عبر مُدقّق صارم، لا عبر تقرير النموذج الذاتي.

الكود الأساسي بلغة TypeScript

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 };
}

يُفحص كل عنوان ووصف مقابل الحد في الكود، بعد التوليد، قبل أن يلمس أي شيء الواجهة البرمجية. إعادة كتابة النموذج مجرد مسودة. المُدقّق هو البوابة.

كيف أستخدمها يوميًا

code
> تحقق من Google Ads الخاص بي خلال آخر 7 أيام

يشغّل Claude استعلام GAQL، ويضع علامة على كل ما هو أقل من 3% نسبة نقر أو أعلى من هدف تكلفة التحويل المحفوظ، ويطلب التأكيد قبل إعادة الكتابة. أؤكد. يولّد عناوين وأوصافًا جديدة، يمررها عبر مُدقّق الأحرف، يستثني ما يفشل، وينشئ إعلانًا جديدًا بحالة PAUSED عبر عملية mutate في واجهة Google Ads. أقارن النص الجديد بالقديم داخل Google Ads مباشرة، أُفعّل ما سأستخدمه فعلًا، وأترك الباقي متوقفًا.

نفس السقف الزمني لنسخة Facebook: نحو 20 دقيقة عوضًا عن بعد ظهر كامل في الواجهة، لأن الجزء الآلي — استخراج البيانات، الكتابة ضمن قيد صارم، تحضير التغيير — هو تمامًا ما ينبغي أن يقوم به نموذج بدلًا مني.

ما لا يكشفه المُدقّق

عدّ الأحرف أمر آلي. الصلة بالموضوع ليست كذلك. قد يكون عنوان من 28 حرفًا، يمرّ كل الفحوصات، ومع ذلك يبقى الرسالة الخاطئة لمصطلح البحث المرتبط به. لا يمكن للمهارة أن تعرف إن كانت مجموعة إعلانات ضعيفة الأداء بسبب عرض سيئ، أو عدم تطابق مع صفحة الهبوط، أو نص ضعيف فعلًا — تستطيع فقط أن تخبرني أن النص ضعيف مقارنةً بالإعلانات المحيطة به. إذا كانت نسبة النقر منخفضة في كل إعلانات حملة ما، فتلك مشكلة استهداف أو صفحة هبوط، وإعطاء المهارة دورات إعادة كتابة أكثر على نية بحث غير متطابقة لا يُنتج إلا نصًا أكثر طاعة وبنفس درجة التجاهل.

أقرأ مخرجات GAQL بنفسي قبل الموافقة على مجموعة إعادة كتابة، كما أفعل في جانب Facebook. تزيل المهارة الكتابة وعدّ الأحرف. لا تزيل الحكم على ما هو معطّل فعليًا.

الأدوات التي أستخدمها لهذا

Claude هو ما تعمل عليه مهارتا الإعلانات — تلك الخاصة بـFacebook وهذه — تتشاركان نفس نمط إعادة الكتابة والتحقق، فقط مقابل واجهة برمجية مختلفة وميزانية أحرف أكثر تشددًا.

واجهة Google Ads API (حزمة npm باسم google-ads-api) — غلاف TypeScript حول واجهة gRPC/REST الخام. يتولى تحديث OAuth وبناء استعلامات GAQL حتى لا تضطر إلى بناء protobuf يدويًا.

الأسئلة الشائعة

هل أحتاج إلى Basic Access، أم تكفي صلاحية الحساب التجريبي؟

تعمل صلاحية الحساب التجريبي فقط مقابل حسابات Google Ads التجريبية — مفيدة للتطوير، لا قيمة لها لحساب حقيقي بنفقات حقيقية. تحتاج إلى Basic Access (تُطلب من مركز الواجهة البرمجية لحساب الإدارة الخاص بك) قبل أن تتمكن هذه المهارة من لمس حملة مباشرة. الموافقة مراجعة يدوية، لا فورية، فاطلبها قبل أن تحتاجها، لا في الأسبوع الذي تريد فيه الانطلاق.

لماذا 5 عناوين و4 أوصاف بدل الحد الأقصى البالغ 15 و4؟

تسمح Google بما يصل إلى 15 عنوانًا، لكن كلًا من Ad Strength والتجارب الفعلية تشير إلى تناقص العائد بعد 8-10 زوايا مختلفة فعليًا — ينتهي أغلب الحسابات بعدة عناوين شبه مكرّرة تملأ العدد فقط. أحدّ مخرجات النموذج بخمسة عناوين جديدة لكل مجموعة إعادة كتابة لأراجع خيارات متمايزة فعلًا، لا لأغربل تسع صيغ للجملة نفسها.

ماذا يحدث إذا فشلت إعادة كتابة النموذج في فحص الأحرف في كل محاولة؟

يُصدر المُدقّق خطأ عوضًا عن تقطيع أو إرسال عنصر يتجاوز الحد بصمت. عمليًا هذا يعني أني أعيد تشغيل الطلب مرة واحدة، وإن فشل مرتين أكتب ذلك العنوان المحدد بيدي. يحدث هذا أكثر مع الأوصاف — 90 حرفًا مساحة أضيق لجملة كاملة مما تبدو عليه.

ذو صلة: للتقارير القراءة فقط عبر GA4 وSearch Console وBing وAhrefs وCore Web Vitals في موصل Claude واحد عوضًا عن بناء مهارة مخصصة لكل منصة، أستخدم SiteWide MCP — نفس فكرة ربط Claude ببيانات تسويقية حقيقية، لكن بتغطية أوسع من منصة إعلانية واحدة.

خلاصة المشغّل

إذا كنت تكتب يدويًا صيغ الإعلانات الإرشادية في البحث وتعدّ الأحرف بنفسك، فهذا تمامًا نوع المهمة الآلية القائمة على قواعد التي ينبغي أن يتولاها نموذج. الجزء الذي يتطلب حكمًا حقيقيًا — هل هي مشكلة نص أم استهداف — يبقى لك. ابنِ المهارة، اتركها تكتب وتتحقق مقابل حدود Google، واحتفظ بالتشخيص لنفسك.

إعلان
تابع القراءة

مقالات ذات صلة

تابع القراءة

احصل على دليل الذكاء الاصطناعي في صندوق بريدك

كل أربعاء. أكثر من 28,400 مشترك. بدون حشو.

↵ ↵ لعرض كل النتائج esc esc للإغلاق