{
  "id": "Wglo1UunAUFbOnT0",
  "name": "Facebook Mention Sentiment Tracker with Alerts",
  "tags": [],
  "nodes": [
    {
      "id": "b2d6f4e1-df0a-4d44-80a8-3f1bc6cb4759",
      "name": "Facebook Mention Received",
      "type": "n8n-nodes-base.facebookTrigger",
      "position": [
        -112,
        400
      ],
      "parameters": {
        "appId": "<__PLACEHOLDER_VALUE__facebook_app_id__>",
        "fields": [
          "mention"
        ],
        "object": "page",
        "options": {}
      },
      "typeVersion": 1
    },
    {
      "id": "7e75e24a-5e57-4b33-a907-c5c9ac96920a",
      "name": "Sentiment & Topic Analysis",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        128,
        400
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-2.5-flash",
          "cachedResultName": "models/gemini-2.5-flash"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "role": "model",
              "content": "=You are a sentiment analysis assistant. Analyze the Facebook mention and classify the sentiment as positive, neutral or negative. Also extract the key topic or theme of the mention.\n\nReturn ONLY valid JSON:\n\n{\n  \"sentiment\": \"positive | neutral | negative\",\n  \"topic\": \"string\",\n  \"confidence\": number (0 to 1)\n}\n"
            },
            {
              "content": "={{ $json.message }}"
            }
          ]
        },
        "jsonOutput": true,
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "bdc5078f-c3ba-4e80-b4ac-d33a512fb7cb",
      "name": "Clean AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        480,
        400
      ],
      "parameters": {
        "jsCode": "// \u2705 Correct path (NO [0])\nconst raw = $json?.content?.parts?.[0]?.text;\n\n// Debug (optional)\nif (!raw) {\n  return [{\n    json: {\n      error: \"No AI response found\",\n      original: $json\n    }\n  }];\n}\n\n// Extract JSON safely\nconst match = raw.match(/\\{[\\s\\S]*\\}/);\n\nlet parsed = {};\n\nif (match) {\n  try {\n    parsed = JSON.parse(match[0]);\n  } catch (e) {\n    parsed = {};\n  }\n}\n\n// Normalize\nconst sentiment = parsed.sentiment?.toLowerCase() || \"unknown\";\n\n// Return clean data\nreturn [\n  {\n    json: {\n      sentiment,\n      topic: parsed.topic || \"unknown\",\n      confidence: parsed.confidence || 0,\n      message: $node[\"Facebook Mention Received\"].json.message,\n      user_name: $node[\"Facebook Mention Received\"].json.from.name,\n      created_time: new Date($node[\"Facebook Mention Received\"].json.created_time).toISOString()\n    }\n  }\n];"
      },
      "typeVersion": 2
    },
    {
      "id": "e407810d-32e6-4fa4-808c-4db49e90aae6",
      "name": " Store Mention (Supabase)",
      "type": "n8n-nodes-base.supabase",
      "onError": "continueErrorOutput",
      "position": [
        816,
        400
      ],
      "parameters": {
        "tableId": "mentions",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "message",
              "fieldValue": "={{ $json.message }}"
            },
            {
              "fieldId": "sentiment",
              "fieldValue": "={{ $json.sentiment }}"
            },
            {
              "fieldId": "topic",
              "fieldValue": "={{ $json.topic }}"
            },
            {
              "fieldId": "user_name",
              "fieldValue": "={{ $json.user_name }}"
            },
            {
              "fieldId": "created_time",
              "fieldValue": "={{ $json.created_time }}"
            },
            {
              "fieldId": "confidence",
              "fieldValue": "={{ $json.confidence }}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "3d4685e7-790e-4a93-853f-6864c4f9d15b",
      "name": "Is Positive Sentiment?",
      "type": "n8n-nodes-base.if",
      "position": [
        1280,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "2ecbaedf-1524-4ef2-b609-4ed1161ea1b5",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.sentiment }}",
              "rightValue": "positive"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "e2782406-abf4-4c58-9984-53e2b11096f9",
      "name": "Telegram (Positive Mention)",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1536,
        -16
      ],
      "parameters": {
        "text": "=\ud83d\udd14 *New Facebook Mention*\n\n*Sentiment:* {{ $('Clean AI Response').item.json.sentiment }}\n*Topic:* {{ $('Clean AI Response').item.json.topic }}\n*Message:* {{ $('Facebook Mention Received').item.json.message }}\n\n*From:* {{ $('Facebook Mention Received').item.json.from.name }}\n*Time:* {{ $('Facebook Mention Received').item.json.created_time }}",
        "chatId": "<__PLACEHOLDER_VALUE__telegram_chat_id__>",
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "d774b397-4de3-4486-a558-459e74d2441b",
      "name": "Storage Failure (Telegram)",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1440,
        816
      ],
      "parameters": {
        "text": "=\u26a0\ufe0f *Storage Failed*\n\nFailed to log Facebook mention to Supabase.\n\n*Error:* {{ $json.error.message }}\n\n*Original Mention:* {{ $('Facebook Mention Received').item.json.message }}",
        "chatId": "<__PLACEHOLDER_VALUE__telegram_chat_id__>",
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "28adb81b-2325-40d8-b53d-06f850fe2a62",
      "name": "Keyword & Critical Detection",
      "type": "n8n-nodes-base.code",
      "position": [
        1264,
        384
      ],
      "parameters": {
        "jsCode": "const keywords = [\"refund\", \"cancel\", \"bug\", \"slow\"];\n\nconst message = $node[\"Facebook Mention Received\"].json.message.toLowerCase();\n\nconst matchedKeywords = keywords.filter(k => message.includes(k));\n\nreturn [{\n  json: {\n    ...$json, // \u2705 this was missing\n    keywords: matchedKeywords,\n    is_critical: matchedKeywords.length > 0\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "e4773c17-69c5-42ce-a196-53eaf97467b1",
      "name": "Is Critical or Negative?",
      "type": "n8n-nodes-base.if",
      "position": [
        1472,
        384
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "a38ec565-8be6-4d23-9ad4-e368761b86f1",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.is_critical }}",
              "rightValue": false
            },
            {
              "id": "225866ba-74db-42c8-ab17-51f92859bc59",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.sentiment }}",
              "rightValue": "negative"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "afc6d23a-0ff6-49ed-9fe7-b33b4c277243",
      "name": "Slack (Critical Mention)",
      "type": "n8n-nodes-base.slack",
      "position": [
        1760,
        368
      ],
      "parameters": {
        "text": "=\ud83d\udea8 *CRITICAL FACEBOOK MENTION*  \ud83d\udc64 *User:* {{ $json.user_name }} \ud83d\udd52 *Time:* {{ $json.created_time }}  \ud83d\udcac *Message:* {{ $json.message }}  \ud83d\udcca *Analysis:* \u2022 Sentiment: *{{ $json.sentiment }}* \u2022 Topic: *{{ $json.topic }}* \u2022 Confidence: *{{ $json.confidence }}*  \ud83d\udea9 *Flags:* \u2022 Keywords: {{ $json.keywords }} \u2022 Critical: {{ $json.is_critical }}  \u26a1 *Action Required:* Immediate attention needed (possible refund / complaint case)",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "C09S57E2JQ2",
          "cachedResultName": "n8n"
        },
        "otherOptions": {}
      },
      "credentials": {
        "slackApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "7a14e008-1b61-4eac-9c6f-c392b52a8b8e",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 822,
        "height": 368,
        "content": "## Mention Ingestion & AI Analysis\nCaptures Facebook mentions, analyzes sentiment and topic using AI and formats the response into a clean, structured output for downstream processing."
      },
      "typeVersion": 1
    },
    {
      "id": "b214ba76-488a-4f28-834a-e422bf38f76a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        688,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 400,
        "height": 368,
        "content": "## Data Persistence (Supabase)\nStores processed mention data, including sentiment, topic and metadata, into Supabase for tracking, analytics and future reference."
      },
      "typeVersion": 1
    },
    {
      "id": "5c365578-caaa-4e32-bbe1-a7247a7dde34",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1168,
        272
      ],
      "parameters": {
        "color": 7,
        "width": 800,
        "height": 368,
        "content": "## Critical Detection & Alerting\nDetects keywords and negative sentiment, classifies critical mentions and triggers immediate Slack alerts for rapid response and issue resolution."
      },
      "typeVersion": 1
    },
    {
      "id": "171334fd-6caa-4544-bc3e-88720d09a0ae",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1168,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 784,
        "height": 320,
        "content": "## Positive Mention Notifications\nFilters positive mentions and sends real-time Telegram notifications to highlight good feedback and improve team visibility on user satisfaction."
      },
      "typeVersion": 1
    },
    {
      "id": "7c27a15d-82a4-42a3-81e5-7df84747354f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1168,
        672
      ],
      "parameters": {
        "color": 7,
        "width": 816,
        "height": 320,
        "content": "## Error Handling & Failure Alerts\nMonitors database failures and sends Telegram alerts with error details to ensure issues are quickly identified and resolved."
      },
      "typeVersion": 1
    },
    {
      "id": "aaa1ba06-35a9-4c97-ab30-d89277114164",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -704,
        -352
      ],
      "parameters": {
        "width": 464,
        "height": 992,
        "content": "## How This Workflow Works\n- The workflow is triggered whenever a new Facebook Page mention is received, capturing the message content, user details and timestamp.\n\n- The mention is sent to the Gemini AI model, which analyzes the sentiment (positive, neutral or negative) and extracts the main topic along with a confidence score.\n\n-  The response from the AI is cleaned and structured in a consistent JSON format to ensure it can be reliably used in further steps.\n\n- The processed data is stored in Supabase, allowing for historical tracking, analytics and reporting.\n\n- If the sentiment is positive, a Telegram notification is sent to highlight positive user feedback.\n\n- The workflow also checks for critical keywords (like refund, bug, cancel, slow) and evaluates whether the mention is critical or negative.\n\n- If a mention is classified as critical or negative, an alert is sent to Slack to ensure the team can take immediate action.\n\n- If any error occurs while storing data in Supabase, a failure alert is sent via Telegram to notify the team for quick resolution.\n\n\n## Setup Steps\n1. Configure the Facebook Trigger node by connecting your Facebook App and Page, ensuring webhook permissions for mention events are properly set.\n2. Set up the Gemini API credentials and configure the AI node to return structured JSON output for sentiment, topic and confidence.\n3. Add and configure the Code node to clean and normalize the AI response into a consistent format.\n4. Create a Supabase project, define the mentions table with required fields and connect it using the Service Role Secret key in n8n credentials.\n5. Configure the Telegram node by adding your bot token and chat ID to receive notifications for positive mentions and failure alerts.\n6. Set up the Slack node by connecting your Slack workspace and selecting the appropriate channel for critical alerts.\n7. Add IF nodes to define routing logic for positive mentions and critical/negative conditions based on sentiment and keyword detection.\n8. Test the workflow using sample data to verify end-to-end execution, ensuring all nodes trigger correctly and alerts are delivered as expected."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "e4217c83-d922-4145-9cf0-14c956d66601",
  "connections": {
    "Clean AI Response": {
      "main": [
        [
          {
            "node": " Store Mention (Supabase)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Positive Sentiment?": {
      "main": [
        [
          {
            "node": "Telegram (Positive Mention)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Critical or Negative?": {
      "main": [
        [
          {
            "node": "Slack (Critical Mention)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    " Store Mention (Supabase)": {
      "main": [
        [
          {
            "node": "Is Positive Sentiment?",
            "type": "main",
            "index": 0
          },
          {
            "node": "Keyword & Critical Detection",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Storage Failure (Telegram)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Facebook Mention Received": {
      "main": [
        [
          {
            "node": "Sentiment & Topic Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Sentiment & Topic Analysis": {
      "main": [
        [
          {
            "node": "Clean AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Keyword & Critical Detection": {
      "main": [
        [
          {
            "node": "Is Critical or Negative?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}