{
  "id": "Sler1Jv8uyaDt7cZ",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Track daily brand mentions from Hacker News to Slack with AI sentiment analysis",
  "tags": [],
  "nodes": [
    {
      "id": "2a7612de-ca5d-4f4d-b0d2-8cd75ab96323",
      "name": "Every Day at 09:00",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1312,
        464
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "cronExpression",
              "expression": "0 9 * * *"
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "f0061436-e3cf-4516-abbf-35c3e6413505",
      "name": "Brand Config",
      "type": "n8n-nodes-base.set",
      "position": [
        -1088,
        464
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "brand-field",
              "name": "brand",
              "type": "string",
              "value": "OpenAI"
            },
            {
              "id": "keywords-field",
              "name": "keywords",
              "type": "string",
              "value": "OpenAI"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "81966f20-5f1c-4e58-b9b2-8cc6f7726a3a",
      "name": "Fetch Reddit Mentions",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -864,
        464
      ],
      "parameters": {
        "url": "=http://hn.algolia.com/api/v1/search?query={{$json[\"keywords\"]}}&tags=story",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "User-Agent",
              "value": "n8n-monitor-bot"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "0e9f423c-3298-4524-a5cf-7a6d799a3d87",
      "name": "Normalize Mentions",
      "type": "n8n-nodes-base.code",
      "position": [
        -640,
        464
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst brand = $('Brand Config').first().json.brand\n\nconst normalized = [];\n\nitems.forEach(item => {\n  const hits = item.json.hits || [];\n  \n  hits.forEach(hit => {\n    normalized.push({\n      platform: 'Hacker News',\n      title: hit.title || '',\n      url: hit.url || `https://news.ycombinator.com/item?id=${hit.objectID}`,\n      snippet: hit.story_text || hit.title || '',\n      author: hit.author || 'unknown',\n      created_at: hit.created_at || new Date(hit.created_at_i * 1000).toISOString(),\n      brand: brand,\n      points: hit.points || 0,\n      num_comments: hit.num_comments || 0\n    });\n  });\n});\n\nreturn normalized.map(item => ({ json: item }));"
      },
      "typeVersion": 2
    },
    {
      "id": "cd01b4a3-fc61-43fb-8d32-b78ccaadd62f",
      "name": "Mentions Exist?",
      "type": "n8n-nodes-base.if",
      "position": [
        -192,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "mention-exists",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $items().length }}",
              "rightValue": 0
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "bbb9eddd-8d0f-48d1-b5a8-f794e1462f7c",
      "name": "Build Daily Summary",
      "type": "n8n-nodes-base.code",
      "position": [
        720,
        320
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst brand = items[0]?.json.brand || 'VivekLabs';\n\nconst totalMentions = items.length;\nconst sentimentCounts = {\n  positive: 0,\n  negative: 0,\n  neutral: 0\n};\n\nitems.forEach(item => {\n  const sentiment = item.json.sentiment || 'neutral';\n  if (sentimentCounts[sentiment] !== undefined) {\n    sentimentCounts[sentiment]++;\n  }\n});\n\nconst top10 = items.slice(0, 10);\n\nlet reportText = `*Daily Brand Mentions Report for ${brand}*\\n\\n`;\nreportText += `\ud83d\udcca *Total Mentions:* ${totalMentions}\\n`;\nreportText += `\u2705 Positive: ${sentimentCounts.positive}\\n`;\nreportText += `\u274c Negative: ${sentimentCounts.negative}\\n`;\nreportText += `\u26aa Neutral: ${sentimentCounts.neutral}\\n\\n`;\nreportText += `*Top Mentions:*\\n`;\n\ntop10.forEach((item, index) => {\n  const data = item.json;\n  const emoji = data.sentiment === 'positive' ? '\u2705' : data.sentiment === 'negative' ? '\u274c' : '\u26aa';\n  const title = data.title || 'No title';\n  const platform = data.platform || 'Hackers Info';\n  const topic = data.topic || 'other';\n  const urgency = data.urgency || 'low';\n  const url = data.url || '';\n  \n  reportText += `${index + 1}. ${emoji} *${title}*\\n`;\n  reportText += `   Platform: ${platform} | Topic: ${topic} | Urgency: ${urgency}\\n`;\n  reportText += `   ${url}\\n\\n`;\n});\n\nreturn [{ json: { text: reportText } }];"
      },
      "typeVersion": 2
    },
    {
      "id": "bfea6659-b7e3-4adf-b01c-72062f040af5",
      "name": "Send Daily Report to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        944,
        320
      ],
      "parameters": {
        "text": "={{$json[\"text\"]}}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "6207ae42-847f-4f24-8497-4adddf98d690",
      "name": "No Mentions Message",
      "type": "n8n-nodes-base.set",
      "position": [
        160,
        608
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "no-mentions-text",
              "name": "text",
              "type": "string",
              "value": "=No new AI engine mentions were found today for {{$node[\"Brand Config\"].json[\"brand\"]}}."
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "bcad6160-5453-456d-b264-fc991c42b7ac",
      "name": "Send No Mentions to Slack",
      "type": "n8n-nodes-base.slack",
      "position": [
        496,
        608
      ],
      "parameters": {
        "text": "={{$json[\"text\"]}}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "8ce97211-b4e1-4e1d-9e15-fd6ebd320247",
      "name": "Checking Score",
      "type": "n8n-nodes-base.if",
      "position": [
        -416,
        464
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "mention-exists",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.num_comments }}",
              "rightValue": 1000
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "def75b6a-d57f-44f2-8a1c-64d0552e6baa",
      "name": "OpenAI Chat Model - GPT-4o-mini",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        32,
        432
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini",
          "cachedResultName": "gpt-4o-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "b49bd7bc-b0ed-4bb2-a495-3eb9dbd83428",
      "name": "Memory - Conversation Buffer",
      "type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
      "position": [
        160,
        432
      ],
      "parameters": {
        "sessionKey": "\"GEO Classify\"",
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.3
    },
    {
      "id": "6b4a610e-a656-45a3-87e5-9d564efc88f2",
      "name": "Output Parser - Structured JSON",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        288,
        432
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"sentiment\": \"positive | negative | neutral\",\n  \"stance\": \"supports | criticizes | questioning | just mentioning\",\n  \"topic\": \"pricing | quality | support | features | bugs | performance | general | other\",\n  \"urgency\": \"low | medium | high\",\n  \"reason\": \"short explanation string\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "9428daf8-21da-47cc-9d7d-88c05404ad20",
      "name": "AI Agent - Classify Mention Sentiments",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        96,
        208
      ],
      "parameters": {
        "text": "=Brand: {{$json[\"brand\"]}}\nPlatform: {{$json[\"platform\"]}}\nTitle: {{$json[\"title\"]}}\nSnippet: {{$json[\"snippet\"]}}\n\nDetermine how this mention talks about the brand.\n",
        "options": {
          "systemMessage": "=You are a brand reputation analyst.\n\nClassify each mention of the brand by:\n- sentiment: positive, negative, or neutral\n- stance: supports, criticizes, questioning, or just mentioning\n- topic: one of [pricing, quality, support, features, bugs, performance, general, other]\n- urgency: low, medium, or high.\n\nYou MUST respond with STRICT JSON only, no markdown, like:\n{\n  \"sentiment\": \"positive | negative | neutral\",\n  \"stance\": \"supports | criticizes | questioning | just mentioning\",\n  \"topic\": \"pricing | quality | support | features | bugs | performance | general | other\",\n  \"urgency\": \"low | medium | high\",\n  \"reason\": \"short explanation string\"\n}\n"
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 2.1
    },
    {
      "id": "485ed40a-9751-4ba2-aad7-28b8f9f8f6af",
      "name": "Format Sentiment Data",
      "type": "n8n-nodes-base.set",
      "position": [
        496,
        320
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "8e26c379-a8fa-4b5e-9d9b-a12f22686645",
              "name": "sentiment",
              "type": "string",
              "value": "={{ $json.output.sentiment }}"
            },
            {
              "id": "d9267ace-ee8c-4662-aa08-b250c6556ffa",
              "name": "stance",
              "type": "string",
              "value": "={{ $json.output.stance }}"
            },
            {
              "id": "d916c361-c65f-4029-b466-ea7fe76ba5c5",
              "name": "topic",
              "type": "string",
              "value": "={{ $json.output.topic }}"
            },
            {
              "id": "b71b8175-4c7f-45fd-bb29-1ffc3c4b3436",
              "name": "urgency",
              "type": "string",
              "value": "={{ $json.output.urgency }}"
            },
            {
              "id": "7c9dcebe-a2a0-4529-bc0c-ad6cc788898d",
              "name": "reason",
              "type": "string",
              "value": "={{ $json.output.reason }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "cf1fb0da-f564-4230-8b8e-b4d811b04cc5",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1408,
        -384
      ],
      "parameters": {
        "width": 448,
        "height": 704,
        "content": "## Daily AI Engine Mentions Tracker \u2013 Overview\n\nThis workflow tracks daily online mentions of a selected brand and sends a summary to Slack. It checks Hacker News each morning, processes the results, analyzes sentiment and urgency with AI, and sends either a detailed report or a \u201cno mentions today\u201d message. This helps teams monitor brand reputation and identify issues early.\n\n### How it works\n1. A daily trigger runs at 09:00 and loads brand configuration.\n2. Mentions are fetched from Hacker News based on brand keywords.\n3. Mentions are normalized into a clean structure.\n4. AI classifies each mention\u2019s sentiment, stance, topic, and urgency.\n5. A daily summary is generated, showing total mentions and the top 10 items.\n6. Slack receives either a detailed report or a no-mentions message.\n\n### Setup steps\n- Set your brand name and keyword inside the \u201cBrand Config\u201d node.\n- Add Slack credentials and select the channel to send reports.\n- Add OpenAI credentials for GPT-4o-mini.\n- Run a sample execution to verify formatting.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "c71bebc3-69e1-4b2f-b3b5-9316e69d5f5a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1392,
        352
      ],
      "parameters": {
        "color": 2,
        "width": 448,
        "height": 304,
        "content": "## Trigger & Brand Setup\nRuns daily at 09:00 and loads the brand name + keyword filters.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "0e11af5a-7d41-4fbc-bf13-1a974922145b",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -928,
        352
      ],
      "parameters": {
        "color": 2,
        "width": 224,
        "height": 304,
        "content": "## Fetch Mentions\nQueries Hacker News for new stories matching the brand keyword.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "4ee80f6b-2907-4068-9295-8f324a5865b9",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -688,
        320
      ],
      "parameters": {
        "color": 2,
        "width": 614,
        "height": 336,
        "content": "## Normalize Mentions\nConverts raw API results into a clean structure for AI classification.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "371de316-878a-48c4-a492-394605e7504b",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -16,
        112
      ],
      "parameters": {
        "color": 2,
        "width": 448,
        "height": 464,
        "content": "## AI Classification\nAI evaluates sentiment, stance, topic, and urgency for each mention.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "d15ba049-379e-4f68-a17c-51f614aee438",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        448,
        112
      ],
      "parameters": {
        "color": 2,
        "width": 400,
        "height": 464,
        "content": "## Format Sentiment Output and Summary\nMaps AI-generated sentiment fields into clean JSON for reporting.Builds a daily Slack-friendly summary including top trending mentions.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "84710f35-de7d-4b58-8c4b-5f043d4573a9",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        864,
        112
      ],
      "parameters": {
        "color": 2,
        "height": 464,
        "content": "## Slack Notifications\nSends either a full daily report or a \u201cno mentions today\u201d message.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "fac8347b-4957-4dee-b866-4955bf268dd7",
      "name": "Error Handling",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1376,
        1040
      ],
      "parameters": {
        "color": 2,
        "width": 584,
        "height": 276,
        "content": "## Error Handling\nCaptures workflow failures and sends details to Slack for quick debugging.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "15ea6ce7-3a12-4b28-aa15-691fbc6e1f83",
      "name": "Error Handler Trigger",
      "type": "n8n-nodes-base.errorTrigger",
      "position": [
        -1232,
        1152
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "7e3a85d0-6586-4a32-b5b3-99aca1fe5f4d",
      "name": "Slack: Send Error Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        -1024,
        1152
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f *Error in API Error Catalog Workflow*\n*Node:* {{ $json.node.name }}\n*Message:* {{ $json.error.message }}\n*Time:* {{ $json.timestamp }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "="
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.3
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "b9d49bbe-de92-4ac0-afd6-7d04141ab9da",
  "connections": {
    "Brand Config": {
      "main": [
        [
          {
            "node": "Fetch Reddit Mentions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Checking Score": {
      "main": [
        [
          {
            "node": "Mentions Exist?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mentions Exist?": {
      "main": [
        [
          {
            "node": "AI Agent - Classify Mention Sentiments",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No Mentions Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Every Day at 09:00": {
      "main": [
        [
          {
            "node": "Brand Config",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize Mentions": {
      "main": [
        [
          {
            "node": "Checking Score",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Daily Summary": {
      "main": [
        [
          {
            "node": "Send Daily Report to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "No Mentions Message": {
      "main": [
        [
          {
            "node": "Send No Mentions to Slack",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Error Handler Trigger": {
      "main": [
        [
          {
            "node": "Slack: Send Error Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Reddit Mentions": {
      "main": [
        [
          {
            "node": "Normalize Mentions",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Sentiment Data": {
      "main": [
        [
          {
            "node": "Build Daily Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Memory - Conversation Buffer": {
      "ai_memory": [
        [
          {
            "node": "AI Agent - Classify Mention Sentiments",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model - GPT-4o-mini": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent - Classify Mention Sentiments",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Output Parser - Structured JSON": {
      "ai_outputParser": [
        [
          {
            "node": "AI Agent - Classify Mention Sentiments",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent - Classify Mention Sentiments": {
      "main": [
        [
          {
            "node": "Format Sentiment Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}