Crisis monitoring with social data: catch the spike in hour one
Poll fast platforms such as X and TikTok hourly and slower ones every four hours with a few narrow queries, count new mentions per hour, and alert when the count is three standard deviations above that hour's normal level. A setup with six queries across four platforms plus comment checks on your own posts is about 11,700 credits a month, roughly $22 on the $47 pack. During an incident, switch the fast platforms to every 15 minutes.
Crisis monitoring is a different job from brand monitoring. Brand monitoring collects every mention and reports weekly. Crisis monitoring ignores most mentions and asks one question every hour: is something unusual happening right now? It needs a baseline, a spike rule and an escalation path that people trust enough to act on.
For tool comparisons, see brand monitoring tools and social media monitoring APIs. This page is the playbook.
Who does this
- Communications and PR teams who need to know before a reporter calls.
- Customer support leads watching for outages and product failures.
- Trust and safety teams watching for scams that use the brand's name.
- Agencies on call for several clients.
The data, by speed
| Step | Platform | Endpoint | Cadence | Credits |
|---|---|---|---|---|
| Latest posts for each query | X | twitter search API (type=latest) | Hourly | 1 |
| Newest videos for each query | TikTok | tiktok search keyword API (sort_by=latest) | Hourly | 1 |
| New posts and comments | reddit search API (sort=new) | Every 4 hours | 1 | |
| Keyword posts | Threads | threads search API | Every 4 hours | 1 |
| Comments on your own latest posts | Instagram, TikTok, Facebook | instagram comments API, tiktok comments API, facebook comments API | Daily | 1 |
| Context on a viral post | Any | twitter tweet API, tiktok video API, twitter replies API | On alert | 1 |
Write six queries, not sixty
- Brand name plus failure words: "down", "outage", "not working".
- Brand name plus safety words: "recall", "burn", "sick", "injury".
- Brand name plus trust words: "scam", "fraud", "hacked", "leak".
- Brand name plus "boycott" or "CEO".
- Your main product name, alone.
- Your support handle or app name.
On X, search operators work, so you can exclude your own account and retweets in the query itself.
Worked example: the monthly budget
| Item | Math | Credits a month |
|---|---|---|
| X and TikTok, hourly | 6 queries × 2 platforms × 24 × 30 | 8,640 |
| Reddit and Threads, every 4 hours | 6 × 2 × 6 × 30 | 2,160 |
| Own-post comments, daily | 10 posts × 3 platforms × 30 | 900 |
| Total | 11,700 | |
11,700 credits is about $22 a month on the $47 pack, and one pack lasts a little over two months. In incident mode, polling X and TikTok every 15 minutes for the same six queries costs 6 × 2 × 4 × 24 = 1,152 credits a day, about $2.17. Switch back when the spike is over.
The spike rule
Raw counts mislead because Monday at 9 a.m. is always busier than Sunday at 3 a.m. Compare each hour with the same hour of the week.
- For each query, keep the count of new posts per hour for the last four weeks.
- Baseline μ and σ = mean and standard deviation of the same weekday and hour across those weeks.
- z = (count this hour − μ) / max(σ, 1).
- Alert when z ≥ 3 and count ≥ 10. The minimum count stops alerts on 0 to 3 mentions.
- Separate reach trigger: any single post with views at least 50 × the median views of your mentions, even if the count is normal.
import sqlite3, statistics, datetime
db = sqlite3.connect("mentions.db") # rows: query, hour_start (ISO), count
def z_for(query, hour):
rows = db.execute(
"SELECT count FROM hourly WHERE query=? AND hour_start IN (?,?,?,?)",
[query] + [(hour - datetime.timedelta(weeks=w)).isoformat() for w in (1, 2, 3, 4)],
).fetchall()
past = [r[0] for r in rows]
now = db.execute("SELECT count FROM hourly WHERE query=? AND hour_start=?",
(query, hour.isoformat())).fetchone()
if not now or len(past) < 3:
return None, 0
mu, sd = statistics.mean(past), statistics.pstdev(past)
return (now[0] - mu) / max(sd, 1), now[0]
hour = datetime.datetime.now().replace(minute=0, second=0, microsecond=0)
for q in ("acme outage", "acme recall", "acme scam"):
z, n = z_for(q, hour)
if z is not None and z >= 3 and n >= 10:
print("ALERT", q, round(z, 1), n)
Severity matrix
| Signal | Low | Medium | High |
|---|---|---|---|
| Spread | One platform | Two platforms within 3 hours | Three or more |
| Reach | Top post under your median | Top post 10 × median | Top post 50 × median or a large account |
| Topic | Complaint | Outage or scam | Safety, legal or executive |
| Response | Support queue | Comms on-call in 30 minutes | Crisis lead now, holding line drafted |
Take the highest row that any signal reaches. Write the response column with your team before you need it.
Pitfalls
- Keyword collisions. If your brand is also a common word, add a product word to every query or the baseline will be all noise.
- Coordinated posting. Many near-identical posts from new accounts look like a crisis and may be a bot campaign. Check account age and text similarity before escalating.
- Sarcasm. Simple sentiment scoring fails on jokes. For spikes, read the top ten posts yourself.
- Alert fatigue. If the team gets more than one false alert a week, raise the count floor rather than ignoring alerts.
- Read-only. The monitor collects public posts. Replies and statements go out through your own accounts.
Run it from an AI agent
claude mcp add --transport http scrapeio https://scrapeio.com/mcp --header "x-api-key: $SCRAPEIO_API_KEY"
When an alert fires, ask: "Run twitter_search type=latest and tiktok_search_keyword sort_by=latest for 'acme recall'. List the 10 posts with the most views, with links, account follower counts and the time each was posted. Summarize the claim being made in two sentences and say whether it appears on more than one platform." The agent does triage in a minute; a person decides the response. Tools are listed on the X MCP server and Reddit MCP server pages.
How to do it with ScrapeIO
One key covers search on X, TikTok, Reddit, Threads, YouTube and LinkedIn, plus comments on your own posts. Every call in this playbook costs 1 credit. The limit is 300 requests a minute per key, enough for 15-minute polling across dozens of queries, and credits never expire, so a quiet month costs nothing extra.
100 free credits, no card. Credits never expire.
Get API key