From octave
Generates platform-ready ad campaign plans with creative, audience targeting, and landing page recommendations from Octave library intelligence.
How this skill is triggered — by the user, by Claude, or both
Slash command
/octave:ads [describe the campaign target and angle][describe the campaign target and angle]The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate platform-ready ad campaign plans grounded in your Octave library intelligence. Creates one ad set per persona or ICP, with creative variants generated from real prospect language extracted from calls and emails. Source cards are persisted to disk so `/octave:ads-resonance` can later map performance back to the exact derivation chain behind each headline.
Generate platform-ready ad campaign plans grounded in your Octave library intelligence. Creates one ad set per persona or ICP, with creative variants generated from real prospect language extracted from calls and emails. Source cards are persisted to disk so /octave:ads-resonance can later map performance back to the exact derivation chain behind each headline.
MCP Server: This skill requires the Octave MCP server. Look for available MCP tools that match the Octave tool names (e.g., list_entities, list_findings, search_knowledge_base, get_entity). The MCP server prefix varies by workspace — it may be {octave_mcp}__, mcp__octave_myworkspace__, or another name. If multiple Octave-like MCP servers are available and you're unsure which to use, ask the user which workspace to target.
This step is critical. Before asking platform/structure questions, establish the campaign's creative direction. The angle is the most important decision — it determines what every headline, description, and keyword should say.
First, scan the user's freeform arguments for context they've already provided:
Using AskUserQuestion, ask:
"How do you want to approach the creative direction for this campaign?"
I have a specific angle — "I know the exact framing and messaging I want. Let me describe it." → Collect their angle in detail (situation, framing, key phrases to include). This becomes the primary creative driver, and library data provides supporting evidence.
Let's brainstorm together — "I have some ideas but want to explore options." → Use the Octave library to surface 3-5 potential angles (derived from use cases, hypotheses, competitor gaps, and findings that match the target audience). Present them as options with a brief rationale for each. Let the user pick one or combine elements. Then proceed.
Auto-generate from my Octave library — "Just use what's in my library to find the best angle." → Analyze the target persona/segment, search for the highest-signal use cases and hypotheses, and select the strongest angle automatically. Present the chosen angle to the user for confirmation before generating creative.
If the user already provided a clear angle in their arguments, acknowledge it and ask: "You mentioned [angle]. Should I build the entire campaign around this, or do you want to explore other angles too?"
The selected angle becomes the primary creative driver for the entire campaign. It shapes:
Example — user input: generate ad campaign for VPs of Engineering at mid-market FinServ companies dealing with compliance automation gaps. Extracted: Target = VPs of Engineering at mid-market Financial Services companies; Situation = manual compliance processes that don't scale; Angle = your product automates the compliance workflow they're currently doing by hand — turning audit prep from weeks to hours. This angle should appear in EVERY variant — pain-focused variants should reference "your team spends weeks preparing for audits that should take hours," outcome-focused should reference "engineering teams that automated compliance prep cut audit cycles by X%," etc.
Ask the user these questions using AskUserQuestion. Each question should be its own AskUserQuestion call — do NOT bundle unrelated questions together (e.g., platform and voice are independent choices and must be asked separately). Collect all answers before proceeding.
Ask which platform they're building for. This determines creative constraints.
| Platform | Headlines | Max H Length | Descriptions | Max D Length | Notes |
|---|---|---|---|---|---|
| Google Search | Up to 15 | 30 chars | Up to 4 | 90 chars | Responsive Search Ads |
| Google Display | Up to 5 | 30 chars | Up to 5 | 90 chars | Responsive Display Ads |
| Meta (Facebook/Instagram) | 1 primary text | 125 chars | 1 headline | 40 chars | Single image/video ads |
| 1 intro text | 150 chars | 1 headline | 70 chars | Sponsored Content |
Ask how they want to structure their ad sets:
Ask what their campaign goal is:
If the user selected Product Launch, ask a follow-up question to collect launch details. This context shapes every variant's creative:
Ask (as a single AskUserQuestion with free-text, or prompt them to describe):
Store these answers and use them throughout Step 3 to ensure every variant is grounded in the specific launch, not generic product messaging. The launch context should be the PRIMARY creative driver — library data (personas, use cases, proof points) provides supporting evidence and targeting, but the launch angle leads.
Before asking, fetch the workspace domain:
→ {octave_mcp}__verify_connection()
Extract the workspace's website domain from the connection response (e.g., acme.com). Use this as the default landing page base URL.
Ask about landing pages:
https://{domain} as the base landing page URL. Append relevant paths per ad set if the user provides them, or suggest paths based on use case (e.g., https://{domain}/compliance, https://{domain}/demo).Ask about voice and tone for the creative:
If they choose "Use my Octave brand voice", fetch it in Step 2:
→ {octave_mcp}__list_entities(entityType: "brand_voice")
→ {octave_mcp}__get_entity(oId: "{brand_voice_oId}") // fetch full voice guidelines (tone, word choice, style rules)
If they choose "Custom", ask them to describe it in 1-2 sentences (e.g., "Sharp, slightly irreverent, like a smart friend who works in the industry").
The selected voice/tone should be applied consistently across ALL variants in ALL ad sets. It shapes word choice, sentence structure, and emotional register — but does NOT override the variant-specific methodology (pain-focused still leads with pain, social proof still leads with proof points, etc.).
Ask if they want to share approximate monthly budget. This helps calibrate the number of ad sets and variants. Not required — skip if they prefer not to share.
Based on the ad set structure chosen in Step 1, fetch the relevant data from Octave MCP.
If ICP or Persona mode:
→ {octave_mcp}__list_entities(entityType: "persona")
If ICP or Segment mode:
→ {octave_mcp}__list_entities(entityType: "segment")
Present the list to the user and ask them to confirm which ones to build ad sets for, or select "all."
Fetch all use cases and competitors — these inform creative themes and negative targeting.
→ {octave_mcp}__list_entities(entityType: "use_case")
→ {octave_mcp}__list_entities(entityType: "competitor")
→ {octave_mcp}__list_entities(entityType: "proof_point")
→ {octave_mcp}__list_entities(entityType: "reference")
Use list_findings to surface real prospect language from calls and emails. This is the highest-value data source for ad creative — it captures how buyers actually describe their problems in their own words.
For each selected persona/segment, fetch findings using natural language queries:
→ {octave_mcp}__list_findings(
query: "what pain points are prospects mentioning",
eventFilters: { personas: ["{persona_oId}"], segments: ["{segment_oId}"] },
limit: 20
)
→ {octave_mcp}__list_findings(
query: "objections from prospects",
eventFilters: { personas: ["{persona_oId}"], segments: ["{segment_oId}"] },
limit: 20
)
→ {octave_mcp}__list_findings(
query: "what's getting customers excited about our product",
eventFilters: { personas: ["{persona_oId}"], segments: ["{segment_oId}"] },
limit: 20
)
Also fetch competitive mentions from conversations:
→ {octave_mcp}__list_findings(
query: "competitor mentions and comparisons",
limit: 20
)
Additionally, search the knowledge base for library-level intelligence (entity descriptions, Motion ICP narratives, hypotheses):
→ {octave_mcp}__search_knowledge_base(
query: "{persona name} pain points challenges objections",
includeResources: false,
limit: 10
)
Priority: Findings from list_findings (real prospect voice) should ALWAYS be preferred over library entity descriptions when writing ad creative. Library data is the fallback when no findings exist.
If the user chose "Suggest from my resources":
→ {octave_mcp}__search_knowledge_base(
query: "{persona/use case} landing page case study datasheet",
includeResources: true,
limit: 5
)
Suggest the most relevant resource URL as the landing page for each ad set.
For EACH competitor entity, build a narrative gap analysis. This is the foundation for all competitive ad variants.
Step 1 — Their public narrative: Read the competitor entity description from the library. This captures their claimed positioning (e.g., "orchestrate any workflow with 100+ integrations").
Step 2 — What prospects actually say about them: Search for real mentions of this competitor in calls and emails using list_findings:
→ {octave_mcp}__list_findings(
query: "what are prospects saying about {competitor name}",
eventFilters: { competitors: ["{competitor_oId}"] },
limit: 20
)
Also search the knowledge base for library-level competitive intelligence:
→ {octave_mcp}__search_knowledge_base(
query: "{competitor name} problems limitations frustrations switching",
includeResources: false,
limit: 10
)
Step 3 — Identify the gap: Compare the competitor's public narrative (what they promise) with what your prospects actually experience (what they say in calls/emails). The gap between promise and reality is your competitive angle.
Produce a Narrative Gap Card for each competitor:
### Competitor: {name}
- **Their narrative**: {what they claim — from library entity description}
- **What prospects actually say**: {direct quotes from calls/emails about this competitor}
- **The gap**: {one sentence: they promise X, prospects experience Y}
- **Your exploit angle**: {how to position against this specific gap}
- **Sample displacement headline**: {one headline that exploits the gap}
If no prospect language exists about a competitor, note: "No field intelligence on {competitor} yet — competitive variant uses library positioning only. Connect call integrations to surface real prospect frustrations with this competitor."
These narrative gap cards drive the competitive variant generation in Step 3.
This step is critical. Before generating any ad creative, build a structured analytical artifact — a Source Card — for every variant type you intend to generate. Source cards are the creative brief for each variant. The creative is derived FROM the card. Headlines and descriptions that can't trace back to a source card don't ship.
The Narrative Gap Card (Step 2E) already serves this purpose for the competitive variant. Now build equivalent cards for every other variant type.
For EACH ad set (persona/segment), build the following source cards using the data fetched in Steps 2A-2C. Not every card is required — skip any where the underlying data doesn't exist (e.g., skip Proof Chain if no proof points match this persona). But always produce at least: Pain Language Audit, one of Proof Chain or Compounding Cost Model, and Self-Selection Matrix.
See source-card-templates.md for the seven source card templates (Pain Language Audit, Proof Chain, Self-Selection Matrix, Compounding Cost Model, Contrarian Thesis, Social Proof Hierarchy, Metric Defensibility).
How Source Cards flow into Step 3:
Each variant's creative generation in Step 3 follows this process:
If a source card reveals that the data doesn't support a variant (e.g., Proof Chain shows no defensible metrics → skip Data-Driven; Self-Selection Matrix shows no question scores above 6/10 → skip Question-Based), skip that variant and note why. This prevents weak variants from diluting the campaign.
Always do this, immediately after building the source cards in Step 2F and before generating creative in Step 3. The persisted file is the data contract between this skill and /octave:ads-resonance: it's what lets the resonance loop trace performance forward from source cards → variants → headlines. Without this file, the loop falls back to reverse-inference from headlines, which is much weaker.
Write source cards to ~/.octave/source_cards/<workspace_slug>/<campaign_slug>.json:
<workspace_slug> is derived from the Octave workspace name returned by {octave_mcp}__verify_connection() (called earlier in Step 1 Question 4 for the landing page domain). Lowercase, replace spaces and special characters with hyphens, strip everything that isn't [a-z0-9-]. Example: workspace "Acme Marketing" → acme-marketing.<campaign_slug> is derived from the campaign's identifying details: <persona-slug>-<segment-slug>-<YYYY-MM-DD>. If the user has explicitly named the campaign, use that name (slugified).If the file already exists at the target path (re-running Step 2F for the same campaign), append a -v2, -v3, etc. suffix. Never overwrite an existing source card file — the resonance loop may have already evaluated predictions tied to it.
The file is a single JSON object. The schema — campaign metadata, one entry per source card, and the headlines_by_variant / descriptions_by_variant maps — is defined in source-cards.template.json, including a fully worked example. Copy that template's structure. The headlines_by_variant and descriptions_by_variant fields start as empty objects — Step 3C fills them in after creative generation, mapping each {ad_set}/{variant_type} key to the headlines and descriptions that were actually generated. This is what the resonance loop matches against ad-platform data later.
ls ~/.octave/source_cards/<workspace_slug>/ 2>/dev/null.mkdir -p ~/.octave/source_cards/<workspace_slug>/.chmod 600 since it may contain prospect quotes from real calls.~/.octave/source_cards/<workspace_slug>/<campaign_slug>.json. The resonance loop (/octave:ads-resonance) will use these to map performance back to derivation chains in future runs."$HOME/.octave/, outside any repo, and is isolated per user; files are user-owned with mode 600If the user explicitly objects to persistence (e.g., they don't want any local files), they can pass --no-persist-source-cards as an argument and Step 2G is skipped. Default is to persist.
CRITICAL: If Step 0 extracted a campaign angle from the user's arguments, that angle MUST be woven into every variant's creative. The angle is not supplementary context — it is the primary lens through which all headlines, descriptions, and keyword strategies should be written. Library data (personas, use cases, proof points) provides supporting evidence, but the user's stated angle leads.
For EACH persona/ICP/segment (based on the structure chosen), generate a complete ad set plan following the output template in ad-set-template.md.
Generate 4-8 ad variants per ad set. Every variant MUST be derived from its corresponding Source Card built in Step 2F. The source card is the creative brief — read it first, use its "headline derivation" field as the starting point, and cite it in attribution. The eight variant types (pain-focused, outcome-focused, social proof, competitive, question-based, data-driven, status quo, authority), each with its driving source card, methodology, and skip condition, are defined in variant-methodologies.md — read that file before generating creative.
Rules for variant selection:
After generating all ad sets, perform a dedicated review pass on EVERY headline across all variants. This is a separate, explicit step — not part of initial generation.
The generation-time rules this review enforces:
Extract all headlines — Collect every headline from every variant across all ad sets into a flat list.
Read each headline in complete isolation — Cover up the variant context, the other headlines, and the descriptions. Ask: "If this headline appeared alone on a search results page with NO surrounding context, would a person in the target audience understand what it means and find it compelling?"
Check against these failure modes:
| Failure Mode | Example | Fix |
|---|---|---|
| Fragment / continuation | "But Not Smarter. Until Now." — only makes sense paired with a preceding headline | Rewrite as standalone thought: "Fast AI Still Gets It Wrong" |
| Vague pronoun / "this" | "Learn How We Fix This" — "This" refers to nothing in isolation | Replace with specific noun: "See How We Solve Manual Audit Prep" |
| Insider jargon in headline | "Your Compliance Drift Is Growing" — "Compliance Drift" is your team's internal term, not buyer language | Use buyer's words: "Your Audit Prep Is Falling Behind" |
| Over character limit | "Can Your Team Sell Without You?" (31 chars) — exceeds 30 char Google limit | Shorten: "Can Reps Sell Without You?" (26 chars) |
| Too generic | "Better Marketing With AI" — could be any company | Add specificity: "AI That Knows Your Buyers" |
CTA headlines are exempt from the standalone-meaning test — Headlines like "Book a Demo Today" or "Get a Free Assessment" are intentionally generic CTAs. They don't need to convey a proposition on their own because Google pairs them with other headlines. But verify there is exactly ONE CTA headline per variant (not zero, not all three).
Rewrite any failing headlines — Fix the headline, recount characters, and verify the replacement also stands alone. Update both the text output and the visual deck (if generated).
Present the review results — Show the user a summary of what was changed:
### Headline Independence Review
Reviewed X headlines across Y variants.
| Original | Issue | Replacement |
|----------|-------|-------------|
| "But Not Smarter. Until Now." | Fragment — meaningless alone | "Fast AI Still Gets It Wrong" |
| ... | ... | ... |
Z headlines passed. N headlines rewritten.
This review step catches errors that are invisible during generation (when you're thinking about headlines as a set) but obvious once you read each one in isolation — which is how Google will actually serve them.
After Steps 3 and 3B are complete and all final headlines are settled, update the source card file written in Step 2G with the actual headlines that were generated for each variant. This is what closes the loop — without this update, the resonance loop has no way to match ad-platform performance back to source cards.
~/.octave/source_cards/<workspace_slug>/<campaign_slug>.json.headlines_by_variant field. The shape is { "<ad_set_name>": { "<variant_type>": [headline strings...], ... }, ... } — see the worked example in source-cards.template.json.descriptions_by_variant field with the same shape.~/.octave/source_cards/<workspace_slug>/<campaign_slug>.json with N final headlines across M variants. The resonance loop will use these to map performance back to derivation chains."Skipping this step means the resonance loop cannot use its forward-inference path for this campaign. It will still work by reverse-inference from headlines, but without the strong derivation chain.
After generating all ad sets, produce a campaign summary:
# Campaign Plan Summary
## Overview
- **Platform**: {platform}
- **Objective**: {objective}
- **Ad Sets**: {count}
- **Total Ad Variants**: {count}
- **Personas Covered**: {list}
- **Segments Covered**: {list}
## Ad Set Breakdown
| Ad Set | Persona | Segment | Primary Theme | Variants | Landing Page |
|--------|---------|---------|---------------|----------|-------------|
| 1 | VP Eng | Enterprise FinServ | Compliance Risk | 4 | /compliance |
| 2 | CTO | Mid-Market SaaS | Dev Efficiency | 3 | /engineering |
| ... | ... | ... | ... | ... | ... |
## Negative Targeting (Campaign-Level)
- **Excluded job titles**: {combined exclusions}
- **Negative keywords**: {combined negative keywords}
- **Excluded demographics**: {age groups, locations if applicable}
## Field Intelligence Coverage
- **Personas with prospect language data**: X of Y
- **Personas using library-only creative**: X of Y
- **Recommendation**: {if low coverage, suggest connecting more integrations}
## Next Steps
1. Review and refine ad creative variants
2. Set up campaign in {platform} using the targeting recommendations
3. Upload creative variants as responsive ads
4. Set budget allocation across ad sets
5. Once the campaign has been running, close the loop with /octave:ads-resonance
Ask the user via AskUserQuestion:
/octave:ads-resonance to analyze it, map winners back to source cards, and feed learnings into the library.If they choose export, ask which platform via AskUserQuestion:
Google Ads (Web UI) export:
123-456-7890). This can be either an MCC or a sub-account — whichever they'll select in the Ads UI before clicking Upload. Using an ID that doesn't match the active account in the UI causes "entity does not exist" errors.~/Desktop/{campaign-name}/), then generate the five numbered CSVs (campaign, ad groups, ads, keywords, negative keywords).Google Ads (Editor) export:
~/Desktop/{campaign-name}-editor.csv.If they choose Generate visual campaign deck, read html-deck-template.md for the full deck structure, section layout, variant color coding, and visual design spec. Follow that template to produce the HTML file.
Before presenting each variant, verify:
/octave:ads-resonance - Analyze this campaign's performance, map winners back to source cards, and feed learnings into the library (the resonance loop)/octave:campaign - Multi-channel campaign content (email, LinkedIn, social, blog, landing pages)/octave:brainstorm - Ideate campaign angles before building/octave:messaging - Build the messaging framework that feeds ad creativenpx claudepluginhub octavehq/lfgtm --plugin octaveHelps create, optimize, and scale paid ad campaigns across Google, Meta, LinkedIn, Twitter/X, and TikTok. Use for strategy, audience targeting, bidding, and optimization.
Provides guidance on paid advertising campaigns across Google Ads, Meta, LinkedIn, Twitter/X, and TikTok. Covers campaign strategy, audience targeting, bidding, and optimization.
Helps create, optimize, and scale paid advertising campaigns on Google Ads, Meta, LinkedIn, and Twitter/X with platform-specific guidance.