Overview
Monitor competitor app reviews daily by searching Google for indexed app store reviews and Reddit for community discussions. Alert on negative sentiment spikes, major bugs, and feature complaints before your competitors react.
Trigger
Daily cron at 09:00 UTC
Schedule
Daily at 09:00 UTC
Workflow Steps
Define competitor apps
Maintain a list of competitor app names with their app store identifiers. Group by category for targeted monitoring.
Google review search
For each competitor app, search Google for '[app name] app reviews 2026'. Google indexes app store reviews and surfaces them in organic results.
Reddit community search
Search Reddit for each competitor app name. Community discussions often surface issues before they appear in formal reviews.
Sentiment scoring
Count negative keywords (bug, crash, slow, broken, worst) in result snippets and titles. Score each app's daily sentiment as positive, mixed, or negative.
Alert on changes
Compare today's sentiment score against the 7-day average. If sentiment drops or negative signal count doubles, fire an alert to Slack or email.
Python Implementation
import requests, os, json
from datetime import date
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
NEG_KW = ['bug', 'crash', 'slow', 'broken', 'worst', 'terrible', 'unusable', 'down', 'error', 'freeze']
def monitor_app(app_name):
g = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': f'{app_name} app reviews 2026'},
timeout=10).json()
r = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'reddit', 'query': f'{app_name} app'}, timeout=10).json()
google_text = ' '.join(o.get('snippet', '') for o in g.get('organic', [])[:5]).lower()
reddit_text = ' '.join(o.get('title', '') for o in r.get('organic', [])[:5]).lower()
all_text = google_text + ' ' + reddit_text
neg_count = sum(1 for kw in NEG_KW if kw in all_text)
return {
'app': app_name, 'date': str(date.today()),
'negative_signals': neg_count,
'sentiment': 'negative' if neg_count >= 4 else 'mixed' if neg_count >= 2 else 'positive',
'google_snippets': [o.get('snippet', '')[:100] for o in g.get('organic', [])[:3]],
'reddit_titles': [o.get('title', '')[:80] for o in r.get('organic', [])[:3]],
}
apps = ['Notion', 'Obsidian', 'Todoist', 'ClickUp', 'Monday']
for app in apps:
result = monitor_app(app)
indicator = '!!!' if result['sentiment'] == 'negative' else '...' if result['sentiment'] == 'mixed' else ' '
print(f"[{result['sentiment'].upper():>8}] {indicator} {app}: {result['negative_signals']} neg signals")JavaScript Implementation
const H = {"x-api-key": process.env.SCAVIO_API_KEY, "Content-Type": "application/json"};
const NEG_KW = ["bug", "crash", "slow", "broken", "worst", "terrible", "unusable", "down", "error", "freeze"];
async function monitorApp(appName) {
const [g, r] = await Promise.all([
fetch("https://api.scavio.dev/api/v1/search", {
method: "POST", headers: H,
body: JSON.stringify({platform: "google", query: `${appName} app reviews 2026`})
}).then(r => r.json()),
fetch("https://api.scavio.dev/api/v1/search", {
method: "POST", headers: H,
body: JSON.stringify({platform: "reddit", query: `${appName} app`})
}).then(r => r.json()),
]);
const googleText = (g.organic || []).slice(0, 5).map(o => o.snippet || "").join(" ").toLowerCase();
const redditText = (r.organic || []).slice(0, 5).map(o => o.title || "").join(" ").toLowerCase();
const allText = googleText + " " + redditText;
const negCount = NEG_KW.filter(kw => allText.includes(kw)).length;
return {
app: appName, negativeSignals: negCount,
sentiment: negCount >= 4 ? "negative" : negCount >= 2 ? "mixed" : "positive",
googleSnippets: (g.organic || []).slice(0, 3).map(o => (o.snippet || "").slice(0, 100)),
redditTitles: (r.organic || []).slice(0, 3).map(o => (o.title || "").slice(0, 80)),
};
}
(async () => {
const apps = ["Notion", "Obsidian", "Todoist", "ClickUp", "Monday"];
for (const app of apps) {
const r = await monitorApp(app);
const ind = r.sentiment === "negative" ? "!!!" : r.sentiment === "mixed" ? "..." : " ";
console.log(`[${r.sentiment.toUpperCase().padStart(8)}] ${ind} ${app}: ${r.negativeSignals} neg signals`);
}
})();Platforms Used
Web search with knowledge graph, PAA, and AI overviews
Community, posts & threaded comments from any subreddit