{
  "schema": "ldwf",
  "version": 1,
  "name": "Competitor Content Tracking",
  "meta": {
    "exportedAt": "2025-11-16T16:51:01.250Z",
    "exporter": "client"
  },
  "graph": {
    "nodes": [
      {
        "type": "code",
        "data": {
          "comment": "⚙️ RSS PARSER & ZEITFILTER\n\n📋 Beschreibung:\nParst die XML-Daten aus allen RSS-Feeds, extrahiert relevante Informationen (Titel, Link, Beschreibung, Datum) und filtert automatisch nur Artikel der letzten 24 Stunden heraus.\n\n🔧 Was macht dieser Code?\n1. Verarbeitet RSS-Feeds von allen drei Wettbewerbern\n2. Extrahiert: Titel, Link, Beschreibung, Datum, Content\n3. Filtert nur Artikel der letzten 24 Stunden\n4. Kombiniert alle Artikel mit Wettbewerber-Zuordnung\n5. Gibt strukturierte Daten für die KI-Analyse aus\n\n🎨 Personalisierungsoptionen:\n- Zeitfenster ändern: Ändern Sie '24' in Zeile 'const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);' zu einer anderen Stundenzahl (z.B. 48 für 2 Tage)\n- Wettbewerber hinzufügen: Kopieren Sie den Block für 'Competitor 1-3' und passen Sie die Slug-Namen an\n- Wettbewerber entfernen: Löschen Sie den entsprechenden Block (z.B. 'Parse Competitor 3')\n- Wettbewerber-Namen anpassen: Ändern Sie 'Wettbewerber 1/2/3' zu echten Namen\n\n💡 Tipp: Der Code ist robust und funktioniert mit den meisten Standard-RSS-Formaten (RSS 2.0, Atom).",
          "executionId": null,
          "errorHandling": {
            "strategy": "stop"
          },
          "name": "RSS Parser & Filter",
          "slug": "rssParser",
          "language": "javascript",
          "code": "// Parse RSS feeds and filter articles from last 24 hours\nconst parseRSSFeed = (xmlText, competitorName) => {\n  try {\n    // Simple XML parsing for RSS feeds\n    const items = [];\n    const itemMatches = xmlText.matchAll(/<item[^>]*>([\\s\\S]*?)<\\/item>/gi);\n    \n    for (const match of itemMatches) {\n      const itemContent = match[1];\n      \n      // Extract fields\n      const title = itemContent.match(/<title[^>]*><!\\[CDATA\\[([\\s\\S]*?)\\]\\]><\\/title>|<title[^>]*>([^<]*)<\\/title>/i);\n      const link = itemContent.match(/<link[^>]*>([^<]*)<\\/link>/i);\n      const description = itemContent.match(/<description[^>]*><!\\[CDATA\\[([\\s\\S]*?)\\]\\]><\\/description>|<description[^>]*>([^<]*)<\\/description>/i);\n      const pubDate = itemContent.match(/<pubDate[^>]*>([^<]*)<\\/pubDate>/i);\n      const content = itemContent.match(/<content:encoded[^>]*><!\\[CDATA\\[([\\s\\S]*?)\\]\\]><\\/content:encoded>/i);\n      \n      items.push({\n        title: title ? (title[1] || title[2] || '').trim() : '',\n        link: link ? link[1].trim() : '',\n        description: description ? (description[1] || description[2] || '').trim() : '',\n        pubDate: pubDate ? pubDate[1].trim() : '',\n        content: content ? content[1].trim() : '',\n        competitor: competitorName\n      });\n    }\n    \n    return items;\n  } catch (error) {\n    ld.log(`Error parsing RSS feed for ${competitorName}: ${error.message}`);\n    return [];\n  }\n};\n\n// Filter articles from last 24 hours\nconst filterRecentArticles = (articles) => {\n  const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);\n  \n  return articles.filter(article => {\n    if (!article.pubDate) return false;\n    \n    try {\n      const articleDate = new Date(article.pubDate);\n      return articleDate >= oneDayAgo;\n    } catch (error) {\n      ld.log(`Error parsing date: ${article.pubDate}`);\n      return false;\n    }\n  });\n};\n\n// Parse all RSS feeds\nconst allArticles = [];\n\n// Parse Competitor 1\nif (rssFeedCompetitor1.output) {\n  const articles1 = parseRSSFeed(\n    typeof rssFeedCompetitor1.output === 'string' ? rssFeedCompetitor1.output : rssFeedCompetitor1.output.body || '',\n    'Wettbewerber 1'\n  );\n  allArticles.push(...articles1);\n}\n\n// Parse Competitor 2\nif (rssFeedCompetitor2.output) {\n  const articles2 = parseRSSFeed(\n    typeof rssFeedCompetitor2.output === 'string' ? rssFeedCompetitor2.output : rssFeedCompetitor2.output.body || '',\n    'Wettbewerber 2'\n  );\n  allArticles.push(...articles2);\n}\n\n// Parse Competitor 3\nif (rssFeedCompetitor3.output) {\n  const articles3 = parseRSSFeed(\n    typeof rssFeedCompetitor3.output === 'string' ? rssFeedCompetitor3.output : rssFeedCompetitor3.output.body || '',\n    'Wettbewerber 3'\n  );\n  allArticles.push(...articles3);\n}\n\n// Filter recent articles\nconst recentArticles = filterRecentArticles(allArticles);\n\nld.log(`Total articles found: ${allArticles.length}`);\nld.log(`Recent articles (last 24h): ${recentArticles.length}`);\n\nreturn {\n  totalArticles: allArticles.length,\n  recentArticles: recentArticles.length,\n  articles: recentArticles\n};"
        },
        "id": "152e4721-b7eb-446d-9562-04930ed4dee5",
        "position": {
          "x": 1100,
          "y": 1160
        }
      },
      {
        "type": "trigger",
        "data": {
          "comment": "⏰ ZEITGESTEUERTER TRIGGER\n\n📋 Beschreibung:\nStartet den Workflow automatisch jeden Tag um 9:00 Uhr morgens. Der Workflow läuft dann vollständig automatisiert durch alle Schritte.\n\n⚙️ Setup:\n- Cron-Expression: '0 9 * * *' bedeutet täglich um 9:00 Uhr\n- Keine weiteren Einstellungen erforderlich\n\n🎨 Personalisierungsoptionen:\n- Ändern Sie die Uhrzeit: z.B. '0 8 * * *' für 8:00 Uhr\n- Mehrmals täglich: z.B. '0 9,15 * * *' für 9:00 und 15:00 Uhr\n- Nur Wochentags: z.B. '0 9 * * 1-5' (Montag-Freitag)\n- Wöchentlich: z.B. '0 9 * * 1' nur montags\n\n💡 Tipp: Testen Sie den Workflow zunächst manuell, bevor Sie ihn zeitgesteuert laufen lassen.",
          "executionId": null,
          "errorHandling": {
            "strategy": "stop"
          },
          "slug": "dailyCompetitorScan",
          "name": "Täglich 9:00 Uhr",
          "kind": "scheduled",
          "cron": "0 9 * * *"
        },
        "id": "004431d7-e8e0-4aed-acb3-aa6c684887e8",
        "position": {
          "x": 10,
          "y": 780
        }
      },
      {
        "type": "agent",
        "data": {
          "comment": "🤖 KI COMPETITIVE INTELLIGENCE ANALYST\n\n📋 Beschreibung:\nEin KI-Agent, der alle gefilterten Artikel analysiert und einen strukturierten Competitive Intelligence Report erstellt. Der Agent identifiziert Produktinnovationen, Content-Strategien, Branchentrends, Wettbewerberpositionierung und leitet konkrete Handlungsempfehlungen ab.\n\n📊 Was wird analysiert?\n- Produktinnovationen & neue Features\n- Content-Marketing-Strategien\n- Branchentrends & Entwicklungen\n- Wettbewerberpositionierung & Messaging\n- Prioritäre Handlungsempfehlungen\n\n🎨 Personalisierungsoptionen:\n- Prompt anpassen: Fügen Sie spezifische Analysefokus-Bereiche hinzu (z.B. \"Achte besonders auf Pricing-Strategien\")\n- Branche angeben: Ersetzen Sie \"[Ihre Branche]\" im Prompt durch Ihre tatsächliche Branche\n- Output-Schema erweitern: Fügen Sie weitere Felder hinzu wie \"pricing_insights\", \"marketing_channels\", \"target_audience\"\n- Analyse-Tiefe: Passen Sie die Anweisungen im Prompt an (z.B. \"Erstelle eine ausführliche 3-seitige Analyse\" vs. \"Erstelle eine kompakte Übersicht\")\n\n💡 Tipps:\n- Der Agent nutzt GPT-4 für hochwertige Analysen\n- Je spezifischer Ihr Prompt, desto relevanter die Insights\n- Das Output-Schema sorgt für strukturierte, konsistente Reports",
          "executionId": null,
          "errorHandling": {
            "strategy": "stop"
          },
          "slug": "competitiveAnalyst",
          "assistantId": null,
          "mode": "create",
          "name": "Competitive Intelligence Analyst",
          "prompt": {
            "mode": "manual",
            "value": "Du bist ein Competitive Intelligence Analyst. Analysiere die folgenden Artikel von unseren Wettbewerbern und erstelle einen umfassenden Report.\n\nArtikel-Daten:\n{{rssParser.output.articles}}\n\nAnzahl der Artikel: {{rssParser.output.recentArticles}}\n\nErstelle eine strukturierte Analyse mit folgenden Schwerpunkten:\n\n1. **Executive Summary**: Fasse die wichtigsten Erkenntnisse in 3-4 Sätzen zusammen\n\n2. **Produktinnovationen**: Welche neuen Produkte, Features oder Services wurden angekündigt? Was sind die wichtigsten Innovationen?\n\n3. **Content-Strategie**: Welche Themen behandeln die Wettbewerber? Welche Content-Formate nutzen sie? Welche Messaging-Strategien sind erkennbar?\n\n4. **Branchentrends**: Welche übergreifenden Trends in [Ihre Branche] werden deutlich? Welche Entwicklungen zeichnen sich ab?\n\n5. **Wettbewerber-Positionierung**: Wie positionieren sich die Wettbewerber? Welche Unique Value Propositions kommunizieren sie?\n\n6. **Handlungsempfehlungen**: Welche konkreten Aktionen sollten wir basierend auf diesen Erkenntnissen priorisieren? Nenne die Top 3-5 wichtigsten Empfehlungen.\n\nSei präzise, datengetrieben und fokussiere auf actionable Insights. Wenn keine neuen Artikel vorhanden sind, gib dies klar an."
          },
          "attachmentIds": [],
          "output": "structured",
          "connectionOverrides": {},
          "outputSchema": [
            {
              "id": "0b47b004-89a4-4c4e-a7b1-e8820fb82670",
              "name": "summary",
              "description": "Executive Summary der wichtigsten Erkenntnisse",
              "type": "string",
              "required": true
            },
            {
              "id": "530f45bd-fe2f-4819-a2f1-6d445e04d335",
              "name": "product_insights",
              "description": "Produktinnovationen und neue Features der Wettbewerber",
              "type": "string",
              "required": true
            },
            {
              "id": "50879f49-fb84-4581-859b-2bc45b2774e3",
              "name": "content_strategy",
              "description": "Content-Marketing-Strategien und Themen",
              "type": "string",
              "required": true
            },
            {
              "id": "05285c0d-3e6d-44e6-a18c-70be59a87437",
              "name": "industry_trends",
              "description": "Identifizierte Branchentrends",
              "type": "string",
              "required": true
            },
            {
              "id": "568c3706-49b7-4843-b73b-0472c842ce1e",
              "name": "competitor_positioning",
              "description": "Wie positionieren sich die Wettbewerber?",
              "type": "string",
              "required": true
            },
            {
              "id": "42f1b0fa-7f9b-4b14-8d58-974eb71c9864",
              "name": "top_priority_actions",
              "description": "Top 3-5 prioritäre Handlungsempfehlungen",
              "type": "string",
              "required": true
            },
            {
              "id": "a4344524-732f-405e-83d2-e296ef355451",
              "name": "articles_analyzed",
              "description": "Anzahl der analysierten Artikel",
              "type": "number",
              "required": true
            },
            {
              "id": "1704636d-7fea-462f-8727-6d96bf52d865",
              "name": "success",
              "description": "Wurde die Analyse erfolgreich durchgeführt?",
              "type": "boolean",
              "required": true
            }
          ],
          "modelId": "c968689a-c0d9-49de-aa76-b10ed15ebb0e",
          "tools": [],
          "maxSteps": 25
        },
        "id": "99db822c-3eab-4ad8-bdb2-b77581271c86",
        "position": {
          "x": 1644,
          "y": 1160
        }
      },
      {
        "type": "http_request",
        "data": {
          "comment": "🌐 RSS FEED ABRUF - WETTBEWERBER 1\n\n📋 Beschreibung:\nRuft den RSS-Feed des ersten Wettbewerbers ab. RSS-Feeds enthalten die neuesten Blog-Artikel, News oder Updates in einem standardisierten XML-Format.\n\n⚙️ Setup - WICHTIG:\n1. Ersetzen Sie die Beispiel-URL durch die echte RSS-Feed-URL Ihres Wettbewerbers\n2. RSS-Feed-URLs enden oft mit '/feed', '/rss', '/feed.xml' oder '/rss.xml'\n3. Tipp: Suchen Sie auf der Wettbewerber-Website nach einem RSS-Icon oder 'RSS Feed' Link\n\n🎨 Personalisierungsoptionen:\n- Ändern Sie den Namen zu einem erkennbaren Wettbewerber-Namen (z.B. 'RSS Feed - Competitor Inc.')\n- Falls der Feed Authentifizierung benötigt, fügen Sie Headers hinzu (z.B. API-Key)\n- Bei langsamen Feeds: Erhöhen Sie das Timeout in den erweiterten Einstellungen\n\n🔍 Wie finde ich RSS-Feeds?\n- Direkt auf der Website nach 'RSS' oder 'Feed' suchen\n- Browser-Extensions wie 'RSS Feed Reader' nutzen\n- URL-Muster testen: website.com/feed, website.com/blog/rss",
          "executionId": null,
          "errorHandling": {
            "strategy": "stop"
          },
          "name": "RSS Feed Wettbewerber 1",
          "slug": "rssFeedCompetitor1",
          "url": {
            "mode": "manual",
            "value": "https://example-competitor1.com/feed.xml"
          },
          "method": "GET",
          "body": {
            "mode": "manual",
            "value": ""
          },
          "queryParams": [],
          "headers": []
        },
        "id": "3894616d-9a3e-4f01-8b07-3217ac50b157",
        "position": {
          "x": 540,
          "y": 400
        }
      },
      {
        "type": "http_request",
        "data": {
          "comment": "🌐 RSS FEED ABRUF - WETTBEWERBER 2\n\n📋 Beschreibung:\nRuft den RSS-Feed des zweiten Wettbewerbers ab. Dieser Node läuft parallel zu den anderen RSS-Abrufen für maximale Geschwindigkeit.\n\n⚙️ Setup - WICHTIG:\n1. Ersetzen Sie die Beispiel-URL durch die echte RSS-Feed-URL\n2. Stellen Sie sicher, dass die URL erreichbar ist (testen Sie sie im Browser)\n\n🎨 Personalisierungsoptionen:\n- Benennen Sie den Node nach dem tatsächlichen Wettbewerber\n- Falls Sie weniger als 3 Wettbewerber tracken: Löschen Sie diesen Node\n- Falls Sie mehr Wettbewerber tracken: Duplizieren Sie diesen Node und passen Sie die URL an\n\n💡 Tipp: Sie können beliebig viele RSS-Feed-Nodes hinzufügen. Der Code-Node im nächsten Schritt verarbeitet alle automatisch.",
          "executionId": null,
          "errorHandling": {
            "strategy": "stop"
          },
          "name": "RSS Feed Wettbewerber 2",
          "slug": "rssFeedCompetitor2",
          "url": {
            "mode": "manual",
            "value": "https://example-competitor2.com/feed.xml"
          },
          "method": "GET",
          "body": {
            "mode": "manual",
            "value": ""
          },
          "queryParams": [],
          "headers": []
        },
        "id": "74fb82e8-024f-4999-8b32-7c2644e2bb39",
        "position": {
          "x": 540,
          "y": 780
        }
      },
      {
        "type": "http_request",
        "data": {
          "comment": "🌐 RSS FEED ABRUF - WETTBEWERBER 3\n\n📋 Beschreibung:\nRuft den RSS-Feed des dritten Wettbewerbers ab. Alle drei Feeds werden parallel abgerufen und dann gemeinsam verarbeitet.\n\n⚙️ Setup - WICHTIG:\n1. Ersetzen Sie die Beispiel-URL durch die echte RSS-Feed-URL\n2. Testen Sie die URL vorab im Browser, um sicherzustellen, dass sie funktioniert\n\n🎨 Personalisierungsoptionen:\n- Benennen Sie den Node nach dem echten Wettbewerber (z.B. 'RSS Feed - Acme Corp')\n- Falls nicht benötigt: Löschen Sie diesen Node UND passen Sie den Code-Node an (entfernen Sie die Zeilen für rssFeedCompetitor3)\n- Für mehr Wettbewerber: Duplizieren Sie diesen Node, ändern Sie die URL und erweitern Sie den Code-Node entsprechend\n\n⚠️ Wichtig: Wenn Sie Nodes hinzufügen/entfernen, müssen Sie auch den Code-Node anpassen!",
          "executionId": null,
          "errorHandling": {
            "strategy": "stop"
          },
          "name": "RSS Feed Wettbewerber 3",
          "slug": "rssFeedCompetitor3",
          "url": {
            "mode": "manual",
            "value": "https://example-competitor3.com/feed.xml"
          },
          "method": "GET",
          "body": {
            "mode": "manual",
            "value": ""
          },
          "queryParams": [],
          "headers": []
        },
        "id": "85766811-22f9-4475-8c2b-14dd98e341fb",
        "position": {
          "x": 540,
          "y": 1160
        }
      },
      {
        "type": "action",
        "data": {
          "comment": "📝 NOTION SEITEN-SPEICHERUNG\n\n📋 Beschreibung:\nSpeichert den fertigen Competitive Intelligence Report automatisch als formatierte Notion-Seite. So haben Sie eine zentrale, durchsuchbare Historie aller Analysen mit Zeitstempel und professioneller Formatierung.\n\n⚙️ Setup - WICHTIG:\n1. Notion-Connection ist bereits verbunden ✓\n2. Passen Sie 'parentId' an:\n   - Aktuell: Wird in Ihrem persönlichen Workspace gespeichert\n   - Alternative: Geben Sie eine spezifische Notion-Seiten-ID ein, um Reports in einem bestimmten Bereich zu sammeln\n3. Der Titel wird automatisch mit aktuellem Datum generiert\n\n🎨 Personalisierungsoptionen:\n- Speicherort ändern: Setzen Sie 'parentId' auf eine spezifische Notion-Seiten-ID (z.B. eine \"Competitive Intelligence\" Übersichtsseite)\n- Titel-Format anpassen: Ändern Sie den Prompt für 'title' (z.B. \"CI Report - KW [Kalenderwoche] - [Datum]\")\n- Content-Format ändern: Passen Sie die Struktur im 'content' Prompt an (Überschriften, Reihenfolge, Formatierung)\n- Icon ändern: Ändern Sie das Emoji im 'icon' Feld (z.B. 🎯, 📈, 🔍)\n- Zusätzliche Tools: Fügen Sie parallel eine Slack-Benachrichtigung oder E-Mail hinzu\n\n💡 Tipps:\n- Erstellen Sie in Notion eine dedizierte Seite für alle CI-Reports und nutzen Sie deren ID als parentId\n- Die Reports werden chronologisch sortiert und sind durchsuchbar\n- Sie können Notion-Datenbanken nutzen für noch bessere Organisation",
          "executionId": null,
          "errorHandling": {
            "strategy": "stop"
          },
          "slug": "saveToNotion",
          "actionId": "7dba4335-2c76-4648-82ab-5a731759245d",
          "config": {
            "connectionId": null,
            "requiresConfirmation": false,
            "modelId": "c968689a-c0d9-49de-aa76-b10ed15ebb0e",
            "fields": {
              "icon": {
                "mode": "manual",
                "value": "📊",
                "prompt": null
              },
              "title": {
                "mode": "prompt",
                "value": null,
                "prompt": "Erstelle einen Titel im Format: Wettbewerber-Analyse - [aktuelles Datum]"
              },
              "content": {
                "mode": "prompt",
                "value": null,
                "prompt": "Erstelle einen gut strukturierten Notion-Report mit folgenden Inhalten:\n\n# Wettbewerber-Analyse - [Aktuelles Datum]\n\n## Überblick\n{{competitiveAnalyst.output.structured.summary}}\n\n## Produktentwicklungen\n{{competitiveAnalyst.output.structured.product_insights}}\n\n## Content-Strategien\n{{competitiveAnalyst.output.structured.content_strategy}}\n\n## Branchentrends\n{{competitiveAnalyst.output.structured.industry_trends}}\n\n## Wettbewerbspositionierung\n{{competitiveAnalyst.output.structured.competitor_positioning}}\n\n## Handlungsempfehlungen\n{{competitiveAnalyst.output.structured.top_priority_actions}}\n\n---\n**Analysierte Artikel:** {{competitiveAnalyst.output.structured.articles_analyzed}}"
              },
              "parentId": {
                "mode": "manual",
                "value": "workspace",
                "prompt": null
              },
              "parentType": {
                "mode": "manual",
                "value": "page_id",
                "prompt": null
              },
              "createInPersonalRoot": {
                "mode": "manual",
                "value": "true",
                "prompt": null
              }
            }
          }
        },
        "id": "c2650ac3-ed4c-4021-8251-a9e710470a63",
        "position": {
          "x": 2172,
          "y": 1160
        }
      }
    ],
    "edges": [
      {
        "id": "b5da6d9e-b611-44a5-ac36-f7b93f2b92a2",
        "source": "85766811-22f9-4475-8c2b-14dd98e341fb",
        "target": "152e4721-b7eb-446d-9562-04930ed4dee5",
        "animated": false,
        "sourceHandle": "output-success",
        "targetHandle": "input-default",
        "conditionId": null
      },
      {
        "id": "b2eb1555-61fb-4c1e-a63c-13c774be9a53",
        "source": "004431d7-e8e0-4aed-acb3-aa6c684887e8",
        "target": "3894616d-9a3e-4f01-8b07-3217ac50b157",
        "animated": false,
        "sourceHandle": "output-success",
        "targetHandle": "input-default",
        "conditionId": null
      },
      {
        "id": "f006af0d-2706-4a43-b0b1-ec65c9178f78",
        "source": "004431d7-e8e0-4aed-acb3-aa6c684887e8",
        "target": "74fb82e8-024f-4999-8b32-7c2644e2bb39",
        "animated": false,
        "sourceHandle": "output-success",
        "targetHandle": "input-default",
        "conditionId": null
      },
      {
        "id": "e2e7d501-008a-4b23-8fd1-2a175aa42413",
        "source": "004431d7-e8e0-4aed-acb3-aa6c684887e8",
        "target": "85766811-22f9-4475-8c2b-14dd98e341fb",
        "animated": false,
        "sourceHandle": "output-success",
        "targetHandle": "input-default",
        "conditionId": null
      },
      {
        "id": "366997e4-1902-42be-8abc-ee0898ada368",
        "source": "99db822c-3eab-4ad8-bdb2-b77581271c86",
        "target": "c2650ac3-ed4c-4021-8251-a9e710470a63",
        "animated": false,
        "sourceHandle": "output-success",
        "targetHandle": "input-default",
        "conditionId": null
      },
      {
        "id": "1c2c07aa-1ed5-4876-a707-48cc1398be92",
        "source": "152e4721-b7eb-446d-9562-04930ed4dee5",
        "target": "99db822c-3eab-4ad8-bdb2-b77581271c86",
        "animated": false,
        "sourceHandle": "output-success",
        "targetHandle": "input-default",
        "conditionId": null
      }
    ]
  }
}