How to Build an AI Ad Headline Generator
Generate scroll-stopping ad headlines using AI trained on winning ads.
Jay Banlasan
The AI Systems Guy
An ai ad headline generator tool saves hours of brainstorming and produces variations you would never think of manually. I use this to generate 30+ headline options in minutes, then pick the 5 best to test. The system is trained on your winning ads, not generic templates.
Headlines are the highest-impact element of any ad. A good one can double your CTR overnight.
What You Need Before Starting
- Anthropic API key
- Python 3.8+ with
anthropicinstalled - A collection of your best-performing headlines with CTR data
- Clear product/offer description
Step 1: Build Your Headline Training Data
WINNING_HEADLINES = [
{"headline": "Stop Wasting Money on Ads That Don't Convert", "ctr": 3.2, "type": "pain"},
{"headline": "We Built 47 Systems for One Client. Here's What Happened.", "ctr": 4.1, "type": "proof"},
{"headline": "Your Competitors Are Already Using This", "ctr": 2.8, "type": "fomo"},
{"headline": "The $300K Question Nobody Asks", "ctr": 3.5, "type": "curiosity"},
{"headline": "I Replaced 3 Employees with One System", "ctr": 4.7, "type": "bold_claim"},
]
HEADLINE_TYPES = [
"question", "bold_claim", "curiosity", "pain_point", "social_proof",
"time_based", "dream_outcome", "pattern_interrupt", "stat_driven",
"before_after", "objection_handling", "fomo", "listicle"
]
Step 2: Create the Generator
import anthropic
from dotenv import load_dotenv
load_dotenv()
def generate_headlines(product, audience, pain_point, count=30):
client = anthropic.Anthropic()
examples = "\n".join([
f"- \"{h['headline']}\" (CTR: {h['ctr']}%, Type: {h['type']})"
for h in WINNING_HEADLINES
])
prompt = f"""Generate {count} ad headlines for Meta Ads.
Product: {product}
Target audience: {audience}
Core pain point: {pain_point}
WINNING HEADLINE EXAMPLES (study the patterns):
{examples}
REQUIREMENTS:
- Max 40 characters each
- Use ALL of these headline types: {', '.join(HEADLINE_TYPES)}
- At least 2 headlines per type
- No generic phrases like "transform your business" or "take it to the next level"
- Use specific numbers when possible
- Write at a grade 5 reading level
- Each headline should make someone stop scrolling
Return as JSON array: [{{"headline": "...", "type": "...", "hook_angle": "..."}}]"""
resp = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2000,
messages=[{"role": "user", "content": prompt}]
)
return resp.content[0].text
Step 3: Score and Rank Headlines
import json
def score_headlines(headlines_json, audience):
client = anthropic.Anthropic()
headlines = json.loads(headlines_json)
headlines_text = "\n".join([f'{i+1}. "{h["headline"]}"' for i, h in enumerate(headlines)])
resp = client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1500,
messages=[{"role": "user", "content": f"""Score each headline 1-10 for a {audience} audience.
Criteria:
- Scroll-stop power (would this make someone pause?)
- Clarity (is the value prop clear in under 2 seconds?)
- Curiosity gap (does it create enough tension to click?)
- Relevance to target audience
Headlines:
{headlines_text}
Return JSON array: [{{"index": N, "headline": "...", "score": N, "reason": "..."}}]
Sort by score descending."""}]
)
return resp.content[0].text
Step 4: A/B Test Format
Group the top scorers by type for structured testing:
def prepare_test_groups(scored_headlines, top_n=10):
headlines = json.loads(scored_headlines)
top = sorted(headlines, key=lambda x: x["score"], reverse=True)[:top_n]
groups = {}
for h in top:
h_type = h.get("type", "unknown")
if h_type not in groups:
groups[h_type] = []
groups[h_type].append(h)
print(f"\nTop {top_n} headlines for testing:\n")
for h_type, items in groups.items():
print(f" {h_type.upper()}:")
for item in items:
print(f" [{item['score']}/10] {item['headline']}")
return top
Step 5: Feed Results Back
After running the ads, log which headlines performed best and add them to your training data:
def update_training_data(headline, ctr, headline_type):
WINNING_HEADLINES.append({
"headline": headline,
"ctr": ctr,
"type": headline_type,
})
# Sort by CTR and keep top 20
WINNING_HEADLINES.sort(key=lambda x: x["ctr"], reverse=True)
while len(WINNING_HEADLINES) > 20:
WINNING_HEADLINES.pop()
The more you test and feed back, the better the generator gets at predicting what your audience responds to.
What to Build Next
Build a headline variation engine that takes your top performer and creates 10 variations with small changes (different numbers, different emotions, different structures). This lets you squeeze more performance from proven winners.
Related Reading
- AI for Creative Strategy and Testing - creative strategy for ad testing
- The Compounding Advantage Nobody Talks About - how tested data compounds over time
- AI for Content Creation at Scale - scaling content production with AI
Want this system built for your business?
Get a free assessment. We will map every system your business needs and show you the ROI.
Get Your Free Assessment