10 Claude Code Skills for Meta Ads

Written By
Ahad ShamsAhad Shams
hero=section

If you run Meta ads at scale, you already know the bottleneck: not strategy, but execution. Pulling reports, uploading creatives, monitoring spend, detecting fatigue — these tasks consume 60–80% of a media buyer's week. Claude Code skills for Meta ads are installable, slash-command-driven automations that sit between you and Meta's API. Each skill is a .md file you drop into .claude/commands/ — Claude Code reads it and executes it on demand. This post gives you the actual file content for all 10 skills. Copy them, install them, and you have a full automation layer for Meta ad operations running in under two hours.

What Are Claude Code Skills for Meta Ads?

Claude Code is Anthropic's agentic coding tool — it runs in your terminal, reads and writes files, executes shell commands, and connects to external APIs via the Model Context Protocol (MCP). A "skill" in Claude Code is a reusable instruction set, stored as a slash command .md file, that Claude executes autonomously when invoked.

For Meta advertisers, this means you can encode your most repetitive workflows — creative generation, performance monitoring, budget reallocation — into named commands that run end-to-end without manual intervention. You type /bleed-check and Claude connects to Meta's Marketing API, pulls live spend data, identifies bleeding ad sets, pauses them, and sends a Slack alert. The entire workflow that previously took 30–45 minutes of manual work completes in under two minutes.

Slash commands live in .claude/commands/ at the project level (shared with your team) or in ~/.claude/commands/ globally (just you). The filename becomes the command: spy.md → /spy. No YAML frontmatter needed — the file content is the prompt Claude Code reads and executes literally.

The broader shift this enables is from reactive ad management to automated, threshold-driven operations. Instead of checking Ads Manager every morning, your skills run on a schedule and surface only what requires human judgment. Over 4 million advertisers now use generative AI tools for Meta creative production, according to Meta's Newsroom — but most are still managing operations manually. The operational automation layer is the larger opportunity.

How Do You Set Up Claude Code Skills for Meta Ads?

Before installing the skills, get three things in place.

Step 1: Install Claude Code. Run: npm install -g @anthropic-ai/claude-code — then authenticate with your Anthropic API key when prompted.

Step 2: Set environment variables. Add to your ~/.zshrc or ~/.bashrc: export META_ACCESS_TOKEN="your_token_here", export META_ACCOUNT_ID="act_123456789", export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/...". Generate your Meta access token from Meta Business Suite > Settings > Business Assets > System Users. You need ads_management and ads_read permissions.

Step 3: Configure CLAUDE.md. Create a CLAUDE.md in your project root. This is the operating context Claude Code reads at startup. Include: your Meta Ad Account ID (referencing $META_ACCOUNT_ID), your API version (v21.0), performance thresholds (ROAS floor for pausing: 0.85x account average; frequency cap warning: 4.0; hook rate floor: 0.25; bleed threshold: $50 spend with 0 purchase conversions in 6h), brand voice rules (tone, prohibited words, target audience), and your directory structure for creatives, campaigns, reports, and logs. Store all credentials as environment variable references — never hardcode tokens in CLAUDE.md.

Step 4: Create the commands directory. Run: mkdir -p .claude/commands — then drop each .md skill file below into that directory.

Step 5: Configure MCP for live Meta data. Create or update ~/.claude/settings.json with an mcpServers block that points to @modelcontextprotocol/server-meta, passing META_ACCESS_TOKEN and META_ACCOUNT_ID as environment variables. Run npx @modelcontextprotocol/server-meta to install on first use. With MCP active, skills like /bleed-check, /rebalance, and /weekly-report can read and write live Meta data without manual data export.

Which 10 Skills Should Every Meta Ads Marketer Build?

These 10 skills cover the full Meta ads workflow: intelligence gathering, creative production, deployment, monitoring, and reporting. Each is a standalone .md file you install independently.

1. Competitor Ad Intelligence Scraper (/spy)

Pulls all active ads from competitor Facebook pages via the Meta Ad Library API, diffs against last week's pull, and produces a structured intelligence report with hooks, CTAs, offers, and creative angle classifications.

File: .claude/commands/spy.md

# /spy — Competitor Ad Intelligence Scraper ## Description Query the Meta Ad Library API for all active ads from a list of competitor pages. Diff against the previous week's pull (stored in ./reports/spy-last.json) to surface only new creative. Output a structured markdown intelligence report. ## Parameters - --competitors (required): Comma-separated Facebook page IDs or @handles - --country (default: US): Country code for ad library query - --output (default: report): Output format — "report" (markdown) or "json" - --save-baseline: Flag to save current pull as the new baseline for next week's diff ## Prerequisites - Meta Ad Library API access (public endpoint) - Access token in $META_ACCESS_TOKEN for authenticated requests - Previous baseline stored at ./reports/spy-last.json (empty on first run) ## Execution Steps 1. Resolve page IDs — for each @handle, call: GET https://graph.facebook.com/v21.0/{handle}?fields=id&access_token=$META_ACCESS_TOKEN 2. Query Ad Library for each page: GET https://graph.facebook.com/v21.0/ads_archive?access_token=$META_ACCESS_TOKEN&fields=id,ad_creative_body,ad_creative_link_caption,ad_creative_link_description,ad_creative_link_title,ad_delivery_start_time,ad_delivery_stop_time,page_name,spend,impressions,currency,ad_snapshot_url&search_page_ids={page_id}&ad_reached_countries=["{country}"]&ad_active_status=ACTIVE&limit=100 — paginate through all results using the "next" cursor. If HTTP 429, wait 60 seconds and retry. 3. Diff against baseline — load ./reports/spy-last.json, identify new ad IDs not in baseline, note stopped ads. 4. Classify each new ad: Hook (opening line or headline), CTA text, Offer type (Discount / Free shipping / Free trial / Social proof / Problem-solution / Product demo / Testimonial / Urgency / Other), Creative angle (Problem-aware / Solution-aware / Product-aware / Brand awareness / Retargeting), Run length (New 0-7d / Testing 8-30d / Winner 30d+). 5. Identify trends — count offer types across competitors, flag any used by 2+ competitors as "Market Trend". 6. Output ./reports/spy-{YYYY-MM-DD}.md with: Summary section, New Ads table (Page | Hook | CTA | Offer Type | Angle | Running), Stopped Ads list, Recommended Creative Angles to Test. 7. If --save-baseline: overwrite ./reports/spy-last.json with current full pull. ## Output Format Markdown report at ./reports/spy-{YYYY-MM-DD}.md. If --output=json, also write ./reports/spy-{YYYY-MM-DD}.json. ## Error Handling - Page ID returns 0 ads: log and continue - API error 100 (invalid page ID): skip and note in report - HTTP 429 rate limit: wait 60 seconds, retry up to 3 times - No baseline exists: note "First run — no diff available" ## Example Invocation /spy --competitors="123456789,987654321,@theirBrand" --country=US --save-baseline

Use this weekly. The output feeds directly into your creative brief for /bulk-creative and /hooks. For a deeper look at how to use competitive intelligence to brief your own ad generation pipeline, see how to generate ad variations .

2. Bulk Creative Generator (/bulk-creative)

Takes a creative brief and generates 50–500 ad variations by programmatically producing HTML/React templates with swapped headlines, CTAs, background colors, and product image placements, then rendering each to PNG via headless browser.

File: .claude/commands/bulk-creative.md

# /bulk-creative — Bulk Creative Generator ## Description Generate N ad creative variations from a single brief. Produce a React HTML template with configurable variation axes (headline, subheadline, CTA, background color, image position). Render each variation to PNG using Puppeteer. Output named files organized for bulk upload and compatible with /deploy-ads manifest format. ## Parameters - --brief (required): Creative brief as a quoted string — include product, offer, audience, and awareness level - --variations (default: 50): Total number of variations to generate (max 500) - --formats (default: "1:1"): Comma-separated aspect ratios — "1:1" (1080x1080), "9:16" (1080x1920), "1.91:1" (1200x628) - --output-dir (default: ./creatives/): Output directory for PNG files - --seed-headlines: Path to a CSV of headline variants to use (optional) ## Prerequisites - Node.js v18+ installed - Puppeteer: run npm install puppeteer in project root - Product images in ./assets/images/ (JPG or PNG, minimum 1080x1080) ## Execution Steps 1. Parse the brief — extract product name, key benefit, primary offer, target audience, awareness level, tone cues. 2. Generate variation axes — headlines (5-10 variations: problem-led, benefit-led, social proof, offer-led, curiosity), CTAs (3-5: Shop Now, Get X% Off, Try Free, Learn More, Start Today), background colors (3-5 hex values), image positions (center, left-aligned, right-aligned). 3. Create HTML template at ./creatives/template.html — self-contained with CSS variables for all variation axes (--headline, --cta, --bg-color, --img-position), brand logo, headline text block, CTA button, product image. Must render at exact pixel dimensions for each format. 4. Generate variation manifest at ./creatives/variations.json listing all combinations with: id, headline, cta, bg_color, img_position, format, filename. Name files: v{NNN}_{format}_{headline-type}_{cta-slug}.png 5. Render PNGs — write and execute ./creatives/render.js using Puppeteer: load template.html with variation params as URL query strings, set viewport to exact format dimensions, screenshot to output dir. Add 200ms delay between renders. 6. Organize into subdirectories: ./creatives/headline-variants/, ./creatives/cta-variants/, ./creatives/color-variants/ 7. Generate ./campaigns/bulk-creative-manifest.json in /deploy-ads format: [{creative_name, image_path, headline, body, cta, format}] ## Output Format - PNG files in ./creatives/ organized by type - ./campaigns/bulk-creative-manifest.json for /deploy-ads - ./creatives/variations.json with full variation metadata - Console summary: "Generated N variations across X formats in Ys" ## Error Handling - Puppeteer not installed: output install command and stop - Template render fails: log error, skip variation, continue - --variations exceeds 500: cap at 500 and warn - Product image not found: use placeholder and warn ## Example Invocation /bulk-creative --brief="Collagen supplement, 30% off, female 28-45, problem-aware" --variations=100 --formats="1:1,9:16"

Building a reliable bulk creative pipeline is one of the highest-leverage moves a performance team can make. For context on the tool landscape you're operating within, the best AI ad generators comparison covers the full spectrum.

3. Meta API Auto-Deployer (/deploy-ads)

Reads a deployment manifest and bulk-creates campaigns, ad sets, and ads in Meta via Graph API v21.0. Handles rate limiting, retry logic, and writes a deployment report with direct Ads Manager links.

File: .claude/commands/deploy-ads.md

# /deploy-ads — Meta API Auto-Deployer ## Description Read a campaign manifest JSON file and create all campaigns, ad sets, ad creatives, and ads in the Meta account via Graph API v21.0. Support draft (paused) and publish (active) modes. Log all created object IDs and any errors. ## Parameters - --manifest (required): Path to the campaign manifest JSON file - --mode (default: draft): "draft" creates everything paused; "publish" sets status to ACTIVE - --dry-run (flag): Validate the manifest and estimate API calls without making any requests ## Prerequisites - $META_ACCESS_TOKEN with ads_management permission - $META_ACCOUNT_ID set - $META_PAGE_ID set (your Facebook Page ID for ad creative) - Creative images at specified paths OR already uploaded (image_hash in manifest) ## Execution Steps 1. Validate manifest — check all required fields, verify image files exist, confirm account ID. If --dry-run: output validation results and stop. 2. Upload creative images — for each ad with image_path: POST https://graph.facebook.com/v21.0/{account_id}/adimages with multipart image data. Extract image_hash from response. Wait 0.5s between uploads. 3. Create campaign — POST https://graph.facebook.com/v21.0/{account_id}/campaigns with name, objective, status (PAUSED or ACTIVE per --mode), special_ad_categories: []. Store campaign_id. 4. Create ad sets — POST https://graph.facebook.com/v21.0/{account_id}/adsets for each ad_set in manifest with campaign_id, targeting, optimization_goal, billing_event, daily_budget, status. Store adset_id. Wait 0.5s between creates. 5. Create ad creatives — POST https://graph.facebook.com/v21.0/{account_id}/adcreatives for each ad with object_story_spec (page_id, link_data with image_hash, link, message, name, call_to_action). Store creative_id. 6. Create ads — POST https://graph.facebook.com/v21.0/{account_id}/ads with name, adset_id, creative.creative_id, status. Wait 0.5s between creates. 7. Retry logic — HTTP 429: wait 60 seconds, retry. HTTP 400: log error, skip item, continue. HTTP 500: wait 5 seconds, retry up to 3 times. 8. Write ./reports/deploy-{YYYY-MM-DD-HHmm}.md with all created IDs, Ads Manager deep links, errors, and total API call count. ## Output Format Deployment report at ./reports/deploy-{YYYY-MM-DD-HHmm}.md with all IDs and Ads Manager deep links ## Error Handling - Manifest file not found: stop with clear path error - Campaign creation fails: stop, do not create ad sets (avoid orphaned objects) - Individual ad fails: log and continue - Token expired: stop with instructions to refresh ## Example Invocation /deploy-ads --manifest=campaigns/summer-sale-manifest.json --mode=draft

What previously took a media buyer 3–4 hours to manually build in the UI completes in under 10 minutes.

4. Performance Bleed Detector (/bleed-check)

Pulls the last 6 hours of spend and conversion data across all active ad sets, identifies any spending above threshold with zero conversions, pauses them via API, and sends a formatted Slack alert.

File: .claude/commands/bleed-check.md

# /bleed-check — Performance Bleed Detector ## Description Connect to Meta Marketing API, pull the last 6 hours of spend and purchase conversion data for all active ad sets, identify "bleeding" ad sets (spend above threshold, conversions below floor), pause each via API, and send a Slack alert with the full list. ## Parameters - --threshold-spend (default: 50): Pause if spend exceeds this USD amount in the window - --threshold-conversions (default: 0): Pause if purchase conversions are at or below this count - --window-hours (default: 6): Lookback window in hours - --alert-channel (default: #meta-alerts): Slack channel name - --dry-run (flag): Identify bleeding ad sets but do NOT pause them or send alerts ## Prerequisites - $META_ACCESS_TOKEN with ads_management permission - $META_ACCOUNT_ID set - $SLACK_WEBHOOK_URL set ## Execution Steps 1. Pull active ad sets — GET https://graph.facebook.com/v21.0/{account_id}/adsets?fields=id,name,status,daily_budget,campaign_id&filtering=[{"field":"adset.effective_status","operator":"IN","value":["ACTIVE"]}]&access_token=$META_ACCESS_TOKEN&limit=100. Paginate to get all. 2. Pull spend and conversion data for the window — for each ad set: GET https://graph.facebook.com/v21.0/{adset_id}/insights?fields=spend,actions,cost_per_action_type,impressions,clicks&time_range={"since":"{now-window_hours}","until":"{now}"}&access_token=$META_ACCESS_TOKEN. Extract spend, purchase_conversions (actions where action_type="purchase"), impressions, clicks. 3. Identify bleeding ad sets — spend > threshold-spend AND purchase_conversions <= threshold-conversions. Build list: [{adset_id, name, spend, impressions, clicks, conversions, campaign_id}]. 4. Pause each bleeding ad set (skip if --dry-run) — POST https://graph.facebook.com/v21.0/{adset_id} with body {"status":"PAUSED","access_token":$META_ACCESS_TOKEN}. Wait 0.3s between calls. 5. Format Slack blocks message with header ("Meta Bleed Alert — N Ad Sets Paused"), account info block, per-ad-set section (name, spend, impressions, clicks, purchases, Ads Manager link). 6. POST to $SLACK_WEBHOOK_URL. Confirm 200 "ok" response. 7. Append to ./logs/bleed-check.log: {timestamp} | Checked {total} ad sets | {N} paused | Names: {list} ## Output Format - Slack message in --alert-channel - Log entry in ./logs/bleed-check.log - Console summary of what was found and paused ## Error Handling - Pause call fails: log error, mark "PAUSE FAILED" in Slack, continue - Slack webhook fails: still write log — do not lose the record - No active ad sets found: log and exit cleanly - $SLACK_WEBHOOK_URL not set: skip Slack, write log only, warn in console ## Example Invocation /bleed-check --threshold-spend=75 --threshold-conversions=0 --window-hours=6 --alert-channel=#meta-alerts /bleed-check --dry-run

Schedule this with cron: 0 */6 * * * claude --command "/bleed-check" — runs every 6 hours automatically. This addresses one of the most painful problems in Meta ads: weekend budget bleed from ad sets that cleared the learning phase and then collapsed.

5. Creative Fatigue Monitor (/fatigue-scan)

Pulls time-series performance data on all active creatives, runs a 7-day rolling trend analysis to detect statistically significant decline, and generates replacement briefs for high-risk creatives.

File: .claude/commands/fatigue-scan.md

# /fatigue-scan — Creative Fatigue Monitor ## Description Pull time-series performance data for all active ad creatives. Calculate trend direction for hook rate, CTR, CPM, and frequency over a rolling window. Flag creatives with statistically significant performance decline or threshold breaches. Generate replacement briefs for high-risk creatives. ## Parameters - --lookback (default: 14): Number of days of data to analyze - --hook-rate-floor (default: 0.25): Minimum acceptable hook rate - --ctr-decline-threshold (default: 0.15): Flag if CTR drops more than this % week-over-week - --frequency-cap (default: 4.0): Flag if frequency exceeds this value - --output (default: ./reports/fatigue-report.md): Output file path - --min-spend (default: 100): Minimum lifetime spend to include a creative in analysis ## Prerequisites - $META_ACCESS_TOKEN with ads_read permission - Creative must have at least --min-spend lifetime spend and 7+ days active ## Execution Steps 1. Get all active ad creatives — GET https://graph.facebook.com/v21.0/{account_id}/ads?fields=id,name,creative{id,name},adset_id,campaign_id,insights{spend,impressions,clicks,actions,video_thru_play_actions,frequency,cpm,cpc,ctr}&filtering=[{"field":"ad.effective_status","operator":"IN","value":["ACTIVE"]}]&access_token=$META_ACCESS_TOKEN 2. Pull daily time-series for each creative — GET https://graph.facebook.com/v21.0/{ad_id}/insights?fields=spend,impressions,clicks,actions,video_thru_play_actions,frequency,cpm,ctr,date_start&time_range={"since":"{today-lookback}","until":"{today}"}&time_increment=1&access_token=$META_ACCESS_TOKEN 3. Calculate metrics per day: hook_rate = video_thru_play_actions/impressions (video) or link_clicks/impressions (static); ctr = clicks/impressions; cpm = spend/impressions*1000; frequency from API. Calculate rolling 7-day averages for week 1 (days 1-7) and week 2 (days 8-14). 4. Classify fatigue risk — HIGH RISK: hook_rate_week2 < hook-rate-floor, OR CTR WoW decline > ctr-decline-threshold, OR frequency > frequency-cap, OR CPM WoW increase > 30%. MEDIUM RISK: hook rate within 20% of floor, CTR decline 10-15%, frequency 3.0-4.0. LOW RISK: all metrics stable or improving. 5. Generate replacement briefs for HIGH RISK creatives — analyze original hook structure, visual treatment, emotional driver. Output: "This creative [original hook] is showing [metric decline]. Test a new variation with the same [angle] but using [new treatment]. Suggested hooks: [3 options]." 6. Write ./reports/fatigue-report-{YYYY-MM-DD}.md with: Account Summary (counts by risk level), High Risk table (Creative Name | Hook Rate | CTR Trend | Frequency | CPM Trend | Recommended Action) plus replacement briefs, Medium Risk table, Low Risk list. ## Output Format Markdown report at --output path ## Error Handling - Creative has < 7 days data: skip and note "insufficient data" - Video metrics unavailable (static ad): skip hook_rate, use CTR only - API returns no time-series: fall back to lifetime insights ## Example Invocation /fatigue-scan --lookback=14 --hook-rate-floor=0.25 --frequency-cap=4.0 --output=./reports/fatigue-report.md

Creative fatigue kills ROAS silently. Most teams don't detect it until CPM has already spiked and CTR collapsed. This skill gives you a 7–14 day early warning system.

6. Budget Reallocation Engine (/rebalance)

Analyzes ROAS, spend, and conversion volume across all ad sets, applies the 15% ROAS threshold rule to identify underperformers, and generates a reallocation plan shifting budget to top performers.

File: .claude/commands/rebalance.md

# /rebalance — Budget Reallocation Engine ## Description Pull current ROAS, spend, and conversion data for all active ad sets. Calculate account-average ROAS. Flag ad sets performing more than --roas-floor percent below account average. Generate a budget reallocation plan shifting budget from underperformers to top performers. Optionally execute the changes via API. ## Parameters - --roas-floor (default: 0.85): Fraction of account average ROAS below which an ad set is flagged - --max-shift-pct (default: 30): Maximum % of an ad set's budget that can be reallocated in a single run - --min-spend (default: 100): Minimum spend to include an ad set in analysis - --lookback (default: 7): Days of data for ROAS calculation - --dry-run (default: true): Show plan without executing - --execute (flag): Apply budget changes via API ## Prerequisites - $META_ACCESS_TOKEN with ads_management permission - $META_ACCOUNT_ID set - Ad sets using ad set-level budgets (not CBO) for direct budget edits ## Execution Steps 1. Pull active ad sets with performance data — GET https://graph.facebook.com/v21.0/{account_id}/adsets?fields=id,name,status,daily_budget,lifetime_budget,campaign_id,insights.date_preset(last_{lookback}_d){spend,actions,purchase_roas,cost_per_action_type,impressions,clicks}&filtering=[{"field":"adset.effective_status","operator":"IN","value":["ACTIVE"]}]&access_token=$META_ACCESS_TOKEN 2. Calculate metrics — for each ad set: total_spend, purchases (actions where type="purchase"), purchase_value (action_values where type="offsite_conversion.fb_pixel_purchase"), roas = purchase_value/total_spend. Skip if spend < --min-spend. 3. Calculate account benchmarks — account_avg_roas = sum(purchase_value)/sum(spend). roas_floor_value = account_avg_roas * --roas-floor. top_performer_threshold = account_avg_roas * 1.15. 4. Classify ad sets — UNDERPERFORMER: roas < roas_floor_value. TOP PERFORMER: roas > top_performer_threshold. MID PERFORMER: between thresholds. 5. Calculate reallocation — for underperformers: reduction = min(current_budget * max-shift-pct, current_budget - min_daily_budget). Distribute available_budget to top performers proportionally by ROAS. Cap any single increase at 30% of current budget. 6. Generate reallocation table: Ad Set | Current Budget | Proposed Budget | Change | Current ROAS | Reasoning. 7. Execute if --execute flag set — POST https://graph.facebook.com/v21.0/{adset_id} with {"daily_budget": new_budget_in_cents, "access_token": $META_ACCESS_TOKEN}. Wait 0.5s between updates. 8. Write ./reports/rebalance-{YYYY-MM-DD}.md with account ROAS benchmarks, reallocation table, projected weekly impact, and execution log. ## Error Handling - All ad sets on CBO: output analysis-only report, note budget edits disabled - Ad set budget update fails: log error, skip, continue - No purchases in window: use CPC as proxy metric - Only 1-2 ad sets with data: flag insufficient sample, do not execute ## Example Invocation /rebalance --roas-floor=0.85 --max-shift-pct=25 --lookback=7 --dry-run /rebalance --roas-floor=0.85 --max-shift-pct=25 --execute

This operationalizes what top agencies treat as a weekly manual process into an automated, threshold-driven system. For a quantified look at what budget automation saves over time, see the time and budget savings with AI ads breakdown.

7. CAPI Setup Assistant (/setup-capi)

Generates complete server-side event tracking implementation for Meta's Conversions API. Supports Shopify webhooks, Stripe payment events, and custom backend integrations — including deduplication logic and a test suite.

File: .claude/commands/setup-capi.md

# /setup-capi — CAPI Setup Assistant ## Description Generate a complete, production-ready implementation of Meta's Conversions API (CAPI) server-side event tracking. Output implementation code, configuration files, webhook setup instructions, and a test script that verifies event delivery and reports match quality scores. ## Parameters - --platform (required): "shopify", "stripe", "node", "python" - --events (required): Comma-separated events — "Purchase,AddToCart,InitiateCheckout,ViewContent,Lead" - --pixel-id (required): Your Meta Pixel ID - --test-mode (default: false): Send events to Meta's test event tool - --output-dir (default: ./capi-implementation/): Directory to write generated files ## Prerequisites - Meta Pixel ID (Events Manager > Data Sources) - Meta System User access token with ads_management + business_management permissions - Node.js 18+ or Python 3.9+ - Existing browser pixel installed on site (for deduplication) ## Execution Steps 1. Generate core CAPI event handler (./capi-implementation/capi-handler.js for Node) — use facebook-nodejs-business-sdk. Create sendCapiEvent(eventName, userData, customData, eventId) function with: UserData (hashed email/phone/name via SHA-256, clientIpAddress, clientUserAgent, fbc from _fbc cookie, fbp from _fbp cookie), CustomData (value, currency, orderId, contentIds), ServerEvent (setEventName, setEventTime, setUserData, setCustomData, setEventSourceUrl, setActionSource=website, setEventId for dedup). Include hashPii() helper using crypto.createHash('sha256'). 2. Generate event-specific handlers in ./capi-implementation/events/{event-name}.js for each event in --events. Purchase handler maps: value=order.total_price, currency=order.currency, order_id=order.id (also used as event_id for dedup), content_ids=order.line_items.map(i=>i.product_id). 3. Generate Shopify webhook handler (if --platform=shopify) in ./capi-implementation/shopify-webhook.js — Express route POST /webhooks/shopify/:event_type, verify HMAC signature from Shopify-Hmac-Sha256 header, map orders/paid → Purchase and checkouts/create → InitiateCheckout, return 200 within 5 seconds. 4. Generate deduplication config in ./capi-implementation/dedup-config.js — document the strategy: browser pixel must fire with eventID matching CAPI's event_id. Browser side: fbq('track', 'Purchase', data, {eventID: orderId}). CAPI side: setEventId(orderId). Same event_id causes Meta to count once, not twice. 5. Generate .env.example with: META_CAPI_TOKEN, META_PIXEL_ID, META_TEST_EVENT_CODE, SHOPIFY_WEBHOOK_SECRET. 6. Generate test script ./capi-implementation/test-events.js — send one test event per event type, use hashed test@example.com, report match quality scores from API response. 7. Generate ./capi-implementation/SETUP.md with: npm install steps, Shopify webhook configuration (Dashboard > Settings > Notifications > Webhooks), environment variable setup, how to read match quality in Events Manager. ## Output Format Directory of implementation files at --output-dir ## Error Handling - --pixel-id not provided: stop with clear error - Unrecognized event name: warn but continue, generate generic handler - npm install fails in test: provide manual install instructions ## Example Invocation /setup-capi --platform=shopify --events="Purchase,InitiateCheckout,AddToCart" --pixel-id=123456789 --test-mode=true

CAPI setup is one of the most commonly botched implementations in Meta advertising — incorrect deduplication leads to inflated conversion counts and misallocated budget. This skill generates production-ready code rather than requiring interpretation of Meta's technical documentation from scratch.

8. Hook & Copy Variation Engine (/hooks)

Takes a single winning ad angle and generates 50+ copy variations using psychological copywriting frameworks — PAS, AIDA, Before/After/Bridge, and pattern interrupts. Outputs a formatted CSV ready for Meta's bulk upload tool.

File: .claude/commands/hooks.md

# /hooks — Hook & Copy Variation Engine ## Description Take a seed hook or winning ad angle and generate N copy variations using defined psychological copywriting frameworks. Tag each by framework, emotional register, and recommended placement. Cross-reference brand voice from CLAUDE.md. Output a CSV formatted for Meta's bulk upload tool. ## Parameters - --seed (required): The seed hook or winning angle as a quoted string - --frameworks (default: "PAS,BAB,AIDA"): Framework list — "PAS", "BAB", "AIDA", "pattern-interrupt", "social-proof", "fear-appeal", "curiosity-gap" - --count (default: 50): Number of variations to generate - --audience (required): Audience description — age, gender, awareness level, pain points - --output (default: ./creatives/hooks-{date}.csv): Output CSV path ## Framework Definitions PAS (Problem/Agitate/Solution): Name the problem → make it emotionally painful → introduce the solution. Headline: "[Problem statement that hits home]". Body: "Every day you [problem], you're [negative consequence]. It doesn't have to be this way. [Product] [solves it]." BAB (Before/After/Bridge): Current painful state → ideal future state → product as the bridge. Headline: "[Specific aspirational result]". Body: "Before [product]: [painful state]. After [product]: [desired state]. The bridge: [how product achieves this]." AIDA (Attention/Interest/Desire/Action): Grab attention → build interest → create desire → clear CTA. Headline: "[Pattern interrupt or bold claim]". Body: "[Surprising hook]. [Specific proof]. [Desire statement]. [CTA with urgency]." Pattern Interrupt: Break expected patterns to force attention. Start with "Stop.", "Wait.", "Don't [expected action].", numbers as openers, rhetorical questions. Social Proof: Lead with credibility — customer count, transformation testimonial, authority endorsement, before/after result. Fear Appeal: Identify threat → quantify cost of inaction → offer solution. Use responsibly, focus on realistic consequences. Curiosity Gap: Create information gap — "The [unexpected thing] about [familiar topic]", "Why [common belief] is wrong". ## Execution Steps 1. Parse seed and audience — extract core angle, product reference, implied pain point, current hook structure, demographics, awareness level, primary pain points. 2. Apply brand voice filter from CLAUDE.md — tone guidelines, prohibited words, preferred vocabulary. Apply to all variations. 3. Generate variations per framework — distribute --count evenly across --frameworks. For each framework vary: emotional intensity (subtle vs. strong), specificity (numbers vs. general), POV (second/first/third person), hook trigger (pain avoidance/aspiration/curiosity/social proof). Each variation needs: primary_text (125 chars max), headline (40 chars max), description (30 chars max). 4. Tag each variation — framework, emotional_register (fear/aspiration/curiosity/social_proof/humor/urgency), awareness_match (which funnel stage it targets), recommended_placement (FEED/STORY/REEL/MESSENGER). 5. Format CSV with columns: ad_name, primary_text, headline, description, framework, emotional_register, awareness_match, recommended_placement, seed_angle. Name each: hook_{framework}_{register}_{NNN}. 6. Write summary at top: total variations, breakdown by framework, top 3 recommended hooks to test first, testing note: "Run 5-10 hooks in a $5/day ABO test for 3-4 days before scaling winners." ## Error Handling - --seed under 5 words: request more detail in console, do not generate - No brand voice in CLAUDE.md: generate without filter, warn user - --count > 200: cap at 200, warn about quality degradation ## Example Invocation /hooks --seed="Most skincare routines are making your skin worse" --frameworks="PAS,BAB,pattern-interrupt" --count=50 --audience="female, 28-45, problem-aware, frustrated with ineffective products"

JPMorgan Chase saw a 450% increase in click-through rate after systematically using AI to generate and test ad copy variations. Anthropic's own growth team compressed RSA creation from 30 minutes to 30 seconds per ad using a similar systematic variation approach.

9. Audience Architecture Auditor (/audience-audit)

Connects to Meta via MCP, pulls all active custom audiences and ad set targeting configurations, runs overlap analysis, maps audiences to funnel stages, and generates an optimized audience architecture recommendation.

File: .claude/commands/audience-audit.md

# /audience-audit — Audience Architecture Auditor ## Description Pull all custom audiences, lookalike audiences, and ad set targeting configurations from the Meta account. Run overlap analysis between ad set audiences. Map all audiences to funnel stages. Identify missing exclusions. Generate an optimized audience architecture with a Mermaid diagram. ## Parameters - --account-id (default: $META_ACCOUNT_ID): Meta ad account ID (with act_ prefix) - --output (default: ./reports/audience-audit.md): Output file path - --include-inactive (flag): Include paused/inactive ad sets in analysis ## Prerequisites - $META_ACCESS_TOKEN with ads_read permission - At least one custom audience created in the account ## Execution Steps 1. Pull all custom audiences — GET https://graph.facebook.com/v21.0/{account_id}/customaudiences?fields=id,name,subtype,approximate_count,time_created,retention_days,rule,lookalike_spec&access_token=$META_ACCESS_TOKEN&limit=100. Categorize by subtype: CUSTOM (customer file), WEBSITE (pixel-based), LOOKALIKE, ENGAGEMENT, OFFLINE. 2. Pull active ad sets and targeting — GET https://graph.facebook.com/v21.0/{account_id}/adsets?fields=id,name,status,targeting,campaign_id,daily_budget,insights{spend,purchase_roas}&filtering=[{"field":"adset.effective_status","operator":"IN","value":["ACTIVE","PAUSED"]}]&access_token=$META_ACCESS_TOKEN 3. Map audiences to funnel stages — TOFU: interest-based, LAL 3-10%, broad. MOFU: website visitors (all pages 30-180d), video view audiences (25/50/75%), engagement audiences, email subscribers, LAL 1-2%. BOFU: product page visitors, add-to-cart, initiate checkout, cart abandoners. RETENTION: past purchasers 180d+, LTV-based audiences. 4. Run overlap analysis — flag ad sets that are simultaneously active, same geo, same optimization event (Purchase), and logically overlapping audience types with no mutual exclusions. Classify overlap pairs as HIGH/MEDIUM/LOW risk. 5. Identify missing exclusions — HIGH impact: purchasers not excluded from prospecting ad sets. MEDIUM: warm audiences not excluded from cold prospecting. LOW: minor interest/LAL overlap. Rank by estimated impact. 6. Generate architecture recommendations — TOFU/MOFU/BOFU audience lists with sizes, exclusion rules for each layer, suggested LAL expansion from best-performing seed audiences. 7. Generate Mermaid flowchart showing: current architecture as-is, funnel stage boxes with audiences, arrows showing exclusion relationships, red markers on problematic overlaps. 8. Write ./reports/audience-audit-{YYYY-MM-DD}.md with: executive summary, current architecture Mermaid diagram, funnel stage mapping table, overlap analysis table (Ad Set Pair | Overlap Risk | Missing Exclusion | Priority), missing exclusions list, recommended architecture. ## Error Handling - No custom audiences: output targeting-only analysis with recommendation to create pixel-based audiences - Mermaid diagram too complex (>20 nodes): generate simplified version and note - Ad set targeting data unavailable: note limitation, analyze available audience data only ## Example Invocation /audience-audit --account-id=act_123456789 --output=./reports/audience-audit.md

Poor audience architecture — overlapping ad sets competing against each other in auction — is one of the most common sources of inflated CPMs that goes undiagnosed for months.

10. Weekly Performance Report Generator (/weekly-report)

Pulls the last 7 days of campaign data from Meta, calculates account-level and campaign-level KPIs, compares week-over-week, and generates a formatted Slack summary plus a detailed markdown report.

File: .claude/commands/weekly-report.md

# /weekly-report — Weekly Performance Report Generator ## Description Pull the last 7 days of Meta campaign data via API. Calculate account-level and campaign-level KPIs. Compare to the prior 7-day period. Identify top winners and underperformers. Generate a Slack-formatted summary and a detailed markdown report. ## Parameters - --date-range (default: last_7d): "last_7d", "last_14d", or "custom:YYYY-MM-DD:YYYY-MM-DD" - --compare (default: previous_7d): "previous_7d", "previous_4w", or "custom:YYYY-MM-DD:YYYY-MM-DD" - --format (default: "slack,markdown"): Comma-separated output formats - --top-n (default: 3): Number of top/bottom performers to highlight - --slack-channel (default: #growth): Slack channel for summary - --output-dir (default: ./reports/): Directory for reports ## Prerequisites - $META_ACCESS_TOKEN with ads_read permission - $META_ACCOUNT_ID set - $SLACK_WEBHOOK_URL set - At least 14 days of account history for WoW comparison ## Execution Steps 1. Calculate date ranges — parse --date-range and --compare into YYYY-MM-DD since/until pairs for primary and comparison periods. 2. Pull account-level metrics for both periods — GET https://graph.facebook.com/v21.0/{account_id}/insights?fields=spend,impressions,clicks,actions,purchase_roas,cost_per_action_type,cpc,cpm,frequency,reach&date_preset={date_range}&access_token=$META_ACCESS_TOKEN. Repeat for comparison period. Extract: total_spend, total_purchases (actions where type="purchase"), total_purchase_value, account_roas, average_cpa, average_cpm, average_ctr, average_frequency. 3. Pull campaign-level metrics — GET https://graph.facebook.com/v21.0/{account_id}/campaigns?fields=id,name,objective,status,insights.date_preset({date_range}){spend,impressions,clicks,actions,purchase_roas,cpm,ctr,frequency,cost_per_action_type}&filtering=[{"field":"campaign.effective_status","operator":"IN","value":["ACTIVE","PAUSED"]}]&access_token=$META_ACCESS_TOKEN. Repeat for comparison period. 4. Pull creative-level metrics for top/bottom identification — GET https://graph.facebook.com/v21.0/{account_id}/ads?fields=id,name,creative{id,name},insights.date_preset({date_range}){spend,purchase_roas,ctr,cpm,actions,impressions}&filtering=[{"field":"ad.effective_status","operator":"IN","value":["ACTIVE"]}]&access_token=$META_ACCESS_TOKEN. Sort by purchase_roas for top/bottom lists. 5. Calculate week-over-week changes — for each metric: absolute_change = current - prior; pct_change = (current-prior)/prior*100; direction = "up" or "down". 6. Determine account health status — GREEN: ROAS >= target AND CPA <= target AND metrics stable. YELLOW: any key metric declined >10% WoW OR ROAS approaching floor. RED: ROAS below floor OR CPA >20% above target. 7. Generate three recommended actions based on data — one about budget allocation, one about creative, one about audience/targeting. Each must reference specific campaign names or metric values. 8. Format Slack blocks message with: header ("Weekly Meta Report — w/c {date}"), account health status, 6-metric field grid (ROAS, CPA, Spend, Purchases, CPM, Frequency — each with WoW change and direction arrow), top N creatives by ROAS, bottom N underperformers, three recommended actions. 9. POST to $SLACK_WEBHOOK_URL. Confirm 200 "ok". 10. Write ./reports/weekly-report-{YYYY-MM-DD}.md with full metrics table (all campaigns, all metrics, WoW), creative performance table (all active ads sorted by ROAS), health assessment with reasoning, three actions with rationale, data notes. ## Error Handling - No data for primary period: stop with error, check date range - No comparison data: generate report without WoW comparison, note limitation - Slack POST fails: log full message to ./reports/slack-backup-{date}.json so it is not lost - Account spend < $100 in period: flag "low spend" warning ## Example Invocation /weekly-report --date-range=last_7d --compare=previous_7d --format=slack,markdown --slack-channel=#growth

Schedule this to run Monday morning: 0 8 * * 1 claude --command "/weekly-report". Agencies using agentic workflows for reporting have documented 90% reductions in manual operational work, according to Advolve's published case studies.

What Results Can You Expect from These Skills?

The performance benchmarks for AI-driven ad operations are well-documented. Advantage+ campaigns deliver 22% higher ROAS on average compared to equivalent manual campaigns, according to Meta's internal studies — and these skills complement that by handling the operational layer Advantage+ cannot automate: intelligence gathering, CAPI setup, fatigue detection, and reporting.

  • Competitor creative research: 2–3 hours/week → /spy (automated) = ~2.5 hours saved
  • Bulk creative production: 4–8 hours per 50 variations → /bulk-creative (10 min) = ~6 hours saved
  • Campaign deployment: 3–4 hours per launch → /deploy-ads (10 min) = ~3 hours saved
  • Bleed detection & pausing: 30 min daily check → /bleed-check (2 min, scheduled) = ~3.5 hours/week saved
  • Creative fatigue analysis: 1–2 hours/week → /fatigue-scan (5 min) = ~1.5 hours saved
  • Budget reallocation: 1 hour/week → /rebalance (5 min) = ~55 min saved
  • CAPI implementation: 4–8 hours (one-time) → /setup-capi (20 min) = ~6 hours saved
  • Hook/copy generation: 2 hours per 50 variations → /hooks (10 min) = ~1.75 hours saved
  • Audience overlap audit: 2–3 hours/month → /audience-audit (10 min) = ~2.5 hours saved
  • Weekly performance report: 1–2 hours/week → /weekly-report (5 min) = ~1.5 hours saved

Running all 10 skills reduces the operational workload of a typical Meta ads setup by roughly 25–30 hours per week. At agency billing rates, that is $2,500–$4,500/week in recovered capacity.

For teams using HeyOz alongside Claude Code, the workflow becomes even tighter. HeyOz is an AI ads factory that takes a product URL and generates 11+ ad formats — video, static, UGC-style, carousel — with AI avatars and auto-scheduling built in, at $44.99/month versus a traditional creative stack that runs $5,650+/month. Claude Code's /hooks skill generates the copy briefs; HeyOz generates the visual creative from those briefs. The /deploy-ads skill then uploads everything to Meta. The creative pipeline from brief to live campaign can run in under an hour. Start a 3-day free trial at heyoz.com.

Frequently Asked Questions

Do I need a developer background to build these skills?

Not necessarily, but you need comfort with the command line, JSON configuration, and basic API concepts. Claude Code is designed for technical users — if you can read a JSON config file and run npm commands, you can build these skills. Claude Code itself will write the actual API calls; your job is to drop the .md files into .claude/commands/ and configure your environment variables. If you have a growth engineer on your team, the entire setup is a 2–3 hour project for them.

Which skill should I build first?

Build /weekly-report first. It connects to Meta, pulls real data, and produces an output you will use immediately. It validates your API connection, your MCP setup, and your environment variables in one skill. Once that works, /bleed-check is the highest-urgency skill — it protects budget in real time. Then /bulk-creative and /hooks for creative scale.

How does Claude Code connect to Meta's API without exposing credentials?

Store your Meta access token as an environment variable (META_ACCESS_TOKEN) in your shell profile or a .env file that is gitignored. Reference it in CLAUDE.md and in your Claude Code settings as ${META_ACCESS_TOKEN}. Claude Code reads environment variables at runtime without them ever appearing in your code or configuration files.

Can these skills run on a schedule without manual invocation?

Yes. Use cron (on Linux/macOS) or Task Scheduler (Windows) to run claude --command "/bleed-check" on a schedule. Most teams set /bleed-check to run every 6 hours and /weekly-report to run Monday morning at 8 AM. The MCP connection handles authentication automatically. Example cron entry: 0 */6 * * * claude --command "/bleed-check" >> /var/log/bleed-check.log 2>&1

What Meta API permissions do I need?

For read-only skills (/spy, /fatigue-scan, /audience-audit, /weekly-report): ads_read permission. For skills that write changes (/deploy-ads, /bleed-check, /rebalance): ads_management permission. For CAPI setup: business_management permission on the dataset. Generate your token from Meta Business Suite > Settings > Business Assets > System Users.

How do skills handle Meta API rate limits?

Meta's Marketing API has hourly call limits that vary by account tier. Each skill file above includes explicit retry logic: wait 60 seconds on HTTP 429, retry up to 3 times with exponential backoff. For bulk operations like /deploy-ads, a 0.5-second delay is specified between each API call. Claude Code's sequential execution naturally distributes API calls over time.

Is this approach compatible with Meta Advantage+ campaigns?

Fully compatible. The skills in this post operate at the ad account level — they read and write via the same Graph API endpoints that power manual Ads Manager operations. Advantage+ campaigns appear as standard campaigns in the API. Your /rebalance and /bleed-check skills work on Advantage+ ad sets the same way they work on manual campaigns. The 22% ROAS improvement from Advantage+ is additive to the operational efficiency gains from these skills — you are not choosing between them.

About the author

Ahad Shams

Ahad Shams is the Founder of HeyOz, an all-in-one ads and content platform built for founders and small teams. He has worked across consumer goods and technology, with experience spanning Fortune 100 companies such as Reckitt Benckiser and Apple. Ahad is a third-time founder; his previous ventures include a WebXR game engine and Moemate, a consumer AI startup that scaled to over 6 million users. HeyOz was born from firsthand experience scaling consumer products and the need for a unified, execution-focused marketing platform.