Overview
This workflow monitors TikTok video comments daily for brand mentions and sentiment signals. It searches for videos mentioning your brand, fetches their comments, classifies mentions as positive, negative, or neutral, and tracks competitor mentions. The output is a daily sentiment report that replaces $500+/mo social listening tools.
Trigger
Cron schedule (daily at 9:00 AM UTC)
Schedule
Runs daily at 9:00 AM UTC
Workflow Steps
Search for brand-related videos
Call Scavio TikTok search/videos to find recent videos mentioning your brand or product.
Fetch comments for each video
Call the video/comments endpoint for each relevant video to get structured comment data.
Filter for brand mentions
Scan comment text for brand keywords, competitor names, and sentiment indicator words.
Classify sentiment
Use keyword matching to classify each mention as positive, negative, or neutral based on context words.
Generate daily sentiment report
Compile mention counts, sentiment breakdown, and notable comments into a daily report.
Python Implementation
import requests
import json
from pathlib import Path
from datetime import datetime
API_KEY = "your_scavio_api_key"
BASE_URL = "https://api.scavio.dev/api/v1/tiktok"
BRAND = "yourbrand"
COMPETITORS = ["competitor1", "competitor2"]
POSITIVE_WORDS = ["love", "amazing", "best", "great", "awesome", "perfect", "recommend"]
NEGATIVE_WORDS = ["hate", "worst", "terrible", "awful", "broken", "scam", "avoid", "disappointing"]
def search_videos(query: str) -> list[dict]:
res = requests.post(
f"{BASE_URL}/search/videos",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"query": query},
timeout=15,
)
res.raise_for_status()
return res.json().get("videos", [])
def get_comments(video_id: str) -> list[dict]:
res = requests.post(
f"{BASE_URL}/video/comments",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"video_id": video_id},
timeout=15,
)
res.raise_for_status()
return res.json().get("comments", [])
def classify_sentiment(text: str) -> str:
lower = text.lower()
pos = sum(1 for w in POSITIVE_WORDS if w in lower)
neg = sum(1 for w in NEGATIVE_WORDS if w in lower)
if pos > neg:
return "positive"
if neg > pos:
return "negative"
return "neutral"
def run():
videos = search_videos(BRAND)
mentions = {"positive": [], "negative": [], "neutral": [], "competitor": []}
for video in videos[:20]:
video_id = video.get("id", "")
if not video_id:
continue
comments = get_comments(video_id)
for comment in comments:
text = comment.get("text", "")
lower = text.lower()
if BRAND.lower() in lower:
sentiment = classify_sentiment(text)
mentions[sentiment].append({
"text": text[:200],
"likes": comment.get("likes", 0),
"video_id": video_id,
})
for comp in COMPETITORS:
if comp.lower() in lower:
mentions["competitor"].append({"text": text[:200], "competitor": comp, "video_id": video_id})
date = datetime.utcnow().strftime("%Y-%m-%d")
report = {
"date": date,
"videos_scanned": min(len(videos), 20),
"positive": len(mentions["positive"]),
"negative": len(mentions["negative"]),
"neutral": len(mentions["neutral"]),
"competitor_mentions": len(mentions["competitor"]),
"top_positive": sorted(mentions["positive"], key=lambda x: x["likes"], reverse=True)[:5],
"top_negative": sorted(mentions["negative"], key=lambda x: x["likes"], reverse=True)[:5],
}
Path(f"tiktok_sentiment_{date}.json").write_text(json.dumps(report, indent=2))
print(f"Sentiment: +{report['positive']} / -{report['negative']} / ~{report['neutral']} | Competitor: {report['competitor_mentions']}")
if __name__ == "__main__":
run()JavaScript Implementation
const API_KEY = "your_scavio_api_key";
const BASE_URL = "https://api.scavio.dev/api/v1/tiktok";
const BRAND = "yourbrand";
const POSITIVE = ["love", "amazing", "best", "great", "awesome"];
const NEGATIVE = ["hate", "worst", "terrible", "awful", "broken"];
async function searchVideos(query) {
const res = await fetch(`${BASE_URL}/search/videos`, { method: "POST", headers: { Authorization: `Bearer ${API_KEY}`, "content-type": "application/json" }, body: JSON.stringify({ query }) });
return (await res.json()).videos ?? [];
}
async function getComments(videoId) {
const res = await fetch(`${BASE_URL}/video/comments`, { method: "POST", headers: { Authorization: `Bearer ${API_KEY}`, "content-type": "application/json" }, body: JSON.stringify({ video_id: videoId }) });
return (await res.json()).comments ?? [];
}
const videos = await searchVideos(BRAND);
let pos = 0, neg = 0, neu = 0;
for (const v of videos.slice(0, 20)) {
const comments = await getComments(v.id ?? "");
for (const c of comments) {
const lower = (c.text ?? "").toLowerCase();
if (!lower.includes(BRAND.toLowerCase())) continue;
const p = POSITIVE.filter((w) => lower.includes(w)).length;
const n = NEGATIVE.filter((w) => lower.includes(w)).length;
if (p > n) pos++; else if (n > p) neg++; else neu++;
}
}
console.log(`Sentiment: +${pos} / -${neg} / ~${neu}`);Platforms Used
TikTok
Trending video, creator, and product discovery