Ad Angle Miner
Summary. Research advertising promises and match them to creatives the brand can make.
Video research produces a structured bank the script writer can reuse, with stable angle ids,
separate product facts and customer language, and template compatibility. Research scores rank
test candidates; they do not predict conversions.
An ad is copy plus creative. This skill finds the angles real buyers respond to and turns each
into an ad idea the user can make:
- Static: a headline and primary text, plus a template from the live library whose layout fits the message.
- Video: a hook, plus a video format from the live catalogue and the observed posts that illustrate the pattern.
- Copy only: the headline and primary text lines, with no creative. Same evidence as static.
Core principle: combine audience relevance with a supported product promise and a feasible
creative. Customer language, demonstrations, first-party performance and advertiser persistence
provide different evidence. Long-running ads and variants are observations, not proof of profit.
A product-led angle can start from verified facts without reviews; label missing evidence.
Do only the work the chosen output needs. Copy and static never search for videos or read
video formats. Copy never looks at templates. Video reuses available reviews for language and insight; collect more only when the angle needs them. A video request may name a selected template or angle: preserve both.
When to Use
- "What static ads should I make?" / "Give me image ad ideas for [brand]" (static)
- "What video ads should I make?" / "Give me video ad hooks for [brand]" (video)
- "Write ad copy / headlines for [brand]" / "What should our ads say?" (copy)
- "What's working in my competitors' ads?" (any; ask which output)
- "I need fresh ad angles" (ask which output)
Prerequisites
- GooseWorks MCP connector (recommended): brand context, competitors, the Meta Ad Library
(imported and live search), comments and reviews through the ScrapeCreators proxy (no key), the
video format catalogue and the static template library. With it connected, no API key is needed.
- Without GooseWorks: a direct ScrapeCreators key (
scrapecreators-api,
competitor-ad-intelligence) and web search. Static and video ideas then describe the layout or
format in words instead of naming a library entry, and there is no hand-off step.
Phase 0: Intake
0A: Choose the output
Read it from the request:
| The user says | Output |
|---|
| static, image ads, banners, "what image ads" | static |
| video, UGC, reels, TikTok, "what video should I make" | video |
| copy, headlines, primary text, "what should our ads say" | copy |
| "ads" or "angles" with no hint | ask once: "Static ad ideas, video ad ideas, or just the copy?" |
The user can pick more than one (for example static and video); then run the union of their
sources, once. Never widen the scope on your own.
0B: What each output runs
| Source | static | video | copy |
|---|
| Brand context (1-0) | yes | yes | yes |
| The brand's own ads (1A) | yes | yes | yes |
| Competitor ads (1B) | yes, image ads first | yes, video ads first | yes, the copy |
| Customer voice: reviews + comments (1C) | yes | reuse reviews; comments on top posts | yes |
| Organic short-form reach (1D) | no | yes | no |
| Internal data (1E) | if provided | if provided | if provided |
| Reddit and forums (1F) | only if asked | only if asked | only if asked |
| Template library (2.5) | yes | no | no |
| Video format catalogue and full recipes (2.5) | no | yes | no |
0C: The rest of the intake
Take what the request and the brand context already answer; ask only for what's missing, in one message:
- Your product: name and what it does in one sentence (with GooseWorks: the brand context).
- Competitors: 2-5 names (with GooseWorks: the tracked ones, or the suggested ones).
- Who it's for, if the brand context doesn't say.
- Search terms the user wants covered, if any. Use them first.
Never invent a customer, a result or a claim: an angle may only promise what the brand's own facts support.
Phase 1: Source Collection
Run only the sections Phase 0B selected. ScrapeCreators calls go through scrapecreators-api
(GooseWorks: data_call_provider with provider scrapecreators, GET). Each is billed per call:
before the first one, say roughly how many you'll run and ask one yes/no. Free sources never need
asking. Large results are saved to a file by some hosts: request a full page and parse the saved
file rather than paging in small pieces.
1-0: Brand Context
With the GooseWorks MCP: brand_read (one brand in the org means use it and say which), with
sections summary, products, competitors, accounts and learnings (the reply is large: parse the
saved file); add kit when you need claims,
voice or photos. Note what it sells, who buys it, its claims and can't-say rules, its offers, which
products have clean photos (check the files: an SVG logo or a small thumbnail is not a clean
product photo), and whether it has screen recordings or footage. competitor_read lists tracked
competitors; with none, its suggestions view names likely ones. Say them in one line and carry on.
1A: The Brand's Own Ads
What the brand already runs decides what is new.
- Find the right page. Search the Meta Ad Library for the brand by name
(/v1/facebook/adLibrary/search/companies, query = brand name) and compare the page with the
one stored on the brand. If the stored page returns no ads but the search finds an active page
with the brand's name, use the found page and tell the user the stored page looks wrong.
- Read its ads (/v1/facebook/adLibrary/company/ads with that page id; status ACTIVE, then
INACTIVE for the stopped ones when the endpoint returns them). Group ads with the same primary
text as variants of one message.
- Sort them:
- Still running for 30+ days, or with 3+ variants: advertiser persistence, worth investigating.
Only label a winner when first-party performance supports it for a stated objective and
measurement window. Duration alone does not establish fatigue or profitability.
- Stopped: inactive, reason unknown unless first-party records explain it. It may have been
seasonal, budget-limited or replaced; do not infer failure from status alone.
- Never run: the white space. An angle buyers talk about that the brand has never run is
the most valuable find.
1B: Competitor Ads
- Imported ads (free):
ads_template_read in competitor mode, one tracked competitor at a time
(filter by its source id). Rows are heavy; keep the source ad id, primary text, CTA, start and
end dates and ratio. Today most imported ads are images; their copy is still evidence.
- Keep it on-category. A tracked competitor can sell something else in another market. Drop
ads that aren't about the same kind of product, and say which competitor was off-category.
- Find who actually advertises in the category (paid): Meta Ad Library keyword search
(/v1/facebook/adLibrary/search/ads) with 2-3 category terms ("chai concentrate", "masala chai"),
country set to the brand's market and status ACTIVE. Keyword search also returns unrelated
advertisers: drop anything off-category. This finds the real competitors the roster misses.
- For every ad keep: the link, advertiser, the hook (first line), the offer, the CTA, days
running and the number of variants. Live searches return each ad's url: use it. Imported
rows return only the ad id: there, and only there, build the link as facebook.com/ads/library
with that id. For a live ad the end date is the day it was fetched (imported rows: the day they
were imported), so write "at least N days, still running".
1C: Customer Voice
What buyers say in their own words. This is what keeps angles from being guesses.
-
The brand's own reviews: its product pages (review widgets often load by script, so a
plain web fetch shows only a few; fetch the raw page HTML and read the review blocks and any
"customers say" summary in it), its TikTok Shop reviews if it sells there (/v1/tiktok/shop/product/reviews), its Amazon
listing (web search and fetch). Keep 4-5 star reviews for outcomes and proof, and 1-3 star
reviews for objections to answer.
-
Competitors' bad reviews: 1-2 star reviews of the top 2 competitors' products, from the same
kinds of sources. These suggest possible gaps to investigate. Claim a gap only when this product
independently supports the promised difference.
-
Comments on what's working: most ads link to a landing page, not a post, so their comments
usually can't be read. Read comments instead on:
- the brand's own top posts (its accounts from the brand context; Instagram
/v2/instagram/user/posts, TikTok /v3/tiktok/profile/videos, then the comments of the 2 best);
- 1-2 complaint or comparison threads found by keyword search in the category (TikTok
/v1/tiktok/search/keyword, then /v1/tiktok/video/comments);
- in video mode, the top organic posts from 1D.
Comments paths: TikTok /v1/tiktok/video/comments, Instagram /v2/instagram/post/comments, YouTube
/v1/youtube/video/comments, Facebook /v1/facebook/post/comments. Look for questions, objections
and "I switched because…".
Keep every quote verbatim with its link. Never paraphrase a quote into something the buyer didn't say.
1D: Organic Short-Form Reach (video only)
What is getting earned reach right now.
-
Free first: the competitor dossiers (competitor_read with a slug) and social_inspiration_library
/ social_inspiration_search. These are often empty; then go to the paid searches.
-
Paid searches (one yes/no for the batch). Terms: the user's own first, then the category, the
main problem it solves, each competitor's name.
| Platform | Path | Query | Notes |
|---|
| TikTok | /v1/tiktok/search/keyword | query, date_posted last-3-months, sort_by most-liked | About 2MB per call: parse it; keep url (tiktok.com/@author/video/id), author, followers, statistics.play_count, create_time, desc, commerce_info |
| Instagram Reels | /v2/instagram/reels/search | query, date_posted last-month | Google-indexed, best-effort, about 9 results a page; no follower count |
| YouTube Shorts | /v1/youtube/search | query, type shorts, nothing else | Adding uploadDate or sortBy with type shorts returns nothing. Rows have only url, title and views: for the 3-5 you'd cite, call /v1/youtube/video for channel, publishDate and isPaidPromotion. YouTube evidence is evergreen: cite its date |
| X | none | none | No X keyword search: use competitor_search_mentions with platform x, or /v1/twitter/user-tweets for a handle |
The full list is the official OpenAPI (docs.scrapecreators.com/openapi.json). If a call errors,
read it there; never guess a path.
-
Keep vertical videos only, far above their account's usual views, from the last ~90 days.
-
Watch the 3-5 strongest (the watch skill, or social_inspiration_watch for saved posts). When
neither is available, read the transcript (YouTube /v1/youtube/video/transcript; otherwise the
caption and first spoken line) rather than guessing from the title.
1E: Internal Data (Optional)
Support tickets, NPS comments, sales call notes the user provides. Treat them as customer voice.
1F: Reddit and Forums (only if asked)
Only when the user asks, or for a product whose buyers mainly talk there (developer tools, some
software). Use reddit-post-finder or /v1/reddit/search. A thread is one person's view: it counts
as customer voice only when the same point also shows up in reviews or comments.
1G: Label Every Reference Paid or Organic
- paid: any of
- it came from an ad library;
- TikTok: commerce_info.bc_label_test_text says "Paid partnership", "Promotional content" or
"Creator earns commission". The is_ads flag is almost always false; ad_source or adv_promotable
alone means unknown;
- Instagram: is_paid_partnership or sponsor tags, or the caption says #ad, sponsored, gifted or
tags the brand as a partner;
- YouTube: isPaidPromotion from /v1/youtube/video (/v1/youtube/video/sponsors only for the
sponsor's name; if they disagree, unknown);
- boosted: platform metadata or a matching ad-library entry identifies promotion.
Cross-posting and high plays relative to followers alone do not establish paid distribution.
- organic: the source identifies unpaid distribution. Without positive evidence, use
unknown with "no paid disclosure observed"; absence of a label does not prove organic reach.
- unknown: you can't tell. Say so; never guess organic. Unknown references may
illustrate a storytelling structure, but their views do not count as verified organic evidence.
Reviews and comments are customer voice, a third kind of evidence. Label them as such.
Phase 2: Angle Extraction
Read buyer case and supported product role.
Before naming an angle, extract a specific current consumer task or decision and
explain why this exact product can help. Record the buyer's inputs, current approach,
constraint and desired output, plus the supported product action and useful role.
Keep source limits and authored scenarios explicit. Carry these as buyer_case and
product_role in the video handoff; a generic pain label or ingredient list is not
enough. Preserve human feedback separately from model ranking.
| Category | What to look for |
|---|
| Pain | Specific frustrations with the status quo or competitors |
| Outcome | Results buyers describe in their own words |
| Identity | How buyers describe themselves or want to be seen |
| Switching | Why people left a competitor |
| Proof | Outcomes, ratings or credentials buyers and the brand can back up |
| Contrast | Old way vs new way, them vs us |
| Objection | The doubt that stops a purchase, answered |
For each angle record: the one-sentence angle, relevant verbatim quotes with links when
available, and the sourced product facts or observations that support it. Do not invent
quotes to meet a quota or require a complaint for a product-led discovery angle. State
which kinds of evidence back it (customer voice, product facts, organic reach, sustained ads), whether the brand already runs it
(1A: measured winner, persistent, inactive, or never observed) and the competitor gap it exploits, if any.
Phase 2.5: Turn Each Angle Into an Ad
Every output gets the words: a headline (8 words or fewer for static, 12 or fewer as a video
hook) and 1-2 sentences of primary text, in the brand's voice.
Claims: only what the brand's own data says (certifications, guarantees, ingredients, offers),
checked for the exact product the ad shows: two products of one brand can differ (one has no
added sugar, the other does).
Flag anything the brand should approve, such as review counts, health benefits, price comparisons
or a named person, rather than writing it as fact. When the brand's sources disagree (two
different numbers for the same claim), flag both.
Static: find the template live, never from a list
The template library grows every week, so never rely on a remembered list of templates or layouts.
- Describe the layout the message needs, in a sentence. Work it out from the angle, not from
a menu: a contrast angle wants two things side by side with ticks and crosses; a proof angle
wants a review card or a rating next to the product; an objection angle might want the doubt as
a quote and the answer as the headline; an offer wants the price story.
- Search for it:
ads_template_read in query mode, with the brand id and that sentence as the
query. It searches the whole library by meaning and returns each match with its description,
search tags and a score, so templates added tomorrow are found the same way. Rank by score.
Run one search per angle; when the best similarity is under about 0.5, try a second phrasing.
- Judge the fit from the template's own description: does the layout carry this message, does
it have room for the headline (some layouts have no text slot), and can the brand supply what it
shows (a product photo, a lifestyle shot, a person)? Pick the best one and say why in one line.
- A competitor's ad can be the template only when nothing in the library fits (from 1B; its
row id is a template id). It is a third party's ad: take the layout only, never its words,
branding or images, and say it's a competitor's ad.
- Keep the result's source type with the id: a community result goes to
goose-ads as a
community ad id, a template as a template id.
Video: pick from the live format catalogue
Read the live video format catalogue for the brand. Only listed formats can be made. When the
brief already chooses a template, use it. For plausible candidates, fetch the full template
recipe before calling the idea make-ready: a card description is not a production contract.
Match the angle to the recipe's story mechanism, speakers, timing, text slots, proof device,
permitted visuals and required assets. Keep the quoted catalogue description for display, and
record the actual template id and compatibility reason. A physical demo needs a real product;
a screen demo needs usable recordings; a silent reveal needs a visual payoff. Do not turn all
angles into testimonials. An unmet essential input makes the pair provisional or incompatible.
For dialogue directions, return an observed same-format reference alongside the angle.
Reuse collected sources before retrieving more. A caption, format description or imagined
beat map cannot establish human dialogue.
Street ads require a complete commercial interaction, with full visual timeline and
spoken exchange inspected. Match physical/service/digital offering and the actual
interaction (sampling, mic-only conversation, or challenge). Preserve source, observation
method/limits, timestamped words and actions, visible setup, participation reason, hook,
brand connection, payoff, and unseen recruitment as explicitly unknown. Label paraphrases
and retain full transcript evidence. Partial hooks and editorial radio excerpts cannot
fill this gap; seed summaries are source leads until inspected in full. The selected
[[references::render-street-interview]] guide and writer's files reference define the record.
For podcasts, an appropriate editorial interview can provisionally teach turn structure,
with commercial and delivery limitations recorded. Neither real performers nor an
observed transcript establishes human authorship or conversion performance.
Carry audience, objective, offer, CTA and exact product through this match. When the angle or
format is fixed, do not replace it to improve a ranking. Report a conflict and suggest a
compatible execution. Never infer that a renderer can make a scene from a generic model name.
Copy only
No template or format. Give 2-3 headline and primary-text variants per angle instead.
Adapt the pattern, never copy: take the shape, structure and angle, never another brand's words,
claims, faces, footage or offer. Spread the list: no more than 3 ideas on one template or format,
and no more than 3 on one angle (variants of one angle count toward that 3).
Phase 3: Scoring & Ranking
| Factor | Weight | Description |
|---|
| Evidence | 40% | How many kinds back it (customer voice, organic reach, sustained ads) and how strong each is |
| Gap | 20% | Never run by the brand, and weak or absent in competitors' ads |
| Fit | 20% | The brand can claim it with its own facts, and buyers like its own customers say it |
| Make-ready | 20% | The template or format fits and the brand has what it needs (copy: 100%) |
Reject unsupported product promises and impossible angle–template pairs before scoring.
Score the remaining pairs out of 100 and rank as research priorities. These weights and caps
are heuristics, not calibrated probabilities of performance. Keep a measured first-party
winner separate from the research score. Do not pad the list when evidence is thin.
- Sustained ads means still running for 30+ days, or 3+ variants of one message. A single
short-lived ad is weak evidence.
- Static and copy can have two kinds (customer voice and sustained ads; there is no organic
search). The brand's own persistent ads count as sustained observations, but lower the Gap score.
- Caps: an idea backed by only one kind of evidence caps at 70. One backed only by short-lived
ads or a single thread caps at 50. In video, a paid post's views never count as evidence.
Phase 4: Output
Print one table in the chat, best first, with up to 10-15 distinct, supported ideas. Every idea needs at least one link a
tool actually returned; no link, no idea.
Static:
| # | Headline | Primary text | Angle | Template (why it fits) | Evidence | Needs | Score |
|---|
Video:
| # | Hook | Angle | Format (quoted card) | Evidence | Needs | Score |
|---|
Copy:
| # | Angle | Headline variants | Primary text | Evidence | Score |
|---|
In Evidence, label each link: customer voice, organic (with views vs usual), or paid (with days
running and variants).
Under the table:
- one line on which sources ran and which were skipped (and why);
- the brand's own ads in one line: measured winners, persistent or inactive ads, and white space;
- the claims the brand must approve;
- if the stored ad page looked wrong (1A), say so.
For video, read the video-handoff reference and save video-angle-bank.v1 with stable angle ids,
brand and product scope, audience/objective/offer/CTA, sourced facts, verbatim quotes, observed
references and compatible template ids. Save it with the workspace file tools in the brand and product's
video-scripts area as angle-bank.json, beside customer-words.json. Also keep a copy in this run.
If workspace writes fail, retain the run copy and pass it directly; say cross-session reuse is
unavailable. Do not pretend a bank was persisted.
A human-readable angle-bank Markdown and ideas JSON remain useful for static and copy output.
For video they may accompany the shared bank, but do not replace it. The script writer consumes
the bank rather than trying to reconstruct research from a chat table.
Then ask: "Which ones should I make? Pick up to 5, or say 'the top 3'." (Copy: skip this.)
Phase 5: Make These (GooseWorks only)
For the picked ideas, with no manual step in between:
- Static: hand each idea's template id (with its source type), headline and primary text to
the
goose-ads skill as the source and the brief.
- Video: one project per idea with
video_project_upsert (brand id, a short name from the
hook, format set to the template id, and no brief, since a brief makes a multi-concept batch).
Then make them one after another with goose-video-local; each idea is that project's brief.
Pass the complete selected idea and shared bank into goose-video-local, including the chosen
angle id, product id, template id, evidence and proof requirements. Its script step must fetch
write-video-ad-script and prepare a validated angle context; never pass only the hook. Keep raw
buyer records outside remixable review data. The local-template path needs a terminal agent;
hosted/server formats have their own runtime and require the same strategy contract there.
Up to 5 per request; offer the rest after. Each paid step of making an ad is approved before it runs.
Tools Required
- GooseWorks MCP (recommended):
brand_read, competitor_read, competitor_search_mentions,
ads_template_read, social_inspiration_library, social_inspiration_search,
data_call_provider, video_catalog_list, video_project_upsert
scrapecreators-api: ad libraries, comments, reviews, social search
competitor-ad-intelligence: deeper teardown of one competitor's ads, when asked
comment-mining: structured mining of a long comment thread
reddit-post-finder: only when Reddit is asked for (1F)
- Web search and fetch: product-page and Amazon reviews
Trigger Phrases
- "What static ads should I make for [brand]?"
- "What video ads should I make for [brand]?"
- "Write ad copy for [brand]"
- "What angles should we run?"
- "What's working in my competitors' ads?"
Related
- [[references::write-video-ad-script]] — consumes the video handoff and fits it to the recipe.