> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mavera.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Influencer Content Analysis

> Evaluate influencer partners by analyzing their YouTube content for brand alignment, creative quality, and brand safety

## 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

```mermaid theme={"dark"}
flowchart LR
    A["YouTube search.list (influencer videos)"] --> B["videos.list (details)"] --> C["POST /assets + POST /video-analysis"] --> D["POST /mave/chat (brand alignment)"] --> E[Influencer scorecard]
```

## Code

<CodeGroup>
  ```python Python theme={"dark"}
  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]}")
  ```

  ```javascript JavaScript theme={"dark"}
  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)}`);
  }
  ```
</CodeGroup>

## Example Output

```text theme={"dark"}
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

<AccordionGroup>
  <Accordion title="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).</Accordion>
  <Accordion title="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.</Accordion>
  <Accordion title="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.</Accordion>
</AccordionGroup>

***

<CardGroup cols={2}>
  <Card title="YouTube Integration" icon="arrow-left" href="/integrations/youtube" />

  <Card title="Video Analysis" icon="video" href="/api-reference/video-analysis" />
</CardGroup>
