Skip to main content

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.

Scenario

YouTube’s Most Popular chart reveals what the platform is amplifying right now — but your brand isn’t on it. This job pulls the top 50 trending videos via videos.list?chart=mostPopular, extracts their categories, tags, and descriptions, then sends the full dataset to Mave with your brand context. Mave identifies content themes that are trending but absent from your channel — gaps your brand could own with timely content. The result is a content gap report with specific video concepts ranked by opportunity size.

Architecture

Code

import os, requests

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_CONTEXT = """
Brand: [Your Brand] — DTC fitness/wellness company
Channel focus: Workout tutorials, nutrition science, product reviews
Audience: 18-35, health-conscious, 60% female, US-based
Current content gaps we suspect: trending challenges, reaction content, collaborations
"""

# 1. Fetch top 50 trending videos (1 quota unit per call)
trending = requests.get(f"{YT_BASE}/videos", params={
    "key": YT, "chart": "mostPopular",
    "part": "snippet,contentDetails,statistics,topicDetails",
    "maxResults": 50, "regionCode": "US",
}).json()

if "error" in trending:
    raise SystemExit(f"YouTube API error: {trending['error']['message']}")

videos = []
category_counts = {}
all_tags = []

for item in trending.get("items", []):
    snippet = item["snippet"]
    stats = item.get("statistics", {})
    category = snippet.get("categoryId", "0")
    tags = snippet.get("tags", [])

    category_counts[category] = category_counts.get(category, 0) + 1
    all_tags.extend(tags[:10])

    videos.append({
        "title": snippet["title"],
        "channel": snippet["channelTitle"],
        "category": category,
        "tags": tags[:10],
        "views": int(stats.get("viewCount", 0)),
        "likes": int(stats.get("likeCount", 0)),
        "description": snippet.get("description", "")[:200],
    })

# 2. Resolve category IDs to names
cat_ids = ",".join(set(category_counts.keys()))
categories = requests.get(f"{YT_BASE}/videoCategories", params={
    "key": YT, "id": cat_ids, "part": "snippet",
}).json()
cat_map = {
    item["id"]: item["snippet"]["title"]
    for item in categories.get("items", [])
}

# 3. Build trending summary
trending_block = "\n".join(
    f"- \"{v['title']}\" by {v['channel']} | Category: {cat_map.get(v['category'], v['category'])} | "
    f"Views: {v['views']:,} | Tags: {', '.join(v['tags'][:5])}"
    for v in sorted(videos, key=lambda x: -x["views"])[:30]
)

category_summary = "\n".join(
    f"- {cat_map.get(cid, cid)}: {count} videos"
    for cid, count in sorted(category_counts.items(), key=lambda x: -x[1])
)

# 4. Gap analysis via Mave
gap = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
    "message": f"""Identify content gaps between what's trending on YouTube and what our brand covers.

BRAND CONTEXT:
{BRAND_CONTEXT}

TRENDING NOW (top 30 by views):
{trending_block}

CATEGORY DISTRIBUTION:
{category_summary}

TOP TRENDING TAGS: {', '.join(set(all_tags)[:30])}

Produce:
1. **Trending themes** our brand is NOT covering (ranked by opportunity size)
2. **Specific video concepts** for each gap (title, format, estimated audience size)
3. **Cross-category opportunities** — trends in non-fitness categories our fitness brand could adapt
4. **Timing urgency** — which gaps are time-sensitive (trend peaking) vs. evergreen
5. **Risk assessment** — which trends could backfire for our brand""",
}).json()

print("TRENDING CONTENT GAP ANALYSIS")
print("=" * 60)
print(f"Analyzed: {len(videos)} trending videos across {len(category_counts)} categories")
print(f"Top categories: {', '.join(cat_map.get(c, c) for c, _ in sorted(category_counts.items(), key=lambda x: -x[1])[:5])}")
print("\n" + gap.get("content", "")[:2500])

Example Output

TRENDING CONTENT GAP ANALYSIS
============================================================
Analyzed: 50 trending videos across 12 categories
Top categories: Entertainment, Music, Sports, Gaming, People & Blogs

## Content Gaps (Ranked by Opportunity)

### 1. "Get Ready With Me" Fitness Edition (HIGH URGENCY)
- 4 trending GRWM videos, none fitness-focused
- Concept: "GRWM for a 5AM Workout" — morning routine + product integration
- Format: 8-12 min, vlog-style, trending audio
- Audience: 2.4M views on average for GRWM content this week

### 2. Reaction/Commentary on Fitness Trends (MEDIUM URGENCY)
- 6 trending reaction videos, fitness commentary absent
- Concept: "Trainer Reacts to Viral Workout Hacks" — debunk + educate
- Format: 10-15 min, split-screen reaction format
- Audience: Commentary format averages 1.8M views

### 3. Challenge Format — Adapted (EVERGREEN)
- 3 trending challenge videos, zero fitness challenges this week
- Concept: "30-Day Morning Routine Challenge" — serialized, daily uploads
- Risk: Challenge fatigue — must feel fresh, not derivative

### 4. Cross-Category: Gaming × Fitness (EXPERIMENTAL)
- Gaming dominates trending (8 videos). No gaming-fitness crossover exists
- Concept: "I Trained Like a Pro Gamer for 7 Days" — posture, nutrition, endurance
- Risk: Low — unique angle, high shareability

## Risk Assessment
- Avoid: Political commentary trending videos — brand misalignment
- Caution: Music trends — licensing complexity for brand channels

Error Handling

Without regionCode, results default to the US. Set this explicitly for non-US brands. Not all regions return 50 results.
YouTube uses numeric category IDs (e.g., 17 = Sports). The videoCategories endpoint translates these. Some categories are region-specific.
This entire job uses ~2 quota units (1 for videos.list, 1 for videoCategories). It’s the most quota-efficient job in this guide.

YouTube Integration

Mave Agent