Scenario
You’re evaluating potential influencer partners for a brand campaign. Instead of relying on follower counts and CPMs, this job searches for each influencer’s recent YouTube content, runs Video Analysis on their top videos, and has Mave evaluate brand alignment across message tone, audience fit, visual style, and content quality. The result is an influencer scorecard that measures creative quality and brand fit — not vanity metrics.Architecture
Code
import os, requests, time
YT = os.environ["YOUTUBE_API_KEY"]
MV = os.environ["MAVERA_API_KEY"]
YT_BASE = "https://www.googleapis.com/youtube/v3"
MV_BASE = "https://app.mavera.io/api/v1"
MV_H = {"Authorization": f"Bearer {MV}", "Content-Type": "application/json"}
BRAND_GUIDELINES = """
Brand tone: Approachable, expert, optimistic. Never cynical or sarcastic.
Visual style: Clean, bright, modern. Avoid cluttered frames or dark aesthetics.
Audience: 25-40, professionals, health-conscious.
Deal-breakers: Profanity, controversial opinions, competitor endorsements, clickbait.
"""
INFLUENCERS = [
{"name": "FitnessCreator1", "channel_id": "UC_CHANNEL_ID_1"},
{"name": "NutritionGuru", "channel_id": "UC_CHANNEL_ID_2"},
{"name": "WellnessVlogger", "channel_id": "UC_CHANNEL_ID_3"},
]
scorecards = []
for influencer in INFLUENCERS:
# 1. Search for recent videos by channel (100 quota units)
search = requests.get(f"{YT_BASE}/search", params={
"key": YT, "channelId": influencer["channel_id"],
"type": "video", "part": "snippet",
"maxResults": 5, "order": "date",
}).json()
if not search.get("items"):
print(f"No videos found for {influencer['name']}")
continue
video_ids = [item["id"]["videoId"] for item in search["items"]]
# 2. Get video stats (1 quota unit)
details = requests.get(f"{YT_BASE}/videos", params={
"key": YT, "id": ",".join(video_ids),
"part": "snippet,statistics,contentDetails",
}).json()
video_scores = []
for video in (details.get("items") or [])[:3]:
vid_id = video["id"]
stats = video.get("statistics", {})
# 3. Upload to Mavera and analyze
upload = requests.post(f"{MV_BASE}/assets", headers=MV_H, json={
"url": f"https://www.youtube.com/watch?v={vid_id}",
"name": f"{influencer['name']} — {video['snippet']['title'][:40]}",
"type": "video",
}).json()
analysis = requests.post(f"{MV_BASE}/video-analysis", headers=MV_H, json={
"asset_id": upload["id"],
"analysis_types": [
"emotional_arc", "pacing", "visual_complexity",
"cognitive_load", "hook_score", "brand_safety",
],
}).json()
for _ in range(30):
time.sleep(3)
status = requests.get(
f"{MV_BASE}/video-analysis/{analysis['id']}", headers=MV_H
).json()
if status.get("status") == "completed":
break
r = status.get("results", {})
video_scores.append({
"title": video["snippet"]["title"][:50],
"views": int(stats.get("viewCount", 0)),
"hook": r.get("hook_score", {}).get("score", 0),
"emotion": r.get("emotional_arc", {}).get("intensity_avg", 0),
"brand_safe": r.get("brand_safety", {}).get("score", 0),
"pacing": r.get("pacing", {}).get("score", 0),
})
time.sleep(1)
# 4. Brand alignment evaluation via Mave
scores_text = "\n".join(
f"- \"{v['title']}\" — views: {v['views']:,}, hook: {v['hook']}/100, "
f"emotion: {v['emotion']:.1f}/10, brand-safe: {v['brand_safe']}/100, pacing: {v['pacing']:.1f}/10"
for v in video_scores
)
alignment = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
"message": f"""Evaluate influencer "{influencer['name']}" for brand partnership.
BRAND GUIDELINES:
{BRAND_GUIDELINES}
VIDEO ANALYSIS SCORES:
{scores_text}
Score 1-100 on:
1. Brand tone alignment
2. Visual style match
3. Audience overlap potential
4. Content quality consistency
5. Risk level (100 = lowest risk)
Overall recommendation: PARTNER / CONSIDER / PASS
Explain each score with evidence from the video analyses.""",
}).json()
avg_hook = sum(v["hook"] for v in video_scores) / len(video_scores) if video_scores else 0
avg_safe = sum(v["brand_safe"] for v in video_scores) / len(video_scores) if video_scores else 0
scorecards.append({
"name": influencer["name"],
"videos_analyzed": len(video_scores),
"avg_hook": round(avg_hook, 1),
"avg_brand_safety": round(avg_safe, 1),
"assessment": alignment.get("content", "")[:600],
})
# 5. Print scorecards
print("INFLUENCER CONTENT ANALYSIS")
print("=" * 60)
for sc in scorecards:
print(f"\n{sc['name']} ({sc['videos_analyzed']} videos analyzed)")
print(f" Avg Hook: {sc['avg_hook']}/100 | Avg Brand Safety: {sc['avg_brand_safety']}/100")
print(f" {sc['assessment'][:500]}")
const YT = process.env.YOUTUBE_API_KEY;
const MV = process.env.MAVERA_API_KEY;
const YT_BASE = "https://www.googleapis.com/youtube/v3";
const MV_BASE = "https://app.mavera.io/api/v1";
const MV_H = { Authorization: `Bearer ${MV}`, "Content-Type": "application/json" };
const BRAND_GUIDELINES = `Tone: Approachable, expert, optimistic. Never cynical.
Visual: Clean, bright, modern. Avoid clutter/dark aesthetics.
Audience: 25-40 professionals, health-conscious.
Deal-breakers: Profanity, controversial takes, competitor endorsements, clickbait.`;
const INFLUENCERS = [
{ name: "FitnessCreator1", channelId: "UC_CHANNEL_ID_1" },
{ name: "NutritionGuru", channelId: "UC_CHANNEL_ID_2" },
{ name: "WellnessVlogger", channelId: "UC_CHANNEL_ID_3" },
];
const scorecards = [];
for (const inf of INFLUENCERS) {
// 1. Recent videos (100 quota units)
const search = await fetch(
`${YT_BASE}/search?key=${YT}&channelId=${inf.channelId}&type=video&part=snippet&maxResults=5&order=date`
).then(r => r.json());
if (!search.items?.length) { console.log(`No videos: ${inf.name}`); continue; }
const videoIds = search.items.map(i => i.id.videoId);
// 2. Stats (1 quota unit)
const details = await fetch(
`${YT_BASE}/videos?key=${YT}&id=${videoIds.join(",")}&part=snippet,statistics,contentDetails`
).then(r => r.json());
const videoScores = [];
for (const video of (details.items || []).slice(0, 3)) {
const upload = await fetch(`${MV_BASE}/assets`, {
method: "POST", headers: MV_H,
body: JSON.stringify({
url: `https://www.youtube.com/watch?v=${video.id}`,
name: `${inf.name} — ${video.snippet.title.slice(0, 40)}`, type: "video",
}),
}).then(r => r.json());
const analysis = await fetch(`${MV_BASE}/video-analysis`, {
method: "POST", headers: MV_H,
body: JSON.stringify({
asset_id: upload.id,
analysis_types: ["emotional_arc", "pacing", "visual_complexity", "cognitive_load", "hook_score", "brand_safety"],
}),
}).then(r => r.json());
let status;
for (let i = 0; i < 30; i++) {
await new Promise(r => setTimeout(r, 3000));
status = await fetch(`${MV_BASE}/video-analysis/${analysis.id}`, { headers: MV_H }).then(r => r.json());
if (status.status === "completed") break;
}
const res = status.results || {};
videoScores.push({
title: video.snippet.title.slice(0, 50),
views: parseInt(video.statistics?.viewCount || "0", 10),
hook: res.hook_score?.score || 0, emotion: res.emotional_arc?.intensity_avg || 0,
brandSafe: res.brand_safety?.score || 0, pacing: res.pacing?.score || 0,
});
await new Promise(r => setTimeout(r, 1000));
}
// 4. Brand alignment
const scoresText = videoScores.map(v =>
`- "${v.title}" — views: ${v.views.toLocaleString()}, hook: ${v.hook}/100, emotion: ${v.emotion.toFixed(1)}/10, brand-safe: ${v.brandSafe}/100`
).join("\n");
const alignment = await fetch(`${MV_BASE}/mave/chat`, {
method: "POST", headers: MV_H,
body: JSON.stringify({
message: `Evaluate "${inf.name}" for partnership.\n\nBRAND:\n${BRAND_GUIDELINES}\n\nSCORES:\n${scoresText}\n\nScore 1-100: tone alignment, visual match, audience overlap, quality consistency, risk level. Recommendation: PARTNER/CONSIDER/PASS.`,
}),
}).then(r => r.json());
const avgHook = videoScores.reduce((s, v) => s + v.hook, 0) / (videoScores.length || 1);
const avgSafe = videoScores.reduce((s, v) => s + v.brandSafe, 0) / (videoScores.length || 1);
scorecards.push({
name: inf.name, videosAnalyzed: videoScores.length,
avgHook: avgHook.toFixed(1), avgBrandSafety: avgSafe.toFixed(1),
assessment: (alignment.content || "").slice(0, 600),
});
}
console.log("INFLUENCER CONTENT ANALYSIS");
console.log("=".repeat(60));
for (const sc of scorecards) {
console.log(`\n${sc.name} (${sc.videosAnalyzed} videos)`);
console.log(` Avg Hook: ${sc.avgHook}/100 | Brand Safety: ${sc.avgBrandSafety}/100`);
console.log(` ${sc.assessment.slice(0, 500)}`);
}
Example Output
INFLUENCER CONTENT ANALYSIS
============================================================
FitnessCreator1 (3 videos analyzed)
Avg Hook: 82.3/100 | Avg Brand Safety: 91.0/100
RECOMMENDATION: PARTNER
- Tone alignment: 88/100 — energetic and positive, no sarcasm
- Visual style: 85/100 — clean studio setup, bright lighting, modern graphics
- Audience overlap: 79/100 — 25-35 demo, professional tone
- Quality consistency: 90/100 — all 3 videos maintain high production value
- Risk level: 92/100 — no profanity, no controversial content found
NutritionGuru (3 videos analyzed)
Avg Hook: 71.0/100 | Avg Brand Safety: 74.0/100
RECOMMENDATION: CONSIDER
- Tone alignment: 72/100 — mostly expert tone but occasional sarcasm
- Visual style: 65/100 — kitchen setting is good but cluttered backgrounds
- Risk level: 68/100 — one video contained unverified health claims
- Action: Request content guidelines agreement before partnership
WellnessVlogger (3 videos analyzed)
Avg Hook: 45.7/100 | Avg Brand Safety: 58.0/100
RECOMMENDATION: PASS
- Tone alignment: 40/100 — cynical commentary style conflicts with brand
- Risk level: 52/100 — two videos mention competitor products favorably
Error Handling
Channel ID vs. username
Channel ID vs. username
YouTube search requires
channelId (starts with UC), not username. Use channels.list?forUsername= to resolve usernames to channel IDs if needed (costs 1 quota unit).Quota cost for multi-influencer runs
Quota cost for multi-influencer runs
Each influencer costs ~101 quota units (1 search + 1 details). Three influencers = 303 units. For 20+ influencers, batch across days or use multiple API keys.
Brand safety limitations
Brand safety limitations
Mavera’s
brand_safety analysis checks visual and audio content but cannot verify factual claims. Cross-reference health/financial claims manually for regulated industries.