{
  "id": "kXnhg0yvw8xoftxs",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Brand Crisis & Reputation Monitor",
  "tags": [],
  "nodes": [
    {
      "id": "650fc6ce-0244-4533-8c40-5b548015b6e3",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1216,
        368
      ],
      "parameters": {
        "width": 427,
        "height": 513,
        "content": "## \ud83d\udee1\ufe0f Brand Crisis & Reputation Monitor\n\n### How it works\nThis workflow continuously monitors online discussions about your brand across Reddit, Glassdoor, and other platforms. It uses Google's AI-powered search to gather insights, then analyzes each mention with AI to detect sentiment, reputation risks, and potential crises. When high-risk issues are detected\u2014like public complaints, allegations, or viral negativity\u2014it instantly alerts your team via Google Chat and creates an urgent task in Asana.\n\n### Setup steps\n1. Connect your SerpAPI credentials for search access\n2. Add Azure OpenAI credentials for AI risk analysis\n3. Connect Google Chat (OAuth2) for crisis alerts\n4. Link your Asana workspace for task creation\n5. Customize the search query with your brand name\n6. Test the workflow manually before enabling the hourly schedule"
      },
      "typeVersion": 1
    },
    {
      "id": "917d9a20-5cab-4704-b4f2-e46b069a3d35",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -736,
        400
      ],
      "parameters": {
        "color": 2,
        "width": 256.1797752808989,
        "height": 142.92696629213475,
        "content": "## \u23f0 Automated Trigger\nRuns hourly to continuously monitor brand mentions across social platforms and review sites."
      },
      "typeVersion": 1
    },
    {
      "id": "c65bbef6-f4b3-4083-a317-d08ae74982e8",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -448,
        368
      ],
      "parameters": {
        "color": 2,
        "width": 463.1460674157303,
        "height": 191.01123595505618,
        "content": "## \ud83d\udd0d Search & Data Collection\nFetches brand mentions from Reddit and review sites using Google AI Mode, then parses all insights, references, and key points into structured data."
      },
      "typeVersion": 1
    },
    {
      "id": "9d3f68df-14d8-44b9-b78b-dbeefca47fb8",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        64,
        384
      ],
      "parameters": {
        "color": 2,
        "width": 463.1460674157303,
        "height": 190.33707865168537,
        "content": "## \ud83e\udd16 AI Risk Detection\nAnalyzes each mention for sentiment, reputation risk, and crisis indicators using Azure OpenAI. Outputs clean JSON with risk levels and action recommendations."
      },
      "typeVersion": 1
    },
    {
      "id": "b564f411-d677-456e-8552-177bdadf0e9f",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        640,
        304
      ],
      "parameters": {
        "color": 2,
        "width": 359.3932584269663,
        "height": 342.3370786516854,
        "content": "## \ud83d\udea8 Crisis Response\nWhen high-risk issues are detected, sends immediate alerts to Google Chat and creates priority tasks in Asana for rapid team response."
      },
      "typeVersion": 1
    },
    {
      "id": "7a79c070-4c1a-4b3c-b6fa-177dc07e6674",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1152,
        160
      ],
      "parameters": {
        "color": 3,
        "width": 298,
        "height": 174,
        "content": "## \ud83d\udd10 Credentials & Security\nUse OAuth2 for Google Chat and Asana. Store SerpAPI and Azure OpenAI keys securely in n8n credentials. Never hardcode tokens in the workflow."
      },
      "typeVersion": 1
    },
    {
      "id": "120f48d2-41e2-49db-a0c4-c1b4ed986460",
      "name": "Schedule: Every Hour",
      "type": "n8n-nodes-base.cron",
      "position": [
        -656,
        576
      ],
      "parameters": {
        "triggerTimes": {
          "item": [
            {
              "mode": "everyHour"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7a2b60d2-2efa-4d3b-83ba-99dcf9988e0b",
      "name": "Filter: High Risk Only",
      "type": "n8n-nodes-base.if",
      "position": [
        592,
        576
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{$json[\"risk_level\"]}}",
              "value2": "High"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "5e152d6b-caf7-4e19-8f50-85a5b3dc3d38",
      "name": "Send Google Chat Alert",
      "type": "n8n-nodes-base.googleChat",
      "position": [
        816,
        480
      ],
      "parameters": {
        "spaceId": "={{ $json.space }}",
        "messageUi": {},
        "authentication": "oAuth2",
        "additionalFields": {}
      },
      "credentials": {
        "googleChatOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2375a1f8-0727-4434-830c-053fc6ad4a08",
      "name": "Create Asana Crisis Task",
      "type": "n8n-nodes-base.asana",
      "position": [
        816,
        672
      ],
      "parameters": {
        "name": "\ud83d\udea8 Social Crisis Detected \u2014 Immediate Action Required",
        "workspace": "1212551193156936",
        "authentication": "oAuth2",
        "otherProperties": {}
      },
      "credentials": {
        "asanaOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "fe06590d-fd23-41ec-9525-e5c8bb5fb343",
      "name": "Fetch Brand Mentions (SerpAPI)",
      "type": "n8n-nodes-serpapi.serpApi",
      "position": [
        -432,
        576
      ],
      "parameters": {
        "q": "site:reddit.com \"[Your Brand Name]\" reviews",
        "operation": "google_ai_mode",
        "requestOptions": {},
        "additionalFields": {}
      },
      "credentials": {
        "serpApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a4a54970-23ba-4d29-a685-e5d2a1d389e8",
      "name": "Parse Search Results",
      "type": "n8n-nodes-base.code",
      "position": [
        -208,
        576
      ],
      "parameters": {
        "jsCode": "const output = [];\n\nfor (const item of items) {\n  const data = item.json;\n\n  const googleAiModeUrl = data.search_metadata?.google_ai_mode_url || null;\n  const references = data.references || [];\n  const textBlocks = data.text_blocks || [];\n\n  // 1\ufe0f\u20e3 Parse text_blocks (paragraphs + lists)\n  for (const block of textBlocks) {\n    // Paragraphs\n    if (block.type === \"paragraph\" && block.snippet) {\n      output.push({\n        source: \"SerpAPI AI Mode\",\n        site: \"Aggregated\",\n        title: \"Summary Insight\",\n        text: block.snippet,\n        url: null,\n        google_ai_mode_url: googleAiModeUrl,\n        category: \"overview\",\n        is_reddit: false\n      });\n    }\n\n    // Lists (complaints / praise / signals)\n    if (block.type === \"list\" && Array.isArray(block.list)) {\n      for (const entry of block.list) {\n        if (entry.snippet) {\n          output.push({\n            source: \"SerpAPI AI Mode\",\n            site: \"Aggregated\",\n            title: \"Key Point\",\n            text: entry.snippet,\n            url: null,\n            google_ai_mode_url: googleAiModeUrl,\n            category: \"key_insight\",\n            is_reddit: false\n          });\n        }\n      }\n    }\n  }\n\n  // 2\ufe0f\u20e3 Parse references (site-wise sentiment sources)\n  for (const ref of references) {\n    const site =\n      ref.source?.toLowerCase().includes(\"reddit\")\n        ? \"Reddit\"\n        : ref.source?.toLowerCase().includes(\"glassdoor\")\n        ? \"Glassdoor\"\n        : ref.source?.toLowerCase().includes(\"ambitionbox\")\n        ? \"AmbitionBox\"\n        : ref.source?.toLowerCase().includes(\"clutch\")\n        ? \"Clutch\"\n        : \"Other\";\n\n    output.push({\n      source: \"Reference\",\n      site,\n      title: ref.title || \"Untitled\",\n      text: ref.snippet || \"\",\n      url: ref.link || null,\n      google_ai_mode_url: googleAiModeUrl,\n      category:\n        site === \"Reddit\"\n          ? \"public_discussion\"\n          : site === \"Clutch\"\n          ? \"client_review\"\n          : \"employee_review\",\n      is_reddit: site === \"Reddit\"\n    });\n  }\n}\n\n// 3\ufe0f\u20e3 Return each insight as a separate n8n item\nreturn output.map(item => ({ json: item }));\n"
      },
      "typeVersion": 2
    },
    {
      "id": "274cad93-b06d-498b-af01-b17c16c5961f",
      "name": "AI Risk Analyzer",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        16,
        576
      ],
      "parameters": {
        "text": "=Analyze the following single social insight collected from online platforms.\n\nInput object:\n{{ JSON.stringify($json, null, 2) }}\n\nYour tasks:\n1. Identify the sentiment (Positive / Neutral / Negative).\n2. Determine whether this content indicates a reputation or crisis risk.\n3. Assign a risk level (Low / Medium / High).\n4. Provide a short, factual reason (1\u20132 lines only).\n5. Identify the primary source platform (Reddit, Glassdoor, AmbitionBox, Clutch, Other).\n6. State whether immediate action is required (true / false).\n\nRespond STRICTLY in the following JSON format:\n\n{\n  \"sentiment\": \"\",\n  \"risk_detected\": true | false,\n  \"risk_level\": \"\",\n  \"reason\": \"\",\n  \"source_platform\": \"\",\n  \"immediate_action_required\": true | false\n}\n",
        "options": {
          "systemMessage": "You are a Social Media Risk & Crisis Detection Analyst AI.\n\nYour responsibility is to analyze public online content from sources such as\nReddit, Glassdoor, AmbitionBox, Clutch, and similar platforms to detect\nreputation risks, negative sentiment spikes, and early crisis signals\nfor a company or brand.\n\nYou must:\n- Focus on sentiment, complaints, allegations, policy issues, unethical behavior,\n  workplace pressure, scams, or public backlash.\n- Treat Reddit and public forums as high-signal sources for crisis detection.\n- Be conservative but decisive when classifying risk levels.\n- Output strictly valid JSON only.\n- Never include explanations outside JSON.\n- Never hallucinate facts not present in the input.\n\nRisk level definitions:\n- Low: Mostly positive or neutral sentiment, no reputational threat.\n- Medium: Repeated negative sentiment or concerns, but no immediate crisis.\n- High: Strong negative sentiment, allegations, unethical practices, or viral risk.\n\nIf the content is insufficient to determine risk, classify as Low with reason.\n"
        },
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "26143f70-bf89-4dcd-9832-9526a61e3b86",
      "name": "Azure OpenAI Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatAzureOpenAi",
      "position": [
        96,
        800
      ],
      "parameters": {
        "model": "gpt-4o-mini",
        "options": {}
      },
      "credentials": {
        "azureOpenAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "d7bb670f-d667-4c14-9c52-ecdfb602519d",
      "name": "Clean AI Output",
      "type": "n8n-nodes-base.code",
      "position": [
        368,
        576
      ],
      "parameters": {
        "jsCode": "const cleanedOutput = [];\n\nfor (const item of items) {\n  const raw = item.json.output;\n\n  if (!raw || typeof raw !== \"string\") {\n    continue;\n  }\n\n  try {\n    const parsed = JSON.parse(raw);\n\n    cleanedOutput.push({\n      sentiment: parsed.sentiment || \"Unknown\",\n      risk_detected: Boolean(parsed.risk_detected),\n      risk_level: parsed.risk_level || \"Low\",\n      reason: parsed.reason || \"\",\n      source_platform: parsed.source_platform || \"Other\",\n      immediate_action_required: Boolean(parsed.immediate_action_required)\n    });\n\n  } catch (error) {\n    // Fail-safe for malformed JSON\n    cleanedOutput.push({\n      sentiment: \"Unknown\",\n      risk_detected: false,\n      risk_level: \"Low\",\n      reason: \"Failed to parse AI response\",\n      source_platform: \"Other\",\n      immediate_action_required: false\n    });\n  }\n}\n\n// Return clean items (one object per insight)\nreturn cleanedOutput.map(obj => ({ json: obj }));\n"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "a2e9c475-bcdb-4613-b572-2bcc3334fff2",
  "connections": {
    "Clean AI Output": {
      "main": [
        [
          {
            "node": "Filter: High Risk Only",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Risk Analyzer": {
      "main": [
        [
          {
            "node": "Clean AI Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Azure OpenAI Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Risk Analyzer",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse Search Results": {
      "main": [
        [
          {
            "node": "AI Risk Analyzer",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule: Every Hour": {
      "main": [
        [
          {
            "node": "Fetch Brand Mentions (SerpAPI)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter: High Risk Only": {
      "main": [
        [
          {
            "node": "Send Google Chat Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Create Asana Crisis Task",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Brand Mentions (SerpAPI)": {
      "main": [
        [
          {
            "node": "Parse Search Results",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}