Overview
This workflow collects product reviews and mentions from Amazon and Reddit, assigns a basic sentiment score to each, and tracks how sentiment trends over time. It helps product teams catch quality issues early, detect the impact of new releases, and monitor competitor product reception without manual review reading.
Trigger
Cron schedule (daily at 11 AM UTC)
Schedule
Runs daily at 11 AM UTC
Workflow Steps
Define product list
Load the list of your own products and competitor products to track from configuration.
Search Amazon and Reddit
Call the Scavio API on both platforms for each product to retrieve recent reviews and discussions.
Extract review text
Pull out the review body, rating, and snippet text from each result.
Score sentiment
Apply a keyword-based or LLM-based sentiment scorer to each review. Classify as positive, neutral, or negative.
Aggregate and trend
Compute the daily sentiment distribution and compare it to the rolling average from the past 7 days.
Alert on shifts
If negative sentiment exceeds the threshold or shifts significantly, send an alert to the product team.
Python Implementation
import requests
import json
from pathlib import Path
API_KEY = "your_scavio_api_key"
POSITIVE_WORDS = {"great", "love", "excellent", "perfect", "best", "amazing"}
NEGATIVE_WORDS = {"broken", "terrible", "worst", "waste", "awful", "bad", "poor"}
def search_product(query: str, platform: str) -> list[dict]:
res = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": platform, "query": f"{query} reviews"},
timeout=15,
)
res.raise_for_status()
return res.json().get("organic", [])
def score_sentiment(text: str) -> str:
words = set(text.lower().split())
pos = len(words & POSITIVE_WORDS)
neg = len(words & NEGATIVE_WORDS)
if pos > neg:
return "positive"
if neg > pos:
return "negative"
return "neutral"
def run():
products = ["your-product-name", "competitor-product"]
results = []
for product in products:
for platform in ["amazon", "reddit"]:
items = search_product(product, platform)
for item in items:
text = item.get("snippet", "") or item.get("title", "")
sentiment = score_sentiment(text)
results.append({
"product": product,
"platform": platform,
"title": item.get("title", ""),
"sentiment": sentiment,
})
counts = {"positive": 0, "neutral": 0, "negative": 0}
for r in results:
counts[r["sentiment"]] += 1
print(f"Tracked {len(results)} mentions")
print(f"Sentiment: {json.dumps(counts)}")
neg_ratio = counts["negative"] / max(len(results), 1)
if neg_ratio > 0.4:
print("ALERT: Negative sentiment exceeds 40% threshold")
if __name__ == "__main__":
run()JavaScript Implementation
const API_KEY = "your_scavio_api_key";
const POSITIVE = new Set(["great", "love", "excellent", "perfect", "best", "amazing"]);
const NEGATIVE = new Set(["broken", "terrible", "worst", "waste", "awful", "bad", "poor"]);
async function searchProduct(query, platform) {
const res = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST",
headers: {
"x-api-key": API_KEY,
"content-type": "application/json",
},
body: JSON.stringify({ platform, query: `${query} reviews` }),
});
if (!res.ok) throw new Error(`scavio ${res.status}`);
const data = await res.json();
return data.organic ?? [];
}
function scoreSentiment(text) {
const words = new Set(text.toLowerCase().split(/\s+/));
let pos = 0, neg = 0;
for (const w of words) {
if (POSITIVE.has(w)) pos++;
if (NEGATIVE.has(w)) neg++;
}
if (pos > neg) return "positive";
if (neg > pos) return "negative";
return "neutral";
}
async function run() {
const products = ["your-product-name", "competitor-product"];
const results = [];
for (const product of products) {
for (const platform of ["amazon", "reddit"]) {
const items = await searchProduct(product, platform);
for (const item of items) {
const text = item.snippet ?? item.title ?? "";
results.push({
product,
platform,
title: item.title ?? "",
sentiment: scoreSentiment(text),
});
}
}
}
const counts = { positive: 0, neutral: 0, negative: 0 };
for (const r of results) counts[r.sentiment]++;
console.log(`Tracked ${results.length} mentions`);
console.log("Sentiment:", JSON.stringify(counts));
const negRatio = counts.negative / Math.max(results.length, 1);
if (negRatio > 0.4) {
console.log("ALERT: Negative sentiment exceeds 40% threshold");
}
}
run();Platforms Used
Amazon
Product search with prices, ratings, and reviews
Community, posts & threaded comments from any subreddit