TikTok hashtag campaigns need continuous monitoring to measure reach, engagement, and creator participation. Manual checking is impractical once a campaign involves dozens of creators. This tutorial builds an automated hashtag monitoring pipeline using the Scavio TikTok API that tracks total views, new video submissions, engagement metrics, and top-performing content. Each API call costs 1 credit ($0.005), and a full campaign check uses 2-3 credits.
Prerequisites
- Python 3.9+ installed
- requests library installed
- A Scavio API key from scavio.dev
- A campaign hashtag to monitor
Walkthrough
Step 1: Get hashtag overview stats
Fetch the overall stats for your campaign hashtag: total views, total videos, and the hashtag ID. This gives you the top-level campaign metrics.
import requests, os
API_KEY = os.environ['SCAVIO_API_KEY']
TIKTOK_URL = 'https://api.scavio.dev/api/v1/tiktok'
def get_hashtag_stats(hashtag: str) -> dict:
resp = requests.post(f'{TIKTOK_URL}/hashtag',
headers={'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'},
json={'hashtag': hashtag})
resp.raise_for_status()
data = resp.json().get('data', {})
return {
'hashtag': hashtag,
'id': data.get('id', ''),
'view_count': data.get('stats', {}).get('view_count', 0),
'video_count': data.get('stats', {}).get('video_count', 0)
}
stats = get_hashtag_stats('yourcampaign')
print(f'#{stats["hashtag"]}: {stats["view_count"]:,} views, {stats["video_count"]:,} videos')Step 2: Fetch recent videos under the hashtag
Get the latest videos posted with your campaign hashtag. This shows real-time campaign activity and creator participation.
def get_hashtag_videos(hashtag: str, count: int = 30) -> list:
resp = requests.post(f'{TIKTOK_URL}/hashtag/posts',
headers={'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'},
json={'hashtag': hashtag, 'count': count, 'cursor': 0})
resp.raise_for_status()
videos = resp.json().get('data', {}).get('videos', [])
return [{
'id': v.get('id', ''),
'author': v.get('author', {}).get('uniqueId', ''),
'author_followers': v.get('author', {}).get('stats', {}).get('followerCount', 0),
'desc': v.get('desc', ''),
'plays': v.get('stats', {}).get('playCount', 0),
'likes': v.get('stats', {}).get('diggCount', 0),
'comments': v.get('stats', {}).get('commentCount', 0),
'shares': v.get('stats', {}).get('shareCount', 0),
'create_time': v.get('createTime', 0)
} for v in videos]
videos = get_hashtag_videos('yourcampaign')
print(f'Found {len(videos)} recent videos')
for v in videos[:3]:
print(f' @{v["author"]}: {v["plays"]:,} plays, {v["likes"]:,} likes')Step 3: Calculate campaign engagement metrics
Compute aggregate engagement metrics across all campaign videos: total reach, average engagement rate, and engagement distribution.
import statistics
def campaign_metrics(videos: list) -> dict:
if not videos:
return {'total_reach': 0, 'avg_engagement': 0}
total_plays = sum(v['plays'] for v in videos)
total_likes = sum(v['likes'] for v in videos)
total_comments = sum(v['comments'] for v in videos)
total_shares = sum(v['shares'] for v in videos)
eng_rates = [
(v['likes'] + v['comments'] + v['shares']) / max(v['plays'], 1) * 100
for v in videos
]
unique_creators = len(set(v['author'] for v in videos))
return {
'total_videos': len(videos),
'unique_creators': unique_creators,
'total_reach': total_plays,
'total_engagement': total_likes + total_comments + total_shares,
'avg_engagement_rate': round(statistics.mean(eng_rates), 2),
'median_engagement_rate': round(statistics.median(eng_rates), 2),
'total_likes': total_likes,
'total_comments': total_comments,
'total_shares': total_shares
}
metrics = campaign_metrics(videos)
for k, v in metrics.items():
print(f'{k}: {v:,}' if isinstance(v, int) else f'{k}: {v}')Step 4: Identify top-performing content and creators
Rank videos and creators by performance to identify your best content and most valuable campaign participants.
def top_performers(videos: list) -> dict:
# Top videos by engagement
by_engagement = sorted(videos,
key=lambda v: v['likes'] + v['comments'] + v['shares'], reverse=True)
# Top creators by total plays across their videos
creator_plays = {}
for v in videos:
creator_plays.setdefault(v['author'], 0)
creator_plays[v['author']] += v['plays']
top_creators = sorted(creator_plays.items(), key=lambda x: x[1], reverse=True)
return {
'top_videos': [{
'author': v['author'],
'plays': v['plays'],
'likes': v['likes'],
'desc': v['desc'][:60]
} for v in by_engagement[:5]],
'top_creators': [{
'username': c[0],
'total_plays': c[1]
} for c in top_creators[:5]]
}
performers = top_performers(videos)
print('Top videos:')
for v in performers['top_videos']:
print(f' @{v["author"]}: {v["plays"]:,} plays, {v["likes"]:,} likes')
print('Top creators:')
for c in performers['top_creators']:
print(f' @{c["username"]}: {c["total_plays"]:,} total plays')Step 5: Build daily monitoring with historical tracking
Save daily snapshots to track campaign growth over time. Compare today's metrics with yesterday to see daily progress.
import json
from datetime import date
def daily_campaign_report(hashtag: str) -> dict:
stats = get_hashtag_stats(hashtag)
videos = get_hashtag_videos(hashtag, count=30)
metrics = campaign_metrics(videos)
performers = top_performers(videos)
report = {
'date': date.today().isoformat(),
'hashtag': hashtag,
'overview': stats,
'metrics': metrics,
'top_performers': performers,
'credits_used': 2
}
# Save and compare with previous
history_file = f'campaign_{hashtag}_history.json'
try:
with open(history_file) as f:
history = json.load(f)
except FileNotFoundError:
history = []
history.append(report)
with open(history_file, 'w') as f:
json.dump(history, f, indent=2)
if len(history) > 1:
prev = history[-2]
view_delta = stats['view_count'] - prev['overview']['view_count']
print(f'Daily growth: +{view_delta:,} views')
print(f'Campaign #{hashtag}: {stats["view_count"]:,} total views, '
f'{metrics["unique_creators"]} creators, {metrics["avg_engagement_rate"]}% avg engagement')
return report
# daily_campaign_report('yourcampaign')Python Example
import os, requests, statistics
API_KEY = os.environ['SCAVIO_API_KEY']
TT = 'https://api.scavio.dev/api/v1/tiktok'
def tiktok(endpoint, body):
return requests.post(f'{TT}/{endpoint}',
headers={'Authorization': f'Bearer {API_KEY}', 'Content-Type': 'application/json'},
json=body).json()
def monitor_hashtag(hashtag):
stats = tiktok('hashtag', {'hashtag': hashtag}).get('data', {})
videos = tiktok('hashtag/posts', {'hashtag': hashtag, 'count': 30, 'cursor': 0})
vids = videos.get('data', {}).get('videos', [])
total_plays = sum(v.get('stats', {}).get('playCount', 0) for v in vids)
creators = len(set(v.get('author', {}).get('uniqueId', '') for v in vids))
print(f'#{hashtag}: {stats.get("stats", {}).get("view_count", 0):,} views')
print(f' Recent: {len(vids)} videos, {creators} creators, {total_plays:,} plays')
print(f' Cost: 2 credits ($0.01)')
monitor_hashtag('yourcampaign')JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY;
const TT = 'https://api.scavio.dev/api/v1/tiktok';
async function tiktokApi(endpoint, body) {
const resp = await fetch(`${TT}/${endpoint}`, {
method: 'POST',
headers: { 'Authorization': `Bearer ${API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify(body)
});
return resp.json();
}
async function monitorHashtag(hashtag) {
const stats = await tiktokApi('hashtag', { hashtag });
const videos = await tiktokApi('hashtag/posts', { hashtag, count: 30, cursor: 0 });
const vids = videos.data?.videos || [];
const plays = vids.reduce((s, v) => s + (v.stats?.playCount || 0), 0);
const creators = new Set(vids.map(v => v.author?.uniqueId)).size;
console.log(`#${hashtag}: ${vids.length} videos, ${creators} creators, ${plays.toLocaleString()} plays`);
}
monitorHashtag('yourcampaign').catch(console.error);Expected Output
#yourcampaign: 2,450,000 views, 1,234 videos
Found 30 recent videos
@creator1: 145,000 plays, 12,300 likes
@creator2: 89,000 plays, 7,800 likes
@creator3: 67,000 plays, 5,400 likes
total_videos: 30
unique_creators: 22
total_reach: 1,234,000
avg_engagement_rate: 8.45
Daily growth: +45,000 views
Cost: 2 credits ($0.01)