{
  "nodes": [
    {
      "id": "3db30f64-8081-4c8f-81e1-269a367f9ca1",
      "name": "Sticky Note - Overview",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -624,
        32
      ],
      "parameters": {
        "color": 5,
        "width": 400,
        "height": 640,
        "content": "## \ud83d\udccb AI Review Analyzer with Sentiment Analysis & Telegram Alerts\n\n**What this workflow does:**\nAutomatically analyzes customer reviews from Google Sheets using OpenAI GPT. Performs translation (Japanese \u2192 English), sentiment analysis, importance classification, and categorization. Results are written back to the spreadsheet, and urgent notifications are sent via Telegram for high-priority or negative reviews.\n\n**Who is this for:**\n- E-commerce businesses monitoring product reviews\n- Customer support teams prioritizing tickets\n- Marketing teams tracking brand sentiment\n\n**Setup Requirements:**\n1. Google Sheets with review data (columns: ReviewID, Keyword, ProcessStatus)\n2. OpenAI API credentials\n3. Telegram Bot Token & Chat ID\n\n**Customization Tips:**\n- Modify the AI prompt to change analysis criteria\n- Adjust sentiment threshold (-0.5) in the \"Check Importance & Sentiment\" node\n- Change notification format in Telegram nodes"
      },
      "typeVersion": 1
    },
    {
      "id": "4ae652d1-76b4-4c08-8ddd-45eacbc46f9e",
      "name": "Sticky Note - Step 1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -160,
        48
      ],
      "parameters": {
        "width": 280,
        "height": 96,
        "content": "### 1\ufe0f\u20e3 Trigger & Data Fetch\nSchedule trigger runs periodically to fetch review data from Google Sheets."
      },
      "typeVersion": 1
    },
    {
      "id": "7ae67ce7-8deb-4887-a0a7-21b4d9c606d5",
      "name": "Sticky Note - Step 2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        176,
        32
      ],
      "parameters": {
        "width": 280,
        "height": 96,
        "content": "### 2\ufe0f\u20e3 Filter & Format\nFilters only unprocessed reviews (empty ProcessStatus) and formats input data for AI analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "7cd12222-46dc-4a05-84bb-50dbbfe06f41",
      "name": "Sticky Note - Step 3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        672,
        -64
      ],
      "parameters": {
        "width": 280,
        "height": 200,
        "content": "### 3\ufe0f\u20e3 AI Analysis\nOpenAI GPT analyzes reviews:\n- Translation (JP \u2192 EN)\n- Sentiment scoring (-1.0 to +1.0)\n- Importance level (High/Medium/Low)\n- Category classification\n- Key phrase extraction"
      },
      "typeVersion": 1
    },
    {
      "id": "a6889aca-b169-4149-a996-03b3f79b21f7",
      "name": "Sticky Note - Step 4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1232,
        32
      ],
      "parameters": {
        "width": 320,
        "height": 128,
        "content": "### 4\ufe0f\u20e3 Save & Notify\nResults are saved to Google Sheets. High-priority or negative reviews trigger urgent Telegram alerts; others receive standard notifications."
      },
      "typeVersion": 1
    },
    {
      "id": "404dfdaf-e97e-438d-bbb9-9b48cd90e3bd",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -144,
        240
      ],
      "parameters": {
        "rule": {
          "interval": [
            {}
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "3450f4b3-3130-4d67-81b6-ffc8a5a64583",
      "name": "Get Review Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        80,
        240
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": "Your Google Sheet"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "a25ee321-9004-4953-8f7a-231d7cc4f54e",
      "name": "Filter Unprocessed",
      "type": "n8n-nodes-base.if",
      "position": [
        320,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "cond1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.ProcessStatus }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "b8e13be4-be46-4284-afa0-851243b13746",
      "name": "Format Input Data",
      "type": "n8n-nodes-base.set",
      "position": [
        560,
        224
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "4c74e666-d822-4d53-840f-9fa1d576d442",
      "name": "AI Agent - Review Analysis",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        800,
        224
      ],
      "parameters": {
        "text": "=Analyze the following Japanese review.\n\n\u3010Original Review\u3011\n{{ $('Get Review Data').item.json['Keyword'] }}\n\n\u3010Tasks\u3011\n1. Translation: Translate this review to English\n2. Sentiment: Classify as Positive/Neutral/Negative\n3. Sentiment Score: Rate from -1.0 (very negative) to +1.0 (very positive)\n4. Importance: Rate as High/Medium/Low\n   - High: Product defects, safety issues, strong complaints, urgent response needed\n   - Medium: Improvement requests, feature requests, specific suggestions\n   - Low: General feedback, minor comments\n5. Category: Choose from Quality/Price/Shipping/Support/Features/Usability/Other\n6. Key Phrase: Summarize in 3-5 words\n\n\u3010Output Format\u3011\nRespond ONLY in the following JSON format:\n```json\n{\n  \"translated_text\": \"Translation result\",\n  \"sentiment\": \"Positive or Neutral or Negative\",\n  \"sentiment_score\": 0.0,\n  \"importance\": \"High or Medium or Low\",\n  \"category\": \"Category name\",\n  \"key_phrase\": \"Key phrase\"\n}\n```",
        "agent": "conversationalAgent",
        "options": {
          "systemMessage": "You are a multilingual review analysis expert. Accurately translate customer reviews and perform sentiment analysis and importance classification. Always respond ONLY in the specified JSON format."
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "dc76a357-a387-47a2-9d5c-e4c4c51280fa",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        672,
        448
      ],
      "parameters": {
        "options": {
          "temperature": 0.3
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a9be3b14-f897-4dd7-92e0-e7cd7e7c17e7",
      "name": "Parse AI Response",
      "type": "n8n-nodes-base.code",
      "position": [
        1056,
        224
      ],
      "parameters": {
        "jsCode": "// Extract and parse JSON from AI Agent output\nconst input = $input.first();\nconst output = input.json.output || input.json.text || '';\n\n// Extract JSON (```json ... ``` or { ... })\nlet jsonStr = output;\nconst jsonMatch = output.match(/```json\\s*([\\s\\S]*?)```/) || output.match(/(\\{[\\s\\S]*\\})/);\nif (jsonMatch) {\n  jsonStr = jsonMatch[1];\n}\n\nlet parsed;\ntry {\n  parsed = JSON.parse(jsonStr.trim());\n} catch (e) {\n  // Default values on parse failure\n  parsed = {\n    translated_text: \"Translation Error\",\n    sentiment: \"Neutral\",\n    sentiment_score: 0,\n    importance: \"Low\",\n    category: \"Other\",\n    key_phrase: \"Parse Error\"\n  };\n}\n\n// Merge with original data\nconst originalData = $('Format Input Data').first().json;\n\nreturn {\n  json: {\n    ...originalData,\n    TranslatedText: parsed.translated_text,\n    Sentiment: parsed.sentiment,\n    SentimentScore: parsed.sentiment_score,\n    Importance: parsed.importance,\n    Category: parsed.category,\n    KeyPhrase: parsed.key_phrase,\n    ProcessStatus: \"Completed\",\n    ProcessedAt: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "48284018-ea86-4009-ad85-c91172c4f53f",
      "name": "Update Spreadsheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1296,
        224
      ],
      "parameters": {
        "columns": {
          "value": {
            "Category": "={{ $json.Category }}",
            "ReviewID": "={{ $json.ReviewID }}",
            "KeyPhrase": "={{ $json.KeyPhrase }}",
            "Sentiment": "={{ $json.Sentiment }}",
            "Importance": "={{ $json.Importance }}",
            "ProcessedAt": "={{ $json.ProcessedAt }}",
            "ProcessStatus": "={{ $json.ProcessStatus }}",
            "SentimentScore": "={{ $json.SentimentScore }}",
            "TranslatedText": "={{ $json.TranslatedText }}"
          },
          "schema": [
            {
              "id": "ReviewID",
              "type": "string",
              "display": true,
              "required": true,
              "displayName": "ReviewID",
              "defaultMatch": true,
              "canBeUsedToMatch": true
            },
            {
              "id": "TranslatedText",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "TranslatedText",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Sentiment",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Sentiment",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "SentimentScore",
              "type": "number",
              "display": true,
              "required": false,
              "displayName": "SentimentScore",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Importance",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Importance",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "Category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "Category",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "KeyPhrase",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "KeyPhrase",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "ProcessStatus",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ProcessStatus",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            },
            {
              "id": "ProcessedAt",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ProcessedAt",
              "defaultMatch": false,
              "canBeUsedToMatch": false
            }
          ],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [
            "ReviewID"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": true
        },
        "options": {
          "cellFormat": "USER_ENTERED"
        },
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "",
          "cachedResultUrl": "",
          "cachedResultName": "Your Google Sheet"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "8caed11a-a5ef-44cf-a35d-2a5134551f42",
      "name": "Check Importance & Sentiment",
      "type": "n8n-nodes-base.if",
      "position": [
        1536,
        224
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "high-importance",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.Importance }}",
              "rightValue": "High"
            },
            {
              "id": "negative-sentiment",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $json.SentimentScore }}",
              "rightValue": -0.5
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "4d4c1e39-f2b1-499b-a5a7-666a65d4f7d0",
      "name": "Urgent Alert (Telegram)",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1776,
        192
      ],
      "parameters": {
        "text": "=\ud83d\udea8 **URGENT REVIEW DETECTED**\n\n\ud83d\udcdd Review ID: {{ $json.ReviewID }}\n\n**Original Review:**\n{{ $json.OriginalText }}\n\n**Translation:**\n{{ $json.TranslatedText }}\n\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\ud83d\udcca **Analysis Results**\n\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n\ud83d\ude0a Sentiment: {{ $json.Sentiment }} ({{ $json.SentimentScore }})\n\u26a0\ufe0f Importance: {{ $json.Importance }}\n\ud83c\udff7\ufe0f Category: {{ $json.Category }}\n\ud83d\udd11 Key Phrase: {{ $json.KeyPhrase }}\n\n\u23f0 Processed: {{ $json.ProcessedAt }}",
        "additionalFields": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "f5c802b5-b7c1-4867-b4b3-fd79bec6b43d",
      "name": "Normal Notification (Telegram)",
      "type": "n8n-nodes-base.telegram",
      "position": [
        1776,
        368
      ],
      "parameters": {
        "text": "=\u2705 Review Processed\n\n\ud83d\udcdd ID: {{ $json.ReviewID }}\n\ud83d\ude0a Sentiment: {{ $json.Sentiment }}\n\u26a0\ufe0f Importance: {{ $json.Importance }}\n\ud83c\udff7\ufe0f Category: {{ $json.Category }}",
        "additionalFields": {}
      },
      "typeVersion": 1.2
    }
  ],
  "connections": {
    "Get Review Data": {
      "main": [
        [
          {
            "node": "Filter Unprocessed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get Review Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Input Data": {
      "main": [
        [
          {
            "node": "AI Agent - Review Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent - Review Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response": {
      "main": [
        [
          {
            "node": "Update Spreadsheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Unprocessed": {
      "main": [
        [
          {
            "node": "Format Input Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Spreadsheet": {
      "main": [
        [
          {
            "node": "Check Importance & Sentiment",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent - Review Analysis": {
      "main": [
        [
          {
            "node": "Parse AI Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Importance & Sentiment": {
      "main": [
        [
          {
            "node": "Urgent Alert (Telegram)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Normal Notification (Telegram)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}