Media Buyer Morning Routine: Automate the Competitor Check
Media buyer morning routine, automated: an overnight competitor scan, diff logic, and a 7:30 Slack digest replace 20 minutes of tabs. Working code inside.

Sections
Every media buyer morning routine starts the same way: fifteen tabs before the first coffee. Meta's Ad Library open for three competitors, TikTok's creative feed for two more, a LinkedIn scroll, last night's spend dashboard, and a Slack thread asking whether anyone saw the new UGC angle a rival shipped at midnight. Twenty minutes of clicking, every working day, and none of it written down anywhere.
TL;DR: The morning competitor check is the most repeated, least systematized ritual in media buying. One scheduled script replaces the tab parade — an overnight scan through the AdLibrary API, a diff against yesterday's snapshot, and a Slack digest at 7:30. You keep the judgment: what to brief, what to test, what to ignore. This guide builds the full pipeline with working code, escalation rules, and a sample digest.
The ritual itself is sound. Checking what competitors launched, what they kept running, and where their format mix is drifting is exactly the right instinct. The problem is that the whole thing lives in muscle memory instead of a system, which means it shrinks on busy days, disappears during launches, and produces nothing the rest of the team can use. A spreadsheet of screenshots from March helps nobody in June.
This is a how-to for replacing the collection half of that ritual with a scheduled pipeline. By the end you will have an overnight competitor scan, diff logic that surfaces only changes, escalation rules that know the difference between a routine creative refresh and an emergency, and a digest waiting in Slack before you sit down.
What Media Buyers Actually Check Every Morning
The 8am sweep looks chaotic from the outside, but it has a stable anatomy. Strip away the doomscrolling and the competitor portion of a media buyer's daily workflow reduces to three questions.
Did anyone launch new creative overnight? New hooks, new offers, a fresh batch of UGC, a price test visible on the landing page. Most buyers scan the Meta Ad Library for their top rivals, glance at one more platform if time allows, and call that coverage. The scan is shallow because it has to be. Eleven ad platforms matter and a human checks two of them.
Is anything scaling? A new ad is a test. An ad still running on day 21 with climbing engagement is a decision someone made with budget. Runtime is the cleanest signal in competitive intelligence because the duds get killed in week one, so any creative a competitor keeps feeding is one their numbers support. Catching that transition early is the difference between responding to a single winner and responding to a category shift three weeks late.
Did the format mix move? When a rival goes from static-heavy to video-heavy inside two weeks, that is a strategy change, and no single ad announces it. The same goes for aspect ratios drifting toward 9:16 or a sudden carousel push. Format shifts tell you where their budget is heading next quarter, which is more useful than any one creative.
Everything else in the morning block (spend pacing, overnight ROAS, comment moderation) already has a dashboard. The competitor check is the one piece still done by hand. That is exactly why it gets squeezed first when the morning gets loud. If the shape of this role is new to you, the broader picture is in what a media buyer actually does all day.
Why the Manual Morning Check Fails Quietly
Nobody decides to stop checking competitors. Coverage just erodes, one skipped morning at a time, until the check is a Monday-only event covering two brands on one platform. Four failure modes do the damage.
It samples instead of monitors. Three brands on Meta is a sample. Your category contains every funded competitor on every platform, and the interesting moves often come from the brand you stopped watching in February. A manual morning competitor check physically cannot widen, because each added brand costs another two minutes you do not have.
It has no memory. The entire value of the check is the diff: what changed since yesterday. A human tab session cannot compute a diff because yesterday was never recorded. You end up re-reading ads you saw last week and trusting your recall to flag what is genuinely new. Recall loses that bet constantly, especially across a roster.
The free tools were not built for it. Meta's Ad Library is a transparency surface, and its official API returns political and social-issue ads programmatically for most regions, which is useful for journalists and useless for a commercial morning sweep. Google's Ads Transparency Center covers Google surfaces only. Neither sends alerts, and neither knows what you saw yesterday. The full taxonomy of what these tools do and don't expose is covered in what an ad library API is.
It does not compound. Screenshots die in Slack threads. The interesting hook you spotted on a Tuesday never reaches the swipe file, the creative team hears about it secondhand, and three months of morning checks leave behind no dataset anyone can query.
Run the arithmetic and the quiet cost gets loud: 20 minutes a day, five days a week, 48 working weeks is 80 hours a year per buyer. Spent on collection. The judgment those hours were supposed to feed gets whatever attention is left.
The Replacement: Overnight Scan, Morning Digest
The fix is not a better dashboard you still have to open. It is a pipeline that runs while you sleep and interrupts you only when something changed. Five components, each small:
- A competitor roster. Every rival saved once, with platform IDs resolved, so the scan never depends on you remembering who matters.
- An overnight scan. A scheduled job at 04:00 pulls each roster brand's recent ads across platforms through multi-platform coverage, plus a keyword sweep for unknown entrants.
- A snapshot store. Yesterday's results on disk, because a diff needs a memory.
- Diff and escalation logic. New creative, scaling signals, and format shifts get classified by severity. Everything unchanged stays silent.
- A digest. One Slack or email message, formatted for a 90-second read, delivered before your first coffee.
This is the same end-to-end pattern as automating competitor ad monitoring, narrowed to the one deliverable a media buyer morning routine actually needs: the brief. It is also the natural first build inside the wider automated competitor ad monitoring use case, because it produces value on day two and grows into reports and databases later.
One honest positioning note before the code. Meta's Ad Library API is free, and if political ads on Meta are all you need, use it and spend nothing. This build uses the AdLibrary API instead, a paid alternative that returns commercial ads across Facebook, Instagram, TikTok, YouTube, Google, LinkedIn, Twitter, Pinterest and more from a single adl_ key, with the runtime, impression, and heat signals the diff logic feeds on. More data, more platforms, one key, no app review.
Step 1: Build the Overnight Scan
Start with the roster. Resolving a brand name to its platform IDs is a free call:
curl -G "https://adlibrary.com/api/advertisers/search" \
-H "Authorization: Bearer adl_your_api_key" \
--data-urlencode "q=Gymshark" \
--data-urlencode "country=US"
The response includes a best_match with the Meta page ID, Google advertiser ID, and LinkedIn company ID when the platforms agree it is the same brand. Save it, also free:
curl -X POST "https://adlibrary.com/api/advertisers" \
-H "Authorization: Bearer adl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Gymshark",
"domain": "gymshark.com",
"meta_page_ids": ["123456789"],
"google_advertiser_ids": ["AR01234567890123456789"],
"linkedin_company_ids": ["987654"]
}'
Do this once per competitor. A saved advertiser holds all of a brand's accounts, which matters because one brand is rarely one account. Nike alone is Nike, Nike Football, and Nike Run Club.
The nightly pull then walks the roster. One curate call per brand returns its recent ads on every platform, merged and deduped, for one credit per brand per session:
import json
import pathlib
import requests
API = "https://adlibrary.com/api"
HEADERS = {"Authorization": "Bearer adl_your_api_key"}
def pull_roster():
advertisers = requests.get(
f"{API}/advertisers", headers=HEADERS
).json()["advertisers"]
snapshot = {}
for adv in advertisers:
r = requests.post(
f"{API}/advertisers/{adv['id']}/curate",
headers=HEADERS, json={},
)
r.raise_for_status()
data = r.json()
ads = [
ad
for platform in ("meta", "google", "linkedin")
for ad in data.get(platform, {}).get("ads", [])
]
snapshot[adv["name"]] = ads
return snapshot
snap = pull_roster()
out = pathlib.Path("snapshots") / "latest.json"
out.write_text(json.dumps(snap))
The roster covers rivals you know about. A keyword sweep catches the ones you don't, surfacing whoever spent on your category's terms overnight:
curl "https://adlibrary.com/api/search" \
-H "Authorization: Bearer adl_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"keyword": "protein powder",
"appType": "3",
"daysBack": 1,
"sortField": "-impression"
}'
Each search costs one credit, and a failed search refunds it automatically. Sort by -impression so the entrants who matter rank first, and respect the rate limits (10 requests per minute, with a Retry-After header on 429s, so pace the roster loop).
Scheduling is the boring part, which is the point. A GitHub Actions schedule trigger runs the script without a server:
on:
schedule:
- cron: "0 4 * * *" # 04:00 UTC, hours before any standup
The serverless setup, secrets handling, and artifact storage for exactly this job are walked through in scheduled competitor scans on GitHub Actions, and if you want a deeper library of scan patterns, the Python ad library API cookbook has ten of them ready to lift.

Step 2: Diff Logic That Surfaces Only Changes
The digest dies the day it lists 200 ads. Your inbox already has enough unread reports, so the rule is absolute: the morning message contains changes, never inventory.
The stable identifier across calls is ad_key, so dedupe and diff on it. Keep yesterday's snapshot, load both, and classify three event types that map one-to-one onto what the manual media buyer morning routine was hunting for:
THRESHOLDS = (14, 30, 60) # runtime days worth announcing
def diff(today, yesterday):
prev = {
ad["ad_key"]: ad
for ads in yesterday.values()
for ad in ads
}
events = []
for brand, ads in today.items():
for ad in ads:
old = prev.get(ad["ad_key"])
if old is None:
events.append(
{"type": "new_creative", "brand": brand, "ad": ad}
)
continue
before = old.get("days_count", 0)
now = ad.get("days_count", 0)
crossed = [t for t in THRESHOLDS if before < t <= now]
if crossed:
events.append(
{"type": "scaling", "brand": brand,
"ad": ad, "milestone": crossed[-1]}
)
return events
New creative is anything with an unseen ad_key. Scaling is a known ad crossing a runtime milestone, with days_count doing the work because survival is the signal. You can sharpen the scaling tier with the heat score (a 0 to 1000 momentum value on every result) and the impressions field: a day-30 survivor with heat above 700 is a different animal from a day-30 zombie nobody is boosting.
Format shifts need a longer window than one day. Compute each brand's video share (ads_type == 2) over the trailing 7 days, compare it to the prior 7, and emit a format_shift event when the mix moves more than 15 points. Weekly granularity keeps this from flapping.
Two snapshots in flat JSON files are enough to start. When the history becomes valuable, and it will the first time someone asks "when did they pivot to UGC?", graduate the store into a real schema. The competitor ad database build covers tables, upserts, and the queries that turn snapshots into a timeline, and cross-platform ad tracking shows how to keep one pipeline coherent when the same creative appears on three platforms.
Step 3: Escalation Rules That Know What Can Wait
Not every change deserves 7:30 attention. The fastest way to kill trust in your own digest is paging yourself for a competitor's routine creative refresh. Severity needs rules, and the rules are just thresholds in config:
| Tier | Trigger | Delivery |
|---|---|---|
| Ping now | Tier-1 rival's new ad with heat above 700, a never-seen landing page path, or a day-30 crossing in your core geo | Direct Slack mention, any hour after 06:00 |
| Digest line | Any new creative, day-14 survivors, single-brand format notes | The 7:30 digest |
| Weekly rollup | Format mix drift, roster totals, fatigue patterns | Monday digest section |
The ping tier should be rare enough to mean something. Once or twice a week is healthy. If it fires daily, your thresholds are too jumpy, and the digest is the right home for most of what it catches.
The landing-page trigger earns its place because a new URL path usually means a new funnel, and funnels are slower and more deliberate than creatives. A quiz page appearing under a competitor's domain is worth more attention than ten new video variants of an old offer. The day-30 trigger matters for the opposite reason: by day 30 a creative has survived multiple budget reviews, which is the strongest public evidence of performance you will get without their dashboard. That kind of ad-fatigue-resistant longevity is the thing your own creative team should study.
Step 4: Ship the Digest Before You Wake Up
Delivery is the easy 10%. A Slack incoming webhook takes one POST:
import requests
def post_digest(events, webhook_url):
lines = [f"*Competitor digest — {len(events)} changes overnight*"]
for e in events[:12]:
ad = e["ad"]
title = ad.get("title") or (ad.get("body") or "")[:80]
lines.append(
f"• [{e['type']}] {e['brand']}: {title} "
f"({ad.get('platform')}, day {ad.get('days_count', '?')})"
)
requests.post(webhook_url, json={"text": "\n".join(lines)})
Cap the list. Twelve lines is a 90-second read, which is all the room a media buyer morning routine should give to collection, and anything past that belongs in the weekly rollup or the database. Prefer email? Swap the webhook for your transactional sender and keep the same text. The channel matters less than the consistency.
If Python is not your team's tool, the same pipeline assembles from no-code parts: the Slack competitor ad alert build does a minimal version in 30 minutes, and the n8n monitoring workflows cover the visual-editor equivalent of everything in this guide. Agencies running this per client should look at automated client competitor reports, where the same diff events feed a deliverable instead of a channel.
A Sample Morning Digest, Annotated
Here is what lands at 7:30 when the pipeline above runs against a nine-brand roster:
Competitor digest — Sun 14 Jun, 07:30
4 changes across 9 tracked brands
NEW Gymshark: 3 new video ads, all 9:16 UGC,
same "form check" hook
→ first new creative batch in 11 days
SCALING AlphaLion: "PR season" video crossed day 30,
heat 812, impressions band up since last week
→ longest-running ad in their current portfolio
FORMAT Legion: video share 38% → 61% over 14 days
→ static-to-video shift, second week running
PING (sent 06:55) NewEntrant Co: first ads seen on
meta + tiktok, landing page /quiz
→ new funnel type for this category
No changes: 5 brands. Credits used overnight: 11.
Every line earns its slot. The NEW entry carries context a raw list never would: the gap since the last batch tells you Gymshark works in pulses, and three variants of one hook means a test matrix, a deliberate act rather than noise. The SCALING line is the day's most actionable item, because a 30-day survivor with heat still rising is a creative worth a teardown. The FORMAT line is a trend confirmed across two weekly windows, so it is safe to bring to a strategy meeting. And the PING already fired separately, but it repeats in the digest so the record is complete.
The last line is quietly the most important. "No changes: 5 brands" is evidence the system looked and found nothing, which is exactly what a 20-minute manual sweep could never prove. Silence becomes data.
What Stays Manual: The Judgment Layer
The pipeline does collection. It does not do judgment, and it should not try. What stays on your plate:
Relevance calls. The script flags that AlphaLion's day-30 video exists. Whether its angle fits your brand, your offer, and your audience is a read only you can make.
The teardown and the brief. When a flagged creative deserves a deep look, run it through AI ad enrichment: one credit returns a scene-by-scene transcript, the hook and offer architecture, and a replication brief. Doing this at portfolio scale is its own workflow, covered in AI ad analysis via API. The decision to rebuild, counter, or ignore stays human.
Test design and budget. What enters your creative testing queue, at what spend, against which control is a media buying call. Pressure-test the numbers before committing: the ROAS calculator tells you what a test must return to be worth running, and the ad spend estimator keeps competitor-envy budgets honest.
The craft itself. Media buying is still negotiation with an auction, and no digest bids for you.
There is a next rung on this ladder. If you want the machine to draft the brief, file the swipe, and open a test plan from the digest's flags, that is the agent layer, and the companion piece on Claude Code agents for media buyers builds exactly that on top of the same API. This guide's pipeline is the foundation those agents stand on.
What the Media Buyer Morning Routine Costs to Automate
The credit math for a media buyer morning routine on autopilot is small and predictable. Nine roster brands at one curate credit per nightly session is 270 credits a month. Two nightly keyword sweeps add 60. Budget another 20 for selective enrichment of flagged winners and the whole system runs near 350 credits a month, with searches that fail refunding themselves.
API access lives on the Business plan at €329/mo with 1000+ monthly credits, which leaves comfortable headroom for a second roster or an agency's multi-client version. Business also includes free integration help, so if the diff store or the webhook fights you, the team will wire it with you rather than pointing at docs. Want to see the data before automating anything? Starter at €29/mo lets you run real searches in the app, then API access switches on when you upgrade. The full tier breakdown is on the pricing page.
Frequently Asked Questions
How long does it take to automate the media buyer morning routine?
A working version is a weekend build. Resolving and saving your roster uses free API calls, the scan plus diff script is roughly 100 lines of Python, and the Slack webhook plus a GitHub Actions schedule takes under an hour. Expect another two weeks of light tuning while you calibrate escalation thresholds against real mornings.
Do I still need to open the Meta Ad Library by hand?
Occasionally, and that is fine. Meta's Ad Library remains useful for free spot checks and one-off deep dives on a single brand. What the digest replaces is the recurring multi-brand sweep. Meta's free API is transparency-scoped, returning political and social-issue ads programmatically for most regions, so the automated commercial layer needs a paid ad library API underneath it.
How many credits does a nightly competitor scan use?
One credit per saved brand per nightly pull, one per keyword sweep, and one per AI teardown you choose to run. A nine-brand roster with two nightly keyword sweeps and modest enrichment lands around 350 credits a month, inside the Business plan's 1000+ monthly allowance. Failed searches refund their credit automatically.
Can the morning digest cover TikTok, YouTube, and LinkedIn as well as Meta?
Yes. The AdLibrary API returns commercial ads across eleven platforms, including Facebook, Instagram, TikTok, YouTube, Google, LinkedIn, Twitter, and Pinterest, from one API key. A saved advertiser merges a brand's accounts across Meta, Google, and LinkedIn into a single call, so the digest is cross-platform by default.
What should stay manual in a morning competitor check?
Judgment. The script collects, diffs, and flags. Deciding whether a competitor's angle fits your brand, which flagged ad gets a brief, and what enters the test queue at what budget stays human. Automation buys back the 20 minutes of collection so the judgment work actually gets the attention it was always supposed to have.
A Media Buyer Morning Routine That Starts at Step Three
Tomorrow morning the digest is already in the channel when you sit down. Four lines, one ping you already saw, five brands confirmed quiet. The 20 minutes you used to spend assembling that picture now go to the part of the media buyer morning routine that was always the actual job: deciding what to do about it.
The build is one roster, one scheduled script, one webhook. The data underneath it is one API key on the Business plan. Close the fifteen tabs, let the scan run tonight, and find out what your category did while you slept.
Related Articles

Claude Code Agents for Media Buyers: Hands-Off Ad Operations in 2026
Build Claude Code agents for ad fatigue detection, pacing checks, anomaly alerts, and competitor angle surfacing. Subagent architecture for media buyers.

Slack Competitor Ad Alerts: A 30-Minute Build
Build Slack competitor ad alerts in 30 minutes: an incoming webhook, a Node poll script with first_seen filtering, dedup on ad_key, and cron scheduling.

How to Automate Competitor Ad Monitoring End to End
Build Slack competitor ad alerts in 30 minutes: an incoming webhook, a Node poll script with first_seen filtering, dedup on ad_key, and cron scheduling.

GitHub Actions Competitor Ad Monitoring: Scheduled Scans, No Server
Build scheduled competitor ad scans with GitHub Actions: cron YAML, API key secrets, diffable JSON history, auto-filed issues, and Slack alerts. No server.

Python Ad Library API Scripts: A Working Cookbook
Five copy-paste Python ad library API scripts: resolve brands, search into pandas, track watchlists, scan winners, and batch-enrich ads with caching.

n8n Competitor Ad Monitoring: 6 Workflows on the AdLibrary API
Build n8n competitor ad monitoring with 6 workflows on the AdLibrary API: daily digests, Slack alerts, Sheets logs, enrichment, and winners scans.

What Does a Media Buyer Do: Daily Decisions, Key Skills, and How the Role Has Evolved
What does a media buyer actually do? Daily tasks, key decisions, required skills, and how the role has changed under algorithmic buying and AI creative tools.