Break down competitors' longest-running ads
Scrapes competitors' Meta Ad Library ads with an Apify Actor, labels each ad's hook and offer with Jev, and saves the patterns to Notion.
Outcome
A table of every competitor ad found, with its hook, offer, awareness stage, days running and Jev's confidence.
The hooks, offers and stages that are common in the ads that have run longest, compared with newer ads.
A Notion page with those patterns and an example ad for each.
How it works
- 1
Pick a scraper
Apify
Search Apify Store for a Facebook Ad Library scraper. Show the user the top results with their authors, descriptions and Store pages, and keep the Actor the user picks once they have checked its price and terms.
- 2
Run it
Apify
After the user approves, read the Actor's input fields, then run it on
competitorsfor active ads incountry, capped atmax_spend_usdwithmaxTotalChargeUsdor by the Actor's own item limit; if your way in can't set a cap, show the user the Actor's price and the expected number of ads first. Keep the run's dataset ID. - 3
Read the ads
Apify
Keep each ad's brand, text, headline, call to action, landing page URL, media type and start date, and work out how many days each has run.
- 4
Label each ad
TypeSafe AISend each ad's text, headline, call to action and media type as the state, with a choice
hookof pain_point (opens on a problem), outcome_promise (opens on a result), social_proof (opens on customers or numbers), curiosity (opens on a question or a surprise), offer (opens on a deal), comparison (against another way or product), founder_story (a founder speaking) and how_to (teaches something); a choiceofferof free_trial, demo, discount, lead_magnet, webinar and none; and a choiceawarenessof problem_unaware, problem_aware, solution_aware, product_aware and most_aware. Keep every answer with its confidence. - 5
Find the patterns
Your agentLeave the ads whose hook, offer or awareness confidence is below
min_confidenceout of the counts, and list them. Compare the ads runningmin_daysor longer with the newer ones: which hooks, offers and awareness stages each brand keeps running, and which it keeps testing. Pick one example ad per pattern. - 6
Save the report
NotionAfter the user approves, create a page under
report_parent, found with a read-only Notion search, with the patterns, the example ads and the full table.
You'll be asked for
The brands to study, as their Meta Ad Library page URLs
e.g. the Ad Library pages of Acme and Globex
Where the ads run, as a two-letter code
e.g. US
How long an ad must have run to count as a long runner
e.g. 60
The most the scraper run may cost
e.g. 5
How sure Jev must be before its answer is used without you
e.g. 0.8
The Notion page the report goes under, by name
e.g. Competitive research
The file your agent runs
competitor-ad-teardown.md
Break down competitors' longest-running ads
Scrapes competitors' Meta Ad Library ads with an Apify Actor, labels each ad's hook and offer with Jev, and saves the patterns to Notion.
Set up the tools below, then run the steps in order for the user, carrying each step's results into the next. The run is done when the user has the outcome below.
Outcome
- A table of every competitor ad found, with its hook, offer, awareness stage, days running and Jev's confidence.
- The hooks, offers and stages that are common in the ads that have run longest, compared with newer ads.
- A Notion page with those patterns and an example ad for each.
Inputs
Ask the user for these before you start.
competitors: the brands to study, as their Meta Ad Library page URLs, e.g. the Ad Library pages of Acme and Globexcountry: where the ads run, as a two-letter code, e.g. USmin_days: how long an ad must have run to count as a long runner, e.g. 60max_spend_usd: the most the scraper run may cost, e.g. 5min_confidence: how sure Jev must be before its answer is used without you, e.g. 0.8report_parent: the Notion page the report goes under, by name, e.g. Competitive research
Set up
Apify (tool:apify/search-actors, tool:apify/run-actor, tool:apify/get-dataset-items)
Use the first option your agent supports.
Notes:
- Run an Actor: The MCP tool waits up to 45 seconds for the run and the API up to 60 with
waitForFinish: read the results with the dataset items call once the run has succeeded. Runs are billed; cap one withmaxTotalChargeUsdon the API. - Get an Actor run's results: Needs the dataset ID from a finished Actor run (
defaultDatasetIdon the run object).
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "apify": { "url": "https://mcp.apify.com" } } }
- Find a scraper in Apify Store: call the MCP tool
search-actors - Run an Actor: call the MCP tool
call-actor - Get an Actor run's results: call the MCP tool
get-dataset-items
CLI (official)
Install the command and sign in with it, then confirm it runs.
npm install -g apify-cli
apify --version
- Find a scraper in Apify Store: run
apify actors search - Run an Actor: run
apify actors call - Get an Actor run's results: run
apify datasets get-items
Note: Sign in with apify login.
Answer typed questions (TypeSafe AI, tool:typesafe/answer-typed-questions)
Use the API.
- Base URL: https://api.typesafe.ai
- Endpoint:
POST /v1/systemone - Auth: send the header
Authorization: Bearer $TYPESAFE_API_KEY - Get a key: https://console.typesafe.ai
Note: Put every question about one record in one request. GET /v1/models lists the models and is the cheapest check of a key; a request over the rate limit gets a 429 with a Retry-After header.
Note: Send state, model (jev-latest) and named questions, each with type, instructions and criteria: a choice maps labels to descriptions, a score lists its levels in order, a noul's is optional. Read a score by its most likely level; send unsure answers to a person.
Create a page (Notion, tool:notion/create-page)
Use the first option your agent supports.
Note: To add a row to a database, set the parent to its data source and match that data source's property schema.
MCP (official, remote)
Add this server to your agent's MCP settings, then sign in when asked.
{ "mcpServers": { "notion": { "url": "https://mcp.notion.com/mcp" } } }
Call the MCP tool notion-create-pages.
CLI (official)
Install the command, then confirm it runs.
npm install --global ntn
ntn --version
Run ntn api v1/pages.
Set $NOTION_API_TOKEN in your environment first (get a key: https://www.notion.so/developers/tokens).
Before step 1, confirm access to each service with its cheapest read-only call, like a list or a search. Never send or change anything to test access.
Steps
- Pick a scraper with Find a scraper in Apify Store (Apify). Search Apify Store for a Facebook Ad Library scraper. Show the user the top results with their authors, descriptions and Store pages, and keep the Actor the user picks once they have checked its price and terms.
- Run it with Run an Actor (Apify). After the user approves, read the Actor's input fields, then run it on
competitorsfor active ads incountry, capped atmax_spend_usdwithmaxTotalChargeUsdor by the Actor's own item limit; if your way in can't set a cap, show the user the Actor's price and the expected number of ads first. Keep the run's dataset ID. - Read the ads with Get an Actor run's results (Apify). Keep each ad's brand, text, headline, call to action, landing page URL, media type and start date, and work out how many days each has run.
- Label each ad with Answer typed questions (TypeSafe AI). Send each ad's text, headline, call to action and media type as the state, with a choice
hookof pain_point (opens on a problem), outcome_promise (opens on a result), social_proof (opens on customers or numbers), curiosity (opens on a question or a surprise), offer (opens on a deal), comparison (against another way or product), founder_story (a founder speaking) and how_to (teaches something); a choiceofferof free_trial, demo, discount, lead_magnet, webinar and none; and a choiceawarenessof problem_unaware, problem_aware, solution_aware, product_aware and most_aware. Keep every answer with its confidence. - Find the patterns yourself. Leave the ads whose hook, offer or awareness confidence is below
min_confidenceout of the counts, and list them. Compare the ads runningmin_daysor longer with the newer ones: which hooks, offers and awareness stages each brand keeps running, and which it keeps testing. Pick one example ad per pattern. - Save the report with Create a page (Notion). After the user approves, create a page under
report_parent, found with a read-only Notion search, with the patterns, the example ads and the full table.
Notes
An ad that runs for months is one its owner keeps paying for, which is why the long runners are the ones to study. Days running are worked out from the start dates, not by Jev, which reads dates as text, and Jev reads only the ad's words, so a hook carried by the image or video is missed.
Apify Store Actors are built by third parties, and Meta's terms restrict collecting data by automated means: read Meta's terms and the Actor's before you run it, and use Meta's Ad Library API where it covers the ads you need. Use the ads for research, not to copy them.
Rules
- Use only the services set up above. The read-only calls they need, like listing ids or polling for results, are fine.
- Ask the user before anything that sends messages, costs money, or changes data, and say how many records it touches. One approval covers a batch the user has seen.
- Never print API keys.
