# Ad Copy Generator

> Generate high-converting Meta ad copy matched to specific image creatives. Analyzes visuals, writes copy that reinforces the image, cross-references account performance data through the official Ads CLI adapter when available, and outputs payload-ready variants.

- Skill: `themattberman/ad-copy-generator` (Agent Skill)
- Install (CLI): `npx skillmds@latest add themattberman/ad-copy-generator`
- Raw SKILL.md: https://api.skillmd.com/api/skills/themattberman/ad-copy-generator/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: TheMattBerman (https://skillmd.com/u/themattberman)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/themattberman/ad-copy-generator

---


# Ad Copy Generator

Write Meta ad copy that's matched to the actual image creative — not generic copy pasted across every ad. Each image gets copy that reinforces its specific message, written in the brand's voice, informed by what's already working in the account.

Read `workspace/brand/` per the _vibe-system protocol if available.

---

## Brand Memory Integration

This skill reads brand context to make every piece of copy sound like the brand, not a template.

**Reads:** `voice-profile.md`, `positioning.md`, `audience.md` (all optional)

On invocation:

1. **Load `voice-profile.md`** — Match tone, vocabulary, forbidden words. Show: "Voice loaded — [tone summary]."
2. **Load `positioning.md`** — Use angle as copy's foundation. Show: "Positioning: [angle]."
3. **Load `audience.md`** — Know who we're talking to, their awareness level, their language. Show: "Writing for [audience summary]."
4. **If `workspace/brand/` doesn't exist** — Skip. Ask for ICP, voice notes, and forbidden words inline. This skill works standalone.

---

## Iteration Detection

Before writing, check for existing copy:

1. **Check `workspace/campaigns/{name}/ads/`** — If copy exists, show what's there.
2. **Ask:** "Revise existing, add variants, or start fresh?"
3. **If nothing exists** — Proceed to generation.

---

## The Process

### Step 1: Pull What's Already Working

Before writing a single word, look at the account. What copy is converting?

```bash
# Top performers by CTR — last 30 days through official Ads CLI
meta --output json --no-input ads insights get \
  --date-preset last_30d \
  --fields spend,impressions,clicks,ctr,cpc,reach \
  --sort ctr_descending \
  --limit 20
```

For creative details, prefer official CLI resources where supported:

```bash
meta --output json --no-input ads ad get AD_ID
meta --output json --no-input ads creative get CREATIVE_ID
```

If official CLI does not expose a needed creative field yet, use direct Graph API only as an explicit fallback.

**Extract patterns:**
- Headline length and structure (questions? numbers? commands?)
- Body copy hooks (opens with pain? data? question? story?)
- Social proof claims (X customers, Y% increase, Z revenue)
- Reading level (short punchy vs. narrative)
- CTA that converts (Learn More vs Get Started vs Book Demo)

Show the user what you found: "Your top 3 ads all open with a specific number and close with social proof. Average headline: 32 chars. I'll match that pattern."

### Step 2: Load Brand Context

Read the client's CLAUDE.md, brand profile, or ask inline:

| Need | Where | Fallback |
|------|-------|----------|
| ICP | `audience.md` or CLAUDE.md | Ask: "Who's this for?" |
| Voice | `voice-profile.md` | Ask: "Any words to avoid? Tone preference?" |
| Pain points | `audience.md` | Extract from top-performing copy |
| Key stats | Brand brief / CLAUDE.md | Ask: "What proof points can I use?" |
| Forbidden words | `voice-profile.md` | Default ban list (see below) |

**Default forbidden words** (always banned unless brand explicitly uses them):
revolutionary, game-changer, cutting-edge, innovative solution, transform your business, unlock your potential, unleash, harness the power, leverage (as verb), next-level, best-in-class, world-class, seamless, robust, synergy

### Step 3: Analyze Each Image Creative

For every image that needs copy, use vision to identify:

1. **Visual format** — Notes app, receipt, tweet, chart, kitchen photo, poster, review, slack, etc.
2. **On-image text** — What copy is already baked into the image?
3. **Angle/hook** — What psychology is the image pulling?
4. **Mood** — Organic/found-footage, professional, urgent, casual, dark, bright
5. **Funnel stage** — Awareness (problem), consideration (solution), conversion (offer)

**The critical rule:** Copy reinforces the image, never repeats it. If the image shows "$17K/month", the body tells the story behind that number. If the image shows a stressed host, the copy describes the chaos. Image and copy are two halves of one message.

### Step 4: Write Copy Using Psychology

Every ad pulls at least one psychological lever. Rotate across variants so Meta can test.

**The Four Horsemen (Kallaway Framework):**

| Horseman | Trigger | Opening Pattern |
|----------|---------|-----------------|
| **Money** | Revenue loss, ROI, cost savings | "Every [thing] you miss is worth $X." |
| **Time** | Wasted hours, efficiency, speed | "Your [person] isn't a [wrong role]." |
| **Status** | Peer comparison, industry moves | "X+ [peers] already [did thing]." |
| **Fear** | Loss aversion, competitive threat | "The [competitor] down the street already has this." |

**Matching psychology to image format:**

| Image Format | Best Psychology | Copy Tone |
|-------------|----------------|-----------|
| Notes app / screenshot | Fear + Money | Casual first-person discovery |
| Fake tweet / social | Status + Fear | Conversational, peer voice |
| Data visualization | Money + Status | Authority, numbers-forward |
| Receipt / POS | Money + Time | Specific, transactional |
| Kitchen / still life | Fear + Time | Emotional, atmospheric |
| Review / testimonial | Status + Money | Third-person proof |
| Slack / workplace | Time + Status | Insider, operational |
| News article | Fear + Status | Urgent, newsjacking |
| Before/after | Money + Time | Contrast, transformation |
| Bold text / poster | Any | Direct, declarative |
| Google review | Status + Money | Social proof, customer voice |
| Whiteboard / letter board | Time + Fear | Physical, tangible |
| Lock screen / notifications | Fear + Time | Urgency, real-time |

### Step 5: Apply Copy Specs

These specs come from analyzing hundreds of winning Meta ads:

| Element | Spec | Why |
|---------|------|-----|
| Headline length | 25-40 chars, never >50 | Truncation on mobile kills CTR |
| Body word count | 50-120 words | Short enough to read, long enough to convince |
| Paragraphs | 2-3, each 1-2 sentences | Mobile readability — walls of text = scroll past |
| Numbers required | ≥1 per variant ($, %, or count) | Specificity = credibility |
| Social proof | Include where natural | "X+ customers" is the highest-converting pattern |
| Opening line | Pain, stat, or bold claim | Never brand name, never "Introducing" |
| Closing line | Social proof + soft CTA | "X+ already made the switch." |
| Line breaks | After every 1-2 sentences | Scannability on mobile |
| No em dashes | Use hyphens or restructure | Rendering inconsistency across placements |
| No emojis in body | Unless brand voice uses them | Most B2B/professional ads don't |

### Step 6: Generate Degrees of Freedom Variants

Meta's algorithm tests combinations. Give it options:

**Per creative:**
- 3-5 headline variants (different angles)
- 3-5 body copy variants (different psychology)
- 1-2 description variants (supporting stat or benefit)

**Rules for variant quality:**
- Each variant MUST hit a different Horseman. V1=Fear, V2=Money, V3=Status, etc.
- No two headlines should use the same structure. Mix questions, statements, numbers, commands.
- No two body variants should open the same way.
- At least one variant should feel like organic content (not an ad).

### Step 7: Cross-Reference with Account Winners

Before finalizing, check your copy against Step 1 findings:
- Does headline length match what's working?
- Are you using similar hook structures?
- Does reading level match?
- Are your social proof claims consistent with what the account already says?

Flag any mismatches: "Your top performers use question headlines. 2 of my 3 headlines are questions — aligned."

---

## Funnel Stage Adjustments

| Stage | Objective | Copy Focus | CTA | Proof Level |
|-------|-----------|------------|-----|-------------|
| **ToFu** | Awareness / Traffic | Problem awareness, curiosity | Learn More | Light — "X+ use this" |
| **MoFu** | Consideration / Leads | Solution proof, specific features | Get Free Audit / See Demo | Medium — case study snippets |
| **BoFu** | Conversion / Sales | Urgency, risk reversal, pricing | Start Free Trial / Book Demo | Heavy — ROI numbers, testimonials |

Adjust body copy density:
- ToFu: 50-80 words (fast read, curiosity-driven)
- MoFu: 80-120 words (more detail, proof points)
- BoFu: 60-100 words (tight, urgent, specific offer)

---

## Output Format

For each creative:

```markdown
## [Creative Name]
*Image: [brief description of what the image shows]*
*Format: [notes app / tweet / receipt / etc.]*
*Psychology: [primary Horseman] + [secondary]*
*Funnel: [ToFu / MoFu / BoFu]*
*Matched to image: [one line on how copy reinforces the visual]*

### Headlines
1. [headline] ([XX] chars) — [Horseman]
2. [headline] ([XX] chars) — [Horseman]
3. [headline] ([XX] chars) — [Horseman]

### Body Copy

**V1 — [Horseman]: [Angle name]**
[body text]
*[word count] words*

**V2 — [Horseman]: [Angle name]**
[body text]
*[word count] words*

**V3 — [Horseman]: [Angle name]**
[body text]
*[word count] words*

### Descriptions
1. [description]
2. [description]

### asset_feed_spec (ready for API)
```json
{
  "bodies": [
    {"text": "V1 body..."},
    {"text": "V2 body..."},
    {"text": "V3 body..."}
  ],
  "titles": [
    {"text": "Headline 1"},
    {"text": "Headline 2"},
    {"text": "Headline 3"}
  ],
  "descriptions": [
    {"text": "Description 1"},
    {"text": "Description 2"}
  ]
}
`` `
```

---

## Campaign File Output

After generation, save to campaign directory:

```
workspace/campaigns/{campaign-name}/ads/
  {creative-name}.md          <- Full copy document
  {creative-name}.json        <- asset_feed_spec JSON
```

Append to `workspace/brand/assets.md`:
```
| {creative-name} copy | ad-copy | YYYY-MM-DD | {campaign-name} | draft | 3 headlines, 3 bodies |
```

---

## Anti-Patterns

- **Reusing copy across creatives** — Every image gets unique copy that matches IT
- **Same psychology across variants** — V1/V2/V3 must hit different Horsemen
- **Starting with brand name** — Nobody cares about your brand in ToFu
- **Generic SaaS language** — See forbidden words list
- **Emoji bullet lists** — Looks like every other ad on Meta
- **Ignoring account data** — Always check what's working first
- **Copy that repeats the image** — Image says the number, copy tells the story
- **Long paragraphs** — 3+ sentences = scroll past on mobile
- **Same headline structure** — Mix questions, stats, commands, statements
- **Hard sell CTAs in ToFu** — "Sign up now" in awareness = low CTR

---

## Quick Mode

If the user provides images and says "write copy for these" without specifying a full workflow:

1. Skip account data pull (or use cached if available)
2. Load brand context if it exists
3. Analyze images → write matched copy → output in standard format
4. Still suggest checking against account data as a next step

---

## Integration

This skill connects to the Meta Ads Copilot ecosystem:

- **Upstream:** `ad-creative-monitor` detects fatigue → triggers copy refresh
- **Downstream:** Copy output feeds into Meta Graph API ad creation/update
- **Learnings loop:** Track which copy patterns win, append to `workspace/brand/learnings.md`

**Saved:** `workspace/campaigns/{name}/ads/` + `workspace/brand/assets.md`

**Next up:** Push copy to Meta via Graph API (`ad-upload` skill) or review in Ads Manager manually.

