Lesson 4 · Social Media Content Analytics
Social Media Analytics Workflow Using Python
Learn to solve real social media analytics problems step by step. Discover which metrics matter for content creators and businesses. Build insights from…
- CourseSocial Media Content Analytics
- Lesson4 of 41
- Video24 min
- FormatJupyter notebook · 15 code cells
What you'll learn
- Key Social Media Analytics Concepts and Metrics
- Beginner Example 1: Calculate Engagement Rate by Platform
- Beginner Example 2: Identify Top 5 Most Liked Posts Across Platforms
- Beginner Example 3: Find Most Commented Platform
- Intermediate Example 1: Analyze Engagement by Posting Hour
- Intermediate Example 2: Compare Top YouTube Category Engagement
- Intermediate Example 3: Viral Content Detection by Outlier Engagement
- Advanced Example 1: Time Series Analysis of Daily Social Media Growth
Data
No separate download needed — the notebook creates or downloads everything it uses.
📓 Full notebook
Download .ipynbSocial Media Analytics Workflow Using Python#
- Learn to solve real social media analytics problems step by step.
- Discover which metrics matter for content creators and businesses.
- Build insights from engagement metrics, trends, and content performance.
- By the end, you will make data-driven recommendations to optimize your content strategy.
import pandas as pd
import numpy as np
import warnings
warnings.filterwarnings('ignore')
Key Social Media Analytics Concepts and Metrics#
- Social media datasets contain posts, videos, engagement, and platform data.
- Metrics like views, likes, comments, click-through rate, and watch time reflect audience behavior.
- Engagement rate shows how often viewers interact with your content.
- Beginners often mistake high views for success or forget relative engagement.
- Correct interpretation of ratios and groupings is critical for insight.
# Load core engagement dataset for multi-platform analysis
np.random.seed(42)
n_posts = 500
views = np.random.randint(100, 100000, n_posts)
df_content = pd.DataFrame({
'post_id': range(1, n_posts+1),
'platform': np.random.choice(['YouTube','Instagram','TikTok'], n_posts),
'date': pd.date_range('2023-01-01', periods=n_posts, freq='6h'),
'views': views,
'likes': (views * np.random.uniform(0.02, 0.15, n_posts)).astype(int),
'comments': (views * np.random.uniform(0.001, 0.05, n_posts)).astype(int),
'shares': (views * np.random.uniform(0.001, 0.03, n_posts)).astype(int)
})
print(df_content.head(3))
# Load YouTube-specific trending videos dataset
try:
from pathlib import Path
import os, pickle
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
SCOPES = ['https://www.googleapis.com/auth/youtube.readonly']
def get_yt_service():
api_key = os.environ.get('YOUTUBE_API_KEY')
if api_key:
return build('youtube', 'v3', developerKey=api_key)
if Path('client_secret.json').exists():
creds = None
if Path('token_ro.pickle').exists():
with open('token_ro.pickle', 'rb') as f:
creds = pickle.load(f)
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file('client_secret.json', SCOPES)
creds = flow.run_local_server(port=0)
with open('token_ro.pickle', 'wb') as f:
pickle.dump(creds, f)
return build('youtube', 'v3', credentials=creds)
raise EnvironmentError('Set YOUTUBE_API_KEY or provide client_secret.json')
def fetch_yt_trending(max_results=200, region='US'):
youtube = get_yt_service()
records, token = [], None
while len(records) < max_results:
resp = youtube.videos().list(
part='snippet,statistics',
chart='mostPopular',
regionCode=region,
maxResults=min(50, max_results - len(records)),
pageToken=token
).execute()
for item in resp.get('items', []):
s = item['snippet']; st = item.get('statistics', {})
records.append({
'video_id': item['id'],
'trending_date': pd.Timestamp.today().date(),
'title': s.get('title', ''),
'channel_title': s.get('channelTitle', ''),
'category_id': s.get('categoryId', ''),
'views': int(st.get('viewCount', 0)),
'likes': int(st.get('likeCount', 0)),
'comment_count': int(st.get('commentCount', 0)),
})
token = resp.get('nextPageToken')
if not token: break
return pd.DataFrame(records)
df_trending = fetch_yt_trending()
print('Live trending data:', df_trending.shape)
except Exception as e:
print(f'Falling back to synthetic: {e}')
np.random.seed(42)
n = 1000
df_trending = pd.DataFrame({
'video_id': [f'vid{i}' for i in range(n)],
'trending_date': pd.date_range('2023-01-01', periods=n, freq='D'),
'title': [f'Video Title {i}' for i in range(n)],
'channel_title': np.random.choice(['ChannelA','ChannelB','ChannelC'], n),
'category_id': np.random.choice([1,2,10,22,24,28], n),
'views': np.random.randint(10000, 5000000, n),
'likes': np.random.randint(100, 200000, n),
'comment_count': np.random.randint(10, 50000, n),
})
print('Synthetic fallback:', df_trending.shape)
print(df_trending.head(3))
Beginner Example 1: Calculate Engagement Rate by Platform#
- Engagement rate = (likes + comments + shares) / views
- This metric shows how actively audiences interact with content.
- Higher engagement means more loyal or interested viewers.
df_content['engagement_rate'] = ((df_content['likes'] + df_content['comments'] + df_content['shares']) / df_content['views']) * 100
platform_engagement = df_content.groupby('platform')['engagement_rate'].mean().sort_values(ascending=False)
print('Average Engagement Rate by Platform (%):\n', platform_engagement.round(2))
Beginner Example 2: Identify Top 5 Most Liked Posts Across Platforms#
- Sorting by likes helps pinpoint posts that resonate strongly with audiences.
- This is often a key early discovery step for content improvement.
top5_likes = df_content.sort_values('likes', ascending=False).head(5)
print(top5_likes[['post_id', 'platform', 'likes', 'views', 'engagement_rate']])
Beginner Example 3: Find Most Commented Platform#
- Comments often indicate deeper engagement or discussion.
- Which platform sparks the most conversations?
platform_comments = df_content.groupby('platform')['comments'].sum()
most_discussed = platform_comments.idxmax()
print(f'Most discussed platform: {most_discussed} with {platform_comments[most_discussed]:,} comments')
Intermediate Example 1: Analyze Engagement by Posting Hour#
- When you post matters. Analyze patterns by hour-of-day.
- Content posted during peak audience times often performs better.
df_content['hour'] = df_content['date'].dt.hour
hourly_engagement = df_content.groupby('hour')['engagement_rate'].mean()
peak_hour = hourly_engagement.idxmax()
print('Average engagement rate by posting hour (%)')
print(hourly_engagement.round(2))
print(f'Best posting hour: {peak_hour}:00 with {hourly_engagement[peak_hour]:.2f}% average engagement')
Intermediate Example 2: Compare Top YouTube Category Engagement#
- Identify which YouTube content categories perform best.
- This informs content strategy decisions at the topic level.
category_means = df_trending.groupby('category_id')[['views','likes','comment_count']].mean()
category_means['engagement_rate'] = ((category_means['likes'] + category_means['comment_count']) / category_means['views']) * 100
top_cat = category_means['engagement_rate'].idxmax()
print('YouTube category engagement rate (mean, %):')
print(category_means[['engagement_rate']].sort_values('engagement_rate', ascending=False))
print(f'Highest average engagement: Category {top_cat}')
Intermediate Example 3: Viral Content Detection by Outlier Engagement#
- Viral posts tend to have much higher engagement than usual.
- Let us flag posts with engagement rate well above the dataset average.
er_mean = df_content['engagement_rate'].mean()
er_std = df_content['engagement_rate'].std()
viral_threshold = er_mean + 2 * er_std
viral_posts = df_content[df_content['engagement_rate'] > viral_threshold]
print(f'Number of viral posts: {len(viral_posts)}')
print('Sample viral posts:')
print(viral_posts[['post_id','platform','views','likes','engagement_rate']].head())
Advanced Example 1: Time Series Analysis of Daily Social Media Growth#
- Understanding how views and engagement change over time reveals content strategy strengths.
- Let us analyze trends using a simulated daily time series.
np.random.seed(42)
n_days = 365
dates = pd.date_range('2023-01-01', periods=n_days, freq='D')
views = np.random.randint(1000, 50000, n_days)
likes = (views * np.random.uniform(0.03, 0.12, n_days)).astype(int)
df_daily = pd.DataFrame({
'date': dates,
'views': views,
'likes': likes,
'engagement_rate': np.round(likes / views * 100, 2)
})
rolling_views = df_daily['views'].rolling(7).mean()
rolling_eng = df_daily['engagement_rate'].rolling(7).mean()
print('Recent weekly average views:', rolling_views.tail(1).values[0])
print('Recent weekly average engagement rate:', rolling_eng.tail(1).values[0])
Advanced Example 2: Audience Segment Insights#
- Segment your audience by platform and hour to personalize strategies.
- Segmented insights often unlock growth that is invisible in overall means.
segment = df_content.groupby(['platform','hour'])['engagement_rate'].mean().unstack()
best_segments = segment.max(axis=1).sort_values(ascending=False)
print('Platform/hour with highest engagement:')
print(best_segments.head())
Advanced Example 3: Correcting Engagement Calculations When Data Is Missing#
- Real-world data may contain missing values in likes, comments, or shares.
- Never let a missing value turn into skewed aggregate metrics.
# Simulate missing likes and shares for random posts
df_content_missing = df_content.copy()
df_content_missing.loc[df_content_missing.sample(frac=0.05, random_state=42).index, 'likes'] = np.nan
df_content_missing.loc[df_content_missing.sample(frac=0.03, random_state=1).index, 'shares'] = np.nan
# Fill missing with zero
df_content_missing[['likes','shares']] = df_content_missing[['likes','shares']].fillna(0)
df_content_missing['engagement_rate'] = ((df_content_missing['likes'] + df_content_missing['comments'] + df_content_missing['shares']) / df_content_missing['views']) * 100
avg_eng_missing = df_content_missing['engagement_rate'].mean()
print(f'Average engagement rate with missing data handled: {avg_eng_missing:.2f}%')
Best Practices: Common Patterns in Social Media Analytics#
- Benchmark against your past content, not just averages.
- Always segment by audience or timing to spot hidden trends.
- Keep metric definitions consistent across teams.
- Use rolling statistics and outlier detection to monitor growth and viral events.
- Test content optimizations iteratively.
# Consistent metric benchmarking example (YouTube trending dataset)
latest_date = df_trending['trending_date'].max()
recent = df_trending[df_trending['trending_date'] > latest_date - pd.Timedelta(days=7)]
historical = df_trending[df_trending['trending_date'] <= latest_date - pd.Timedelta(days=7)]
recent_mean = recent['views'].mean()
historical_mean = historical['views'].mean()
change = ((recent_mean - historical_mean) / historical_mean) * 100 if historical_mean > 0 else np.nan
print(f'Average trending video views last 7 days: {recent_mean:.0f}')
print(f'Previous period: {historical_mean:.0f}')
print(f'Change vs previous period: {change:.2f}%')
Common Analytics Error Example: Wrongly Aggregated Engagement Data#
- A common error is to average numerator and denominator before dividing.
- Always sum or average after calculating ratios per-row.
# Wrong way: Averaging likes and views separately, then dividing
wrong_engagement = (df_content['likes'].mean() + df_content['comments'].mean() + df_content['shares'].mean()) / df_content['views'].mean() * 100
# Right way: Mean of the engagement rate we already calculated
right_engagement = df_content['engagement_rate'].mean()
print(f'Wrongly computed engagement rate: {wrong_engagement:.2f}%')
print(f'Proper engagement rate (mean of per-post): {right_engagement:.2f}%')
End-to-End Analytics Task: Make a Content Strategy Recommendation#
- Let us go from raw data to an actionable recommendation for improving engagement.
- Identify your best content type and ideal posting hour in one workflow.
summary = df_content.groupby(['platform','hour'])['engagement_rate'].mean().unstack()
best_platform = summary.mean(axis=1).idxmax()
best_hour = summary.loc[best_platform].idxmax()
print(f'Optimal platform for engagement: {best_platform}')
print(f'Best hour to post on {best_platform}: {best_hour}:00')
print(f'Recommendation: Focus content on {best_platform} around {best_hour}:00 hour to maximize audience interaction.')
Continue Learning: Explore More Analytics and Visualization#
- Try creating charts of engagement trends over time.
- Look at platform-specific insights.
- Check out more examples and tutorials on YouTube for hands-on guidance.
Found this useful?
All lessons, notebooks and datasets here are free. If they helped you, a coffee keeps new lessons coming.



