{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "ec98a813-e04e-4810-a1ee-e4ddc50ba3a2",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        96,
        -16
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 8
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "6fa661ea-5d2a-4edb-93c0-b66ecc002b06",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        304,
        -16
      ],
      "parameters": {
        "mode": "raw",
        "options": {},
        "jsonOutput": "{\n  \"region\": \"US\"\n}\n"
      },
      "typeVersion": 3.4
    },
    {
      "id": "2fc88d37-787a-4df6-8aa2-69a6be7463d1",
      "name": "Fetch Google Trends RSS",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        480,
        -16
      ],
      "parameters": {
        "url": "=https://trends.google.com/trending/rss?geo={{ $json.region.toUpperCase().trim() }}",
        "options": {}
      },
      "typeVersion": 4.3
    },
    {
      "id": "d1ea6748-15a4-4e4f-968a-dc82d9da72fd",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1696,
        128
      ],
      "parameters": {
        "text": "=Analyze the following merged social media data.\n\nTasks:\n- Infer main topics dynamically\n- Summarize public discussion\n- Analyze engagement signals\n- Determine trend strength\n\nDATA:\n{{ $json.merged_data_text }}\n",
        "options": {
          "systemMessage": "You are a social trend analysis engine.\n\nIMPORTANT OUTPUT RULE:\nYou MUST output a JSON object with this EXACT structure:\n\n{\n  \"topics\": [\n    {\n      \"topic_name\": string,\n      \"discussion_summary\": string,\n      \"engagement_signals\": {\n        \"total_estimated_views\": number,\n        \"total_estimated_likes\": number\n      },\n      \"trend_strength\": \"weak\" | \"moderate\" | \"strong\" | \"viral\",\n      \"insight\": string,\n      \"content_recommendation\": string\n    }\n  ]\n}\n\nRules:\n- ALWAYS use the key \"topics\" (never trends, never results)\n- NEVER return a single object, always an array in \"topics\"\n- NEVER change key names\n- Output MUST be valid JSON only\n- Do NOT wrap JSON in markdown\n"
        },
        "promptType": "define"
      },
      "retryOnFail": true,
      "typeVersion": 3.1
    },
    {
      "id": "2a7e81bf-6e9d-4047-8e7e-eed3151a23eb",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        1696,
        288
      ],
      "parameters": {
        "options": {},
        "modelName": "models/gemini-flash-latest"
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "c714b370-5636-47c6-becc-bf1f037d5590",
      "name": "Format Google Output",
      "type": "n8n-nodes-base.code",
      "position": [
        688,
        -16
      ],
      "parameters": {
        "jsCode": "const xml = items[0].json.data;\n\n// helper ambil isi tag\nfunction getTag(text, tag) {\n  const re = new RegExp('<' + tag + '>([\\\\s\\\\S]*?)<\\\\/' + tag + '>', 'i');\n  const m = text.match(re);\n  return m ? m[1].trim() : null;\n}\n\n// ambil semua <item>...</item>\nconst itemRegex = /<item>([\\s\\S]*?)<\\/item>/g;\nconst itemBlocks = [];\nlet itemMatch;\n\nwhile ((itemMatch = itemRegex.exec(xml)) !== null) {\n  itemBlocks.push(itemMatch[1]);\n}\n\nconst trends = itemBlocks.map(block => {\n  // ambil news item\n  const newsRegex = /<ht:news_item>([\\s\\S]*?)<\\/ht:news_item>/g;\n  const newsBlocks = [];\n  let newsMatch;\n\n  while ((newsMatch = newsRegex.exec(block)) !== null) {\n    newsBlocks.push(newsMatch[1]);\n  }\n\n  return {\n    keyword: getTag(block, 'title'),\n    approx_traffic: getTag(block, 'ht:approx_traffic'),\n    published_at: (() => {\n      const d = getTag(block, 'pubDate');\n      return d ? new Date(d).toISOString() : null;\n    })(),\n    image: {\n      url: getTag(block, 'ht:picture'),\n      source: getTag(block, 'ht:picture_source')\n    },\n    news: newsBlocks.map(n => ({\n      title: getTag(n, 'ht:news_item_title'),\n      url: getTag(n, 'ht:news_item_url'),\n      source: getTag(n, 'ht:news_item_source'),\n      image: getTag(n, 'ht:news_item_picture')\n    }))\n  };\n});\n\nreturn [\n  {\n    json: {\n      source: 'Google Trends',\n      geo: $('Edit Fields').first().json.region,\n      generated_at: new Date().toISOString(),\n      trends\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "972c9900-dc9b-4bfe-bcc1-75c74a95ec05",
      "name": "TikTok Scrapper",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        880,
        -16
      ],
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": "OtzYfK1ndEGdwWFKQ",
          "cachedResultUrl": "https://console.apify.com/actors/OtzYfK1ndEGdwWFKQ/input",
          "cachedResultName": "TikTok Data Extractor (clockworks/free-tiktok-scraper)"
        },
        "timeout": {},
        "operation": "Run actor and get dataset",
        "customBody": "={\n  \"searchQueries\": {{ JSON.stringify($json.trends.slice(0, 5).map(t => t.keyword)) }},\n  \"resultsPerPage\": 5,\n  \"searchType\": \"video\",\n  \"sortType\": \"most-liked\",\n  \"shouldDownloadVideos\": false,\n  \"shouldDownloadCovers\": false\n}",
        "actorSource": "store"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1
    },
    {
      "id": "797ed501-27c0-43eb-a79c-9314e6b38eb1",
      "name": "Instagram Scrapper",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        880,
        128
      ],
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": "7YASHOuDdgJuPjqsP",
          "cachedResultUrl": "https://console.apify.com/actors/7YASHOuDdgJuPjqsP/input",
          "cachedResultName": "Instagram Free Hashtag Scraper (scrapesmith/instagram-free-hashtag-scraper)"
        },
        "timeout": {},
        "operation": "Run actor and get dataset",
        "customBody": "={\n  \"hashtags\": {{ JSON.stringify($json.trends.slice(0, 5).map(t => t.keyword.replace(/\\s+/g, ''))) }},\n  \"resultsLimit\": 5,\n  \"enhanceUserSearchWithWildcard\": true\n}",
        "actorSource": "store"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1
    },
    {
      "id": "fd790b27-abad-4ea8-b452-29dfa22a8c02",
      "name": "X Scrapper",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        880,
        288
      ],
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": "CJdippxWmn9uRfooo",
          "cachedResultUrl": "https://console.apify.com/actors/CJdippxWmn9uRfooo/input",
          "cachedResultName": "Tweet Scraper|$0.25/1K Tweets | Pay-Per Result | No Rate Limits (kaitoeasyapi/twitter-x-data-tweet-scraper-pay-per-result-cheapest)"
        },
        "timeout": {},
        "operation": "Run actor and get dataset",
        "customBody": "={\n  \"searchTerms\": {{ JSON.stringify($json.trends.slice(0, 5).map(t => t.keyword)) }},\n  \"maxItems\": 10,\n  \"sort\": \"Latest\",\n  \"includeUserInfo\": true\n}",
        "actorSource": "store"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "retryOnFail": true,
      "typeVersion": 1
    },
    {
      "id": "9ff898ae-44bf-4676-9fda-5bba9e9152e7",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1328,
        112
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3.2
    },
    {
      "id": "0d7a5b7f-1b62-4538-a355-aa7105a0f55a",
      "name": "Tiktok Output",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        -16
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst keyword = items[0]?.json.searchQuery || \"Trending\";\n\nreturn [{\n    json: {\n        platform: \"tiktok\",\n        keyword: keyword,\n        summary: items.map(i => ({\n            caption: i.json.text || i.json.caption,\n            views: i.json.playCount || 0,\n            likes: i.json.diggCount || 0\n        })).slice(0, 5) // Ambil 5 teratas\n    }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "ac0e890f-a454-4b69-89fc-8e2c7cc83822",
      "name": "Instagram Output",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        128
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst keyword = items[0]?.json.query || \"Trending\";\n\nreturn [{\n    json: {\n        platform: \"instagram\",\n        keyword: keyword,\n        summary: items.map(i => ({\n            caption: i.json.caption,\n            likes: i.json.likesCount || i.json.edge_liked_by?.count || 0\n        })).slice(0, 5)\n    }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "73133474-f236-4b87-b444-e802b7edaf91",
      "name": "X Output",
      "type": "n8n-nodes-base.code",
      "position": [
        1088,
        288
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst keyword = items[0]?.json.keyword || \"Trending\";\n\nreturn [{\n    json: {\n        platform: \"x_twitter\",\n        keyword: keyword,\n        summary: items.map(i => ({\n            text: i.json.full_text || i.json.text,\n            views: i.json.view_count || 0,\n            likes: i.json.favorite_count || 0\n        })).slice(0, 5)\n    }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "d26ee8fc-b935-4193-84b7-52885a86544f",
      "name": "Code in JavaScript",
      "type": "n8n-nodes-base.code",
      "position": [
        1504,
        128
      ],
      "parameters": {
        "jsCode": "// Ambil semua item hasil merge\nconst items = $items();\n\n// Kembalikan sebagai STRING JSON\nreturn [\n  {\n    json: {\n      merged_data_text: JSON.stringify(items.map(i => i.json), null, 2)\n    }\n  }\n];\n"
      },
      "typeVersion": 2
    },
    {
      "id": "5012e2c2-2dde-4868-a3d0-6cf45a8b78aa",
      "name": "Parse Output",
      "type": "n8n-nodes-base.code",
      "position": [
        2000,
        128
      ],
      "parameters": {
        "jsCode": "const results = [];\n\nfor (const item of $items()) {\n  let text = item.json.output;\n\n  // hapus ```json ``` fence\n  text = text.replace(/```json|```/g, '').trim();\n\n  let parsed;\n  try {\n    parsed = JSON.parse(text);\n  } catch (e) {\n    parsed = {\n      error: true,\n      raw_output: text\n    };\n  }\n\n  results.push({ json: parsed });\n}\n\nreturn results;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "89162d92-4494-451a-a489-b2124fdae483",
      "name": "Discord",
      "type": "n8n-nodes-base.discord",
      "position": [
        2416,
        128
      ],
      "parameters": {
        "content": "=\ud83d\ude80 **LAPORAN TREN: {{ $json.topic_name }}**\n\n\ud83d\udcdd **Ringkasan Diskusi:**\n{{ $json.discussion_summary }}\n\n\ud83d\udcca **Statistik:**\nViews/Likes: {{ $json.engagement_signals.total_estimated_views || $json.engagement_signals.total_estimated_likes || '0' }}\n\n\ud83d\udca1 **Insight:**\n{{ $json.insight }}\n\n\u2705 **Rekomendasi Konten:**\n{{ $json.content_recommendation }}\n\n--------------------------------------------------",
        "options": {},
        "authentication": "webhook"
      },
      "credentials": {
        "discordWebhookApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "6cbea001-c525-45f1-bad5-e277bb1c9326",
      "name": "Split Out",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        2208,
        128
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "topics"
      },
      "typeVersion": 1
    },
    {
      "id": "66f760bb-2f05-442f-9bbc-ba59befefd69",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        -272
      ],
      "parameters": {
        "width": 512,
        "height": 800,
        "content": "### **AI-Driven Social Intelligence Agent**\n\nThis workflow is a professional-grade market intelligence tool that automatically synchronizes search trends with real-world social media activity to identify high-potential viral content.\n\n### **How it works**\n1. **Schedule Trigger:** Automatically runs at your preferred interval (e.g., every morning) to fetch fresh market data.\n2. **Multi-Source Acquisition:** - **Google Trends:** Monitors regional RSS feeds to capture rising search interests.\n   - **Social Media Scrapers:** Uses **Apify** actors to safely extract trending posts from TikTok, Instagram, and X (Twitter) without account risk.\n3. **Data Aggregation:** Custom JavaScript logic merges disparate platform data into a unified context, optimizing AI token efficiency.\n4. **AI Synthesis & Intelligence:** **Google Gemini** cross-references the data to identify \"The Common Thread\"\u2014topics trending across multiple platforms simultaneously.\n5. **Granular Delivery:** Uses a **Split Out** mechanism to deliver each trend as an individual, readable report to **Discord**.\n\n### **Setup steps**\n1. **API Keys:** Provide your **Apify API Token** and **Google Gemini API Key**.\n2. **Region Configuration:** Set your target country code (e.g., `JP`, `ID`, `US`) in the **\"Edit Fields\"** node.\n3. **Discord Integration:** Paste your Discord Webhook URL into the **Discord** node.\n4. **Resilience:** All scrapers are pre-configured with \"Continue on Fail\" to ensure report delivery even if one source is down.\n\n### **Requirements**\n- n8n instance.\n- Apify Account (for Social Media scraping).\n- Google Gemini API Key.\n- Discord Server (for receiving reports)."
      },
      "typeVersion": 1
    },
    {
      "id": "c817048b-3f56-4a6e-b5b4-ddc3f20a0a29",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        464,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 576,
        "content": "## **1. Multi-Platform Data Fetching**\nExtracts raw trending data from Google Search (via RSS) and deep-scrapes TikTok, Instagram, and X using Apify's robust industrial actors."
      },
      "typeVersion": 1
    },
    {
      "id": "a166ac4c-8d19-4e73-a4fb-6f7706f59157",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1488,
        16
      ],
      "parameters": {
        "color": 7,
        "width": 624,
        "height": 400,
        "content": "## **2. AI Synthesis & Trend Intelligence**\nAggregates all raw social data and uses LLMs (Gemini) to cross-reference topics, removing noise and identifying the \"why\" behind the trend."
      },
      "typeVersion": 1
    },
    {
      "id": "d8f91f70-4aca-478a-ba9f-a4cb4886daf3",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2176,
        0
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 304,
        "content": "## **3. Granular Reporting & Alerting**\nConverts complex AI analysis into readable formats and sends instant, per-topic alerts to your team via Discord Webhooks."
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Parse Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "X Output": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Discord",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "X Scrapper": {
      "main": [
        [
          {
            "node": "X Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Fetch Google Trends RSS",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Output": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Tiktok Output": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "TikTok Scrapper": {
      "main": [
        [
          {
            "node": "Tiktok Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Instagram Output": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Instagram Scrapper": {
      "main": [
        [
          {
            "node": "Instagram Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Google Output": {
      "main": [
        [
          {
            "node": "TikTok Scrapper",
            "type": "main",
            "index": 0
          },
          {
            "node": "Instagram Scrapper",
            "type": "main",
            "index": 0
          },
          {
            "node": "X Scrapper",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Google Trends RSS": {
      "main": [
        [
          {
            "node": "Format Google Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    }
  }
}