DEV Community

Cover image for Build a YouTube Comment Sentiment Dashboard with Node.js
Olamide Olaniyan
Olamide Olaniyan

Posted on

Build a YouTube Comment Sentiment Dashboard with Node.js

YouTubers obsess over comments.

Which is funny, because most creator tools focus on views, subscribers, and watch timeβ€”not what people are actually saying.

In this tutorial, we'll build a YouTube Comment Analyzer that:

  1. Fetches all comments from any video
  2. Analyzes sentiment and extracts themes
  3. Identifies your biggest fans (and trolls)

This is the same analysis that agencies charge creators hundreds of dollars for.

The Problem with YouTube's Data API

YouTube's API is... okay. But:

  • Rate limits that make bulk analysis painful
  • Complex OAuth setup
  • Comments are spread across multiple nested API calls

SociaVault's comments endpoint gives you everything in one call.

The Stack

  • Node.js: Runtime
  • SociaVault API: To fetch comments
  • OpenAI API: For sentiment analysis
  • Express.js: Simple web dashboard (optional)

Step 1: Setup

mkdir youtube-comment-analyzer
cd youtube-comment-analyzer
npm init -y
npm install axios openai dotenv express
Enter fullscreen mode Exit fullscreen mode

Create .env:

SOCIAVAULT_API_KEY=your_sociavault_key
OPENAI_API_KEY=your_openai_key
Enter fullscreen mode Exit fullscreen mode

Step 2: Fetch Video Comments

Create index.js:

require('dotenv').config();
const axios = require('axios');
const OpenAI = require('openai');

const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
const SOCIAVAULT_BASE = 'https://api.sociavault.com';

async function getVideoComments(videoUrl) {
  console.log('πŸ“₯ Fetching comments...');

  try {
    const response = await axios.get(`${SOCIAVAULT_BASE}/v1/scrape/youtube/video/comments`, {
      params: { url: videoUrl },
      headers: { 'Authorization': `Bearer ${process.env.SOCIAVAULT_API_KEY}` }
    });

    const comments = response.data.data || [];
    console.log(`βœ… Fetched ${comments.length} comments`);

    return comments.map(c => ({
      author: c.author || c.authorDisplayName,
      text: c.text || c.textDisplay,
      likes: c.likeCount || c.likes || 0,
      published: c.publishedAt || c.published,
      replies: c.replyCount || c.totalReplyCount || 0
    }));
  } catch (error) {
    console.error('Error fetching comments:', error.message);
    return [];
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Get Video Metadata

It helps to have context about the video itself:

async function getVideoInfo(videoUrl) {
  console.log('πŸ“₯ Fetching video info...');

  try {
    const response = await axios.get(`${SOCIAVAULT_BASE}/v1/scrape/youtube/video`, {
      params: { url: videoUrl },
      headers: { 'Authorization': `Bearer ${process.env.SOCIAVAULT_API_KEY}` }
    });

    const video = response.data.data;
    return {
      title: video.title,
      channel: video.channelTitle || video.channel,
      views: video.viewCount || video.views,
      likes: video.likeCount || video.likes,
      published: video.publishedAt
    };
  } catch (error) {
    console.error('Error fetching video info:', error.message);
    return null;
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: AI-Powered Analysis

Now the fun partβ€”let's analyze those comments:

async function analyzeComments(comments, videoTitle) {
  console.log('πŸ€– Analyzing with AI...');

  // Sample for large comment sections
  const sample = comments.slice(0, 100);

  const prompt = `
    Analyze these YouTube comments for the video "${videoTitle}".

    Return a JSON object with:
    {
      "sentiment": {
        "positive": percentage,
        "negative": percentage,
        "neutral": percentage
      },
      "themes": [top 5 themes or topics people are discussing],
      "questions": [top 3 questions viewers are asking],
      "suggestions": [top 3 content suggestions from viewers],
      "topFans": [names of 3 most engaged/positive commenters],
      "criticalFeedback": [top 3 constructive criticisms],
      "viralPotential": [3 comments that could be highlighted/pinned],
      "summary": "2-3 sentence overall analysis"
    }

    Comments:
    ${JSON.stringify(sample.map(c => ({ author: c.author, text: c.text, likes: c.likes })))}
  `;

  const completion = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: prompt }],
    response_format: { type: 'json_object' }
  });

  return JSON.parse(completion.choices[0].message.content);
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Find Video Ideas from Comments

YouTube comments are goldmines for content ideas:

async function findVideoIdeas(comments) {
  console.log('πŸ’‘ Extracting video ideas...');

  const prompt = `
    These are comments from a YouTube video. Extract potential video ideas.

    Look for:
    - Questions that could be full videos
    - Requests for related content
    - Confusion that needs clarification
    - Popular sub-topics worth expanding

    Return JSON:
    {
      "videoIdeas": [
        {
          "title": "suggested video title",
          "reason": "why this would perform well",
          "basedOn": "the comment that inspired this"
        }
      ]
    }

    Comments:
    ${JSON.stringify(comments.slice(0, 75).map(c => c.text))}
  `;

  const completion = await openai.chat.completions.create({
    model: 'gpt-4o-mini',
    messages: [{ role: 'user', content: prompt }],
    response_format: { type: 'json_object' }
  });

  return JSON.parse(completion.choices[0].message.content);
}
Enter fullscreen mode Exit fullscreen mode

Step 6: The Main Analysis Function

async function analyzeVideo(videoUrl) {
  console.log('\n🎬 YouTube Comment Analyzer\n');
  console.log('═══════════════════════════════════════\n');

  // 1. Get video info
  const video = await getVideoInfo(videoUrl);
  if (video) {
    console.log(`πŸ“Ή ${video.title}`);
    console.log(`πŸ“Ί ${video.channel}`);
    console.log(`πŸ‘οΈ ${Number(video.views).toLocaleString()} views | πŸ‘ ${Number(video.likes).toLocaleString()} likes\n`);
  }

  // 2. Get comments
  const comments = await getVideoComments(videoUrl);
  if (comments.length === 0) {
    console.log('No comments found.');
    return;
  }

  // 3. Calculate basic metrics
  const totalLikes = comments.reduce((sum, c) => sum + (c.likes || 0), 0);
  const avgLikes = (totalLikes / comments.length).toFixed(1);
  const topComment = comments.reduce((max, c) => c.likes > max.likes ? c : max, comments[0]);

  console.log(`πŸ’¬ ${comments.length} comments analyzed`);
  console.log(`❀️ ${totalLikes.toLocaleString()} total comment likes (avg: ${avgLikes})`);
  console.log(`πŸ† Top comment: "${topComment.text.substring(0, 50)}..." (${topComment.likes} likes)\n`);

  // 4. AI Analysis
  const analysis = await analyzeComments(comments, video?.title || 'Unknown');

  console.log('═══════════════════════════════════════');
  console.log('πŸ“Š SENTIMENT ANALYSIS');
  console.log('═══════════════════════════════════════\n');

  console.log(`  βœ… Positive: ${analysis.sentiment.positive}%`);
  console.log(`  😐 Neutral:  ${analysis.sentiment.neutral}%`);
  console.log(`  ❌ Negative: ${analysis.sentiment.negative}%`);

  console.log('\n🏷️ Top Themes:');
  analysis.themes.forEach((theme, i) => {
    console.log(`  ${i + 1}. ${theme}`);
  });

  console.log('\n❓ Questions from Viewers:');
  analysis.questions.forEach((q, i) => {
    console.log(`  ${i + 1}. ${q}`);
  });

  console.log('\nπŸ’‘ Content Suggestions:');
  analysis.suggestions.forEach((s, i) => {
    console.log(`  ${i + 1}. ${s}`);
  });

  console.log('\n⭐ Your Top Fans:');
  analysis.topFans.forEach((fan, i) => {
    console.log(`  ${i + 1}. ${fan}`);
  });

  console.log('\nπŸ“ Summary:', analysis.summary);

  // 5. Video Ideas (bonus)
  const ideas = await findVideoIdeas(comments);

  console.log('\n═══════════════════════════════════════');
  console.log('πŸ’‘ VIDEO IDEAS FROM COMMENTS');
  console.log('═══════════════════════════════════════\n');

  ideas.videoIdeas.forEach((idea, i) => {
    console.log(`${i + 1}. "${idea.title}"`);
    console.log(`   Why: ${idea.reason}`);
    console.log(`   Based on: "${idea.basedOn.substring(0, 50)}..."\n`);
  });

  return { video, comments, analysis, ideas };
}
Enter fullscreen mode Exit fullscreen mode

Step 7: Run It

async function main() {
  const videoUrl = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ'; // Replace with any video
  await analyzeVideo(videoUrl);
}

main();
Enter fullscreen mode Exit fullscreen mode

Sample Output

🎬 YouTube Comment Analyzer
═══════════════════════════════════════

πŸ“Ή How to Build a SaaS in 2024
πŸ“Ί TechWithTim
πŸ‘οΈ 245,892 views | πŸ‘ 12,453 likes

πŸ“₯ Fetching comments...
βœ… Fetched 847 comments
πŸ’¬ 847 comments analyzed
❀️ 5,234 total comment likes (avg: 6.2)
πŸ† Top comment: "This is exactly what I needed! Been stru..." (234 likes)

πŸ€– Analyzing with AI...

═══════════════════════════════════════
πŸ“Š SENTIMENT ANALYSIS
═══════════════════════════════════════

  βœ… Positive: 78%
  😐 Neutral:  17%
  ❌ Negative: 5%

🏷️ Top Themes:
  1. Appreciation for step-by-step format
  2. Questions about specific tech stack choices
  3. Requests for follow-up on deployment
  4. Comparisons to other tutorials
  5. Pricing and monetization questions

❓ Questions from Viewers:
  1. Can you do a video on adding Stripe integration?
  2. How does this scale with more users?
  3. What about authentication best practices?

πŸ’‘ Content Suggestions:
  1. Series on adding payment processing
  2. Deep dive into database optimization
  3. Video on marketing the finished SaaS

⭐ Your Top Fans:
  1. @CodeWithChris
  2. @DevMike
  3. @SarahCodes

πŸ“ Summary: Viewers are overwhelmingly positive about the tutorial format and pacing. The main areas of confusion center around deployment and scaling, suggesting strong demand for follow-up content.

═══════════════════════════════════════
πŸ’‘ VIDEO IDEAS FROM COMMENTS
═══════════════════════════════════════

1. "From Zero to Stripe: Adding Payments to Your SaaS"
   Why: 47 comments mentioned payment integration
   Based on: "Great video! Now how do I actually charge people..."

2. "Scaling Node.js: From 100 to 100,000 Users"
   Why: Performance questions indicate intermediate audience ready for advanced content
   Based on: "What happens when this gets real traffic..."

3. "SaaS Authentication Deep Dive (OAuth, Magic Links, Sessions)"
   Why: Authentication confusion is a clear knowledge gap
   Based on: "I'm confused about the auth part. Can you..."
Enter fullscreen mode Exit fullscreen mode

Taking It Further

1. Simple Web Dashboard

const express = require('express');
const app = express();

app.get('/analyze', async (req, res) => {
  const { url } = req.query;

  if (!url) {
    return res.status(400).json({ error: 'URL required' });
  }

  const result = await analyzeVideo(url);
  res.json(result);
});

app.listen(3000, () => {
  console.log('Dashboard running on http://localhost:3000');
});
Enter fullscreen mode Exit fullscreen mode

2. Compare Multiple Videos

async function compareVideos(urls) {
  const results = [];

  for (const url of urls) {
    const analysis = await analyzeVideo(url);
    results.push(analysis);
  }

  // Compare sentiment across videos
  console.log('\nπŸ“Š Sentiment Comparison:');
  results.forEach((r, i) => {
    console.log(`${i + 1}. ${r.video.title}`);
    console.log(`   Positive: ${r.analysis.sentiment.positive}%`);
  });

  return results;
}
Enter fullscreen mode Exit fullscreen mode

3. Automated Weekly Reports

const cron = require('node-cron');

// Run every Monday at 9am
cron.schedule('0 9 * * 1', async () => {
  const channelVideos = await getChannelVideos(channelUrl);
  const latestVideo = channelVideos[0];

  const analysis = await analyzeVideo(latestVideo.url);
  await sendEmailReport(analysis);
});
Enter fullscreen mode Exit fullscreen mode

What You Just Built

This is the core of what VidIQ and TubeBuddy charge $50+/month for.

Except:

  • You own the code
  • You can customize the analysis prompts
  • You can integrate it with your own tools
  • It costs maybe $2-5/month to run

Get Started

  1. Get your SociaVault API Key
  2. Get an OpenAI API Key
  3. Paste in any YouTube URL
  4. Start understanding your audience

Your comments section is full of gold. Start mining it.

Top comments (0)