Ad research
A teardown of what a brand (or a whole market) advertises, from the public ad libraries: what they say, which ads they keep paying for, where they send people, and what to test in response. For a 4-call snapshot first, use the lurk skill.
Calling LurkAPI
With MCP (the LurkAPI plugin or connector), call the tools by name, like tiktok_profile; your client may prefix them (mcp__plugin_lurkapi_lurkapi__tiktok_profile). With only find_endpoints and call_endpoint, run a tool as call_endpoint with endpoint set to its name and params to its arguments. Results come trimmed: no nulls, one URL per image or video. A long result comes in parts: its _note gives the offset for the next part, which is free.
Without MCP (Codex, Cursor, scripts), every tool is GET https://api.lurkapi.com plus its path, with the same params as a query string (URL-encoded) and the key from LURKAPI_API_KEY in the x-api-key header:
curl -s "https://api.lurkapi.com/v1/tiktok/profile?handle=nike" -H "x-api-key: $LURKAPI_API_KEY"
If LURKAPI_API_KEY isn't set but LURKAPI_KEY is (the name older docs used), use that. Raw answers are big: pipe them through jq to keep the fields you need. No key yet? Ask the user to create one at https://lurkapi.com/dashboard (100 free credits on sign-up, then a balance below 25 tops back up to 25 every day) and to set LURKAPI_API_KEY in their shell. Never ask for the key in the chat, and never print it.
Credits. Each call costs what the table at the end says, not_found included; failures on our side (5xx) are free. Every answer carries credits_remaining. Before a run of more than 20 calls, check the balance with account_credit_balance (free) and tell the user what the run will cost. If a call answers missing_api_key, insufficient_credits or signup_required, stop and pass on what it says.
Pick the libraries
| Library | Covers | Use it for |
|---|---|---|
| Meta | Facebook, Instagram, Messenger, Threads; every country | Almost every consumer brand. Start here. |
| Search, YouTube, Maps, Play, Shopping; every country | Search intent, YouTube video ads, ecommerce. | |
| About the last year | B2B and hiring brands. | |
| TikTok | Ads shown in the EU, the UK, Switzerland and Turkey only | Targeting and reach, which no other library shows. Empty doesn't mean they skip TikTok elsewhere. |
Default to Meta and Google; add LinkedIn for B2B and TikTok when Europe matters or the user asks.
Find the advertiser
- Meta:
facebook_search_companies(query=<brand>), then thepage_idof the right page insearchResults: the exact name, BLUE_VERIFIED inverification, the mostlikes. Big brands run regional pages; ask which one if it matters. - Google: with the website, skip the lookup and pass
domainbelow. Without it, or to catch other sites,google_search_advertisers(query=<brand>)givesadvertisers[].advertiser_idwithnumber_of_ads_estimate, and the sites inwebsites[].domain. - LinkedIn: search by
companydirectly, below. - TikTok:
tiktok_ad_library_search(query=<brand>)first, to read theadvertiser_nameexactly as the library spells it (often a legal entity, like a B.V. or a GmbH); then search withadvertiser_name.
Pull the live ads
facebook_company_ads(pageId=<page_id>, status=active, trim=true): up to 30 ads, most seen first, andsearchResultsCount, the estimated number live. More pages (cursor, 10 ads each) only if the first page doesn't show the patterns; two usually do.media_type=videofocuses on video.google_company_ads(domain=<website>)(oradvertiser_id): up to 100 ads a page withformat,firstShown,lastShownanddaysShown. Adomainlists everyone advertising the site, resellers, affiliates and agencies included: count an ad as the brand's only when itsadvertiserNamecontains the brand's name. The list has no copy: for the text and landing page of the few that matter,google_ad(url=<adUrl>), one call each.linkedin_search_ads(company=<brand>): about 24 previews a page, whosetextcan be cut short. For full copy and the payer,linkedin_ad(url=<adLibraryUrl>)on the ones you quote.tiktok_ad_library_search(advertiser_name=<name>): 12 a page, from the last 30 days. Thentiktok_ad_library_ad(ad_id=<id>)on two or three: itstargeting(countries,age,gender,interests) andreach_by_countryshow who they're after.
For a market rather than a brand, search the ads by keyword instead: facebook_search_ads(query=<keyword>, status=active, country=US) (group the results by page_name to see who competes), tiktok_ad_library_search(query=<keyword>) and linkedin_search_ads(keyword=<keyword>).
Find the winners
Performance isn't public, but persistence is. An advertiser keeps paying for what works.
- Meta: days since
start_date(Unix seconds) on an ad that's still active. Over 30 days is a keeper; the longest-running live ads are the swipe file. A highcollation_count(many versions of one ad) means they're scaling or testing it. - Google:
daysShown, and alastShownof today or yesterday. - Repetition: the same hook or offer across many ads and formats is a deliberate bet.
- What's new:
facebook_company_ads(pageId=<page_id>, status=active, sort_by=relevancy_monthly_grouped, trim=true)lists the newest launches first, which is what they're testing now.
Read them
For each library, then across them:
- Angles: the pain, desire, persona or comparison each ad leads with. Cluster them and count.
- Hooks: the opening line of
snapshot.body.text(carousels:snapshot.cards[].body), verbatim. - Offers and calls to action: discounts, trials, bundles, guarantees;
snapshot.cta_text. - Landing pages:
snapshot.link_url. Several products or campaigns usually show up as several destinations. - Formats and placements:
snapshot.display_format,publisher_platform, Google'sformat. - Gaps: angles a competitor never uses, and markets or platforms they skip.
Skip catalog ads whose text holds template tags like {{product.name}}; they carry no message.
Budget
One brand on Meta and Google is about 4 calls, plus one per ad you open in full. A brand on all four libraries with a few details opened is about 10 to 15. Several competitors multiply that: say the estimate first, and look at all of them shallowly before going deep on the most active one.
Report
# Ad teardown: <brand>, <date>
| Library | Live ads | Oldest live ad | Main formats |
| --- | --- | --- | --- |
## Angles
| Angle | How often | Example (quoted) | Link |
## Hooks worth stealing
- "<verbatim>" (<library>, running <n> days)
## Offers and calls to action
## Landing pages
## What they're testing
Ads with many versions, recent launches, new angles.
## Tests for us
3 to 5, each tied to evidence above.
Link every ad you cite: Meta https://www.facebook.com/ads/library/?id=<ad_archive_id>, Google its adUrl, LinkedIn its adLibraryUrl, TikTok its url.
Pitfalls
- Don't call an ad a winner because it's live; run time is the signal, and even that is a proxy.
- Spend, impressions and targeting are public only for political and issue ads (and in the EU, some reach data). Don't invent them.
- Google ads more than about a year old don't come back.
- TikTok's library is Europe only and LinkedIn's about a year back: an empty answer limits what you can say, nothing more.
Calls and credits
| Tool | REST path | Credits |
|---|---|---|
facebook_search_companies |
/v1/facebook/adLibrary/search/companies |
1 credit |
google_search_advertisers |
/v1/google/adLibrary/advertisers/search |
1 credit |
tiktok_ad_library_search |
/v1/tiktok/ad-library/search |
1 credit |
facebook_company_ads |
/v1/facebook/adLibrary/company/ads |
1 credit |
google_company_ads |
/v1/google/company/ads |
1 credit |
google_ad |
/v1/google/ad |
1 credit |
linkedin_search_ads |
/v1/linkedin/ads/search |
1 credit |
linkedin_ad |
/v1/linkedin/ad |
1 credit |
tiktok_ad_library_ad |
/v1/tiktok/ad-library/ad |
1 credit |
facebook_search_ads |
/v1/facebook/adLibrary/search/ads |
1 credit |
Each tool's link opens its docs as markdown: every param and its values, and a real response.
