The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"name": "15 - Live Source Run Logger (Manual)",
"nodes": [
{
"parameters": {
"content": "## WF15 \u2014 Live Source Run Logger v0.1 (DEC-126)\n\n**\u041d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:** \u0435\u0434\u0438\u043d\u044b\u0439 \u0436\u0443\u0440\u043d\u0430\u043b \u043f\u0440\u043e\u0433\u043e\u043d\u043e\u0432 live-\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0445 \u0432\u043e\u0440\u043a\u0444\u043b\u043e\u0443 \u2014 \u0432\u043a\u043b\u0430\u0434\u043a\u0430 live_source_runs (23 \u043a\u043e\u043b\u043e\u043d\u043a\u0438, docs/TABLE_SCHEMA.md). WF11/WF12/WF13 \u043f\u0438\u0448\u0443\u0442 \u0432 \u043d\u0435\u0451 \u0410\u0412\u0422\u041e\u041c\u0410\u0422\u0418\u0427\u0415\u0421\u041a\u0418 (\u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0435 \u043d\u043e\u0434\u044b). WF15 \u2014 \u0440\u0443\u0447\u043d\u043e\u0439 \u043b\u043e\u0433\u0433\u0435\u0440 \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u0435\u0432: \u043f\u0440\u043e\u0433\u043e\u043d\u044b WF09 (Avito live), \u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0431\u044d\u043a\u0444\u0438\u043b\u043b, \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 guard-\u043e\u043c \u043f\u043e\u043f\u044b\u0442\u043a\u0438, \u043f\u0440\u043e\u0433\u043e\u043d\u044b WF04 \u043f\u043e \u0441\u0430\u0439\u0442\u0430\u043c.\n\n\u041a\u0430\u0436\u0434\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442: \u0447\u0442\u043e \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u043b\u043e\u0441\u044c, \u043a\u0430\u043a\u043e\u0439 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u043e\u0438\u043b\u043e, \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0431\u0440\u0430\u043d\u043e, \u0431\u044b\u043b \u043b\u0438 \u043f\u0440\u043e\u0433\u043e\u043d \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d \u0433\u0435\u0439\u0442\u043e\u043c, \u0447\u0442\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0434\u0430\u043b\u044c\u0448\u0435.\n\n**\u041f\u0440\u0430\u0432\u0438\u043b\u0430:** $0, \u0431\u0435\u0437 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432, \u0431\u0435\u0437 Claude; \u0442\u043e\u043a\u0435\u043d\u044b \u043e\u0434\u043e\u0431\u0440\u0435\u043d\u0438\u044f \u041d\u0415 \u043b\u043e\u0433\u0438\u0440\u0443\u044e\u0442\u0441\u044f (\u0442\u043e\u043b\u044c\u043a\u043e yes/no); active=false; \u0437\u0430\u043f\u0443\u0441\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0440\u0443\u0447\u043d\u0443\u044e; MSK +03:00. \u041f\u0438\u0448\u0435\u0442 \u0422\u041e\u041b\u042c\u041a\u041e live_source_runs.",
"height": 520,
"width": 640
},
"id": "wf15-note-1",
"name": "Overview Note RU",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
-460,
-300
]
},
{
"parameters": {
"content": "## Setup & Test\n\n1. \u0421\u043e\u0437\u0434\u0430\u0442\u044c \u0432\u043a\u043b\u0430\u0434\u043a\u0443 live_source_runs (23 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0438\u0437 docs/TABLE_SCHEMA.md). \u041d\u0415 \u0430\u043a\u0442\u0438\u0432\u0438\u0440\u043e\u0432\u0430\u0442\u044c.\n2. \u0412\u0441\u0442\u0430\u0432\u0438\u0442\u044c SPREADSHEET_ID \u0438 \u043f\u0435\u0440\u0435\u043f\u0440\u0438\u0432\u044f\u0437\u0430\u0442\u044c \u043a\u0440\u0435\u0434\u0435\u043d\u0448\u043b \u043d\u0430 Append-\u043d\u043e\u0434\u0435.\n3. \u0417\u0430\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043f\u043e\u043b\u044f \u0432 Set Run Log Entry (workflow/source_family/platform/mode/\u0441\u0447\u0451\u0442\u0447\u0438\u043a\u0438/\u0441\u0442\u043e\u0438\u043c\u043e\u0441\u0442\u044c) \u043f\u043e\u0434 \u043b\u043e\u0433\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u043f\u0440\u043e\u0433\u043e\u043d.\n4. Execute once -> live_source_runs +1; Validate-\u043d\u043e\u0434\u0430 \u0431\u0440\u043e\u0441\u0430\u0435\u0442 \u043f\u043e\u043d\u044f\u0442\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443 \u043f\u0440\u0438 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0445 enum-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u0445 (mode: fixture/live/deterministic/llm_summary/blocked_by_guard; status: completed/failed/blocked/partial; source_family: classifieds/social_channel/public_discussion/public_lead_source/lead_triage/web_competitor/report_layer/other).\n5. \u041f\u043e\u0432\u0442\u043e\u0440\u043d\u044b\u0439 \u043f\u0440\u043e\u0433\u043e\u043d \u0441 \u0442\u0435\u043c\u0438 \u0436\u0435 \u043f\u043e\u043b\u044f\u043c\u0438 \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c (append-only \u0436\u0443\u0440\u043d\u0430\u043b) \u2014 run_id \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u044b\u043c.",
"height": 520,
"width": 620
},
"id": "wf15-note-2",
"name": "Setup and Test Note RU",
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
220,
-300
]
},
{
"parameters": {},
"id": "wf15-start",
"name": "Manual Start",
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
-420,
460
]
},
{
"parameters": {
"jsCode": "// OPERATOR-EDITED run log entry. Fill these fields to log one run of any live-capable workflow\n// (typically WF09 Avito live runs or guard-blocked attempts). $0, no external calls, no Claude.\nfunction moscowIsoNow(){var m=new Date(Date.now()+10800000);return m.toISOString().replace('Z','+03:00');}\nfunction moscowStamp(){var z=function(n){return String(n).padStart(2,'0');};var m=new Date(Date.now()+10800000);return m.getUTCFullYear()+z(m.getUTCMonth()+1)+z(m.getUTCDate())+'_'+z(m.getUTCHours())+z(m.getUTCMinutes())+z(m.getUTCSeconds());}\nreturn [{ json: {\n run_id:'manual_log_'+moscowStamp(), // or the original workflow run_id being logged\n created_at:moscowIsoNow(),\n workflow:'WF09 - Avito Classifieds Connector', // which workflow ran\n source_family:'classifieds', // classifieds/social_channel/public_discussion/public_lead_source/lead_triage/web_competitor/report_layer/other\n platform:'avito',\n mode:'live', // fixture/live/deterministic/llm_summary/blocked_by_guard\n approval_token_used:'yes', // yes/no \u2014 NEVER paste the token value itself\n source_allowlist:'', // queries/groups/channels/domains used\n max_items:10,\n items_received:0,\n items_relevant:0,\n items_written_raw:0,\n items_unique:0,\n items_duplicate:0,\n hard_skipped:0,\n external_calls:0,\n estimated_source_cost_usd:0,\n llm_calls:0,\n estimated_llm_cost_usd:0,\n status:'completed', // completed/failed/blocked/partial\n error_summary:'',\n operator_next_action:'',\n notes:'manually logged via WF15'\n}}];"
},
"id": "wf15-entry",
"name": "Set Run Log Entry",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
-200,
460
]
},
{
"parameters": {
"jsCode": "// Validate & normalize the run log row: enum checks + numeric coercion, so the live_source_runs tab\n// stays queryable. Throws a clear error instead of writing junk. No external calls.\nfunction str(v){return v==null?'':String(v).trim();}\nfunction num(v){var n=Number(v);return isFinite(n)?n:0;}\nconst MODES=['fixture','live','deterministic','llm_summary','blocked_by_guard'];\nconst STATUSES=['completed','failed','blocked','partial'];\nconst FAMILIES=['classifieds','social_channel','public_discussion','public_lead_source','lead_triage','web_competitor','report_layer','other'];\nconst r=$input.first().json;\nif(!str(r.run_id))throw new Error('WF15: run_id is required');\nif(!str(r.workflow))throw new Error('WF15: workflow is required');\nif(MODES.indexOf(str(r.mode))<0)throw new Error('WF15: mode must be one of '+MODES.join('/'));\nif(STATUSES.indexOf(str(r.status))<0)throw new Error('WF15: status must be one of '+STATUSES.join('/'));\nif(FAMILIES.indexOf(str(r.source_family))<0)throw new Error('WF15: source_family must be one of '+FAMILIES.join('/'));\nif(['yes','no'].indexOf(str(r.approval_token_used))<0)throw new Error('WF15: approval_token_used must be yes/no \u2014 never the token itself');\nif(/I_APPROVE/i.test(JSON.stringify(r)))throw new Error('WF15: approval token VALUE detected in the entry \u2014 remove it; log only yes/no');\nconst NUM=['max_items','items_received','items_relevant','items_written_raw','items_unique','items_duplicate','hard_skipped','external_calls','estimated_source_cost_usd','llm_calls','estimated_llm_cost_usd'];\nconst out=Object.assign({},r);\nfor(const k of NUM)out[k]=num(r[k]);\nreturn [{ json: out }];"
},
"id": "wf15-validate",
"name": "Validate Run Log Row",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
20,
460
]
},
{
"parameters": {
"authentication": "serviceAccount",
"operation": "append",
"documentId": {
"__rl": true,
"value": "PASTE_SPREADSHEET_ID",
"mode": "id"
},
"sheetName": {
"__rl": true,
"value": "live_source_runs",
"mode": "name"
},
"columns": {
"mappingMode": "autoMapInputData",
"value": {},
"matchingColumns": [],
"schema": []
},
"options": {}
},
"id": "wf15-append",
"name": "Append live_source_runs",
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.5,
"position": [
240,
460
],
"retryOnFail": true,
"maxTries": 3,
"waitBetweenTries": 5000
},
{
"parameters": {
"jsCode": "// Final summary. No external calls.\nconst r=$('Validate Run Log Row').first().json;\nreturn [{ json: { workflow:'15 - Live Source Run Logger', logged_run_id:r.run_id, logged_workflow:r.workflow, mode:r.mode, status:r.status, estimated_source_cost_usd:r.estimated_source_cost_usd, estimated_llm_cost_usd:r.estimated_llm_cost_usd, next_action:'Row appended to live_source_runs. Keep COSTS_AND_LIMITS.md in sync for paid runs.' } }];"
},
"id": "wf15-final",
"name": "Final Summary Output",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
460,
460
]
}
],
"connections": {
"Manual Start": {
"main": [
[
{
"node": "Set Run Log Entry",
"type": "main",
"index": 0
}
]
]
},
"Set Run Log Entry": {
"main": [
[
{
"node": "Validate Run Log Row",
"type": "main",
"index": 0
}
]
]
},
"Validate Run Log Row": {
"main": [
[
{
"node": "Append live_source_runs",
"type": "main",
"index": 0
}
]
]
},
"Append live_source_runs": {
"main": [
[
{
"node": "Final Summary Output",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "wf15-v002-lead-source-family-20260617"
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
15 - Live Source Run Logger (Manual). Uses googleSheets. Event-driven trigger; 7 nodes.
Source: https://github.com/CodeVinci8/vinci-ai-pilot/blob/main/n8n/workflows/15_live_source_run_logger.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
TrackCollect_deeper. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 80 nodes.
This template is ideal for solo store owners, eCommerce marketers, automation beginners, or anyone using Shopify and Gmail who wants to recover lost revenue without coding.
PCN. Uses googleSheets, httpRequest, @n-octo-n/n8n-nodes-json-database, itemLists. Event-driven trigger; 60 nodes.
Product Ad Machine. Uses googleDrive, googleSheets, httpRequest, @ffmpeg-micro/n8n-nodes-ffmpeg-micro. Event-driven trigger; 60 nodes.
Basic AI SEO KW Research n8n DataForSEO Gumroad 030125. Uses googleSheets, googleDrive, httpRequest. Event-driven trigger; 56 nodes.