n8n tutorial - Lesson 16: YouTube Performance Tracker Built in n8n
Hi everyone, in this session we build a complete YouTube Performance Tracker in n8n — an n8n analytics workflow that snapshots your channel stats weekly, calculates view and like deltas, and delivers an AI-written report straight to Telegram. This is part of the n8n Workflow Automation Tutorial series and introduces the Snapshot + Delta pattern, one of the most practical techniques for tracking lifetime-only APIs like YouTube Data API v3.
How to do:
Step 1 — Create the History Sheet
Set up a Google Sheet as an append-only history store before touching n8n — every weekly run will add rows here, never overwrite them.- Create a new Google Sheet named T5-Performance-Snapshots (Sheet ID:
1_7qk78gg2pnfAcrDN-JmuT6GXPvMQ3o84k8jqRdgsFk). - Inside the sheet, create a tab named Snapshots with exactly 5 columns:
video_id,video_title,snapshot_date,view_count,like_count. - Leave the sheet empty for now — the first workflow run will populate the first 5 rows (one per video). Each subsequent weekly run appends 5 more rows.
Note — YouTube Data API v3 only returns lifetime stats (total views, total likes since upload). There is no built-in "views this week" endpoint. The Snapshot + Delta pattern solves this: save a snapshot each week, then subtract last week's snapshot from this week's to get the weekly delta.
Step 2 — Create the Workflow and Add the Schedule Trigger
Create a new workflow namedT5-B4-Performance-Insight and configure it to run automatically every Sunday at 6 PM.
- In n8n, create a new workflow and name it
T5-B4-Performance-Insight. - Add a Schedule Trigger node. Set the Mode to Custom (Cron) and enter the expression
0 18 * * 0(Sunday at 18:00).
Step 3 — Fetch the Last Snapshots (Reference Lookup Pattern)
The first two nodes after the trigger load previous snapshot data so the workflow can calculate deltas — this is the reference lookup half of the Snapshot + Delta pattern.- Add a Google Sheets node named Get Last Snapshots. Set Operation to Get Many and point it at the Snapshots tab of your history sheet.
- Critical: Enable Always Output Data on this node. This ensures the workflow continues even when the sheet is empty (first run). Without this setting, n8n stops the chain here on week 1.
- Add a Code node named Aggregate Last. Set Mode to Run Once for All Items. Write code that:
- Iterates all snapshot rows and builds a map of
videoId → latest snapshot(sort bysnapshot_datedescending, keep only the most recent entry per video). - Outputs a single item:
{ lastMap: {...}, count: N }.
- Iterates all snapshot rows and builds a map of
Production tip — Building a videoId → snapshot map in one Code node gives you O(1) lookup in the downstream Calculate Delta node, instead of looping through all rows for every video. Always use this map pattern for cross-node lookups.
Step 4 — Fetch Current Video Stats from YouTube
Pull the latest video list and stats from YouTube Data API v3 using two HTTP Request nodes, following the same fan-out pattern used in earlier sessions of this n8n tutorial series.- Add an HTTP Request node named Get All Videos. Configure it to call the YouTube search.list endpoint with parameters:
channelId: your channel IDorder:datemaxResults:50type:video
- Add a Split Out node named Split Videos to split the returned
items[]array so each video becomes its own item. - Add another HTTP Request node named Get Video Stats. Call the YouTube videos.list endpoint with
part=snippet,statisticsand pass thevideoIdfrom each item. This fans out one HTTP call per video. - Add another Split Out node named Split Stats to unpack the stats
items[]returned per video.
Note — Always add a Split Out node after every HTTP list endpoint in n8n. The API returns an array inside a JSON object; without Split Out, downstream nodes receive one item containing the whole array instead of individual items per video.
Step 5 — Flatten Current Stats with a Code Node
Normalize the raw YouTube API response into a clean 5-field structure that matches your history sheet columns.- Add a Code node named Flatten Current. For each item, extract and return:
video_idvideo_titleview_count:parseInt()the value (API returns strings)like_count:parseInt()the valuesnapshot_date: current timestamp in ISO format (new Date().toISOString())
Tip — Always parseInt() YouTube statistics fields. The API returns view counts and like counts as strings, not numbers. If you skip this, delta calculations will produce string concatenation ("1000" + "200") instead of arithmetic.
Step 6 — Branch: Save Snapshots and Calculate Delta in Parallel
After Flatten Current, the workflow splits into two parallel branches — one saves the new snapshot, the other computes the weekly delta.- Branch A — Append New Snapshots:
- Add a Google Sheets node named Append New Snapshots.
- Set Operation to Append Row and point it at the Snapshots tab.
- Enable Auto-Map — the 5 field names from Flatten Current match the column headers exactly.
- This appends 5 new rows every Sunday, building an audit history that never overwrites past data.
- Branch B — Calculate Delta:
- Add a Code node named Calculate Delta. Set Mode to Run Once for All Items.
- Inside the code, reference the map from the lookup node:
$('Aggregate Last').first().json.lastMap. - For each current video item, look up its last snapshot in
lastMap. If no entry exists, setis_first_snapshot: trueand treatlast = 0so delta equals the current value. - Output 5 items, each containing:
video_id,video_title,current_views,last_views,delta_views,current_likes,last_likes,delta_likes,is_first_snapshot.
Production tip — The is_first_snapshot flag is essential. Without it, your AI report would say "you gained 50,000 views this week" on week 1, which is misleading — those are lifetime views. Pass this flag to the AI prompt so it can phrase the first report correctly (e.g., "baseline snapshot established").
Step 7 — Aggregate Delta Items into One AI Input
Collect the 5 per-video delta items into a single structured input object for the AI node.- Add a Code node named Build Insight Input. Set Mode to Run Once for All Items.
- Inside the code, aggregate all 5 items and output a single item containing:
videos_json: the full array of per-video delta objects (serialized as JSON string for the prompt)total_delta_view: sum of alldelta_viewstotal_delta_like: sum of alldelta_likesis_first_week:trueif any video hasis_first_snapshot: truesnapshot_date_str: formatted date string inDD/MM/YYYY
Step 8 — Generate the Weekly Report with AI
Pass the aggregated input to an AI node that writes a formatted Telegram-ready weekly performance report.- Add a Basic LLM Chain node named Performance Insight.
- Configure it:
- Model: Claude Haiku (claude-haiku-4-5 or equivalent)
- Temperature:
0.3(consistent, factual output) - Max Tokens:
2000
- Write the system/user prompt using 4 XML blocks:
<task>: instruct the AI to write a weekly YouTube performance report<telegram_markdown_legacy_syntax>: specify use of legacy Markdown (single*for bold, not**; no V2 syntax)<report_structure>: define the sections (summary, per-video breakdown, top performer, closing note)<input>: inject the dynamic values —{{$json.videos_json}},{{$json.total_delta_view}},{{$json.is_first_week}},{{$json.snapshot_date_str}}
Tip — Always use Telegram Markdown legacy syntax (single *bold*, single _italic_) in your AI prompt — not Markdown V2. Telegram's V2 mode requires escaping nearly every special character, which causes AI-generated text to break formatting unpredictably. Set Parse Mode on the Telegram node to Markdown (not MarkdownV2) to match.
Step 9 — Send the Report to Telegram
Route the AI output to your Telegram channel as the final step of the n8n analytics workflow.- Add a Telegram node named Send Weekly Report.
- Select your existing Telegram credential (reuse the personal bot credential created in earlier sessions).
- Set Parse Mode to Markdown (legacy, not V2).
- Disable Append n8n Attribution to keep the message clean.
- Map the message content to
{{$json.text}}(or the output field from the LLM Chain node).
Step 10 — Activate and Verify
Activate the workflow and confirm both branches execute correctly on the first run.- Click Active to enable the workflow. It will now run every Sunday at 18:00 automatically.
- Run a manual test execution. On the first run (empty sheet), verify:
- Get Last Snapshots outputs 0 rows but does NOT stop the chain (because Always Output Data is ON).
- Aggregate Last outputs
{ lastMap: {}, count: 0 }. - Calculate Delta produces 5 items all with
is_first_snapshot: trueanddelta = current. - Append New Snapshots writes 5 rows to the sheet.
- A Telegram message arrives with the weekly report.
- Check for the ⚠️ "Credentials for Google OAuth2 API are not set" warning icon on HTTP nodes. If the manual execution succeeds, this is a known n8n UI stale display bug — ignore it.
Note — The warning icon ⚠️ on HTTP nodes saying credentials are not set can appear even when credentials are correctly configured. Always verify by running a manual execution — if it succeeds, the credential is working and the warning is a UI rendering issue in n8n's editor.
Key Lessons from This Session
- Always Output Data: ON for reference lookups, OFF for conditional triggers. A node that fetches reference data (like snapshot history) must output an empty item if no data exists, so downstream nodes still run. A node that gates an action (like "get approved rows before sending replies") should stop the chain when empty — turn Always Output Data OFF for those.
- Snapshot + Delta is the correct pattern for lifetime-stats APIs. YouTube Data API v3 only returns total lifetime counts. Store weekly snapshots in an append-only sheet, then subtract last week from this week to derive deltas.
- Use a Code node to build a lookup map (O(1)) instead of looping. Reference
$('NodeName').first().json.mapFieldin downstream Code nodes for efficient cross-node lookups. - Handle the first-run edge case with an
is_first_snapshotflag. Without it, week 1 deltas equal lifetime totals, which produces a misleading AI report. - Always
parseInt()YouTube statistics fields. The API returns numeric values as strings; arithmetic operations will silently produce wrong results otherwise. - Add Split Out after every HTTP list endpoint. List APIs return arrays nested inside a JSON wrapper; Split Out unpacks them so each item flows through subsequent nodes individually.
- Use Telegram Markdown legacy, not V2. V2 requires escaping special characters and breaks AI-generated text; legacy single-asterisk syntax is far more reliable.
- n8n UI ⚠️ credential warnings can be stale bugs. Verify by running a manual execution — success means the credential is fine regardless of what the icon shows.
Conclusion:
In this n8n workflow automation tutorial session, we built a 12-node YouTube Performance Tracker using the Snapshot + Delta pattern — a robust solution for any API that only exposes lifetime statistics. The workflow runs automatically every Sunday, calculates weekly view and like deltas, generates an AI-written report via Claude, and delivers it to Telegram. In the next session (Session 17), we'll build a pipeline that generates SEO descriptions, hashtags, and timestamps for new videos — continuing the progression toward a fully automated YouTube channel management system in n8n.
If you have any questions, feel free to leave a comment below. Thank you!Tags: n8n analytics workflow, n8n tutorial, n8n workflow automation, YouTube automation n8n, snapshot delta pattern n8n, n8n Google Sheets integration, n8n Telegram bot, YouTube Data API n8n
Maybe you are interested!
- Getting Started with n8n: Interface & Your First Manual Trigger
- n8n HTTP Request Node: Connect Any API Without Code
- Branching Workflows: IF, Switch & Merge Nodes in n8n
- n8n Expressions & Built-in Variables: The Complete Guide
- Comparing AI Models in n8n: Claude vs Gemini vs ChatGPT
- Connect Gmail to n8n: OAuth Setup & Reading Emails
- Build an AI Email Classifier with n8n
- Automated Email Digest to Telegram with n8n
- Google Sheets Automation with n8n: 4 Key Operations
- Auto-Generate Google Docs from Data with n8n

