Knowing when and where people talk about your brand online is essential for reputation management, competitive intelligence, and customer feedback. Manual monitoring doesn't scale -- you need automated tools that continuously search the web, social media, and forums for mentions of your brand, products, or executives.
This tutorial shows how to build a brand mention monitoring system with Python and the SearchHive API, including alerting and trend analysis.
Key Takeaways
- SearchHive's SwiftSearch API searches the live web, returning fresh results with timestamps
- A complete monitoring system needs: search, deduplication, storage, and alerting
- Running hourly checks catches mentions within 60 minutes of publication
- SQLite stores mention history for trend analysis over weeks and months
- The free tier supports monitoring ~5 brands hourly
Prerequisites
- Python 3.8+
- SearchHive API key (free at searchhive.dev)
- Optional: Slack or Discord webhook URL for alerts
pip install requests searchhive
Step 1: Set Up the Database
Store every mention with deduplication to avoid duplicate alerts:
import sqlite3
from datetime import datetime
def init_db(db_path="brand_monitor.db"):
# Initialize database for brand mention tracking
conn = sqlite3.connect(db_path)
c = conn.cursor()
c.execute("39| CREATE TABLE IF NOT EXISTS mentions ( 40| id INTEGER PRIMARY KEY AUTOINCREMENT, 41| brand TEXT NOT NULL, 42| url TEXT UNIQUE NOT NULL, 43| title TEXT, 44| snippet TEXT, 45| source TEXT, 46| discovered_at TEXT DEFAULT CURRENT_TIMESTAMP 47| ) 48|"))
c.execute("51| CREATE INDEX IF NOT EXISTS idx_mentions_brand 52| ON mentions(brand, discovered_at) 53|"))
c.execute("56| CREATE TABLE IF NOT EXISTS brands ( 57| id INTEGER PRIMARY KEY AUTOINCREMENT, 58| name TEXT UNIQUE NOT NULL, 59| search_query TEXT NOT NULL, 60| created_at TEXT DEFAULT CURRENT_TIMESTAMP 61| ) 62|"))
conn.commit()
conn.close()
init_db()
Step 2: Search for Brand Mentions
Use SwiftSearch to find recent mentions across the web:
import requests
import time
API_KEY="***"
BASE_URL = "https://api.searchhive.dev/v1"
def search_mentions(brand_name, query=None):
# Search the web for recent brand mentions
if not query:
query = f'"{brand_name}"'
response = requests.post(
f"{BASE_URL}/search",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"query": query,
"num_results": 20,
"freshness": "week" # Only results from the past week
}
)
if response.status_code != 200:
print(f"API error: {response.status_code}")
return []
results = response.json().get("results", [])
mentions = []
for r in results:
mentions.append({
"url": r.get("url", ""),
"title": r.get("title", ""),
"snippet": r.get("snippet", ""),
"source": r.get("source", r.get("domain", ""))
})
return mentions
# Example: search for brand mentions
mentions = search_mentions("SearchHive")
print(f"Found {len(mentions)} mentions")
for m in mentions[:5]:
print(f" {m['title'][:60]}")
print(f" {m['url']}")
Step 3: Deduplicate and Store Mentions
Avoid alerting on the same mention twice by using the URL as a unique key:
import sqlite3
def save_mentions(brand_name, mentions, db_path="brand_monitor.db"):
# Save new mentions to database, return only new ones
conn = sqlite3.connect(db_path)
c = conn.cursor()
new_mentions = []
for mention in mentions:
url = mention["url"]
try:
c.execute(
"INSERT INTO mentions (brand, url, title, snippet, source) VALUES (?, ?, ?, ?, ?)",
(brand_name, url, mention["title"], mention["snippet"], mention["source"])
)
new_mentions.append(mention)
except sqlite3.IntegrityError:
pass # Already tracked
conn.commit()
conn.close()
return new_mentions
def add_brand(name, search_query=None, db_path="brand_monitor.db"):
# Add a brand to monitor
if not search_query:
search_query = f'"{name}"'
conn = sqlite3.connect(db_path)
c = conn.cursor()
try:
c.execute(
"INSERT INTO brands (name, search_query) VALUES (?, ?)",
(name, search_query)
)
conn.commit()
print(f"Added brand: {name}")
except sqlite3.IntegrityError:
print(f"Already tracking: {name}")
conn.close()
# Set up brands to monitor
add_brand("SearchHive")
add_brand("SearchHive API")
add_brand("searchhive.dev", '"searchhive.dev" OR "SearchHive review"')
# Search and save
mentions = search_mentions("SearchHive")
new = save_mentions("SearchHive", mentions)
print(f"New mentions: {len(new)}")
Step 4: Set Up Alert Notifications
Get notified immediately when new mentions appear:
import requests
SLACK_WEBHOOK = "https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
def send_slack_alert(brand, mentions):
# Send a Slack notification for new mentions
if not mentions:
return
blocks = [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*New {brand} Mentions ({len(mentions)})*"
}
}
]
for m in mentions[:5]: # Max 5 in one message
blocks.append({
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"*<{m['url']}|{m['title'][:80]}>*
{m['snippet'][:150]}"
}
})
if len(mentions) > 5:
blocks.append({
"type": "section",
"text": {
"type": "mrkdwn",
"text": f"...and {len(mentions) - 5} more"
}
})
try:
requests.post(SLACK_WEBHOOK, json={"blocks": blocks}, timeout=10)
print(f"Slack alert sent: {len(mentions)} mentions")
except Exception as e:
print(f"Slack error: {e}")
def send_discord_alert(webhook_url, brand, mentions):
# Send a Discord notification for new mentions
if not mentions:
return
content_lines = [f"**New {brand} Mentions ({len(mentions)})**
"]
for m in mentions[:5]:
content_lines.append(f"- [{m['title'][:70]}]({m['url']})")
try:
requests.post(
webhook_url,
json={"content": "\n".join(content_lines)},
timeout=10
)
except Exception as e:
print(f"Discord error: {e}")
Step 5: Monitor Multiple Sources
Different sources require different search queries for best results:
def search_all_sources(brand_name):
# Search across different web sources for brand mentions
queries = [
f'"{brand_name}"', # General web
f'"{brand_name}" review OR opinion', # Reviews
f'"{brand_name}" vs OR comparison', # Comparisons
f'"{brand_name}" alternative OR competitor', # Competitive intel
]
all_mentions = []
seen_urls = set()
for query in queries:
mentions = search_mentions(brand_name, query)
for m in mentions:
if m["url"] not in seen_urls:
seen_urls.add(m["url"])
m["query_type"] = query
all_mentions.append(m)
time.sleep(1)
return all_mentions
# Run multi-source search
all_mentions = search_all_sources("SearchHive")
new = save_mentions("SearchHive", all_mentions)
if new:
send_slack_alert("SearchHive", new)
Step 6: Analyze Mention Trends
Track mention volume over time to spot trends:
import sqlite3
from datetime import datetime, timedelta
def get_mention_trend(brand, days=30, db_path="brand_monitor.db"):
# Get daily mention counts for trend analysis
conn = sqlite3.connect(db_path)
c = conn.cursor()
c.execute("294| SELECT DATE(discovered_at) as date, COUNT(*) as count 295| FROM mentions 296| WHERE brand = ? 297| AND discovered_at >= date('now', ?) 298| GROUP BY DATE(discovered_at) 299| ORDER BY date 300|"), (brand, f"-{days} days"))
rows = c.fetchall()
conn.close()
return [{"date": r[0], "mentions": r[1]} for r in rows]
def get_mention_summary(brand, days=7, db_path="brand_monitor.db"):
# Get summary stats for a brand
conn = sqlite3.connect(db_path)
c = conn.cursor()
c.execute("313| SELECT 314| COUNT(*) as total, 315| COUNT(DISTINCT source) as unique_sources, 316| MIN(discovered_at) as earliest, 317| MAX(discovered_at) as latest 318| FROM mentions 319| WHERE brand = ? 320| AND discovered_at >= date('now', ?) 321|"), (brand, f"-{days} days"))
row = c.fetchone()
conn.close()
return {
"brand": brand,
"period_days": days,
"total_mentions": row[0],
"unique_sources": row[1],
"earliest": row[2],
"latest": row[3]
}
# Example: weekly summary
trend = get_mention_trend("SearchHive", days=14)
print("Daily mention trend:")
for day in trend:
bar = "#" * day["mentions"]
print(f" {day['date']}: {day['mentions']} {bar}")
summary = get_mention_summary("SearchHive", days=7)
print(f"\nWeekly summary: {summary['total_mentions']} mentions "
f"from {summary['unique_sources']} sources")
Step 7: Complete Monitoring Script
Combine everything into a runnable monitoring script:
import sqlite3
import requests
import time
from datetime import datetime
API_KEY="***"
BASE_URL = "https://api.searchhive.dev/v1"
DB_PATH = "brand_monitor.db"
SLACK_WEBHOOK = "your-webhook-url"
def run_monitor():
# Full monitoring cycle for all tracked brands
print(f"=== Brand Monitor - {datetime.now().strftime('%Y-%m-%d %H:%M')} ===")
conn = sqlite3.connect(DB_PATH)
c = conn.cursor()
c.execute("SELECT name, search_query FROM brands")
brands = c.fetchall()
conn.close()
for brand_name, query in brands:
print(f"\nChecking: {brand_name}")
# Search for mentions
mentions = search_mentions(brand_name, query)
# Save and get new ones
new_mentions = save_mentions(brand_name, mentions, DB_PATH)
# Alert on new mentions
if new_mentions:
print(f" {len(new_mentions)} NEW mentions!")
send_slack_alert(brand_name, new_mentions)
else:
print(f" No new mentions")
time.sleep(2)
print("\n=== Done ===")
if __name__ == "__main__":
run_monitor()
Run it on a schedule:
# Check every hour
0 * * * * /usr/bin/python3 /path/to/brand_monitor.py >> /var/log/brand_monitor.log 2>&1
Common Issues
False positives: Quoted searches (using "exact phrase") reduce noise from partial matches. Use specific brand names rather than generic terms.
Source quality: Some mentions come from low-quality sites. Add a source whitelist or blacklist in your save_mentions function.
Rate limits: The free tier allows ~500 searches/month. Hourly monitoring of 5 brands uses ~120 credits/day (30/day * 4 queries/brand). The Starter plan ($9/mo) gives 5K credits for much more coverage.
Delayed indexing: Some mentions take 24-48 hours to appear in search results. For real-time social monitoring, supplement with platform-specific APIs (Twitter API, Reddit API).
Cost Comparison
| Tool | Pricing | Custom Queries | API Access |
|---|---|---|---|
| Google Alerts | Free | Limited | No API |
| Mention.com | $49-$179/mo | Yes | Yes |
| Brandwatch | $800+/mo | Yes | Yes |
| SearchHive Free | $0 | Full control | Yes |
| SearchHive Starter | $9/mo | Full control | Yes |
Next Steps
- Add sentiment analysis (positive/negative/neutral) on mention snippets
- Track competitor brands alongside your own
- Build a dashboard with Flask or Streamlit for visual trends
- Integrate with CRM to link mentions to sales opportunities
Get started free with 500 credits at searchhive.dev -- no credit card required. Check the docs for the full API reference.
Related: /tutorials/how-to-build-an-seo-monitoring-tool-with-search-apis | /tutorials/how-to-scrape-instagram-data-for-marketing-research
Compare: /compare/serpapi