Get a Slack message when a competitor launches an ad
Put a competitor's ad accounts on a watchlist and get new, stopped, changed and removed ads in Slack, Discord, your inbox or a signed webhook. Setup, message formats, intervals per plan and limits.
The AdLib team · · 6 min read
A competitor launches a new campaign on a Tuesday. You find out three weeks later, when someone forwards a screenshot. By then you don't know when it started, how many versions they tried, or which ones they already pulled.
Checking the ad libraries by hand does not scale past a couple of accounts, and the libraries have no alerts. A watchlist does the checking for you and posts what changed into the channel your team already reads. This is how to set one up, what the messages look like, and what it cannot catch.
What you can do with it
- Hear about launches the day they show up. New ads land in a Slack or Discord channel with the ad's text and its library link.
- See what they pull. Stopped ads, and ads the library removed entirely, are in the same alert.
- Catch changes. When an ad's text, media, CTA or landing page changes, it is listed as changed.
- Feed your own systems. Your endpoint gets a signed JSON event to store, tag or route.
- Get a mail digest. For people who don't live in Slack.
Step 1: find the advertiser ids
A watchlist holds advertiser ids in the form <platform>:<id>. Get them from a domain:
curl "https://api.adlibapi.com/v1/companies/samsung.com" \
-H "X-API-Key: $ADLIB_API_KEY"The accounts list has every account of the company with a score and a role. Pick the ones you trust. One domain, every ad account walks through reading that list. For the examples below we use four Samsung accounts from our homepage demo: the Samsung page on Meta (meta:142116395934723), SAMSUNG ELECTRONICS CO, LTD on TikTok (tiktok:7489059244545785873), Samsung Electronics Benelux on Snapchat and Samsung Deutschland on Amazon.
Step 2: create the watchlist with a Slack webhook
In Slack, create an incoming webhook for the channel (Slack's own setup gives you a https://hooks.slack.com/services/... URL). Then:
curl -X POST "https://api.adlibapi.com/v1/watchlists" \
-H "X-API-Key: $ADLIB_API_KEY" -H "Content-Type: application/json" \
-d '{"name": "Competitors",
"advertisers": ["meta:142116395934723", "tiktok:7489059244545785873",
"snapchat:Samsung Electronics Benelux", "amazon:Samsung Deutschland"],
"webhook_url": "https://hooks.slack.com/services/T000/B000/XXXX",
"interval_hours": 24,
"email_alerts": true}'Discord works the same way with a https://discord.com/api/webhooks/... URL. To check the channel before the first real alert, send a test:
curl -X POST "https://api.adlibapi.com/v1/webhooks/test" \
-H "X-API-Key: $ADLIB_API_KEY" -H "Content-Type: application/json" \
-d '{"url": "https://hooks.slack.com/services/T000/B000/XXXX"}'The channel gets "AdLib: test message. This channel will receive watchlist alerts."
The first check of each advertiser is the baseline. It records the ads running now and sends nothing, so you are not flooded with every existing ad. From the second check on, you get one alert per advertiser whenever something changed.
How often: intervals per plan
interval_hours sets how often each advertiser is checked, from 1 to 168, default 24. The plan sets the shortest interval and how many advertisers you can watch:
| Plan | Advertisers | Shortest interval |
|---|---|---|
| Free | 1 | 24 h |
| Starter | 10 | 24 h |
| Growth | 50 | 12 h |
| Pro | 250 | 6 h |
| Business | 1,000 | 1 h |
For most competitor tracking, daily is enough. Shorter intervals matter when a launch is time-critical, for example around a product release or a sale.
What the Slack message looks like
Slack and Discord cannot verify signatures and want a message, not JSON, so they get a readable summary. The first line counts the changes for one advertiser, then up to five ads follow, each with its headline or text (cut at 120 characters) and its library link. From the demo, a new ad on Samsung's Italian Meta page:
AdLib: Samsung (meta:142116395934723). 1 new, 0 started, 0 stopped, 0 changed.
• New: La missione sta per iniziare: preparati a esplorare nuovi mondi, e vivere ogni avventura da protagonista. 🕹️ Dove? 📍 Lu… https://www.facebook.com/ads/library/?id=1740621664087735When the library removed an ad, the first line adds ", 1 removed from the library (kept in AdLib)" and the ad is listed as "• Removed:". Removed ads are listed first, then new, started, stopped and changed.
The email digest uses the same text with up to 25 ads, a subject starting with "AdLib alert:", a pointer to GET /v1/advertisers/{id}/changes for the full list, and the PATCH call that turns the mails off.
Your own endpoint: the signed event
Point webhook_url at your own server and you get the full advertiser.changes event instead:
POST https://api.yourcompany.com/adlib
X-AdLib-Event: advertiser.changes
X-AdLib-Delivery: 48213
X-AdLib-Signature: t=1793102400,v1=5f2c…{
"event": "advertiser.changes",
"watchlist_id": "0b7c6a8e-1f2d-4c3b-9a8e-5d6f7a8b9c0d",
"advertiser_id": "meta:142116395934723",
"crawled_at": "2026-10-27T08:00:00Z",
"summary": { "new": 1, "started": 0, "stopped": 0, "changed": 0, "removed": 0 },
"new": [ { "type": "discovered", "at": "...", "ad_id": "meta:1740621664087735", "ad": { ... } } ],
"started": [], "stopped": [], "changed": [], "removed": []
}The ids, delivery number and signature above are examples. Each entry carries the full ad object, so you can store it without another call.
X-AdLib-Signature is t=<unix time>,v1=<hex HMAC-SHA256 of "<t>.<raw body>"> with your webhook secret from GET /v1/webhooks/secret. Verify it on the raw body before parsing, and reject old timestamps. The webhooks reference has a Python example. Answer with a 2xx quickly and do the work afterwards. Failed deliveries are retried, GET /v1/webhooks/deliveries lists recent ones with status codes, and POST /v1/webhooks/deliveries/{id}/redeliver sends one again.
Removed ads
removed lists ads the platform's own library no longer shows: taken down for a policy violation, deleted by the advertiser, or past the library's retention. For watched advertisers we look up stopped ads one by one. When a library no longer returns an ad in two lookups at least 20 hours apart, we record the removal. The alert after that reports it, and the ad stays in AdLib with removed_from_library_at set. Why that matters is in what happens to ads the platforms delete.
What it costs
Creating a watchlist is free, and the checks and webhook deliveries are included in the plan. What the plan limits is the number of advertisers and the shortest interval. Reading more afterwards costs the usual credits: 1 per event from GET /v1/advertisers/{id}/changes, and the ad prices on credits and billing if you open an ad in full.
Honest limits
- Only what a check sees. An ad that starts and ends between two checks can be missed. Shorter intervals leave fewer gaps.
- No history before the watchlist. The baseline starts the record. Ads a platform removed before that cannot be recovered.
- Slack shows five ads. A big launch lists the first five; the full list is in the email (up to 25), the JSON event, or the changes endpoint.
- Slack and Discord messages are unsigned. Use your own endpoint when you need to verify the sender.
- Platforms fail sometimes. A library can be down or block a check, and a failed check sends no alert.
GET /v1/watchlists/{id}shows each advertiser'slast_crawl_at,last_errorandnext_crawl_at, so you can see when that happened.
Do this now
Pick the one competitor you would most hate to miss. With a free key (5,000 credits a month, no card, one watched advertiser, checked every 24 hours), find its main account and create the watchlist:
curl -X POST "https://api.adlibapi.com/v1/watchlists" \
-H "X-API-Key: $ADLIB_API_KEY" -H "Content-Type: application/json" \
-d '{"name": "Main competitor", "advertisers": ["meta:142116395934723"],
"webhook_url": "https://hooks.slack.com/services/T000/B000/XXXX", "email_alerts": true}'The baseline runs right away, and the next change lands in your channel. When an alert names an ad you want to understand, everything you can know about one ad shows the three calls that take it apart. Without webhooks, poll GET /v1/advertisers/{id}/changes?since= for a weekly digest, as described in ad history and the archive.
Questions people ask
- How do I get a Slack message when a competitor launches an ad?
- Find the competitor's advertiser ids, then create a watchlist with POST /v1/watchlists and set webhook_url to a Slack incoming webhook. After each check that finds something, a readable summary with up to five ads is posted to the channel.
- How often are competitors checked?
- Every interval_hours, 24 by default. The shortest interval depends on the plan: Free and Starter 24 hours, Growth 12, Pro 6 and Business 1.
- What is in the alert?
- New, started, stopped and changed ads since the last check, and ads the platform's library has removed. Slack and Discord get a summary line plus up to five ads with their library links. Your own endpoint gets the full advertiser.changes JSON event, signed with X-AdLib-Signature.
- Can I get alerts by email instead?
- Yes. Set "email_alerts": true on the watchlist and a digest goes to your account's email after every check that found something, with or without a webhook.
- Do watchlist checks cost credits?
- No. Creating a watchlist is free, and checks and webhook deliveries are included in the plan. The plan limits how many advertisers you can watch: 1 on Free, 10 on Starter, 50 on Growth, 250 on Pro and 1,000 on Business.
- Why did I get no alert after creating the watchlist?
- The first check of an advertiser is the baseline. It records the current ads and sends no event. Alerts start with the next check that finds a change.