Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsBlogPro
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Authors
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges
  • Chrome Extension
  • Skill Manager

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

ProTermsPrivacyRefunds
Back to skills

Meta Ads Publisher

BSecurity

Create and publish ads to Meta (Facebook/Instagram) Ads Manager via the Marketing API — campaigns, ad sets, ads, image upload, carousel + video-placeholder support, all created PAUSED for human review. Runs a mandatory holistic pre-publish review and dual user confirmation. Use after /creative_director has prepared creatives, copy, and landing pages. Triggers (EN): "publish to Meta", "create Meta ads", "push ads to Ads Manager", "launch the campaign on Facebook/Instagram", "/meta_ads_publishe...

2 stars
0 votes
0 copies
0 views
Added 10/2/2026
ai-agentsgobashapi

Works with

cliapi

Security Analysis

B75/100
criticalExfiltrates credentials via HTTP — exact pattern from Snyk ToxicSkills study

Pro shows the line behind each finding and how to fix it

Scanned 10/2/2026

$npx -y skills add agentik-os/claude-code-skills --skill meta_ads_publisher --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Meta Ads Publisher?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Meta Ads Publisher
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/agentik-os-meta-ads-publisher/badge)](https://www.skillsdirectory.com/skills/agentik-os-meta-ads-publisher)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
Files
SKILL.md
---
name: meta_ads_publisher
description: Create and publish ads to Meta (Facebook/Instagram) Ads Manager via the Marketing API — campaigns, ad sets, ads, image upload, carousel + video-placeholder support, all created PAUSED for human review. Runs a mandatory holistic pre-publish review and dual user confirmation. Use after /creative_director has prepared creatives, copy, and landing pages. Triggers (EN): "publish to Meta", "create Meta ads", "push ads to Ads Manager", "launch the campaign on Facebook/Instagram", "/meta_ads_publisher". Triggers (FR): "publie sur Meta", "crée les pubs Meta", "lance la campagne Facebook/Instagram", "envoie les pubs dans Ads Manager", "mets les pubs en ligne (en pause)".
---

# Meta Ads Publisher

Publish campaign assets to Meta Ads Manager via Marketing API.

## Single-execution craft (do NOT parallelize)

This skill performs ONE stateful, sequential publish operation — it is not a fan-out audit.
The chain is strictly ordered and each step's output is the next step's input:
**campaign → `campaign_id` → ad set → `adset_id` → upload image → `image_hash` → ad.**

- **NEVER run parallel agents against the same ad account.** Concurrent writers race on
  the same campaign/ad-set state and create duplicate or orphaned objects (R-SCOPE: one writer
  per ad account). If multiple ads are needed, create them serially within the single ad set.
- **Craft upgrades (apply every run):**
  1. **Idempotency** — before creating a campaign, list existing campaigns
     (`GET /act_{AD_ACCOUNT}/campaigns?fields=name,status`) and reuse/abort on an exact-name
     match instead of silently creating a duplicate.
  2. **Copy ↔ creative fidelity** — the ad copy, CTA, and landing URL must be carried verbatim
     from the /creative_director output; never paraphrase, re-write, or "improve" approved copy
     at publish time. This skill is a faithful courier, not an editor.
  3. **Fail loud, fail paused** — if any API call errors mid-chain, STOP, report the exact Graph
     API error + the IDs already created, and never proceed to the next step on a guess.

> **Portability note (VPS-only infra):** credentials below assume a local `.env` and the OmegaOS
> `TOOLS.md`. On any other host, export `META_AD_ACCOUNT_ID`, `META_PAGE_ID`, `META_ACCESS_TOKEN`
> in the environment (or your secret manager) — the curl logic is host-agnostic and needs no change.

## Prerequisites

- Meta Marketing API token (system user with ads_management permission)
- Ad Account ID
- Facebook Page ID
- Payment method on ad account (required by API)
- Approved creatives from /creative_director

## Credentials

Set these in your `.env` file:

```
META_AD_ACCOUNT_ID=act_your_account_id
META_PAGE_ID=your_facebook_page_id
META_ACCESS_TOKEN=your_access_token
```

See TOOLS.md for how to obtain these credentials.

## Workflow

### 1. Gather Assets

Before publishing, confirm you have:
- [ ] Campaign name and objective
- [ ] Ad set targeting (geo, age, interests)
- [ ] Daily/lifetime budget
- [ ] Image files (uploaded or local paths)
- [ ] Ad copy for each creative
- [ ] Landing page URLs
- [ ] CTA type (LEARN_MORE, SIGN_UP, etc.)

### 2. Pre-Publish Holistic Review ⚠️ MANDATORY

**Before creating ANY ads, review the full picture:**

```
┌─────────────────────────────────────────────────────────┐
│  HOLISTIC REVIEW CHECKLIST                              │
├─────────────────────────────────────────────────────────┤
│  □ Ad copy matches creative visuals                     │
│  □ Landing page URL is correct for each ad              │
│  □ CTA matches the funnel stage (TOFU/MOFU/BOFU)        │
│  □ Targeting makes sense for the offer                  │
│  □ Budget is appropriate for test/scale phase           │
│  □ All ads in set are thematically consistent           │
│  □ No typos or broken links                             │
│  □ DSA compliance fields filled (EU targeting)          │
│  □ Image dimensions correct (1:1, 4:5, etc.)            │
│  □ Video placeholders have complete copy                │
└─────────────────────────────────────────────────────────┘
```

**Present summary to user:**
```markdown
## 📋 Pre-Publish Review

**Campaign:** [name]
**Objective:** [TRAFFIC/LEADS/etc]
**Budget:** €[X]/day

**Ad Set:** [name]
**Targeting:** [countries], ages [X-Y]

**Ads to create:**
| # | Name | Type | Landing Page | CTA |
|---|------|------|--------------|-----|
| 1 | ... | Image | /path | LEARN_MORE |
| 2 | ... | Video | /path | SIGN_UP |

**Copy preview:**
> [First 100 chars of each ad's copy...]

✅ All checks passed. Ready to publish?
```

**Wait for user confirmation before proceeding.**

### 3. Create Campaign

```bash
curl -X POST "https://graph.facebook.com/v21.0/act_{AD_ACCOUNT}/campaigns" \
  -d "name=Campaign Name" \
  -d "objective=OUTCOME_TRAFFIC" \
  -d "status=PAUSED" \
  -d "special_ad_categories=[]" \
  -d "is_adset_budget_sharing_enabled=false" \
  -d "access_token=$TOKEN"
```

**Objectives:**
- `OUTCOME_AWARENESS` — Brand awareness
- `OUTCOME_TRAFFIC` — Website traffic
- `OUTCOME_ENGAGEMENT` — Post engagement
- `OUTCOME_LEADS` — Lead generation
- `OUTCOME_SALES` — Conversions

### 4. Create Ad Set

```bash
curl -X POST "https://graph.facebook.com/v21.0/act_{AD_ACCOUNT}/adsets" \
  -d "name=Ad Set Name" \
  -d "campaign_id={CAMPAIGN_ID}" \
  -d "status=PAUSED" \
  -d "billing_event=IMPRESSIONS" \
  -d "optimization_goal=LINK_CLICKS" \
  -d "bid_strategy=LOWEST_COST_WITHOUT_CAP" \
  -d "daily_budget=2000" \
  -d 'targeting={"geo_locations":{"countries":["DE","AT","CH"]},"age_min":25,"age_max":55,"targeting_automation":{"advantage_audience":0}}' \
  -d "dsa_beneficiary=Company Name" \
  -d "dsa_payor=Company Name" \
  -d "access_token=$TOKEN"
```

**Required for EU targeting:**
- `dsa_beneficiary` — Who benefits from the ads
- `dsa_payor` — Who pays for the ads
- `targeting_automation.advantage_audience` — 0 to disable, 1 to enable

### 5. Upload Images

```bash
curl -X POST "https://graph.facebook.com/v21.0/act_{AD_ACCOUNT}/adimages" \
  -F "filename=@/path/to/image.png" \
  -F "access_token=$TOKEN"
```

Returns `image_hash` for use in ad creative.

### 6. Create Ads

**Single Image Ad:**
```bash
curl -X POST "https://graph.facebook.com/v21.0/act_{AD_ACCOUNT}/ads" \
  -d "name=Ad Name" \
  -d "adset_id={ADSET_ID}" \
  -d "status=PAUSED" \
  -d 'creative={"object_story_spec":{"page_id":"{PAGE_ID}","link_data":{"image_hash":"{HASH}","link":"https://...","message":"Ad copy here","call_to_action":{"type":"LEARN_MORE"}}}}' \
  -d "access_token=$TOKEN"
```

**Carousel Ad:**
```bash
curl -X POST "https://graph.facebook.com/v21.0/act_{AD_ACCOUNT}/ads" \
  -d "name=Carousel Ad" \
  -d "adset_id={ADSET_ID}" \
  -d "status=PAUSED" \
  -d 'creative={"object_story_spec":{"page_id":"{PAGE_ID}","link_data":{"message":"Main copy","link":"https://...","child_attachments":[{"link":"...","image_hash":"...","name":"Slide title","description":"Slide desc"}],"multi_share_optimized":true}}}' \
  -d "access_token=$TOKEN"
```

**Video Ad (placeholder — copy only, no video):**
Create as link ad with copy. Video uploaded later:
```bash
curl -X POST "https://graph.facebook.com/v21.0/act_{AD_ACCOUNT}/ads" \
  -d "name=VIDEO PLACEHOLDER - Name" \
  -d "adset_id={ADSET_ID}" \
  -d "status=PAUSED" \
  -d 'creative={"object_story_spec":{"page_id":"{PAGE_ID}","link_data":{"link":"https://...","message":"Video script as ad copy","name":"Headline","description":"Subhead","call_to_action":{"type":"LEARN_MORE"}}}}' \
  -d "access_token=$TOKEN"
```

### 7. Post-Publish Confirmation

After creating all ads, provide summary:

```markdown
## ✅ Ads Published to Meta

**Campaign:** [name] (ID: xxx) — PAUSED
**Ad Set:** [name] (ID: xxx) — PAUSED

**Ads Created:**
| # | Name | Type | ID | Status |
|---|------|------|-----|--------|
| 1 | ... | Image | xxx | PAUSED |
| 2 | ... | Carousel | xxx | PAUSED |
| 3 | ... | Video Placeholder | xxx | PAUSED |

**Review in Ads Manager:**
https://www.facebook.com/adsmanager/manage/ads?act={AD_ACCOUNT}

**Next steps:**
1. Review ads in Ads Manager
2. Upload videos for placeholder ads
3. When ready, set status to ACTIVE
```

## CTA Types

| Type | Use Case |
|------|----------|
| LEARN_MORE | General info, tutorials |
| SIGN_UP | Email capture, courses |
| DOWNLOAD | Lead magnets, PDFs |
| GET_OFFER | Promotions, discounts |
| BOOK_NOW | Consultations, calls |
| CONTACT_US | B2B inquiries |
| SHOP_NOW | E-commerce |
| WATCH_MORE | Video content |

## Common Errors

| Error | Solution |
|-------|----------|
| No Payment Method | Add credit card to ad account |
| App in Development Mode | Switch app to Live mode |
| DSA fields required | Add dsa_beneficiary and dsa_payor |
| Advantage Audience required | Add targeting_automation.advantage_audience |
| Invalid image dimensions | Use 1:1, 4:5, or 9:16 aspect ratios |

## Integration with Creative Team

```
/campaign_planner → Strategy approved
        ↓
/creative_director → Assets created
        ↓
/meta_ads_publisher → Published to Meta (PAUSED)
        ↓
User reviews in Ads Manager → ACTIVE
```

## Output contract & verification

**Produces (Done Criteria):**
- One campaign, ≥1 ad set, ≥1 ad — **all `status=PAUSED`** — in the target ad account.
- A post-publish summary table with the **real** campaign/ad-set/ad IDs returned by the API.
- A working Ads Manager review link for the account.

**VERIFY (run before claiming done — runtime is the only truth, L1):**
```bash
# Confirm every created object exists AND is paused. Fail if any row is ACTIVE.
curl -s "https://graph.facebook.com/v21.0/{CAMPAIGN_ID}?fields=name,status&access_token=$TOKEN"
curl -s "https://graph.facebook.com/v21.0/{ADSET_ID}?fields=name,status&access_token=$TOKEN"
curl -s "https://graph.facebook.com/v21.0/act_{AD_ACCOUNT}/ads?fields=name,status&access_token=$TOKEN"
```
Done only when each GET returns the object with `"status":"PAUSED"`. A 200 on POST is not proof —
read back the object.

**No-hallucination guardrail (R-CITE):**
- Every ID in the summary table MUST come from an actual API response body — **never invent,
  guess, or pattern-fill an ID.** If a call failed, the ID cell reads `FAILED: <error>`, not a number.
- Quote the exact Graph API error string on any failure; do not summarize it as "something went wrong".
- The review checklist (§2) is graded against the real assets on disk/URL, not assumed.

## Safety Rules

1. **Always create as PAUSED** — Never auto-activate ads
2. **Always do holistic review** — Check copy ↔ creative match
3. **Always confirm with user** — Before creating, after creating
4. **Always provide Ads Manager link** — For manual review
5. **Never modify active ads** — Only paused/draft

Attribution

agentik-osagentik-os
View sourceSee grades on GitHubMore from agentik-os →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Caveman

Terse caveman voice: answer first, fluff gone, every technical fact kept. Use for /caveman, "caveman mode", "talk like caveman", "be brief", "less tokens". Stays on until "stop caveman" or "normal mode".

1100021 votes

Hyperplan

Adversarial multi-agent planning skill. Self-orchestrates 5 hostile category members (unspecified-low, unspecified-high, deep, ultrabrain, artistry) via team-mode for ruthless cross-critique debate, distills only the defensible insights, then MANDATORILY hands the distilled insight bundle to the `plan` agent for executable plan formalization. Use when planning needs maximum rigor and surfacing of weak assumptions, blind spots, and over-engineering. Triggers: 'hyperplan', 'hpp', '/hyperplan', ...

698431 votes

Writing Skills

Create and manage Claude Code skills in HASH repository following Anthropic best practices. Use when creating new skills, modifying skill-rules.json, understanding trigger patterns, working with hooks, debugging skill activation, or implementing progressive disclosure. Covers skill structure, YAML frontmatter, trigger types (keywords, intent patterns), UserPromptSubmit hook, and the 500-line rule. Includes validation and debugging with SKILL_DEBUG. Examples include rust-error-stack, cargo-dep...

3931 votes

Mcp Code Execution

Routes multi-tool workflows through MCP servers for large datasets and pipelines. Use when Bash tool overhead is limiting throughput on data-heavy tasks.

3421 votes

catchup

Recovers the conversation and failed tool calls of a previous Codex, Amp, Claude Code, Antigravity, Cline, Copilot CLI, Cursor, DeepSeek Harness, Grok Build, Kimi, OpenCode, Pi Agent, or ZCode session. Use when the user says "catch up", "what did the last session do", "get me up to speed", "I switched agents", asks to recover/summarize a previous session before continuing, or asks to diagnose or report a catchup failure. Do NOT use for the current conversation, git history, or any non-agent log.

741 votes
View all in ai-agents →