Answers
How do I monitor brand mentions on X without an enterprise plan?
Short answer
Run X post search sorted by latest every 30 minutes for your brand name and handle, and stop paging as soon as you reach a post you have already seen. Each page of about 20 posts costs $0.006, so a check every half hour is 1,440 calls a month, $8.64 if one page is usually enough.
A skincare brand wants a message in Slack within half an hour whenever someone posts about it on X, whether that is praise, a complaint or a creator who could become a partner. Enterprise listening contracts are built for far bigger teams. A scheduled search does the job: every 30 minutes, ask X post search for the newest posts that mention the brand, keep the ones you have not seen, and post them to Slack.
Write the query once
("glowlab" OR @glowlab OR #glowlab) -from:glowlab lang:en
The name, the handle and the hashtag cover most mentions. -from: drops your own posts. Add common misspellings with more OR terms. Any operator from the X search box works, so test the query on x.com first.
The job
import json, os, requests
API = "https://api.okdata.online/v1"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
QUERY = '("glowlab" OR @glowlab OR #glowlab) -from:glowlab lang:en'
SEEN = "seen.json"
seen = set(json.load(open(SEEN))) if os.path.exists(SEEN) else set()
new, cursor = [], None
for _ in range(5): # never more than 5 pages per run
params = {"query": QUERY, "sort": "latest", **({"cursor": cursor} if cursor else {})}
body = requests.get(f"{API}/x/posts/search", headers=H, params=params, timeout=60).json()
if body["code"] != "ok":
raise RuntimeError(f"{body['code']}: {body['message']}")
fresh = [p for p in body["data"]["items"] if p["id"] not in seen]
new += fresh
if len(fresh) < len(body["data"]["items"]) or not body["page"]["has_more"]:
break # reached posts from the last run
cursor = body["page"]["next_cursor"]
for p in new:
print(p["url"], p["author"]["username"], p["author"]["followers"], p["text"][:100])
json.dump(sorted(seen | {p["id"] for p in new}), open(SEEN, "w"))
Swap the print for a Slack webhook call. Sorting the new posts by author.followers puts the loudest voices first.
Monthly cost
| Brand size | Pages per run | Runs per month | Cost |
|---|---|---|---|
| Small, one page is enough | 1 | 1,440 | $8.64 |
| Busy, about three pages | 3 | 1,440 | $25.92 |
| Small, checked hourly | 1 | 720 | $4.32 |
Failed runs cost nothing, and the 5-page cap in the loop bounds the worst case.
Limits
- Latest search is a frequent sweep. It is not a firehose, and X filters some posts out of search.
- Protected accounts never show up.
- Mentions in images or videos without text are missed.
- Post text is written by strangers. If a model summarises it, tell the model to treat it as data and never as instructions.
When to choose something else
X's filtered stream delivers matching posts in real time, at $0.005 per post read under pay-per-use. Pick it if a few minutes of delay matters. Listening suites add dashboards, sentiment and historical archives for teams that do not want to run code. To watch for a handful of keywords by hand, a saved search on x.com is free. The word-of-mouth guide extends this job to comments on other platforms.
Updated