Werkstattbericht Content-Automatisierung – Teil 2 von 8. Wie ich für einen meiner Blogs die Beitragsproduktion mit n8n und Claude automatisiert habe: was funktioniert hat, was nicht, und was am Ende dabei herauskam. Bereits erschienen: 1 · 2. Die übrigen 6 Teile folgen.
Es gibt zwei Arten, eine Content-Automatisierung zu bauen. Die eine ist, bei null anzufangen und sechs Wochen zu brauchen. Die andere ist, sich eine fertige Vorlage zu nehmen, sie zu importieren und festzustellen, dass sie funktioniert.
Ich habe die zweite gewählt. Und um es vorwegzunehmen: Ich würde es wieder tun. Aber „funktioniert“ und „tut, was du denkst“ sind zwei sehr verschiedene Dinge, und der Unterschied zwischen beiden hat mich zwei Tage gekostet.
Dies ist Teil 2 des Werkstattberichts. In Teil 1 ging es um die Zahlen, die das Ganze ausgelöst haben – null Klicks in drei Monaten. Jetzt geht es um das, was ich mir da eigentlich in die n8n-Instanz importiert habe.
Was die Vorlage kann
Zwei Workflows, nicht einer
Die Vorlage heißt „nano WordPress Blog Automation Pro (Deeper Research)“ und besteht aus zwei getrennten Workflows.
Der Trigger-Workflow ist klein: sieben Nodes. Ein Zeitplan feuert alle 20 Minuten, liest aus einer Google-Tabelle alle Zeilen mit Status = To Do, schickt sie durch eine Schleife und ruft für jede Zeile den zweiten Workflow auf. Danach zehn Minuten warten, nächste Zeile.
Der Artikel-Workflow ist der große: 120 Nodes, davon acht deaktiviert. Er hat keinen eigenen Zeitplan, sondern einen Execute Workflow Trigger – er ist also ein Unter-Workflow und läuft nur, wenn ihn jemand aufruft.
Das ist eine saubere Trennung, und sie ist der Grund, warum die Vorlage überhaupt beherrschbar bleibt. Wer schon einmal versucht hat, Zeitplan, Warteschlange und Artikelproduktion in einen einzigen Workflow zu quetschen, weiß, wie schnell das Bild unlesbar wird.
Kleiner Exkurs für alle, die n8n nicht kennen: Ein „Node“ ist ein Kästchen auf einer Leinwand, das genau eine Sache tut – eine HTTP-Anfrage stellen, ein Feld setzen, eine Schleife drehen, ein Sprachmodell fragen. Die Kästchen sind mit Linien verbunden, und was aus dem einen herausfällt, geht in das nächste hinein. 120 Nodes klingt nach viel, ist es aber nicht: Allein für „Bild erzeugen, herunterladen, verkleinern, in WebP wandeln, hochladen, Metadaten setzen“ gehen sechs davon drauf, und das passiert vier Mal pro Beitrag.
Was pro Beitrag tatsächlich passiert
Ich habe mir aus der JSON-Datei zusammengetragen, was ein einzelner Durchlauf auslöst:
| Textmodell | GPT-4o an allen sieben LLM-Nodes |
| Recherche | Perplexity, als Werkzeug an drei Research-Agenten gehängt |
| Bilder | Gemini 2.5 Flash Image („Nano Banana“), ein Titelbild plus ein Bild je Kapitel |
| Bildverarbeitung | auf 800 px verkleinert, als WebP nach WordPress und nach Google Drive |
| Veröffentlichung | status: draft — kein Beitrag geht ungefragt online |
| Schlagwörter | werden erzeugt und, falls nicht vorhanden, in WordPress angelegt |
| Ablage | zusätzlich ein Google Doc je Beitrag plus eine Zeile in der Tabelle „Final Blogs“ |
Mit der Einstellung „Have Deeper Research = Yes“ sind das je Beitrag rund 14 GPT-4o-Aufrufe, sieben Perplexity-Recherchen und vier Bildgenerierungen. Bei 14 Beiträgen pro Woche also ungefähr 200 Modellaufrufe, 100 Recherchen und 56 Bilder – wöchentlich.
Das status: draft ist übrigens der Grund, warum ich diese Serie überhaupt entspannt schreiben kann. Alles, was gleich kommt, ist in Entwürfen passiert, nicht auf der Seite.

Der teuerste Tippfehler: ein fehlendes per_page
Zehn von 21 Kategorien
Der Workflow holt sich die Kategorien meines Blogs live von WordPress, damit das Modell selbst die passende auswählen kann. Der Node dafür heißt HTTP Request Get Categories und ruft auf:
https://wildnisruf.de/wp-json/wp/v2/categories
Sieht harmlos aus. Ist es nicht.
Die WordPress-REST-API liefert ohne per_page genau zehn Einträge. Ich habe es an dieser Seite hier nachgemessen: ein Abruf ohne per_page liefert zehn Einträge, und per_page=101 beantwortet WordPress mit rest_invalid_param und dem Hinweis, der Wert müsse zwischen 1 und 100 liegen. Wer mehr als 100 Einträge braucht, muss also blättern.
Ich habe es an meiner Seite nachgemessen. Zurück kamen diese zehn:
Aktivitäten (8) · Allgemein (77) · Camping (60) · Europa (42) · Grundlagen (38) · Jagd (78) · Jagdrecht (79) · Jagdschein (80) · Nachrichten (81) · Naturfitness (115)
Ich habe 21. Für die Automatik unsichtbar waren also: Wanderungen (10), Survival (61), Sport (64), Sicherheit (35), Wanderausrüstung (43), Wanderbekleidung (50), Tierarten (83), Waffenrecht (84), Rezepte (82), Technik (124) und Verschiedenes (1).
Elf Kategorien. Darunter Wanderungen und Survival – also genau die beiden, um die es auf einer Outdoor-Seite geht.
Warum der Notnagel gerade nicht greift
Jetzt kommt der Teil, der mich wirklich geärgert hat.
Die Vorlage denkt mit: In meiner Themen-Tabelle gibt es eine Spalte für die Kategorie-ID, und der Prompt sagt dem Modell sinngemäß, es solle diese Standard-Kategorie nehmen, wenn es keine passende findet. Ein Notnagel für den Fall, dass nichts passt.
Der greift nur nie. Denn das Modell findet immer irgendetwas halbwegs Passendes unter den zehn sichtbaren. „Aktivitäten“ passt auf fast jeden Outdoor-Beitrag. „Allgemein“ passt sowieso. Der Fall „ich finde nichts“ tritt praktisch nicht ein – und deshalb wird der Notnagel nie gezogen.
Praktisch heißt das: Ein Beitrag, den ich sauber der Kategorie 10 „Wanderungen“ zugeordnet hatte, wäre in „Aktivitäten“ oder „Allgemein“ gelandet. Bei 1.121 geplanten Beiträgen.
Das Muster dahinter ist verallgemeinerbar, und deshalb erzähle ich es so ausführlich: Ein Fehler, der eine Fehlermeldung erzeugt, ist ein billiger Fehler. Du siehst ihn, du behebst ihn. Ein Fehler, der eine plausible falsche Antwort erzeugt, ist teuer – weil nichts rot leuchtet. Der Abruf der zehn Kategorien war erfolgreich. Alles in Ordnung, sagt der Server.
Die Korrektur war ein angehängter Parameter:
…/categories?per_page=100&orderby=id&order=asc
Die Sprachanweisung, die ins Leere lief
Ein Feldname, neun Prompts
Neun der Prompts im Workflow enthielten diese Zeile:
must generate the content entirely in
{{ $('Global Configuration').first().json['Content Language'] }}
Der Node Global Configuration setzt allerdings ein Feld namens Language mit dem Wert german. Nicht Content Language.
Ein Zugriff auf ein nicht existierendes Feld wirft in n8n keinen Fehler – er löst sich zu einem leeren Wert auf. In den Prompts stand also buchstäblich:
„must generate the content entirely in „ „
Neun Mal. Alle übrigen Anweisungen im Workflow sind auf Englisch, die Perplexity-System-Prompts ebenfalls. Dass die Beiträge trotzdem überwiegend auf Deutsch herauskamen, lag einzig daran, dass das Thema deutsch formuliert war und das Modell daraus die Sprache erriet.
Das ist kein Zustand, auf den man 1.121 Beiträge baut. Und es ist auch nicht immer gutgegangen – in Teil 3 zeige ich dir den Beitrag, in dem ein Unterkapitel komplett auf Englisch herauskam, Überschrift inklusive.
Die Korrektur war ein Handgriff: Feld umbenannt in Content Language, Wert auf Deutsch. Ein einziges Feld repariert alle neun Stellen.
Exkurs: .first() ist nicht „das aktuelle Element“
Der dritte Befund ist der lehrreichste, weil er ein Missverständnis betrifft, das man in n8n leicht entwickelt.
Der Node Update Image Meta Data schrieb den Alternativtext jedes Kapitelbildes so:
alt_text = {{ $('Split Out Chapters').first().json.image.alt_text }}
.first() bedeutet: das erste Element aus dem Ausgang jenes Nodes – nicht „das Element, das gerade durch die Schleife läuft“. In jedem Schleifendurchlauf kommt also derselbe Wert heraus: der von Kapitel 1.
Ergebnis: Alt-Text, Titel, Beschriftung und Beschreibung des ersten Kapitelbildes standen an allen Kapitelbildern. Der korrekte Alt-Text wurde pro Kapitel sauber erzeugt – und dann weggeworfen.
Für Barrierefreiheit ist das ein echter Verlust, für die Bildersuche auch. Die Korrektur:
alt_text = {{ $('Loop Over Items').item.json.image.alt_text }}
.item statt .first(). Merk dir den Unterschied, er kommt in Teil 3 noch einmal vor – dort ist dieselbe Verwechslung die wahrscheinlichste Erklärung dafür, dass ein Beitrag dreimal dieselbe Kapitelüberschrift trug.

Was ich sonst noch fand
Die 50 ältesten Beiträge
Für die interne Verlinkung zog der Workflow die Sitemap und schnitt sie mit einem Limit-Node auf 50 Einträge zu. Meine Sitemap enthält 71 URLs, sortiert nach lastmod – die ältesten zuerst.
Heute hieße das: 21 Beiträge werden nie verlinkt. Bei 1.121 Beiträgen: 1.071. Die gesamte interne Verlinkung der Seite würde dauerhaft auf denselben 50 Altbeiträgen von 2022 landen, und jeder neue Beitrag bliebe ohne eingehenden Link.
Ich habe das Limit zunächst auf 200 gesetzt, als Notpflaster. Die richtige Lösung war ein kompletter Neubau – der ist Teil 5 dieser Serie, und er ist der Teil, auf den ich am meisten stolz bin.
Nebenbei: Der Sitemap-Pfad war fest verdrahtet als /post-sitemap.xml, obwohl es in meiner Tabelle eine Spalte Sitemap Xml gibt, die der Workflow zwar auf Vorhandensein prüft, aber nirgends benutzt. Soweit mir bekannt – und das solltest du an deiner Installation prüfen: Yoast teilt die Beitrags-Sitemap ab 1.000 Einträgen in post-sitemap1.xml, post-sitemap2.xml auf. Wenn das stimmt, wäre die Verlinkung ab Beitrag 1.001 stillschweigend ausgefallen.
Wartezeiten ohne Einheit – und was nicht drin war
Sieben Wait-Nodes standen auf amount: 3, ohne dass die Einheit gesetzt war. Drei was? Sekunden? Minuten? Stunden?
Ich konnte es aus der Datei nicht sicher beantworten, und ich habe die Frage deshalb zunächst als offen markiert, statt zu raten. Sieben mal drei Stunden wären über einen Tag pro Beitrag gewesen. Aufgelöst wurde die Frage erst einen Tag später, durch die Zeitstempel echter Entwürfe – die Geschichte steht in Teil 4.
Unabhängig von der Antwort habe ich in allen sieben Nodes unit: "seconds" ausdrücklich eingetragen. Eine explizit gesetzte Einheit kann nicht falsch verstanden werden.
Und eine Sache, die nicht drin war, ist erwähnenswert, weil sie bei gekauften Vorlagen keineswegs selbstverständlich ist: Ich habe die JSON-Datei nach API-Schlüsseln durchsucht – OpenAI, Google, Perplexity, Bearer-Token. Nichts gefunden. Es waren ausschließlich Referenzen auf n8n-Credentials hinterlegt. Die Datei kann man weitergeben, ohne dass Schlüssel mitgehen.
Enthalten waren allerdings die Google-Sheets-Dokument-ID und die n8n-instanceId. Beides keine Geheimnisse – aber auch nichts, was in fremde Hände muss.
Was dagegen sehr wohl drinstand: In zwei Google-Sheets-Nodes zeigte die hinterlegte Blatt-Adresse auf ein fremdes Dokument – das des Vorlagenautors. Typischer Rückstand aus der Vorlage, und einer, der stillschweigend zu Fehlern führt. Auch dazu mehr in Teil 4.
Fazit
Nach dem ersten Durchgang standen fünf A-Befunde, fünf B-Befunde und sechs C-Befunde. Sechs davon habe ich sofort korrigiert und als Fassung v2.2 abgelegt:
| # | Node | vorher | nachher |
|---|---|---|---|
| 1 | Global Configuration | Feld Language = german | Feld Content Language = Deutsch |
| 2 | HTTP Request Get Categories | …/categories | …/categories?per_page=100&orderby=id&order=asc |
| 3 | Update Image Meta Data | $('Split Out Chapters').first() | $('Loop Over Items').item |
| 4 | Limit Internal Links | 50 | 200 |
| 5 | Get Post Sitemap | fest /post-sitemap.xml | aus der Tabellenspalte Sitemap Xml |
| 6 | 7 × Wait | Einheit nicht gesetzt | unit: "seconds" |
Vier Felder, ein Parameter, eine Zahl. Zusammen etwa zehn Minuten Arbeit – und ohne sie hätten 1.121 Beiträge in den falschen Kategorien gestanden, mit Alt-Texten des jeweils ersten Bildes und einer Sprachanweisung, die auf ein leeres Feld zeigt.
Die Lehre daraus ist unspektakulär und trotzdem die wichtigste dieser Serie: Eine fertige Vorlage nimmt dir das Bauen ab, nicht das Verstehen. Was du nicht gelesen hast, hast du nicht geprüft – und was du nicht geprüft hast, läuft trotzdem. Vierzehnmal die Woche.
Im nächsten Teil wird es unangenehmer. Da sehen wir uns an, was die Vorlage tatsächlich geschrieben hat – und warum in einem Beitrag über Wildbrethygiene plötzlich von Weidehaltung, Betäubung und Zutrieb die Rede war.
Alle Teile der Serie
- Teil 1: Null Klicks in drei Monaten
- Teil 2: 120 Nodes geerbt (dieser Beitrag)
- Teil 3: Schlachttiere im Wildbret-Beitrag – folgt
- Teil 4: Vier Beiträge in zwei Sekunden – folgt
- Teil 5: Interne Verlinkung, neu gebaut – folgt
- Teil 6: Yoast über die REST-API – folgt
- Teil 7: Stil, Modelle und Kosten – folgt
- Teil 8: Bilanz nach zwei Tagen – folgt
◀ Zurück zu Teil 1: Null Klicks in drei Monaten

[…] habe: was funktioniert hat, was nicht, und was am Ende dabei herauskam. Bereits erschienen: 1 · 2. Die übrigen 6 Teile […]