17 KiB
Video Analytics Guide
Overview
This guide covers the setup, interpretation, and best practices for the Changemaker Lite video analytics system. The analytics platform tracks views, watch time, engagement metrics, and traffic sources while maintaining strong privacy protections.
Table of Contents
- Getting Started
- Understanding Metrics
- Interpreting Data
- Privacy & Compliance
- Best Practices
- Advanced Analytics
Getting Started
Initial Setup
1. Enable Analytics in Environment:
# .env
VIDEO_ANALYTICS_RETENTION_DAYS=90
VIDEO_ANALYTICS_IP_HASHING_ENABLED=true
2. Verify Tracking Endpoints:
# Test view recording
curl -X POST http://localhost:4100/api/track/view \
-H "Content-Type: application/json" \
-d '{"videoId": 1, "referer": "https://example.com"}'
# Should return: {"viewId": 1}
3. Check Database Tables:
-- Verify tables exist
SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public'
AND table_name LIKE 'video_%';
-- Should show:
-- video_views
-- video_events
-- video_schedule_history
Accessing Analytics
Quick Analytics (Video Card):
- Navigate to
/app/media/library - Hover over any video card
- Click "Analytics" button (bar chart icon)
- View quick stats modal
Detailed Analytics (Full Modal):
- From quick analytics, click "View Detailed Analytics"
- Or press
Akeyboard shortcut while hovering - Explore 3 tabs: Overview, Charts, Viewers
Global Dashboard:
- Navigate to
/app/media/analytics - View platform-wide statistics
- See top performing videos
- Switch between views/watch time metrics
Understanding Metrics
Core Metrics
1. Total Views
Definition: Number of times the video play button was clicked.
What it measures:
- Initial engagement
- Link/sharing effectiveness
- Thumbnail appeal
Good benchmark:
- New video: 10+ views in first 24h
- Established content: 50+ views per week
- Viral content: 500+ views in first week
Not included:
- Page loads without play
- Autoplay (if implemented)
- Repeated views from same IP within 1 hour
2. Unique Viewers
Definition: Deduplicated viewers based on IP hash (anonymous) or user ID (registered).
What it measures:
- Actual reach (not inflated by repeat views)
- Audience size
- Content discovery
Calculation:
-- Anonymous unique viewers (by IP hash)
SELECT COUNT(DISTINCT ip_address) FROM video_views
WHERE video_id = ? AND user_id IS NULL;
-- Registered unique viewers
SELECT COUNT(DISTINCT user_id) FROM video_views
WHERE video_id = ? AND user_id IS NOT NULL;
Typical ratios:
- Unique viewers / Total views: 60-80% (healthy)
- Below 50%: High repeat viewing (engagement or confusion?)
- Above 90%: Limited repeat engagement
3. Average Watch Time
Definition: Mean duration viewers spent watching the video.
What it measures:
- Content quality
- Viewer interest retention
- Optimal video length validation
Formula:
Average Watch Time = Total Watch Time Seconds / Total Views
Benchmarks by video length:
- Short (< 2 min): 70%+ of duration
- Medium (2-10 min): 50%+ of duration
- Long (> 10 min): 30%+ of duration
Red flags:
- Average < 30s on 5-min video: Poor hook
- Average < 10% of duration: Wrong audience targeting
- Average > 95%: Possible bot traffic
4. Completion Rate
Definition: Percentage of viewers who watched ≥95% of the video.
What it measures:
- Content value through to end
- Call-to-action effectiveness
- Audience match
Formula:
Completion Rate = (Completed Views / Total Views) × 100
Industry benchmarks:
- Educational content: 40-60%
- Entertainment: 30-50%
- Promotional: 20-40%
- Tutorial/How-to: 50-70%
Completion threshold: 95% (configurable in code)
5. Total Watch Time
Definition: Cumulative seconds all viewers spent watching.
What it measures:
- Overall engagement
- Platform value (YouTube-style metric)
- Content ROI
Use cases:
- Compare videos of different lengths fairly
- Calculate "watch hours" for reporting
- Prioritize content for promotion
Example:
- Video A: 100 views, 2 min avg = 200 min total
- Video B: 50 views, 5 min avg = 250 min total
- Video B has higher total watch time (better engagement)
Interpreting Data
Analytics Dashboard Tabs
Overview Tab
Stat Cards:
- Total Views: Overall reach indicator
- Unique Viewers: True audience size
- Avg Watch Time: Engagement quality
- Completion Rate: Content effectiveness
Total Watch Time Card:
- Displayed in hours/minutes format
- Secondary display shows raw seconds
- Use for comparing videos of different lengths
Top Referrers Table:
- Shows traffic sources (domains)
- Sortable by view count
- Identifies effective promotion channels
- "Direct" = no referrer (bookmarks, direct links)
Interpreting referrers:
google.com (45 views) → SEO working well
facebook.com (23 views) → Social sharing successful
example.com (12 views) → Partner site traffic
(direct) (67 views) → Email links or bookmarks
Charts Tab
Views Over Time (Area Chart):
- Last 30 days by default
- Identifies trends and spikes
- Helps correlate with marketing campaigns
Patterns to look for:
- Steady climb: Organic growth, good SEO
- Spike then drop: Campaign effect, needs sustained promotion
- Plateau: Market saturation, needs refresh
- Decline: Algorithm change, content aging
Traffic Sources Distribution (Pie Chart):
- Visual breakdown of referrer sources
- Quickly identify dominant channels
- Guide marketing budget allocation
Example interpretation:
70% Direct → Email campaign working well
15% Social → Increase social promotion
10% Search → Improve SEO
5% Other → Diversify sources
Viewers Tab
Registered Viewers Table:
- Shows logged-in users who watched
- Columns: User, Email, Watch Time, Status
- Filter by "Completed" vs "Partial"
- Sort by watch time
Use cases:
- Follow-up emails to partial viewers
- Identify super fans (high completion)
- A/B test messaging based on completion
- Segment audiences for future content
Privacy note: Only shows registered users who consented to tracking.
Global Analytics Dashboard
Platform Statistics:
- Total Videos: Content library size
- Total Views: Platform reach
- Total Watch Time: Cumulative engagement
- Avg Completion Rate: Platform-wide quality metric
Calculated Averages:
- Avg Views per Video: total views ÷ total videos
- Avg Watch Time per Video: total watch time ÷ total videos
Top Videos Table:
- Switchable metric (Views or Watch Time)
- Rank column (🥇🥈🥉 for top 3)
- Helps identify best performers
- Guide content strategy
Privacy & Compliance
GDPR Compliance
Article 6 (Lawful Basis):
- Anonymous users: Legitimate interest (analytics)
- Registered users: Explicit consent required
Article 17 (Right to be Forgotten):
- Users can request analytics deletion
- Admin can reset analytics via "Reset Analytics" button
- Deletes all views, events, and computed stats
Article 13 (Transparency):
- Disclose tracking in privacy policy
- Explain what data is collected
- How data is used (analytics only)
Data Minimization
What we collect: ✅ IP address (SHA-256 hashed) ✅ User agent (truncated) ✅ Referrer URL ✅ Watch time (seconds) ✅ Video events (play, pause, seek, complete)
What we don't collect: ❌ Exact geolocation ❌ Device fingerprints ❌ Cross-site tracking cookies ❌ Personally identifiable information (PII) for anonymous users
Retention Policy
Default Settings:
VIDEO_ANALYTICS_RETENTION_DAYS=90
Retention schedule:
- 0-90 days: Full data retained
- 90+ days: Automatically deleted (nightly job)
Configuring retention:
# Short-term (30 days)
VIDEO_ANALYTICS_RETENTION_DAYS=30
# Long-term (1 year)
VIDEO_ANALYTICS_RETENTION_DAYS=365
# Indefinite (not recommended)
VIDEO_ANALYTICS_RETENTION_DAYS=0
IP Address Hashing
How it works:
// SHA-256 hash before storage
const ipHash = crypto
.createHash('sha256')
.update(ipAddress)
.digest('hex');
// Original: 192.168.1.100
// Stored: a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e
Benefits:
- One-way: Cannot reverse to original IP
- Consistent: Same IP = same hash (deduplication works)
- Secure: Prevents IP exposure in data breaches
Limitations:
- Cannot geolocate (by design)
- Cannot block specific IPs retroactively
- Rainbow table attacks possible (but impractical)
User Consent
Best practices:
- Cookie banner: Disclose analytics tracking
- Privacy policy: Link to detailed data usage
- Opt-out option: Allow users to disable tracking
- Clear language: No legal jargon
Example consent text:
We use analytics to understand how our videos perform.
We collect anonymized view data (IP hash, watch time, referrer).
For registered users, we track which videos you watch to improve recommendations.
You can opt out in your account settings.
Best Practices
Analyzing Performance
1. Compare Similar Videos Don't compare short vs long videos using view count alone.
Good comparison:
Video A (2 min): 100 views, 80% completion
Video B (2 min): 120 views, 65% completion
→ Video A is better (higher completion despite fewer views)
Bad comparison:
Video A (2 min): 100 views
Video B (10 min): 80 views
→ Can't conclude which is better without watch time/completion
2. Track Trends, Not Absolutes Focus on improvement over time, not hitting arbitrary numbers.
Example trend analysis:
Month 1: 50 avg views/video, 40% completion
Month 2: 65 avg views/video, 45% completion
Month 3: 75 avg views/video, 50% completion
→ Positive trend! Content quality improving.
3. Identify Drop-off Points Use the VideoEvent table to find where viewers quit.
SQL Query:
-- Find common seek/pause points
SELECT
FLOOR(timestamp / 30) * 30 AS time_bucket,
COUNT(*) AS event_count,
event_type
FROM video_events
WHERE video_id = ? AND event_type IN ('pause', 'seek')
GROUP BY time_bucket, event_type
ORDER BY time_bucket;
Interpretation:
- High pause rate at 2:30 → Boring section?
- Many seeks past 1:00 → Intro too long?
- Seeks to end → Looking for conclusion?
Improving Metrics
Increase Views:
- Better thumbnails - A/B test visual appeal
- Compelling titles - Use action verbs, questions
- SEO optimization - Keywords in title/description
- Social promotion - Share on relevant platforms
- Email campaigns - Send to engaged subscribers
Increase Watch Time:
- Strong hook - First 10 seconds are critical
- Clear structure - Tell viewers what to expect
- Pacing - Remove slow sections
- Visual variety - Change scenes, graphics
- Audio quality - Poor audio = instant exit
Increase Completion Rate:
- Deliver value early - Don't save best for last
- Match length to content - Shorter often better
- Call to action - Give reason to watch to end
- End screens - Tease next video
- Remove fluff - Every second must add value
A/B Testing
Test variables one at a time:
- Thumbnails - Same video, different thumbnail
- Titles - "How to X" vs "X Explained"
- Length - 5-min vs 10-min version
- Format - Tutorial vs case study
Minimum test duration: 1 week or 100 views
Statistical significance: Use chi-square test for completion rates:
Video A: 50/100 completed (50%)
Video B: 60/100 completed (60%)
→ 10% improvement, test for significance
Reporting
Weekly Report Template:
# Video Performance Report - Week of [Date]
## Top Performers
1. [Video Title] - 500 views, 65% completion
2. [Video Title] - 400 views, 70% completion
3. [Video Title] - 350 views, 55% completion
## Platform Metrics
- Total Views: 2,500 (+15% vs last week)
- Avg Watch Time: 3:45 (+10s vs last week)
- Avg Completion: 58% (+3% vs last week)
## Traffic Sources
- Direct: 45%
- Social: 30%
- Search: 15%
- Other: 10%
## Action Items
- [ ] Improve thumbnail for [Low Performer]
- [ ] Create follow-up email for partial viewers
- [ ] Double down on Facebook promotion (highest completion)
Advanced Analytics
Custom Queries
Find your best time to publish:
SELECT
EXTRACT(DOW FROM created_at) AS day_of_week,
EXTRACT(HOUR FROM created_at) AS hour_of_day,
COUNT(*) AS view_count,
AVG(watch_time_seconds) AS avg_watch_time
FROM video_views
GROUP BY day_of_week, hour_of_day
ORDER BY view_count DESC
LIMIT 10;
Identify super fans (registered users):
SELECT
u.name,
u.email,
COUNT(DISTINCT vv.video_id) AS videos_watched,
SUM(vv.watch_time_seconds) AS total_watch_time,
AVG(vv.watch_time_seconds) AS avg_watch_time
FROM video_views vv
JOIN users u ON vv.user_id = u.id
GROUP BY u.id, u.name, u.email
HAVING COUNT(DISTINCT vv.video_id) >= 5
ORDER BY total_watch_time DESC
LIMIT 20;
Calculate retention curve:
WITH time_buckets AS (
SELECT
video_id,
view_id,
FLOOR(timestamp / 10) * 10 AS time_bucket
FROM video_events
WHERE video_id = ? AND event_type = 'complete'
)
SELECT
time_bucket,
COUNT(DISTINCT view_id) AS viewers_at_time,
(COUNT(DISTINCT view_id) * 100.0 / (
SELECT COUNT(DISTINCT id) FROM video_views WHERE video_id = ?
)) AS retention_percentage
FROM time_buckets
GROUP BY time_bucket
ORDER BY time_bucket;
Integrations
Google Analytics (Future):
- Send video events to GA4
- Track conversions from video views
- Cross-reference with site analytics
Email Marketing (Future):
- Segment users by completion rate
- Send follow-up emails to partial viewers
- Recommend similar videos based on watch history
CRM Integration (Future):
- Sync super fans to CRM
- Track video engagement per lead
- Score leads based on video views
Machine Learning Opportunities
Recommendation Engine:
- Collaborative filtering (users who watched X also watched Y)
- Content-based (similar titles, producers, duration)
- Hybrid approach
Predictive Analytics:
- Predict video performance before publishing
- Forecast future views based on trends
- Identify optimal video length per category
Anomaly Detection:
- Flag unusual spike in views (bot traffic?)
- Detect sudden drop in completion (video broken?)
- Alert on referrer spam
Troubleshooting
Low View Count
Diagnosis:
- Check if video is published (
isPublished = true) - Verify video is not scheduled for future (
scheduledPublishAt) - Review sharing/promotion efforts
- Check if thumbnail is loading
Solutions:
- Publish immediately if scheduled too far out
- Generate and share preview link
- Post to social media
- Add to email newsletter
Low Completion Rate
Diagnosis:
- Watch video yourself critically
- Check drop-off points (VideoEvent table)
- Review average watch time vs duration
- Compare to similar videos
Solutions:
- Trim intro (if drop-off < 30s)
- Add chapters/timestamps (if drop-off mid-video)
- Improve pacing (if gradual decline)
- Ensure audio quality (if sharp drop-off)
Tracking Not Working
Check list:
- ✅ Network tab shows 200 OK responses
- ✅ Rate limits not exceeded (Redis keys)
- ✅ No CORS errors in console
- ✅ videoRef.current exists before tracking
- ✅ Heartbeat interval running (check console logs)
Debug mode:
// Add to VideoViewerModal.tsx
console.log('Recording view:', { videoId: video.id });
console.log('Heartbeat sent:', { viewId, watchTimeSeconds });
Inaccurate Metrics
Common causes:
- Bot traffic - High views, low watch time
- Autoplayers - Views without intent
- Video loops - Same user, repeated views
- Test data - QA testing inflating numbers
Solutions:
- Filter views with < 5s watch time
- Exclude internal IPs (if known)
- Reset analytics for test videos
- Use unique viewers metric instead of total views
Future Roadmap
Q2 2026:
- Heatmap visualization (drop-off points)
- Exported reports (CSV, PDF)
- Email digests (weekly summaries)
Q3 2026:
- Recommendation engine
- A/B testing framework
- Advanced segmentation
Q4 2026:
- Predictive analytics
- ML-based insights
- Real-time dashboards
Resources
Documentation:
- Media Admin Features Guide
- API Documentation
- CLAUDE.md - Project overview
External Resources:
Support:
- GitHub Issues: https://github.com/anthropics/changemaker-lite/issues
- Wiki: https://wiki.changemaker-lite.org
Last Updated: February 2026 Version: 1.0 Author: Changemaker Lite Development Team