Tutorial

How to Monitor App Reviews via a Search API

Track app store reviews and ratings by searching Google for app review pages. Detect sentiment shifts, feature requests, and competitor review changes.

Monitor app reviews by searching Google for app store review pages, extracting review snippets and rating data from search results, and tracking changes over time. App store APIs are restrictive and often require developer accounts, but Google indexes app review pages from both the Apple App Store and Google Play Store. By searching for your app name plus review-related keywords, you can capture review snippets, rating mentions, and competitor review data through a single search API.

Prerequisites

  • Python 3.8+ installed
  • requests library installed
  • A Scavio API key from scavio.dev
  • App names to monitor

Walkthrough

Step 1: Search for app reviews

Query Google for app review pages to capture indexed review content.

Python
import os, requests, re, json, datetime

API_KEY = os.environ['SCAVIO_API_KEY']

def search_app_reviews(app_name: str) -> list:
    queries = [
        f'{app_name} app reviews 2026',
        f'{app_name} app store rating',
        f'{app_name} user reviews',
    ]
    all_results = []
    for query in queries:
        resp = requests.post('https://api.scavio.dev/api/v1/search',
            headers={'x-api-key': API_KEY},
            json={'platform': 'google', 'query': query}, timeout=15)
        results = resp.json().get('organic_results', [])
        all_results.extend(results[:3])
    return all_results

reviews = search_app_reviews('Slack')
print(f'Found {len(reviews)} review-related results')
for r in reviews[:3]:
    print(f"  {r.get('title', '')[:60]}")

Step 2: Extract rating data

Parse search results for rating numbers and review counts.

Python
def extract_ratings(results: list) -> dict:
    ratings = []
    for r in results:
        text = (r.get('title', '') + ' ' + r.get('snippet', '')).lower()
        # Look for rating patterns like "4.5/5", "4.5 stars", "rated 4.5"
        rating_matches = re.findall(r'(\d+\.?\d*)\s*(?:/5|stars?|out of 5|rating)', text)
        for match in rating_matches:
            try:
                val = float(match)
                if 1 <= val <= 5:
                    ratings.append(val)
            except ValueError:
                pass
        # Look for review counts like "10K reviews", "5,000 reviews"
        count_matches = re.findall(r'([\d,]+[KkMm]?)\s*reviews?', text)
        if count_matches:
            pass  # Store for tracking
    avg_rating = round(sum(ratings) / len(ratings), 1) if ratings else 0
    return {
        'ratings_found': len(ratings),
        'average': avg_rating,
        'min': min(ratings) if ratings else 0,
        'max': max(ratings) if ratings else 0,
    }

rating_data = extract_ratings(reviews)
print(f"Average rating: {rating_data['average']} (from {rating_data['ratings_found']} mentions)")

Step 3: Detect sentiment signals

Analyze review snippets for positive and negative sentiment keywords.

Python
POSITIVE = ['love', 'great', 'excellent', 'best', 'amazing', 'fast', 'easy', 'reliable', 'intuitive']
NEGATIVE = ['slow', 'buggy', 'crash', 'expensive', 'terrible', 'worst', 'broken', 'frustrating', 'unusable']

def analyze_sentiment(results: list) -> dict:
    positive_count = 0
    negative_count = 0
    positive_snippets = []
    negative_snippets = []
    for r in results:
        text = r.get('snippet', '').lower()
        pos = sum(1 for w in POSITIVE if w in text)
        neg = sum(1 for w in NEGATIVE if w in text)
        if pos > neg:
            positive_count += 1
            positive_snippets.append(r.get('snippet', '')[:100])
        elif neg > pos:
            negative_count += 1
            negative_snippets.append(r.get('snippet', '')[:100])
    total = positive_count + negative_count
    return {
        'positive': positive_count,
        'negative': negative_count,
        'sentiment_ratio': round(positive_count / total, 2) if total > 0 else 0,
        'top_positive': positive_snippets[:2],
        'top_negative': negative_snippets[:2],
    }

sentiment = analyze_sentiment(reviews)
print(f"Sentiment: {sentiment['positive']} positive, {sentiment['negative']} negative")
print(f"Ratio: {sentiment['sentiment_ratio']}")

Step 4: Track changes over time

Store daily review data and detect significant changes in ratings or sentiment.

Python
HISTORY_FILE = 'app_review_history.json'

def store_review_data(app: str, rating_data: dict, sentiment: dict):
    history = []
    try:
        with open(HISTORY_FILE) as f:
            history = json.load(f)
    except FileNotFoundError:
        pass
    entry = {
        'app': app,
        'date': datetime.date.today().isoformat(),
        'rating': rating_data,
        'sentiment': sentiment,
    }
    history.append(entry)
    with open(HISTORY_FILE, 'w') as f:
        json.dump(history, f, indent=2)
    return entry

def detect_changes(app: str) -> dict:
    try:
        with open(HISTORY_FILE) as f:
            history = json.load(f)
    except FileNotFoundError:
        return {'change': 'no history'}
    entries = [h for h in history if h['app'] == app]
    if len(entries) < 2:
        return {'change': 'insufficient data'}
    prev = entries[-2]
    curr = entries[-1]
    rating_change = curr['rating']['average'] - prev['rating']['average']
    sentiment_change = curr['sentiment']['sentiment_ratio'] - prev['sentiment']['sentiment_ratio']
    return {
        'rating_change': round(rating_change, 1),
        'sentiment_change': round(sentiment_change, 2),
        'alert': abs(rating_change) > 0.3 or abs(sentiment_change) > 0.2,
    }

store_review_data('Slack', rating_data, sentiment)
changes = detect_changes('Slack')
print(f"Changes: {changes}")

Python Example

Python
import requests, os, re
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}

def app_reviews(app):
    data = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
        json={'platform': 'google', 'query': f'{app} app reviews 2026'}).json()
    results = data.get('organic_results', [])[:5]
    return [{'title': r.get('title', ''), 'snippet': r.get('snippet', '')[:80]} for r in results]

print(app_reviews('Slack'))

JavaScript Example

JavaScript
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function appReviews(app) {
  const r = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST', headers: H,
    body: JSON.stringify({platform: 'google', query: `${app} app reviews 2026`})
  });
  return ((await r.json()).organic_results || []).slice(0, 5)
    .map(r => ({title: r.title, snippet: (r.snippet || '').slice(0, 80)}));
}
appReviews('Slack').then(console.log);

Expected Output

JSON
An app review monitoring system that tracks ratings, sentiment, and review changes over time by querying Google for app store review content.

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8+ installed. requests library installed. A Scavio API key from scavio.dev. App names to monitor. A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Track app store reviews and ratings by searching Google for app review pages. Detect sentiment shifts, feature requests, and competitor review changes.