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

# Playlist-Based Content Strategy

> Reverse-engineer competitor YouTube playlist structures to identify content themes, sequencing strategies, and exploitable gaps

## Scenario

Your competitors organize their YouTube content into playlists that reveal their content strategy — topic clusters, sequencing, and narrative arcs. This job pulls a competitor's playlists and their items, then sends the full structure to Mave for strategic analysis. Mave identifies what content themes the competitor prioritizes, how they sequence viewer journeys, and where their playlist strategy has gaps your brand could exploit. The result is a reverse-engineered content strategy with actionable recommendations.

## Architecture

```mermaid theme={"dark"}
flowchart LR
    A["YouTube playlists.list (competitor)"] --> B[playlistItems.list per playlist] --> C["POST /api/v1/mave/chat"] --> D[Content theme + sequencing analysis]
```

## Code

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

  COMPETITOR_CHANNEL_ID = "UC_COMPETITOR_CHANNEL_ID"

  # 1. Get all playlists (1 quota unit per page)
  playlists_data = requests.get(f"{YT_BASE}/playlists", params={
      "key": YT, "channelId": COMPETITOR_CHANNEL_ID,
      "part": "snippet,contentDetails", "maxResults": 25,
  }).json()

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

  playlists = []
  for pl in playlists_data.get("items", []):
      playlists.append({
          "id": pl["id"],
          "title": pl["snippet"]["title"],
          "description": pl["snippet"].get("description", "")[:200],
          "video_count": pl["contentDetails"]["itemCount"],
          "published": pl["snippet"]["publishedAt"][:10],
      })

  print(f"Found {len(playlists)} playlists")

  # 2. Get items for each playlist (1 quota unit per page per playlist)
  playlist_details = []
  for pl in playlists[:10]:
      items_data = requests.get(f"{YT_BASE}/playlistItems", params={
          "key": YT, "playlistId": pl["id"],
          "part": "snippet", "maxResults": 20,
      }).json()

      videos = []
      for item in items_data.get("items", []):
          s = item["snippet"]
          videos.append({
              "position": s["position"],
              "title": s["title"],
              "description": s.get("description", "")[:150],
          })

      playlist_details.append({
          "title": pl["title"],
          "description": pl["description"],
          "video_count": pl["video_count"],
          "published": pl["published"],
          "videos": videos,
      })

  # 3. Build playlist map for Mave
  playlist_block = ""
  for pd in playlist_details:
      playlist_block += f"\n### Playlist: \"{pd['title']}\" ({pd['video_count']} videos, created {pd['published']})\n"
      playlist_block += f"Description: {pd['description']}\n"
      playlist_block += "Videos (in order):\n"
      for v in pd["videos"]:
          playlist_block += f"  {v['position']+1}. {v['title']}\n"

  # 4. Strategic analysis via Mave
  analysis = requests.post(f"{MV_BASE}/mave/chat", headers=MV_H, json={
      "message": f"""Analyze this competitor's YouTube playlist strategy.

  COMPETITOR PLAYLISTS:
  {playlist_block}

  Produce:
  1. **Content Themes**: What topics does this competitor prioritize? Rank by investment (playlist count × video count).
  2. **Sequencing Strategy**: How do they order videos within playlists? Do they follow a learning path, chronological release, or engagement-optimized sequence?
  3. **Narrative Arcs**: Do playlists tell a story? Identify any viewer journey patterns (awareness → consideration → conversion).
  4. **Content Gaps**: What obvious topics are MISSING from their playlist strategy?
  5. **Recommendations**: 3-5 playlist concepts our brand should create to fill gaps the competitor hasn't covered.
  6. **Counter-Programming**: For each competitor playlist, suggest a playlist we could create that directly competes but differentiates.""",
  }).json()

  print("\nPLAYLIST-BASED CONTENT STRATEGY")
  print("=" * 60)
  print(f"Competitor channel: {COMPETITOR_CHANNEL_ID}")
  print(f"Playlists analyzed: {len(playlist_details)}")
  print(f"Total videos across playlists: {sum(pd['video_count'] for pd in playlist_details)}")
  print("\n" + analysis.get("content", "")[:2500])
  ```

  ```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 COMPETITOR_CHANNEL_ID = "UC_COMPETITOR_CHANNEL_ID";

  // 1. Playlists (1 quota unit)
  const playlistsData = await fetch(
    `${YT_BASE}/playlists?key=${YT}&channelId=${COMPETITOR_CHANNEL_ID}&part=snippet,contentDetails&maxResults=25`
  ).then(r => r.json());

  if (playlistsData.error) throw new Error(playlistsData.error.message);

  const playlists = (playlistsData.items || []).map(pl => ({
    id: pl.id, title: pl.snippet.title,
    description: (pl.snippet.description || "").slice(0, 200),
    videoCount: pl.contentDetails.itemCount,
    published: pl.snippet.publishedAt.slice(0, 10),
  }));

  console.log(`Found ${playlists.length} playlists`);

  // 2. Playlist items (1 quota unit per playlist)
  const playlistDetails = [];
  for (const pl of playlists.slice(0, 10)) {
    const itemsData = await fetch(
      `${YT_BASE}/playlistItems?key=${YT}&playlistId=${pl.id}&part=snippet&maxResults=20`
    ).then(r => r.json());

    const videos = (itemsData.items || []).map(item => ({
      position: item.snippet.position,
      title: item.snippet.title,
      description: (item.snippet.description || "").slice(0, 150),
    }));

    playlistDetails.push({ ...pl, videos });
  }

  // 3. Build block
  const playlistBlock = playlistDetails.map(pd => {
    const vids = pd.videos.map(v => `  ${v.position + 1}. ${v.title}`).join("\n");
    return `### Playlist: "${pd.title}" (${pd.videoCount} videos, ${pd.published})\nDescription: ${pd.description}\nVideos:\n${vids}`;
  }).join("\n\n");

  // 4. Analysis
  const analysis = await fetch(`${MV_BASE}/mave/chat`, {
    method: "POST", headers: MV_H,
    body: JSON.stringify({
      message: `Analyze competitor YouTube playlist strategy.\n\n${playlistBlock}\n\nProduce: 1) Content themes ranked by investment 2) Sequencing strategy 3) Narrative arcs 4) Content gaps 5) Our playlist recommendations 6) Counter-programming per playlist`,
    }),
  }).then(r => r.json());

  console.log("\nPLAYLIST-BASED CONTENT STRATEGY");
  console.log("=".repeat(60));
  console.log(`Playlists: ${playlistDetails.length} | Videos: ${playlistDetails.reduce((s, p) => s + p.videoCount, 0)}`);
  console.log((analysis.content || "").slice(0, 2500));
  ```
</CodeGroup>

## Example Output

```text theme={"dark"}
PLAYLIST-BASED CONTENT STRATEGY
============================================================
Competitor channel: UC_COMPETITOR_CHANNEL_ID
Playlists analyzed: 8
Total videos across playlists: 142

## Content Themes (by investment)
1. **Product Tutorials** (3 playlists, 48 videos) — heaviest investment
2. **Customer Stories** (2 playlists, 31 videos) — social proof focus
3. **Industry Trends** (1 playlist, 22 videos) — thought leadership
4. **Webinar Replays** (1 playlist, 28 videos) — repurposed live content
5. **Company Culture** (1 playlist, 13 videos) — employer branding

## Sequencing Strategy
- Tutorial playlists follow a learning path: basics → intermediate → advanced
- Customer stories are ordered by company size (SMB → Enterprise)
- Trend playlists are reverse-chronological (newest first)

## Content Gaps
1. **No comparison/vs. content** — they avoid direct competitor mentions
2. **No community content** — no user-generated or collaborative videos
3. **No Shorts playlists** — all content is 5-30min long-form
4. **No FAQ/troubleshooting** — support content is absent

## Recommended Playlists for Our Channel
1. "Us vs. [Competitor]" — Direct comparison playlist (they won't make this)
2. "60-Second Tips" — Shorts playlist filling their short-form gap
3. "Community Showcase" — Feature customer content they ignore
4. "Ask Us Anything" — FAQ format they haven't adopted
5. "Behind the Product" — Transparency content they lack
```

## Error Handling

<AccordionGroup>
  <Accordion title="Empty or private playlists">Private playlists are not returned by the API. Unlisted playlists are also hidden. The analysis only covers public content.</Accordion>
  <Accordion title="Quota cost for deep playlist scraping">Each `playlists.list` page = 1 unit, each `playlistItems.list` page = 1 unit. 10 playlists × 1 page = 11 total units. For channels with 50+ playlists, paginate with `nextPageToken` and batch across runs.</Accordion>
  <Accordion title="Playlist item limit">The `playlistItems` endpoint returns max 50 items per page. Playlists with 100+ videos need pagination. The code fetches the first 20 items per playlist — sufficient for sequencing analysis.</Accordion>
</AccordionGroup>

***

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

  <Card title="Mave Agent" icon="brain" href="/api-reference/mave" />
</CardGroup>
