Resumen
Collects nuevo TikTok videos posted bajo un marca hashtag diario, almacena creator y video metadata, y identifies high-engagement UGC for potential reposting o creator outreach.
Desencadenador
Diario cron at 8 AM
Programación
Diario at 8 AM (cron: 0 8 * * *)
Pasos del flujo de trabajo
Obtener hashtag video feed
POST to Scavio TikTok hashtag videos endpoint for el marca hashtag. Retrieve ultimo 50 videos con creator y engagement datos.
Filtrar for nuevo videos
Comparar returned video IDs contra el seen_videos tabla. Procesar solo videos no previously collected.
Almacenar video y creator datos
Insert video_id, titulo, author_username, author_sec_uid, view_count, like_count, comment_count, share_count, y created_at en ugc_videos tabla.
Calcular engagement tasa
Compute (likes + comentarios + shares) / views for cada nuevo video. Almacenar as engagement_rate campo.
Marcar high-engagement UGC
Mark videos con engagement_rate above 5% y view_count above 10,000 as high_priority = 1 for creator outreach o contenido approval queues.
Generar diario UGC resumen
Salida diario conteo of nuevo UGC videos, total nuevo views, y lista of high-priority creators for resena.
Implementacion en Python
import sqlite3
import requests
from datetime import date
import time
DB_PATH = "tiktok_ugc.db"
SCRAVIO_KEY = "YOUR_API_KEY"
API_BASE = "https://api.scavio.dev/api/v1/tiktok"
HEADERS = {"Authorization": f"Bearer {SCRAVIO_KEY}"}
BRAND_HASHTAG = "yourbrand"
ENGAGEMENT_THRESHOLD = 0.05
VIEW_THRESHOLD = 10000
def init_db():
conn = sqlite3.connect(DB_PATH)
conn.execute("""
CREATE TABLE IF NOT EXISTS ugc_videos (
video_id TEXT PRIMARY KEY, hashtag TEXT, author_username TEXT,
author_sec_uid TEXT, title TEXT, view_count INTEGER, like_count INTEGER,
comment_count INTEGER, share_count INTEGER, engagement_rate REAL,
high_priority INTEGER DEFAULT 0, created_at TEXT, collected_date TEXT
)
""")
conn.commit()
return conn
def fetch_hashtag_videos(hashtag: str) -> list:
resp = requests.post(
f"{API_BASE}/hashtag/videos",
headers=HEADERS,
json={"hashtag": hashtag, "count": 50}
)
resp.raise_for_status()
return resp.json().get("data", {}).get("videos", [])
def calc_engagement_rate(video: dict) -> float:
stats = video.get("stats", {})
views = stats.get("playCount", 0)
if not views:
return 0.0
interactions = stats.get("diggCount", 0) + stats.get("commentCount", 0) + stats.get("shareCount", 0)
return round(interactions / views, 4)
def run():
conn = init_db()
today = date.today().isoformat()
videos = fetch_hashtag_videos(BRAND_HASHTAG)
new_count = 0
high_priority = []
for v in videos:
vid_id = v.get("id")
if not vid_id:
continue
existing = conn.execute("SELECT 1 FROM ugc_videos WHERE video_id=?", (vid_id,)).fetchone()
if existing:
continue
stats = v.get("stats", {})
er = calc_engagement_rate(v)
views = stats.get("playCount", 0)
is_priority = 1 if (er >= ENGAGEMENT_THRESHOLD and views >= VIEW_THRESHOLD) else 0
author = v.get("author", {})
conn.execute(
"INSERT OR IGNORE INTO ugc_videos VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",
(vid_id, BRAND_HASHTAG, author.get("uniqueId"), author.get("secUid"),
v.get("desc"), views, stats.get("diggCount"), stats.get("commentCount"),
stats.get("shareCount"), er, is_priority, v.get("createTime"), today)
)
new_count += 1
if is_priority:
high_priority.append(author.get("uniqueId"))
conn.commit()
print(f"Today: {new_count} new UGC videos. High-priority creators: {high_priority}")
if __name__ == "__main__":
run()
Implementacion en JavaScript
const Database = require('better-sqlite3');
const fetch = require('node-fetch');
const DB_PATH = 'tiktok_ugc.db';
const SCRAVIO_KEY = 'YOUR_API_KEY';
const API_BASE = 'https://api.scavio.dev/api/v1/tiktok';
const HEADERS = { 'Authorization': `Bearer ${SCRAVIO_KEY}`, 'Content-Type': 'application/json' };
const BRAND_HASHTAG = 'yourbrand';
const db = new Database(DB_PATH);
db.exec(`CREATE TABLE IF NOT EXISTS ugc_videos (
video_id TEXT PRIMARY KEY, hashtag TEXT, author_username TEXT, author_sec_uid TEXT,
title TEXT, view_count INTEGER, like_count INTEGER, comment_count INTEGER, share_count INTEGER,
engagement_rate REAL, high_priority INTEGER DEFAULT 0, created_at TEXT, collected_date TEXT
)`);
async function fetchHashtagVideos(hashtag) {
const res = await fetch(`${API_BASE}/hashtag/videos`, {
method: 'POST', headers: HEADERS,
body: JSON.stringify({ hashtag, count: 50 })
});
return ((await res.json()).data?.videos) || [];
}
function calcER(v) {
const s = v.stats || {};
const views = s.playCount || 0;
if (!views) return 0;
return ((s.diggCount || 0) + (s.commentCount || 0) + (s.shareCount || 0)) / views;
}
async function run() {
const today = new Date().toISOString().slice(0, 10);
const videos = await fetchHashtagVideos(BRAND_HASHTAG);
let newCount = 0; const highPriority = [];
for (const v of videos) {
if (!v.id || db.prepare('SELECT 1 FROM ugc_videos WHERE video_id=?').get(v.id)) continue;
const er = calcER(v); const views = v.stats?.playCount || 0;
const priority = er >= 0.05 && views >= 10000 ? 1 : 0;
db.prepare('INSERT OR IGNORE INTO ugc_videos VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)').run(
v.id, BRAND_HASHTAG, v.author?.uniqueId, v.author?.secUid, v.desc,
views, v.stats?.diggCount, v.stats?.commentCount, v.stats?.shareCount,
er, priority, v.createTime, today
);
newCount++;
if (priority) highPriority.push(v.author?.uniqueId);
}
console.log(`${newCount} new UGC videos. High-priority: ${highPriority.join(', ')}`);
}
run().catch(console.error);
Plataformas utilizadas
TikTok
Descubrimiento de videos, creadores y productos en tendencia