AutomationFlowsWeb Scraping › Weekly Summary

Weekly Summary

40_435_WEEKLY_SUMMARY. Uses httpRequest. Scheduled trigger; 7 nodes.

Cron / scheduled trigger★★★★☆ complexity7 nodesHTTP Request
Web Scraping Trigger: Cron / scheduled Nodes: 7 Complexity: ★★★★☆ Added:

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 →

Download .json
{
  "name": "40_435_WEEKLY_SUMMARY",
  "nodes": [
    {
      "id": "435-schedule",
      "name": "Every Monday 09:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        200,
        400
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * 1"
            }
          ]
        }
      }
    },
    {
      "id": "435-fetch-pieces",
      "name": "Fetch Content Pieces",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        200
      ],
      "parameters": {
        "method": "GET",
        "url": "https://directus.automation-plus-ki.de/items/330_knowledge_items",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer ={{ $env.DIRECTUS_TOKEN }}"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "limit",
              "value": "100"
            },
            {
              "name": "sort",
              "value": "-created_at"
            }
          ]
        },
        "options": {
          "timeout": 10000
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "435-fetch-pipeline",
      "name": "Fetch Pipeline Jobs",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        360
      ],
      "parameters": {
        "method": "GET",
        "url": "https://directus.automation-plus-ki.de/items/400_content_pipeline",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer ={{ $env.DIRECTUS_TOKEN }}"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "limit",
              "value": "100"
            },
            {
              "name": "sort",
              "value": "-created_at"
            }
          ]
        },
        "options": {
          "timeout": 10000
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "435-fetch-executions",
      "name": "Fetch n8n Executions",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        520
      ],
      "parameters": {
        "method": "GET",
        "url": "http://10.0.1.16:5678/api/v1/executions",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-N8N-API-KEY",
              "value": "={{ $env.N8N_API_KEY }}"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "limit",
              "value": "100"
            }
          ]
        },
        "options": {
          "timeout": 10000
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "435-fetch-opportunities",
      "name": "Fetch Content Opportunities",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        440,
        680
      ],
      "parameters": {
        "method": "GET",
        "url": "https://directus.automation-plus-ki.de/items/320_content_opportunities",
        "authentication": "none",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer ={{ $env.DIRECTUS_TOKEN }}"
            }
          ]
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "limit",
              "value": "20"
            },
            {
              "name": "sort",
              "value": "-created_at"
            }
          ]
        },
        "options": {
          "timeout": 10000
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "435-analyse",
      "name": "Weekly Analysis",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        740,
        440
      ],
      "parameters": {
        "jsCode": "// \u2500\u2500 Hilfsfunktionen \u2500\u2500\nconst now = Date.now();\nconst msPerDay = 86400000;\nconst isThisWeek = (dateStr) => {\n  if (!dateStr) return false;\n  return (now - new Date(dateStr).getTime()) < 7 * msPerDay;\n};\n\n// \u2500\u2500 Content Pieces \u2500\u2500\nlet pieces = [];\ntry { pieces = $('Fetch Content Pieces').first().json?.data ?? []; } catch(e) {}\nconst piecesThisWeek = pieces.filter(p => isThisWeek(p.created_at ?? p.CreatedAt));\nconst byStatus = {};\nfor (const p of piecesThisWeek) {\n  const s = p.status ?? 'unknown';\n  byStatus[s] = (byStatus[s] ?? 0) + 1;\n}\n\n// Top Pieces (published zuerst, dann approved, dann draft)\nconst statusOrder = { published: 0, approved: 1, review: 2, draft: 3, idea: 4 };\nconst topPieces = [...piecesThisWeek]\n  .sort((a, b) => (statusOrder[a.status] ?? 9) - (statusOrder[b.status] ?? 9))\n  .slice(0, 5);\n\n// \u2500\u2500 Pipeline Jobs \u2500\u2500\nlet pipelineJobs = [];\ntry { pipelineJobs = $('Fetch Pipeline Jobs').first().json?.data ?? []; } catch(e) {}\nconst jobsThisWeek = pipelineJobs.filter(j => isThisWeek(j.created_at ?? j.CreatedAt));\nconst jobsByStatus = {};\nconst jobsByStage = {};\nfor (const j of jobsThisWeek) {\n  const s = j.status ?? 'unknown';\n  const stage = j.stage ?? 'unknown';\n  jobsByStatus[s] = (jobsByStatus[s] ?? 0) + 1;\n  jobsByStage[stage] = (jobsByStage[stage] ?? 0) + 1;\n}\nconst jobsDone = jobsByStatus['completed'] ?? jobsByStatus['done'] ?? 0;\nconst jobsFailed = jobsByStatus['failed'] ?? jobsByStatus['error'] ?? 0;\nconst jobsTotal = jobsThisWeek.length;\nconst successRate = jobsTotal > 0 ? Math.round(jobsDone / jobsTotal * 100) : 0;\n\n// Bottleneck: Stage mit meisten Fehlern\nconst failedJobs = jobsThisWeek.filter(j => ['failed','error'].includes(j.status));\nconst failedByStage = {};\nfor (const j of failedJobs) {\n  const stage = j.stage ?? 'unknown';\n  failedByStage[stage] = (failedByStage[stage] ?? 0) + 1;\n}\nconst bottleneck = Object.entries(failedByStage).sort((a,b) => b[1]-a[1])[0];\n\n// \u2500\u2500 n8n Ausf\u00fchrungen \u2500\u2500\nlet executions = [];\ntry { executions = $('Fetch n8n Executions').first().json?.data ?? []; } catch(e) {}\nconst execThisWeek = executions.filter(e => isThisWeek(e.startedAt ?? e.created_at));\nconst execSuccess = execThisWeek.filter(e => e.status === 'success').length;\nconst execFailed = execThisWeek.filter(e => ['error','failed'].includes(e.status)).length;\nconst execRate = execThisWeek.length > 0 ? Math.round(execSuccess / execThisWeek.length * 100) : 0;\n\n// Top Workflows nach Ausf\u00fchrungen\nconst wfCount = {};\nfor (const e of execThisWeek) {\n  const wfName = e.workflowData?.name ?? e.workflowId ?? 'unbekannt';\n  wfCount[wfName] = (wfCount[wfName] ?? 0) + 1;\n}\nconst topWorkflows = Object.entries(wfCount).sort((a,b) => b[1]-a[1]).slice(0, 3);\n\n// \u2500\u2500 Content Opportunities \u2500\u2500\nlet opportunities = [];\ntry { opportunities = $('Fetch Content Opportunities').first().json?.data ?? []; } catch(e) {}\nconst newOpportunities = opportunities.filter(o => isThisWeek(o.created_at ?? o.CreatedAt));\nconst topOpportunities = newOpportunities.slice(0, 3);\n\n// \u2500\u2500 Gesamtbewertung \u2500\u2500\nconst contentScore = piecesThisWeek.length >= 5 ? '\ud83d\udfe2' : piecesThisWeek.length >= 2 ? '\ud83d\udfe1' : '\ud83d\udd34';\nconst pipelineScore = successRate >= 80 ? '\ud83d\udfe2' : successRate >= 50 ? '\ud83d\udfe1' : '\ud83d\udd34';\nconst n8nScore = execRate >= 90 ? '\ud83d\udfe2' : execRate >= 70 ? '\ud83d\udfe1' : '\ud83d\udd34';\n\n// \u2500\u2500 Report zusammenbauen \u2500\u2500\nconst kw = Math.ceil((new Date().getTime() - new Date(new Date().getFullYear(), 0, 1).getTime()) / (7 * msPerDay));\nconst dateStr = new Date().toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric', timeZone: 'Europe/Berlin' });\n\nlet report = `\ud83d\udcca *AIOS Weekly Summary \u2014 KW${kw}* (${dateStr})\\n`;\nreport += `\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\\n\\n`;\n\n// KPI-\u00dcberblick\nreport += `*KPIs auf einen Blick:*\\n`;\nreport += `${contentScore} Content: ${piecesThisWeek.length} neue Pieces\\n`;\nreport += `${pipelineScore} Pipeline: ${successRate}% Erfolgsrate (${jobsDone}/${jobsTotal} Jobs)\\n`;\nreport += `${n8nScore} n8n: ${execRate}% Erfolgsrate (${execSuccess}/${execThisWeek.length} Runs)\\n\\n`;\n\n// Content-Produktion\nreport += `*\ud83d\udcdd Content-Produktion:*\\n`;\nif (piecesThisWeek.length === 0) {\n  report += `\u2022 Keine neuen Pieces diese Woche\\n`;\n} else {\n  const statusLabels = { published: 'Published', approved: 'Approved', review: 'In Review', draft: 'Draft', idea: 'Idee' };\n  for (const [s, count] of Object.entries(byStatus)) {\n    report += `\u2022 ${statusLabels[s] ?? s}: ${count}\\n`;\n  }\n}\nif (topPieces.length > 0) {\n  report += `\\n*Top Pieces:*\\n`;\n  for (const p of topPieces) {\n    const icon = p.status === 'published' ? '\u2705' : p.status === 'approved' ? '\ud83d\udfe2' : '\ud83d\udcdd';\n    const title = (p.title ?? p.topic ?? 'Unbekannt').substring(0, 50);\n    report += `${icon} ${title}\\n`;\n  }\n}\nreport += `\\n`;\n\n// Pipeline-Gesundheit\nreport += `*\u2699\ufe0f Pipeline-Gesundheit:*\\n`;\nif (jobsTotal === 0) {\n  report += `\u2022 Keine Jobs diese Woche\\n`;\n} else {\n  report += `\u2022 Gesamt: ${jobsTotal} | \u2705 ${jobsDone} | \u274c ${jobsFailed}\\n`;\n  if (bottleneck) {\n    report += `\u2022 \ud83d\udea8 Bottleneck: Stage \"${bottleneck[0]}\" (${bottleneck[1]} Fehler)\\n`;\n  }\n}\nreport += `\\n`;\n\n// n8n-Statistik\nreport += `*\ud83d\udd04 n8n-Aktivit\u00e4t:*\\n`;\nreport += `\u2022 ${execThisWeek.length} Runs | \u2705 ${execSuccess} | \u274c ${execFailed}\\n`;\nif (topWorkflows.length > 0) {\n  report += `\u2022 Aktivste Workflows:\\n`;\n  for (const [name, count] of topWorkflows) {\n    const shortName = name.substring(0, 35);\n    report += `  - ${shortName}: ${count}x\\n`;\n  }\n}\nreport += `\\n`;\n\n// Content-Chancen\nif (newOpportunities.length > 0) {\n  report += `*\ud83d\udca1 Neue Content-Chancen (${newOpportunities.length}):*\\n`;\n  for (const o of topOpportunities) {\n    const topic = (o.topic ?? o.keyword ?? o.title ?? 'Unbekannt').substring(0, 45);\n    report += `\u2022 ${topic}\\n`;\n  }\n  report += `\\n`;\n}\n\n// Empfehlung\nreport += `*\ud83d\udccc Fokus n\u00e4chste Woche:*\\n`;\nif (bottleneck) {\n  report += `\u2022 Stage \"${bottleneck[0]}\" debuggen (${bottleneck[1]} Fehler)\\n`;\n}\nif (piecesThisWeek.length < 3) {\n  report += `\u2022 Content-Produktion hochfahren (Ziel: 5+ Pieces/Woche)\\n`;\n}\nif (newOpportunities.length > 0) {\n  const bestOpportunity = topOpportunities[0];\n  const topic = (bestOpportunity?.topic ?? bestOpportunity?.keyword ?? 'Trend-Thema').substring(0, 40);\n  report += `\u2022 Beste Chance: \"${topic}\" aufgreifen\\n`;\n}\nif (!bottleneck && piecesThisWeek.length >= 3 && newOpportunities.length === 0) {\n  report += `\u2022 Alles im gr\u00fcnen Bereich \u2014 weiter so! \ud83d\ude80\\n`;\n}\n\nreturn [{ json: { report } }];"
      }
    },
    {
      "id": "435-send",
      "name": "Send to Telegram",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1000,
        440
      ],
      "parameters": {
        "method": "POST",
        "url": "=https://api.telegram.org/bot{{ $env.TELEGRAM_BOT_TOKEN }}/sendMessage",
        "authentication": "none",
        "sendBody": true,
        "specifyBody": "string",
        "body": "={{ JSON.stringify({ chat_id: $env.TELEGRAM_ALLOWED_CHAT_ID, text: $json.report, parse_mode: 'Markdown' }) }}",
        "options": {
          "timeout": 10000
        }
      },
      "onError": "continueRegularOutput"
    }
  ],
  "connections": {
    "Every Monday 09:00": {
      "main": [
        [
          {
            "node": "Fetch Content Pieces",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Pipeline Jobs",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch n8n Executions",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch Content Opportunities",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Content Pieces": {
      "main": [
        [
          {
            "node": "Weekly Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Pipeline Jobs": {
      "main": [
        [
          {
            "node": "Weekly Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch n8n Executions": {
      "main": [
        [
          {
            "node": "Weekly Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Content Opportunities": {
      "main": [
        [
          {
            "node": "Weekly Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Analysis": {
      "main": [
        [
          {
            "node": "Send to Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "saveDataErrorExecution": "all",
    "saveDataSuccessExecution": "none"
  },
  "staticData": null,
  "tags": [
    "content",
    "reporting"
  ],
  "meta": {
    "description": "435 \u2014 W\u00f6chentlicher Summary: Content-Produktion, Pipeline-Gesundheit, n8n-Stats, Content-Chancen \u2014 jeden Montag 09:00 via Telegram"
  }
}
Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

40_435_WEEKLY_SUMMARY. Uses httpRequest. Scheduled trigger; 7 nodes.

Source: https://github.com/timo-goetz-ai/apki-core-platform/blob/main/automations/n8n-workflows/content-pipeline/40_435_WEEKLY_SUMMARY.json — original creator credit. Request a take-down →

More Web Scraping workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Web Scraping

Birthday Automation - Production (Fixed). Uses stopAndError, httpRequest, emailSend, bannerbear. Scheduled trigger; 86 nodes.

Stop And Error, HTTP Request, Email Send +1
Web Scraping

This template runs two scheduled workflows to govern Microsoft Entra ID (Azure AD) guest accounts by detecting stale users via Microsoft Graph, staging deletions in SharePoint with a 72-hour window, n

Microsoft SharePoint, Microsoft Teams, Microsoft Entra +1
Web Scraping

Jira-Allure-Auto-Qa. Uses httpRequest, jira. Scheduled trigger; 68 nodes.

HTTP Request, Jira
Web Scraping

Spotify-Sync-Surrealdb-V1. Uses httpRequest, n8n-nodes-surrealdb, spotify. Scheduled trigger; 62 nodes.

HTTP Request, N8N Nodes Surrealdb, Spotify
Web Scraping

As n8n instances scale, teams often lose track of sub-workflows—who uses them, where they are referenced, and whether they can be safely updated. This leads to inefficiencies like unnecessary copies o

HTTP Request, n8n, N8N Trigger +1