Documentation Index Fetch the complete documentation index at: https://contentstats.io/docs/llms.txt
Use this file to discover all available pages before exploring further.
Why Track Hourly Instead of Daily?
Most analytics tools update daily. ContentStats.io provides hourly snapshots , giving you 24× more data points and critical advantages.
Benefits of Hourly Tracking
Catch Viral Moments Detect when content goes viral within hours, not days
Granular Growth Data See exactly when and how your content gains traction
Optimize Posting Times Discover the exact hours when your audience is most active
Daily vs Hourly Tracking Comparison
Metric Daily Tracking Hourly Tracking Data Points 7 per week 168 per week Viral Detection 24+ hours delay Real-time Cost Optimization Can’t stop early Stop when needed Algorithm Insights Limited Detailed
Real-World Examples
Example 1: Catching Viral Moments
Daily Tracking:
Day 1: 10,000 views
Day 2: 500,000 views ← Went viral sometime yesterday
Day 3: 750,000 views
Result : You don’t know when it went viral or why.
Hourly Tracking:
Hour 1: 10,000 views
Hour 2: 12,000 views
Hour 3: 15,000 views
...
Hour 16: 45,000 views
Hour 17: 250,000 views ← Viral moment detected!
Hour 18: 400,000 views
Result : You know it went viral at 5 PM. Check what happened at that exact time!
Use Cases Perfect for Hourly Tracking
1. Product Launches
Track minute-by-minute performance:
async function trackProductLaunch ( launchVideos ) {
// Start tracking all launch videos
const tracked = await Promise . all (
launchVideos . map ( url => trackVideo ( url , 7 ))
);
// Check every hour for viral potential
const checkInterval = setInterval ( async () => {
for ( const video of tracked ) {
const data = await getVideo ( video . id );
const latest = data . snapshots [ data . snapshots . length - 1 ];
const hourAgo = data . snapshots [ data . snapshots . length - 2 ];
const hourlyGrowth = parseInt ( latest . views ) - parseInt ( hourAgo . views );
if ( hourlyGrowth > 10000 ) { // Viral threshold
console . log ( '🔥 VIRAL ALERT:' , data . video_link );
console . log ( 'Hourly growth:' , hourlyGrowth , 'views' );
// Boost paid promotion
await boostPromotion ( data . video_link );
}
}
}, 60 * 60 * 1000 ); // Check hourly
}
2. Influencer Campaign Monitoring
Verify influencers deliver results in real-time:
async function monitorInfluencerPost ( videoId , expectedHourlyViews ) {
const video = await getVideo ( videoId );
const snapshots = video . snapshots ;
if ( snapshots . length < 2 ) return ;
const latest = snapshots [ snapshots . length - 1 ];
const hourAgo = snapshots [ snapshots . length - 2 ];
const actualGrowth = parseInt ( latest . views ) - parseInt ( hourAgo . views );
if ( actualGrowth < expectedHourlyViews * 0.5 ) {
// Underperforming - alert immediately
await sendAlert ({
type: 'underperforming' ,
influencer: video . current_metadata . creator ,
expected: expectedHourlyViews ,
actual: actualGrowth ,
hoursPassed: snapshots . length
});
}
}
3. Algorithm Testing
Test how platform algorithms respond to your content:
function analyzeAlgorithmBoost ( snapshots ) {
const boostPatterns = [];
for ( let i = 1 ; i < snapshots . length ; i ++ ) {
const current = parseInt ( snapshots [ i ]. views );
const previous = parseInt ( snapshots [ i - 1 ]. views );
const growth = current - previous ;
// Calculate average growth excluding current hour
const avgGrowth = snapshots
. slice ( 0 , i )
. reduce (( sum , s , idx , arr ) => {
if ( idx === 0 ) return sum ;
return sum + ( parseInt ( arr [ idx ]. views ) - parseInt ( arr [ idx - 1 ]. views ));
}, 0 ) / ( i - 1 );
// Detect algorithm boost (2x average growth)
if ( growth > avgGrowth * 2 ) {
boostPatterns . push ({
hour: i ,
time: snapshots [ i ]. snapshot_time ,
growth: growth ,
multiplier: ( growth / avgGrowth ). toFixed ( 1 ) + 'x'
});
}
}
return boostPatterns ;
}
// Example output:
// [
// { hour: 12, time: '2024-01-29T12:00:00Z', growth: 15000, multiplier: '2.5x' },
// { hour: 18, time: '2024-01-29T18:00:00Z', growth: 12000, multiplier: '2.0x' }
// ]
// Insight: Algorithm boost at 12 PM and 6 PM
4. Competitive Response
React to competitor activity immediately:
async function monitorCompetitorLaunch ( competitorVideos ) {
const trackedCompetitors = await Promise . all (
competitorVideos . map ( url => trackVideo ( url , 3 ))
);
// Check every hour
setInterval ( async () => {
for ( const comp of trackedCompetitors ) {
const data = await getVideo ( comp . id );
if ( data . snapshots . length >= 2 ) {
const latest = data . snapshots [ data . snapshots . length - 1 ];
const previous = data . snapshots [ data . snapshots . length - 2 ];
const growth = parseInt ( latest . views ) - parseInt ( previous . views );
if ( growth > 50000 ) { // High performing
// Competitor content performing well - analyze and respond
await analyzeCompetitorStrategy ( data );
await createResponseContent ( data . current_metadata );
}
}
}
}, 60 * 60 * 1000 );
}
Insights Only Possible with Hourly Data
1. Peak Engagement Hours
function findPeakHours ( snapshots ) {
const hourlyEngagement = snapshots . map (( snapshot , i ) => {
if ( i === 0 ) return null ;
const previous = snapshots [ i - 1 ];
const hour = new Date ( snapshot . snapshot_time ). getHours ();
return {
hour: hour ,
engagementGrowth : (
( parseInt ( snapshot . likes ) - parseInt ( previous . likes )) +
( parseInt ( snapshot . comments ) - parseInt ( previous . comments ))
)
};
}). filter ( Boolean );
// Group by hour of day
const hourlyAvg = {};
hourlyEngagement . forEach ( entry => {
if ( ! hourlyAvg [ entry . hour ]) {
hourlyAvg [ entry . hour ] = [];
}
hourlyAvg [ entry . hour ]. push ( entry . engagementGrowth );
});
// Calculate averages
const avgByHour = Object . keys ( hourlyAvg ). map ( hour => ({
hour: parseInt ( hour ),
avgEngagement: hourlyAvg [ hour ]. reduce (( a , b ) => a + b ) / hourlyAvg [ hour ]. length
})). sort (( a , b ) => b . avgEngagement - a . avgEngagement );
return avgByHour . slice ( 0 , 3 ); // Top 3 hours
}
// Example output:
// [
// { hour: 18, avgEngagement: 1250 }, // 6 PM best
// { hour: 12, avgEngagement: 980 }, // 12 PM second
// { hour: 21, avgEngagement: 870 } // 9 PM third
// ]
2. Content Half-Life
How long does content stay relevant?
function calculateContentHalfLife ( snapshots ) {
const peakSnapshot = snapshots . reduce (( max , s ) => {
const maxGrowth = max . growth || 0 ;
const currentGrowth = parseInt ( s . views );
return currentGrowth > maxGrowth ? { ... s , growth: currentGrowth } : max ;
}, {});
const peakIndex = snapshots . indexOf ( peakSnapshot );
const peakViews = parseInt ( peakSnapshot . views );
// Find when views drop to 50% of peak growth rate
for ( let i = peakIndex + 1 ; i < snapshots . length ; i ++ ) {
const current = snapshots [ i ];
const previous = snapshots [ i - 1 ];
const currentGrowth = parseInt ( current . views ) - parseInt ( previous . views );
const peakGrowth = peakViews - ( peakIndex > 0 ? parseInt ( snapshots [ peakIndex - 1 ]. views ) : 0 );
if ( currentGrowth < peakGrowth * 0.5 ) {
return {
peakHour: peakIndex ,
halfLifeHours: i - peakIndex ,
message: `Content peaked at hour ${ peakIndex } , half-life reached after ${ i - peakIndex } hours`
};
}
}
return { message: 'Content still growing' };
}
3. Viral Velocity Score
Measure how fast content goes viral:
function calculateViralVelocity ( snapshots ) {
const velocities = [];
for ( let i = 1 ; i < Math . min ( snapshots . length , 25 ); i ++ ) { // First 24 hours
const current = parseInt ( snapshots [ i ]. views );
const initial = parseInt ( snapshots [ 0 ]. views );
const totalGrowth = current - initial ;
const velocityScore = totalGrowth / i ; // Views per hour
velocities . push ( velocityScore );
}
const avgVelocity = velocities . reduce (( a , b ) => a + b ) / velocities . length ;
// Classify viral potential
let classification ;
if ( avgVelocity > 10000 ) classification = '🔥 VIRAL' ;
else if ( avgVelocity > 5000 ) classification = '📈 HIGH POTENTIAL' ;
else if ( avgVelocity > 1000 ) classification = '✅ GOOD' ;
else classification = '📊 NORMAL' ;
return {
avgVelocity: Math . round ( avgVelocity ),
classification ,
viewsPerHour: Math . round ( avgVelocity )
};
}
Cost Efficiency
Hourly tracking lets you stop early when you have enough data:
async function trackUntilConfident ( videoUrl , maxDays = 7 ) {
const tracking = await trackVideo ( videoUrl , maxDays );
// Check every hour
const checkInterval = setInterval ( async () => {
const video = await getVideo ( tracking . id );
// Stop if we have 48 hours of data and clear pattern
if ( video . snapshots . length >= 48 ) {
const velocity = calculateViralVelocity ( video . snapshots );
// Clear conclusion reached
if ( velocity . classification === '🔥 VIRAL' ||
velocity . classification === '📊 NORMAL' ) {
await stopVideo ( tracking . id );
clearInterval ( checkInterval );
console . log ( 'Stopped early - conclusion:' , velocity . classification );
console . log ( 'Saved:' , maxDays - 2 , 'days of tracking costs' );
}
}
}, 60 * 60 * 1000 );
}
Best Practices
Data updates hourly, so don’t poll more frequently: // ✅ Good: Check hourly
setInterval ( checkVideo , 60 * 60 * 1000 );
// ❌ Bad: Wastes API calls
setInterval ( checkVideo , 5 * 60 * 1000 );
Store Historical Snapshots
Build your own database of performance patterns: async function archiveSnapshots ( videoId ) {
const video = await getVideo ( videoId );
await db . snapshots . insertMany (
video . snapshots . map ( s => ({
... s ,
videoId: video . id ,
platform: video . platform ,
archivedAt: new Date ()
}))
);
}
Hourly data creates beautiful, insightful charts: // Perfect for Chart.js, Recharts, etc.
const chartData = snapshots . map ( s => ({
time: new Date ( s . snapshot_time ). toLocaleTimeString (),
views: parseInt ( s . views ),
likes: parseInt ( s . likes )
}));
Next Steps
Real-Time Analytics Build real-time dashboards
Automate Analytics Set up automated tracking
Track Videos Start tracking hourly
Quickstart Get started now