Running a TikTok hashtag campaign without tracking is flying blind. You need to know: how many videos used your hashtag, total views generated, which creators drove the most engagement, and how the campaign is trending over time. This tutorial builds a hashtag campaign tracker using the Scavio TikTok API endpoints. Track campaign performance, identify top-performing content, and generate reports at $0.005 per API call.
Prerequisites
- Python 3.9+ installed
- requests library installed
- A Scavio API key from scavio.dev
- A TikTok hashtag campaign to track
Walkthrough
Step 1: Pull hashtag overview data
Use the hashtag endpoint to get the total video count and view stats for your campaign hashtag.
import os, requests, time, json
from datetime import datetime
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
TT_URL = 'https://api.scavio.dev/api/v1/tiktok'
TT_H = {'Authorization': f'Bearer {SCAVIO_KEY}', 'Content-Type': 'application/json'}
def get_hashtag_overview(hashtag: str) -> dict:
"""Get hashtag stats overview."""
resp = requests.post(f'{TT_URL}/hashtag', headers=TT_H,
json={'hashtag': hashtag})
data = resp.json().get('data', {})
challenge = data.get('challengeInfo', data)
stats = challenge.get('stats', data.get('stats', {}))
return {
'hashtag': hashtag,
'video_count': stats.get('videoCount', 0),
'view_count': stats.get('viewCount', 0),
'timestamp': datetime.now().isoformat(),
}
overview = get_hashtag_overview('tiktokmademebuyit')
print(f"Hashtag: #{overview['hashtag']}")
print(f"Videos: {overview['video_count']:,}")
print(f"Views: {overview['view_count']:,}")Step 2: Fetch and analyze campaign videos
Pull videos under your campaign hashtag. Analyze engagement rates, identify top creators, and track content themes.
def get_campaign_videos(hashtag: str, count: int = 20) -> list:
"""Get videos from a hashtag campaign."""
resp = requests.post(f'{TT_URL}/hashtag/videos', headers=TT_H,
json={'hashtag': hashtag, 'count': count, 'cursor': 0})
videos = resp.json().get('data', {}).get('videos', [])
results = []
for v in videos:
stats = v.get('stats', {})
author = v.get('author', {})
views = stats.get('playCount', 0)
likes = stats.get('diggCount', 0)
comments = stats.get('commentCount', 0)
shares = stats.get('shareCount', 0)
eng_rate = (likes + comments + shares) / views if views > 0 else 0
results.append({
'video_id': v.get('id', ''),
'description': v.get('desc', '')[:100],
'author': author.get('uniqueId', ''),
'author_followers': author.get('stats', {}).get('followerCount', 0) if isinstance(author.get('stats'), dict) else 0,
'views': views,
'likes': likes,
'comments': comments,
'shares': shares,
'engagement_rate': eng_rate,
})
results.sort(key=lambda x: x['views'], reverse=True)
return results
videos = get_campaign_videos('tiktokmademebuyit')
print(f'Campaign videos: {len(videos)}')
print('\nTop performers:')
for v in videos[:5]:
print(f' {v["views"]:>12,} views | {v["engagement_rate"]:5.1%} eng | @{v["author"]:15s} | {v["description"][:30]}')Step 3: Identify top creators and content patterns
Find which creators are driving the most campaign engagement and what content patterns work best.
def analyze_campaign_creators(videos: list) -> dict:
"""Identify top creators and content patterns."""
creator_stats = {}
for v in videos:
author = v['author']
if author not in creator_stats:
creator_stats[author] = {'videos': 0, 'total_views': 0,
'total_likes': 0, 'total_engagement': 0}
cs = creator_stats[author]
cs['videos'] += 1
cs['total_views'] += v['views']
cs['total_likes'] += v['likes']
cs['total_engagement'] += v['engagement_rate']
# Calculate averages and rank
ranked = []
for author, stats in creator_stats.items():
stats['author'] = author
stats['avg_engagement'] = stats['total_engagement'] / stats['videos'] if stats['videos'] else 0
stats['avg_views'] = stats['total_views'] / stats['videos'] if stats['videos'] else 0
ranked.append(stats)
ranked.sort(key=lambda x: x['total_views'], reverse=True)
# Engagement analysis
all_eng = [v['engagement_rate'] for v in videos]
avg_eng = sum(all_eng) / len(all_eng) if all_eng else 0
all_views = [v['views'] for v in videos]
return {
'unique_creators': len(creator_stats),
'top_creators': ranked[:10],
'avg_engagement': avg_eng,
'total_views': sum(all_views),
'avg_views': sum(all_views) / len(all_views) if all_views else 0,
}
analysis = analyze_campaign_creators(videos)
print(f"Unique creators: {analysis['unique_creators']}")
print(f"Total views: {analysis['total_views']:,}")
print(f"Avg engagement: {analysis['avg_engagement']:.1%}")
print(f"\nTop creators:")
for c in analysis['top_creators'][:5]:
print(f" @{c['author']:15s} | {c['videos']} videos | {c['total_views']:>10,} views | {c['avg_engagement']:.1%} eng")Step 4: Build the campaign tracking report
Generate a comprehensive campaign report. Track the hashtag over time by running this periodically and comparing snapshots.
TRACKING_FILE = 'campaign_tracker.json'
def load_tracking_history() -> list:
if os.path.exists(TRACKING_FILE):
with open(TRACKING_FILE) as f:
return json.load(f)
return []
def save_tracking_snapshot(snapshot: dict):
history = load_tracking_history()
history.append(snapshot)
with open(TRACKING_FILE, 'w') as f:
json.dump(history, f, indent=2)
def campaign_report(hashtag: str) -> dict:
"""Generate a full campaign tracking report."""
overview = get_hashtag_overview(hashtag)
time.sleep(0.3)
videos = get_campaign_videos(hashtag, count=20)
analysis = analyze_campaign_creators(videos)
snapshot = {
'timestamp': datetime.now().isoformat(),
'hashtag': hashtag,
'video_count': overview['video_count'],
'total_views': analysis['total_views'],
'unique_creators': analysis['unique_creators'],
'avg_engagement': analysis['avg_engagement'],
'top_creator': analysis['top_creators'][0]['author'] if analysis['top_creators'] else '',
'credits_used': 2,
'cost': 0.010,
}
save_tracking_snapshot(snapshot)
# Check growth vs previous snapshot
history = load_tracking_history()
if len(history) >= 2:
prev = history[-2]
view_growth = snapshot['total_views'] - prev.get('total_views', 0)
creator_growth = snapshot['unique_creators'] - prev.get('unique_creators', 0)
print(f'Growth since last check:')
print(f' Views: +{view_growth:,}')
print(f' Creators: +{creator_growth}')
print(f'\nCampaign Report: #{hashtag}')
print(f' Total videos: {overview["video_count"]:,}')
print(f' Sample views: {analysis["total_views"]:,} (from {len(videos)} videos)')
print(f' Unique creators: {analysis["unique_creators"]}')
print(f' Avg engagement: {analysis["avg_engagement"]:.1%}')
print(f' Top creator: @{snapshot["top_creator"]}')
print(f' Tracking cost: ${snapshot["cost"]}')
print(f' History: {len(history)} snapshots')
return snapshot
campaign_report('tiktokmademebuyit')Python Example
import os, requests, time
SCAVIO_KEY = os.environ['SCAVIO_API_KEY']
TT_H = {'Authorization': f'Bearer {SCAVIO_KEY}', 'Content-Type': 'application/json'}
def track_hashtag(hashtag):
# Hashtag overview
resp = requests.post('https://api.scavio.dev/api/v1/tiktok/hashtag', headers=TT_H,
json={'hashtag': hashtag})
stats = resp.json().get('data', {}).get('stats', {})
time.sleep(0.3)
# Recent videos
resp2 = requests.post('https://api.scavio.dev/api/v1/tiktok/hashtag/videos', headers=TT_H,
json={'hashtag': hashtag, 'count': 10, 'cursor': 0})
videos = resp2.json().get('data', {}).get('videos', [])
total_plays = sum(v.get('stats', {}).get('playCount', 0) for v in videos)
creators = len(set(v.get('author', {}).get('uniqueId', '') for v in videos))
print(f'#{hashtag}: {stats.get("videoCount", 0):,} total videos')
print(f' Recent sample: {total_plays:,} plays from {creators} creators')
track_hashtag('tiktokmademebuyit')JavaScript Example
const SCAVIO_KEY = process.env.SCAVIO_API_KEY;
const TT_H = { Authorization: `Bearer ${SCAVIO_KEY}`, 'Content-Type': 'application/json' };
async function trackHashtag(hashtag) {
const overview = await fetch('https://api.scavio.dev/api/v1/tiktok/hashtag', {
method: 'POST', headers: TT_H, body: JSON.stringify({ hashtag })
}).then(r => r.json());
const stats = overview.data?.stats || {};
const videos = await fetch('https://api.scavio.dev/api/v1/tiktok/hashtag/videos', {
method: 'POST', headers: TT_H, body: JSON.stringify({ hashtag, count: 10, cursor: 0 })
}).then(r => r.json());
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}: ${(stats.videoCount || 0).toLocaleString()} total videos`);
console.log(` Recent: ${plays.toLocaleString()} plays from ${creators} creators`);
}
trackHashtag('tiktokmademebuyit');Expected Output
Hashtag: #tiktokmademebuyit
Videos: 45,200,000
Views: 892,000,000,000
Campaign videos: 20
Top performers:
8,234,567 views | 7.2% eng | @shopqueen | This product is everything I
5,891,234 views | 5.8% eng | @dealsunder50 | Amazon finds you NEED from T
Unique creators: 18
Total views: 28,450,000
Avg engagement: 5.4%
Campaign Report: #tiktokmademebuyit
Total videos: 45,200,000
Sample views: 28,450,000 (from 20 videos)
Unique creators: 18
Avg engagement: 5.4%
Top creator: @shopqueen
Tracking cost: $0.010
History: 1 snapshots