Overview
Knowing what your competitors post on TikTok and how their audience responds gives you a strategic edge. This workflow runs daily at 9 AM, fetches recent posts for a list of competitor accounts, records engagement metrics, and detects spikes that indicate viral content. Over time it builds a competitor content database you can mine for content ideas and format insights. Tracking 5 competitors costs roughly 5 credits per day ($0.025).
Trigger
Cron 9 AM UTC daily
Schedule
Daily 9 AM
Workflow Steps
Load Competitor List
Read the list of competitor TikTok usernames from configuration.
Fetch Competitor Posts
For each competitor, call Scavio TikTok API to retrieve their recent posts and engagement data.
Calculate Engagement Baselines
Compute average engagement rate per competitor based on historical data.
Detect Viral Content
Flag any post with engagement significantly above the competitor's baseline as a viral hit.
Append to Competitor Database
Store daily snapshots in a JSONL file for trend analysis and content mining.
Python Implementation
import requests, os, json
from pathlib import Path
from datetime import date
API_KEY = os.environ["SCAVIO_API_KEY"]
TH = {"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}
COMPETITORS = ["competitor1", "competitor2", "competitor3", "competitor4", "competitor5"]
DB_FILE = Path("competitor_tiktok.jsonl")
def fetch_posts(username: str) -> list:
resp = requests.post(
"https://api.scavio.dev/api/v1/tiktok/user/posts",
headers=TH,
json={"username": username},
timeout=15,
)
resp.raise_for_status()
return resp.json().get("posts", [])
def load_baselines() -> dict:
baselines = {}
if DB_FILE.exists():
for line in DB_FILE.read_text().strip().split("\n")[-30:]:
entry = json.loads(line)
for comp, data in entry.get("competitors", {}).items():
baselines.setdefault(comp, []).append(data.get("avg_engagement", 0))
return {k: sum(v) / len(v) if v else 0 for k, v in baselines.items()}
def run():
baselines = load_baselines()
today_data = {"date": str(date.today()), "competitors": {}}
viral_alerts = []
for username in COMPETITORS:
posts = fetch_posts(username)
if not posts:
continue
total_likes = sum(p.get("likes", 0) for p in posts)
total_views = sum(p.get("views", 0) for p in posts)
avg_engagement = (total_likes / max(total_views, 1)) * 100
today_data["competitors"][username] = {
"post_count": len(posts),
"total_views": total_views,
"total_likes": total_likes,
"avg_engagement": round(avg_engagement, 2),
}
baseline = baselines.get(username, avg_engagement)
for p in posts:
post_eng = p.get("likes", 0) / max(p.get("views", 1), 1) * 100
if post_eng > baseline * 3:
viral_alerts.append(f"@{username}: {p.get('url', '')} ({post_eng:.1f}% vs {baseline:.1f}% baseline)")
with open(DB_FILE, "a") as f:
f.write(json.dumps(today_data) + "\n")
print(f"Tracked {len(COMPETITORS)} competitors on {date.today()}")
for alert in viral_alerts:
print(f" VIRAL: {alert}")
run()JavaScript Implementation
const TH = {'Authorization': 'Bearer '+process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
const fs = await import('fs');
const COMPETITORS = ['competitor1','competitor2','competitor3','competitor4','competitor5'];
const DB_FILE = 'competitor_tiktok.jsonl';
async function fetchPosts(username) {
const r = await fetch('https://api.scavio.dev/api/v1/tiktok/user/posts', {method:'POST', headers:TH, body:JSON.stringify({username})});
return (await r.json()).posts || [];
}
function loadBaselines() {
const baselines = {};
try {
const lines = fs.readFileSync(DB_FILE, 'utf8').trim().split('\n').slice(-30);
for (const line of lines) {
const entry = JSON.parse(line);
for (const [comp, data] of Object.entries(entry.competitors || {})) {
if (!baselines[comp]) baselines[comp] = [];
baselines[comp].push(data.avgEngagement || 0);
}
}
} catch {}
const result = {};
for (const [k,v] of Object.entries(baselines)) result[k] = v.reduce((s,x)=>s+x,0)/v.length;
return result;
}
const baselines = loadBaselines();
const todayData = {date:new Date().toISOString().split('T')[0], competitors:{}};
const viralAlerts = [];
for (const username of COMPETITORS) {
const posts = await fetchPosts(username);
if (!posts.length) continue;
const totalLikes = posts.reduce((s,p)=>s+(p.likes||0),0);
const totalViews = posts.reduce((s,p)=>s+(p.views||0),0);
const avgEngagement = totalViews > 0 ? Math.round(totalLikes/totalViews*10000)/100 : 0;
todayData.competitors[username] = {postCount:posts.length, totalViews, totalLikes, avgEngagement};
const baseline = baselines[username] || avgEngagement;
for (const p of posts) {
const eng = (p.views||1) > 0 ? (p.likes||0)/(p.views||1)*100 : 0;
if (eng > baseline * 3) viralAlerts.push('@'+username+': '+(p.url||'')+' ('+eng.toFixed(1)+'% vs '+baseline.toFixed(1)+'%)');
}
}
fs.appendFileSync(DB_FILE, JSON.stringify(todayData)+'\n');
console.log('Tracked '+COMPETITORS.length+' competitors');
viralAlerts.forEach(a => console.log(' VIRAL: '+a));Platforms Used
TikTok
Trending video, creator, and product discovery