Building a TikTok ecommerce trend tracker with an API lets you monitor viral products, trending hashtags, and emerging niches in real time so you can source winning products before your competitors spot them. This tutorial walks you through searching for ecommerce-related TikTok content, extracting product signals from hashtags and captions, and building a scoring system that ranks trends by velocity and engagement.
Prerequisites
- Scavio API key with TikTok access (free 250 credits/mo at scavio.dev)
- Python 3.9+ or Node.js 18+
- Basic understanding of ecommerce product research
Walkthrough
Step 1: Define product discovery search queries
Build a list of TikTok search queries that surface viral products. Use hashtag-style queries and product-category keywords that dropshippers and DTC brands commonly monitor. Include both broad trend queries and niche-specific ones.
search_queries = [
'tiktok made me buy it',
'viral product 2026',
'amazon finds must have',
'small business check',
'dropshipping winning product',
'kitchen gadget viral',
'skincare routine viral',
'home organization hack',
]Step 2: Search TikTok for trending content
Query the Scavio TikTok search endpoint for each product discovery query. Collect video metadata including view counts, likes, shares, hashtags, and posting dates. This raw data becomes your trend signal.
import requests
API_KEY = 'your_scavio_api_key'
def search_tiktok(query, count=20):
resp = requests.post(
'https://api.scavio.dev/api/v1/tiktok/search/videos',
headers={'Authorization': f'Bearer {API_KEY}'},
json={'query': query, 'count': count}
)
resp.raise_for_status()
return resp.json().get('videos', [])
all_videos = []
for q in search_queries:
videos = search_tiktok(q, count=20)
for v in videos:
v['search_query'] = q
all_videos.extend(videos)
print(f'Collected {len(all_videos)} videos across {len(search_queries)} queries')Step 3: Extract and rank hashtags by engagement
Parse hashtags from all collected videos and aggregate engagement metrics per hashtag. Hashtags that appear across multiple high-engagement videos signal a trending product or niche.
from collections import defaultdict
hashtag_stats = defaultdict(lambda: {'total_views': 0, 'total_likes': 0, 'video_count': 0})
for v in all_videos:
for tag in v.get('hashtags', []):
tag_lower = tag.lower()
hashtag_stats[tag_lower]['total_views'] += v.get('views', 0)
hashtag_stats[tag_lower]['total_likes'] += v.get('likes', 0)
hashtag_stats[tag_lower]['video_count'] += 1
# Rank by a composite score: views * sqrt(video_count)
import math
ranked = sorted(
hashtag_stats.items(),
key=lambda x: x[1]['total_views'] * math.sqrt(x[1]['video_count']),
reverse=True
)
print('Top trending hashtags:')
for tag, stats in ranked[:15]:
print(f' #{tag}: {stats["total_views"]:,} views, {stats["video_count"]} videos')Step 4: Score and classify product trends
Assign a trend score to each hashtag cluster based on engagement velocity (views per video), breadth (number of unique videos), and recency. Classify trends as emerging, peaking, or saturated based on score thresholds.
def score_trend(stats):
views_per_video = stats['total_views'] / max(stats['video_count'], 1)
breadth = stats['video_count']
score = (views_per_video / 1000) * math.sqrt(breadth)
if score > 100 and breadth < 10:
phase = 'emerging'
elif score > 50:
phase = 'peaking'
else:
phase = 'saturated'
return {'score': round(score, 1), 'phase': phase, 'views_per_video': int(views_per_video)}
trends = []
for tag, stats in ranked[:30]:
trend = score_trend(stats)
trend['hashtag'] = tag
trend['total_views'] = stats['total_views']
trend['video_count'] = stats['video_count']
trends.append(trend)
for t in trends[:10]:
print(f'#{t["hashtag"]} | score: {t["score"]} | phase: {t["phase"]} | {t["views_per_video"]:,} views/vid')Step 5: Export trend report
Save the scored trends to a JSON file that you can feed into your product research workflow, Slack alerts, or dashboard. Include the raw data so you can re-score with different thresholds later.
import json
report = {
'scan_date': '2026-05-12',
'total_videos_analyzed': len(all_videos),
'unique_hashtags': len(hashtag_stats),
'top_trends': trends,
}
with open('tiktok_ecommerce_trends.json', 'w') as f:
json.dump(report, f, indent=2)
print(f'Exported {len(trends)} trends to tiktok_ecommerce_trends.json')Python Example
import requests
import math
import json
from collections import defaultdict
API_KEY = 'your_scavio_api_key'
search_queries = [
'tiktok made me buy it',
'viral product 2026',
'amazon finds must have',
'dropshipping winning product',
]
def search_tiktok(query, count=20):
resp = requests.post(
'https://api.scavio.dev/api/v1/tiktok/search/videos',
headers={'Authorization': f'Bearer {API_KEY}'},
json={'query': query, 'count': count}
)
resp.raise_for_status()
return resp.json().get('videos', [])
all_videos = []
for q in search_queries:
videos = search_tiktok(q, count=20)
for v in videos:
v['search_query'] = q
all_videos.extend(videos)
hashtag_stats = defaultdict(lambda: {'total_views': 0, 'total_likes': 0, 'video_count': 0})
for v in all_videos:
for tag in v.get('hashtags', []):
tag_lower = tag.lower()
hashtag_stats[tag_lower]['total_views'] += v.get('views', 0)
hashtag_stats[tag_lower]['total_likes'] += v.get('likes', 0)
hashtag_stats[tag_lower]['video_count'] += 1
ranked = sorted(
hashtag_stats.items(),
key=lambda x: x[1]['total_views'] * math.sqrt(x[1]['video_count']),
reverse=True
)
trends = []
for tag, stats in ranked[:30]:
vpv = stats['total_views'] / max(stats['video_count'], 1)
score = (vpv / 1000) * math.sqrt(stats['video_count'])
phase = 'emerging' if score > 100 and stats['video_count'] < 10 else ('peaking' if score > 50 else 'saturated')
trends.append({
'hashtag': tag,
'score': round(score, 1),
'phase': phase,
'total_views': stats['total_views'],
'video_count': stats['video_count'],
})
report = {
'scan_date': '2026-05-12',
'total_videos': len(all_videos),
'top_trends': trends,
}
with open('tiktok_ecommerce_trends.json', 'w') as f:
json.dump(report, f, indent=2)
print(f'Analyzed {len(all_videos)} videos, found {len(trends)} trends')
for t in trends[:5]:
print(f' #{t["hashtag"]} | score: {t["score"]} | {t["phase"]}')JavaScript Example
const fs = require('fs');
const API_KEY = 'your_scavio_api_key';
const searchQueries = [
'tiktok made me buy it',
'viral product 2026',
'amazon finds must have',
'dropshipping winning product',
];
async function searchTiktok(query, count = 20) {
const resp = await fetch('https://api.scavio.dev/api/v1/tiktok/search/videos', {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, count }),
});
const data = await resp.json();
return data.videos || [];
}
async function main() {
const allVideos = [];
for (const q of searchQueries) {
const videos = await searchTiktok(q, 20);
videos.forEach(v => { v.search_query = q; });
allVideos.push(...videos);
}
const hashtagStats = {};
for (const v of allVideos) {
for (const tag of v.hashtags || []) {
const t = tag.toLowerCase();
if (!hashtagStats[t]) hashtagStats[t] = { totalViews: 0, totalLikes: 0, videoCount: 0 };
hashtagStats[t].totalViews += v.views || 0;
hashtagStats[t].totalLikes += v.likes || 0;
hashtagStats[t].videoCount += 1;
}
}
const ranked = Object.entries(hashtagStats)
.sort((a, b) => b[1].totalViews * Math.sqrt(b[1].videoCount) - a[1].totalViews * Math.sqrt(a[1].videoCount))
.slice(0, 30);
const trends = ranked.map(([tag, stats]) => {
const vpv = stats.totalViews / Math.max(stats.videoCount, 1);
const score = (vpv / 1000) * Math.sqrt(stats.videoCount);
const phase = score > 100 && stats.videoCount < 10 ? 'emerging' : score > 50 ? 'peaking' : 'saturated';
return { hashtag: tag, score: Math.round(score * 10) / 10, phase, totalViews: stats.totalViews, videoCount: stats.videoCount };
});
const report = { scan_date: '2026-05-12', total_videos: allVideos.length, top_trends: trends };
fs.writeFileSync('tiktok_ecommerce_trends.json', JSON.stringify(report, null, 2));
console.log(`Analyzed ${allVideos.length} videos, found ${trends.length} trends`);
trends.slice(0, 5).forEach(t => console.log(` #${t.hashtag} | score: ${t.score} | ${t.phase}`));
}
main();Expected Output
Analyzed 80 videos, found 30 trends
#tiktokmademebuyit | score: 245.3 | peaking
#viralproduct | score: 189.7 | peaking
#amazonfind | score: 134.2 | emerging
#kitchengadget | score: 98.4 | peaking
#dropshipping2026 | score: 76.1 | emerging