YouTube impressions decay after publish: videos peak in search visibility within days, then gradually drop as newer content competes. Tracking this decay helps creators understand their content's shelf life. This tutorial tracks search position over time using daily API queries instead of relying on YouTube Studio (which only shows your own videos).
Prerequisites
- Python 3.8+
- A Scavio API key
- Video URLs or keywords to track
Walkthrough
Step 1: Track search position for a keyword
Query YouTube search daily and record where your video ranks.
import requests, os, json
from datetime import date
H = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
def track_position(keyword: str, target_channel: str) -> dict:
resp = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'youtube', 'query': keyword}, timeout=10)
results = resp.json().get('organic', [])
for i, r in enumerate(results):
if target_channel.lower() in r.get('channel', '').lower():
return {'keyword': keyword, 'position': i + 1, 'date': date.today().isoformat(),
'title': r.get('title', ''), 'views': r.get('views', '')}
return {'keyword': keyword, 'position': None, 'date': date.today().isoformat(), 'not_found': True}Step 2: Build a daily tracking loop
Track multiple keywords daily and store position history.
from pathlib import Path
def daily_rank_track(keywords: list, channel: str) -> dict:
history_file = Path('yt_rank_history.json')
history = json.loads(history_file.read_text()) if history_file.exists() else {}
today = date.today().isoformat()
today_data = []
for kw in keywords:
position = track_position(kw, channel)
today_data.append(position)
history[today] = today_data
history_file.write_text(json.dumps(history, indent=2))
return {'date': today, 'tracked': len(keywords), 'found': sum(1 for d in today_data if d.get('position')),
'positions': today_data}Step 3: Calculate decay rate
Analyze position history to compute impression decay curves.
def calculate_decay(history: dict, keyword: str) -> dict:
positions = []
for day, data in sorted(history.items()):
for entry in data:
if entry.get('keyword') == keyword and entry.get('position'):
positions.append({'date': day, 'position': entry['position']})
if len(positions) < 2:
return {'keyword': keyword, 'insufficient_data': True}
first_pos = positions[0]['position']
last_pos = positions[-1]['position']
days_tracked = len(positions)
decay_rate = (last_pos - first_pos) / days_tracked if days_tracked > 0 else 0
return {
'keyword': keyword,
'first_position': first_pos,
'current_position': last_pos,
'days_tracked': days_tracked,
'decay_rate_per_day': round(decay_rate, 2),
'positions_lost': last_pos - first_pos,
'trend': 'declining' if decay_rate > 0.1 else 'stable' if abs(decay_rate) < 0.1 else 'improving',
}Step 4: Generate decay report
Produce a summary report of which content is decaying fastest.
def decay_report(history_file: str = 'yt_rank_history.json') -> dict:
history = json.loads(Path(history_file).read_text())
keywords = set()
for day_data in history.values():
for entry in day_data:
if entry.get('keyword'):
keywords.add(entry['keyword'])
decays = [calculate_decay(history, kw) for kw in keywords]
decays = [d for d in decays if not d.get('insufficient_data')]
decays.sort(key=lambda d: d.get('decay_rate_per_day', 0), reverse=True)
return {
'total_keywords': len(decays),
'fastest_decaying': decays[:3],
'most_stable': [d for d in decays if d.get('trend') == 'stable'],
'improving': [d for d in decays if d.get('trend') == 'improving'],
}Python Example
import requests, os, json
from datetime import date
def track_yt_rank(keyword, channel):
r = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'},
json={'platform': 'youtube', 'query': keyword}).json()
for i, v in enumerate(r.get('organic',[])):
if channel.lower() in v.get('channel','').lower():
return i + 1
return NoneJavaScript Example
async function trackYTRank(keyword, channel) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'},
body: JSON.stringify({platform: 'youtube', query: keyword})
});
const results = (await r.json()).organic || [];
const idx = results.findIndex(v => v.channel?.toLowerCase().includes(channel.toLowerCase()));
return idx >= 0 ? idx + 1 : null;
}Expected Output
A YouTube impression decay tracker that monitors search position daily and calculates decay rates per keyword, identifying content that needs refreshing.