{
  "id": "YB0hfLqSYnFZ63ZL",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "AI Virality Scoring Engine: Channel Intelligence Extraction & Trend Harvesting",
  "tags": [],
  "nodes": [
    {
      "id": "4d1b5785-5820-4ba1-bed9-aeeae16928ab",
      "name": "Get a channel",
      "type": "n8n-nodes-base.youTube",
      "position": [
        0,
        -112
      ],
      "parameters": {
        "part": [
          "brandingSettings"
        ],
        "channelId": "UCUevUDRxTDJCoG1KxQveXag",
        "operation": "get"
      },
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "f176bd2d-7a36-4b05-8a45-d208652e3375",
      "name": "Get many videos",
      "type": "n8n-nodes-base.youTube",
      "position": [
        0,
        208
      ],
      "parameters": {
        "limit": 50,
        "filters": {
          "channelId": "UCUevUDRxTDJCoG1KxQveXag"
        },
        "options": {
          "order": "date"
        },
        "resource": "video"
      },
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "2f92d1c0-5345-429b-b62c-9267b4e4e68c",
      "name": "Get a video",
      "type": "n8n-nodes-base.youTube",
      "position": [
        416,
        208
      ],
      "parameters": {
        "part": [
          "statistics",
          "snippet"
        ],
        "options": {},
        "videoId": "={{ $json.videoIds }}",
        "resource": "video",
        "operation": "get"
      },
      "credentials": {
        "youTubeOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "6fb0fb5f-1105-4cd7-9b62-4492376ef7a3",
      "name": "Merge",
      "type": "n8n-nodes-base.merge",
      "position": [
        1120,
        96
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "24de6cd5-068f-49e7-98de-1346af2266fd",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1328,
        96
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "a10c05db-be37-48f6-8a15-b91ccd112288",
      "name": "OpenRouter Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        2176,
        1328
      ],
      "parameters": {
        "model": "deepseek/deepseek-r1",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "7c21fb84-1105-44d1-9cb3-33f68c204cf6",
      "name": "OpenRouter Chat Model1",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenRouter",
      "position": [
        1536,
        272
      ],
      "parameters": {
        "model": "deepseek/deepseek-r1",
        "options": {}
      },
      "credentials": {
        "openRouterApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "803c8094-d060-486f-bad7-d194410b88c4",
      "name": "Trigger \u2013 Daily Trend Scan",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -256,
        880
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 7
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "a5367252-9bcf-41b0-bd87-2c6a08a97b75",
      "name": "Trigger \u2013 Weekly Intelligence Extraction",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -240,
        0
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks"
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "5c8fb61d-d587-4347-a4ad-a636666fe51d",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        624
      ],
      "parameters": {
        "width": 256,
        "height": 432,
        "content": "## Daily Automation Trigger \n\nThis workflow runs once per day."
      },
      "typeVersion": 1
    },
    {
      "id": "afd78ce4-084a-4394-b1db-bfbdcdf4c417",
      "name": "Fetch \u2013 News RSS (30)",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        128,
        992
      ],
      "parameters": {
        "url": "https://news.google.com/rss?hl=en-US&gl=US&ceid=US:en",
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "5be1b81a-9ac3-4679-aec8-0168d34cef1b",
      "name": "Fetch \u2013 Reddit Hot (50)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        128,
        736
      ],
      "parameters": {
        "url": "https://www.reddit.com/r/all/hot.json?limit=50",
        "options": {}
      },
      "typeVersion": 4.4
    },
    {
      "id": "a60c16be-d43f-4e09-9a2f-a244f8d22ea9",
      "name": "Get \u2013 Channel Profile",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        112,
        1216
      ],
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "FQy0ynWtmG6pU7Ib",
          "cachedResultUrl": "/projects/fXqNaRMFXN8afHCV/datatables/FQy0ynWtmG6pU7Ib",
          "cachedResultName": "youtube-channel-profile"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "8b058f92-de10-446f-bf26-35db32e3ecff",
      "name": "Get - Previous Video Stats",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        112,
        1456
      ],
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "8adMKNXUkXIG584y",
          "cachedResultUrl": "/projects/fXqNaRMFXN8afHCV/datatables/8adMKNXUkXIG584y",
          "cachedResultName": "youtube-channel-video-stat"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "810dcf83-7ba0-4c97-bd97-62cbd320e2dd",
      "name": "Get - Previous Video Stats Analysis  Report",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        112,
        1696
      ],
      "parameters": {
        "operation": "get",
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "4aeqCqJQMMxHENQz",
          "cachedResultUrl": "/projects/fXqNaRMFXN8afHCV/datatables/4aeqCqJQMMxHENQz",
          "cachedResultName": "youtube-channel-profile-analysis-result"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "313dc85a-7de2-4696-a163-eba2ab856b12",
      "name": "Merge \u2013 All Trend Sources",
      "type": "n8n-nodes-base.merge",
      "position": [
        896,
        976
      ],
      "parameters": {},
      "typeVersion": 3.2
    },
    {
      "id": "7a94b74e-b1b5-44e5-9681-1bc4d42cc50f",
      "name": "Normalize \u2013 Channel Profile Objects",
      "type": "n8n-nodes-base.set",
      "position": [
        352,
        1216
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "62ac0a86-9d6a-442e-becc-4d4a34bf5bf6",
              "name": "channelProfile",
              "type": "object",
              "value": "={{ $json }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "6f74bb2e-a2fb-459c-a8b2-be3fcb1666fa",
      "name": "Aggregate \u2013 Previous Video Stats Data",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        352,
        1456
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "recentVideosStats"
      },
      "typeVersion": 1
    },
    {
      "id": "7b7ae02c-98d3-4052-a11a-d22a80b57e85",
      "name": "Normalize \u2013 Previous Video Stats Analysis  Report",
      "type": "n8n-nodes-base.set",
      "position": [
        352,
        1696
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ea67236b-2e1b-4042-8df3-a8ea25f6e173",
              "name": "previousChannelProfileAnalysisResult",
              "type": "object",
              "value": "={{ $json }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "52a920d5-abb7-4ad4-be11-353e4d6364fb",
      "name": "Aggregate \u2013 Trends Objects",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1136,
        976
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "trends"
      },
      "typeVersion": 1
    },
    {
      "id": "900047d1-c724-468f-bb03-18c74ed24467",
      "name": "Aggregate \u2013 Reddit Objects",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        576,
        736
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "reddit"
      },
      "typeVersion": 1
    },
    {
      "id": "89e58f8c-0d6e-4b96-8313-322b06f8e6a7",
      "name": "Aggregate \u2013 RSS Objects",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        576,
        992
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "googleNews"
      },
      "typeVersion": 1
    },
    {
      "id": "5479f17c-bd7b-4a36-b1fd-4fe3fed94178",
      "name": "Merge \u2013 All Sources Data",
      "type": "n8n-nodes-base.merge",
      "position": [
        1552,
        1104
      ],
      "parameters": {
        "numberInputs": 4
      },
      "typeVersion": 3.2
    },
    {
      "id": "2eb5b964-3a05-404f-b05e-4be105b1c979",
      "name": "Aggregate \u2013 Sources Data",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        1856,
        1136
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "1987ef0a-b08f-4594-906d-3b8af2e6c774",
      "name": "AI \u2013 Virality Scoring Engine",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        2176,
        1136
      ],
      "parameters": {
        "text": "={{ $json }}",
        "options": {
          "systemMessage": "You are a YouTube/TikTok content strategist and virality analyst.\n\nYour task is to score trending topics against a specific channel\u2019s proven performance patterns.\n\nYou are given:\n1) channelProfile \u2192 AI-extracted patterns of what works on this channel\n2) previousVideosStats \u2192 historical performance stats\n3) previousChannelProfileAnalysisResult \u2192 from previous analysis based on previous videos stats\n4) trends \u2192 today\u2019s RSS news and Reddit posts\n\nYou must NOT summarize trends.\n\nYou must evaluate each trend based on how well it matches the channel\u2019s DNA and audience interest.\n\nFor each trend, analyze:\n- Topic similarity to top_topics\n- Match with high_performing_title_patterns\n- Alignment with dominant_content_formats\n- Relevance to audience_interest_signals\n- Whether this topic fits content_to_create_more\n- Risk of falling into content_to_avoid\n\nScore each trend from 0\u2013100 for \u201cviral fit\u201d for THIS channel.\n\nReturn ONLY the top 3 trends in this JSON format:\n\n{\n  \"topPicks\": [\n    {\n      \"title\": \"\",\n      \"source\": \"\",\n      \"viralScore\": 0,\n      \"whyThisFitsChannel\": \"\",\n      \"suggestedTitle\": \"\",\n      \"suggestedContentFormat\": \"\"\n    }\n  ]\n}"
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "a26d2ba0-4756-49e6-80dc-d82f353082f4",
      "name": "Insert -  Into Video  Recommendation Table",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        2736,
        1136
      ],
      "parameters": {
        "columns": {
          "value": {
            "title": "={{ $json.title }}",
            "source": "={{ $json.source }}",
            "viralScore": "={{ $json.viralScore }}",
            "suggestedTitle": "={{ $json.suggestedTitle }}",
            "whyThisFitsChannel": "={{ $json.whyThisFitsChannel }}",
            "suggestedContentFormat": "={{ $json.suggestedContentFormat }}"
          },
          "schema": [
            {
              "id": "title",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "title",
              "defaultMatch": false
            },
            {
              "id": "source",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "source",
              "defaultMatch": false
            },
            {
              "id": "viralScore",
              "type": "number",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "viralScore",
              "defaultMatch": false
            },
            {
              "id": "whyThisFitsChannel",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "whyThisFitsChannel",
              "defaultMatch": false
            },
            {
              "id": "suggestedTitle",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "suggestedTitle",
              "defaultMatch": false
            },
            {
              "id": "suggestedContentFormat",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "suggestedContentFormat",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "BnxuiJoIzImMpOsK",
          "cachedResultUrl": "/projects/fXqNaRMFXN8afHCV/datatables/BnxuiJoIzImMpOsK",
          "cachedResultName": "youtube-channel-video-recommendation"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "f806d0a1-a428-4049-83a4-f2cce8c414d5",
      "name": "Send Recommended Videos To Telegram",
      "type": "n8n-nodes-base.telegram",
      "position": [
        2944,
        1136
      ],
      "parameters": {
        "text": "=\ud83d\udd25 Daily Content Opportunity\n\nTopic: {{ $json.title }}\n\nSource: {{ $json.source }}\n\nVirality Score: {{ $json.viralScore }}/100\n\nThe Strategy\n{{ $json.whyThisFitsChannel }}\n\nSuggested Execution\n\ud83c\udfac Title: {{ $json.suggestedTitle }}\n\n\ud83d\udcdd Format: {{ $json.suggestedContentFormat }}",
        "chatId": "123456789",
        "additionalFields": {
          "appendAttribution": false
        }
      },
      "credentials": {
        "telegramApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "4f8ea0b9-cf60-4f24-8885-b47db536d712",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        48,
        608
      ],
      "parameters": {
        "color": 2,
        "width": 1248,
        "height": 544,
        "content": "## Trend Sources (RSS + Reddit), Trend Preparation\n**Combine and normalize trending topics from multiple sources into a consistent structure.** "
      },
      "typeVersion": 1
    },
    {
      "id": "6f2c113a-7d2e-482a-bde5-97bef4509cdd",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2688,
        912
      ],
      "parameters": {
        "color": "#0A9484",
        "width": 528,
        "height": 528,
        "content": "## Save To Data Table And Telegram Delivery  \n**Save the output to data table and send the top 3 to your telegram account.** "
      },
      "typeVersion": 1
    },
    {
      "id": "962e91f7-ec52-453e-811a-08de7d111096",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -720,
        1184
      ],
      "parameters": {
        "color": 4,
        "width": 1248,
        "height": 720,
        "content": "## Channel Intelligence (Data Store)\n**Fetch previously learned channel intelligence and historical performance data to guide AI scoring.** "
      },
      "typeVersion": 1
    },
    {
      "id": "a4abaccf-a90a-44f7-ac50-fc6b3cdc30c1",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1472,
        912
      ],
      "parameters": {
        "width": 544,
        "height": 432,
        "content": "## Merge For AI\n**Combine trends, channel profile, and past video stats into a single object for AI analysis.** "
      },
      "typeVersion": 1
    },
    {
      "id": "b2e0636c-fccf-49bd-9d06-67845e53e61a",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2112,
        912
      ],
      "parameters": {
        "color": 6,
        "width": 336,
        "height": 592,
        "content": "## AI \u2013 Virality Scoring Engine\n**AI scores each trend based on how well it matches the channel\u2019s proven patterns and audience interests. Returns only the top 3 opportunities.** "
      },
      "typeVersion": 1
    },
    {
      "id": "46c452f4-008a-443c-b382-2c4bf731dacf",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1504,
        -112
      ],
      "parameters": {
        "color": 6,
        "width": 288,
        "height": 560,
        "content": "## AI Channel Pattern Analysis\n**This converts raw statistics into actionable channel intelligence.** "
      },
      "typeVersion": 1
    },
    {
      "id": "69690266-c813-441f-9e2c-3fdf55e0c242",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -368,
        -160
      ],
      "parameters": {
        "width": 272,
        "height": 320,
        "content": "## Weekly Automation Trigger \n\n**This workflow runs once per week.**"
      },
      "typeVersion": 1
    },
    {
      "id": "08f34617-e583-4c26-98b8-b7fa94e3ad03",
      "name": "Sticky Note8",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -48,
        -256
      ],
      "parameters": {
        "color": 2,
        "width": 832,
        "height": 304,
        "content": "## Fetch Channel Information\n**channel information such as description, keywords, and branding is retrieved.\nThis gives AI additional context about the creator\u2019s niche and intent.** "
      },
      "typeVersion": 1
    },
    {
      "id": "7d55330f-be1b-4e80-b9fb-27f0921b3246",
      "name": "Sticky Note9",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1072,
        -112
      ],
      "parameters": {
        "width": 384,
        "height": 400,
        "content": "## Merge For AI\n**Combine Channel Info + Video Stats, this ensures the AI receives consistent and machine-readable input for accurate pattern recognition.** "
      },
      "typeVersion": 1
    },
    {
      "id": "48e7550b-bd3f-4ccb-9b77-72dddf249141",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1840,
        -112
      ],
      "parameters": {
        "color": "#0A9484",
        "width": 448,
        "height": 400,
        "content": "## Save Raw Data to Data Table\n**Persist AI-Generated Channel Profile (Intelligence)** "
      },
      "typeVersion": 1
    },
    {
      "id": "f57c1cd6-208d-4f14-b742-f4c6f5f96962",
      "name": "Insert -  Into Channel Profile Analysis Report",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        2096,
        96
      ],
      "parameters": {
        "columns": {
          "value": {
            "timing": "={{ $json.timing }}",
            "topics": "={{ $json.topics.join('|') }}",
            "formats": "={{ $json.formats.join('|') }}",
            "doMoreOf": "={{ $json.do_more_of.join('|') }}",
            "duration": "={{ $json.duration }}",
            "stopDoing": "={{ $json.stop_doing.join('|') }}",
            "titleFormulas": "={{ $json.title_formulas.join('|') }}",
            "whatAudienceLikes": "={{ $json.what_audience_likes.join('|') }}"
          },
          "schema": [
            {
              "id": "topics",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "topics",
              "defaultMatch": false
            },
            {
              "id": "titleFormulas",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "titleFormulas",
              "defaultMatch": false
            },
            {
              "id": "formats",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "formats",
              "defaultMatch": false
            },
            {
              "id": "doMoreOf",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "doMoreOf",
              "defaultMatch": false
            },
            {
              "id": "stopDoing",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "stopDoing",
              "defaultMatch": false
            },
            {
              "id": "timing",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "timing",
              "defaultMatch": false
            },
            {
              "id": "duration",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "duration",
              "defaultMatch": false
            },
            {
              "id": "whatAudienceLikes",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "whatAudienceLikes",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "4aeqCqJQMMxHENQz",
          "cachedResultUrl": "/projects/fXqNaRMFXN8afHCV/datatables/4aeqCqJQMMxHENQz",
          "cachedResultName": "youtube-channel-profile-analysis-result"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "3b30fb05-54b2-41fd-b99e-072262618c53",
      "name": "Code - Format output-2",
      "type": "n8n-nodes-base.code",
      "position": [
        2528,
        1136
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nconst items = $input.all();\nlet finalResults = [];\n\n// Process each input item\nfor (const item of items) {\n  let rawOutput = item.json.output;\n\n  // 1. Remove the Markdown code block wrappers\n  const cleanJsonString = rawOutput.replace(/```json|```/gi, \"\").trim();\n\n  try {\n    // 2. Parse the string into a JSON object\n    const parsedData = JSON.parse(cleanJsonString);\n\n    // 3. Extract the array and push its contents into our finalResults\n    if (parsedData.topPicks && Array.isArray(parsedData.topPicks)) {\n      parsedData.topPicks.forEach(pick => {\n        finalResults.push({ json: pick });\n      });\n    } else {\n      // If the AI didn't return an array, just return the whole object\n      finalResults.push({ json: parsedData });\n    }\n\n  } catch (error) {\n    // Error handling\n    finalResults.push({\n      json: {\n        error: \"Failed to parse JSON\",\n        details: error.message\n      }\n    });\n  }\n}\n\n// 4. Returning this array will result in 3 separate items in n8n\nreturn finalResults;"
      },
      "typeVersion": 2
    },
    {
      "id": "c43e3b0d-7fda-49b8-8a0c-3e5eadeb820a",
      "name": "Code - Format output",
      "type": "n8n-nodes-base.code",
      "position": [
        1888,
        96
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nconst items = $input.all();\n\nreturn items.map((item, index) => {\n  // Parse the string output into a JSON object if it's still a string\n  const data = typeof item.json.output === 'string' \n    ? JSON.parse(item.json.output.replace(/```json\\n|\\n```/g, '')) \n    : item.json.output;\n\n  return {\n    json: {\n      source_id: index + 1,\n      // Core Strategy\n      topics: data.top_topics,\n      title_formulas: data.high_performing_title_patterns,\n      formats: data.dominant_content_formats,\n      \n      // Actionable Insights\n      do_more_of: data.content_to_create_more,\n      stop_doing: data.content_to_avoid,\n      \n      // Logistics\n      timing: data.best_publish_time_utc || \"Varies - check analytics\",\n      duration: data.best_duration_range_sec || \"10-20 minutes recommended\",\n      \n      // Engagement Signals\n      what_audience_likes: data.audience_interest_signals\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "706b7eb1-d1c9-4b40-a0de-28269dcdfac6",
      "name": "Sticky Note12",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1632,
        -240
      ],
      "parameters": {
        "color": "#F9F34E",
        "width": 768,
        "height": 2160,
        "content": "## \ud83e\udde0 How This System Works \u2014 End-to-End Overview (WF1 + WF2)\n\n**This project implements an AI-powered content strategist for a faceless YouTube channel using n8n and AI.**\n\n**It does not blindly create videos from trends.**\n**Instead, it learns what works for the channel first, then finds trends that match that proven pattern.**\n\n**\ud83d\udd39 WF1 - Channel Intelligence Extraction (Learn the Channel DNA)**\n1.  Fetch channel metadata and the last 50 videos from YouTube.\n2. Normalize video statistics into a clean dataset (titles, views, likes, comments, publish time, tags).\n3. Send this dataset to AI for pattern extraction, not summarization.\n4. AI identifies:\n    \u2022 Topics that perform best\n    \u2022 Title styles that attract views\n    \u2022 Content formats the audience prefers\n    \u2022 What to create more of / avoid\n5. Save:\n    \u2022 Raw video stats (facts)\n    \u2022 AI-generated Channel Profile (intelligence)\n    \u2022 into Data Store for reuse.\n\n**\u2705 Result: The system now understands the channel\u2019s content DNA.**\n\n\n**\ud83d\udd39 WF2 - Trend Harvesting & Virality Scoring (Find What Fits Today)**\n1. On a daily schedule, fetch trending topics from News RSS and Reddit.\n2. Merge and normalize all trends into a consistent format.\n3. Shortlist the trends to a manageable number (e.g., top 50).\n4. Fetch the saved Channel Profile and historical stats from Data Store.\n5. Combine:\n    \u2022 Today\u2019s trends\n    \u2022 Channel intelligence\n    \u2022 Past performance data\n    \u2022 into one AI input payload.\n6. AI evaluates each trend and scores how well it fits the channel\u2019s proven patterns.\n7. Return only the Top 3 viral opportunities for that specific channel.\n\n**\u2705 Result: Instead of asking \u201cwhat\u2019s trending?\u201d, the system answers \u201cwhat should THIS channel create today?\u201d**"
      },
      "typeVersion": 1
    },
    {
      "id": "3db0ef50-bf63-4a3f-a965-8c3c7913a253",
      "name": "Sticky Note13",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -768,
        176
      ],
      "parameters": {
        "color": 4,
        "width": 1776,
        "height": 256,
        "content": "## Fetch Historical Video Statistics\n**The workflow pulls recent videos including titles, views, likes, comments, publish time, and tags.\nThis raw performance data is used for pattern extraction.** "
      },
      "typeVersion": 1
    },
    {
      "id": "38b59149-f835-4e2d-b22f-df1e88e6e01a",
      "name": "AI Channel Pattern Analysis",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        1536,
        96
      ],
      "parameters": {
        "text": "={{ $json }}",
        "options": {
          "systemMessage": "You are a helpful assistantYou are a YouTube channel growth analyst.\n\nYou analyze historical video performance data to reverse-engineer what type of content performs best for a channel.\n\nYou must extract patterns, not summarize videos.\n\nFocus on:\n- Topics that consistently get high engagement\n- Title structures that correlate with high views\n- Ideal video duration range\n- Best publishing time of day (UTC)\n- Content format pattern (e.g. listicle, news, tutorial, explainer, reaction, comparison)\n- Audience interest signals from tags and titles\n- What the channel should make MORE of\n- What the channel should AVOID\n\nReturn your answer strictly in this JSON format:\n\n{\n  \"top_topics\": [],\n  \"high_performing_title_patterns\": [],\n  \"best_duration_range_sec\": \"\",\n  \"best_publish_time_utc\": \"\",\n  \"dominant_content_formats\": [],\n  \"audience_interest_signals\": [],\n  \"content_to_create_more\": [],\n  \"content_to_avoid\": []\n}"
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "bb96eaef-c5db-400d-84a0-a1758d601fc9",
      "name": "Insert -  Into Channel Video Stat",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        640,
        208
      ],
      "parameters": {
        "columns": {
          "value": {
            "title": "={{ $json.snippet.title }}",
            "channelId": "={{ $json.snippet.channelId }}",
            "likeCount": "={{ $json.statistics.likeCount }}",
            "viewCount": "={{ $json.statistics.viewCount }}",
            "description": "={{ $json.snippet.description }}",
            "publishedAt": "={{ $json.snippet.publishedAt }}",
            "commentCount": "={{ $json.statistics.commentCount }}",
            "favoriteCount": "={{ $json.statistics.favoriteCount }}"
          },
          "schema": [
            {
              "id": "channelId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "channelId",
              "defaultMatch": false
            },
            {
              "id": "title",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "title",
              "defaultMatch": false
            },
            {
              "id": "description",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "description",
              "defaultMatch": false
            },
            {
              "id": "publishedAt",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "publishedAt",
              "defaultMatch": false
            },
            {
              "id": "viewCount",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "viewCount",
              "defaultMatch": false
            },
            {
              "id": "likeCount",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "likeCount",
              "defaultMatch": false
            },
            {
              "id": "favoriteCount",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "favoriteCount",
              "defaultMatch": false
            },
            {
              "id": "commentCount",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "commentCount",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "8adMKNXUkXIG584y",
          "cachedResultUrl": "/projects/fXqNaRMFXN8afHCV/datatables/8adMKNXUkXIG584y",
          "cachedResultName": "youtube-channel-video-stat"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "a671e84a-8353-4fbb-834e-d3c103ce9caf",
      "name": "Insert -  Into Channel Profile",
      "type": "n8n-nodes-base.dataTable",
      "position": [
        416,
        -112
      ],
      "parameters": {
        "columns": {
          "value": {
            "title": "={{ $json.title }}",
            "keywords": "={{ $json.keywords }}",
            "channelId": "={{ $json.id }}",
            "description": "={{ $json.description }}"
          },
          "schema": [
            {
              "id": "channelId",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "channelId",
              "defaultMatch": false
            },
            {
              "id": "title",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "title",
              "defaultMatch": false
            },
            {
              "id": "description",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "description",
              "defaultMatch": false
            },
            {
              "id": "keywords",
              "type": "string",
              "display": true,
              "removed": false,
              "readOnly": false,
              "required": false,
              "displayName": "keywords",
              "defaultMatch": false
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "dataTableId": {
          "__rl": true,
          "mode": "list",
          "value": "FQy0ynWtmG6pU7Ib",
          "cachedResultUrl": "/projects/fXqNaRMFXN8afHCV/datatables/FQy0ynWtmG6pU7Ib",
          "cachedResultName": "youtube-channel-profile"
        }
      },
      "typeVersion": 1.1
    },
    {
      "id": "d65071ea-6a08-4d3e-b886-90c43ad8fb62",
      "name": "Aggregate -  Channel Stat",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        864,
        208
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData",
        "destinationFieldName": "channelStat"
      },
      "typeVersion": 1
    },
    {
      "id": "a8002cd1-2409-4db9-ada4-f70148767651",
      "name": "Normalize \u2013 Channel Profile Data",
      "type": "n8n-nodes-base.set",
      "position": [
        624,
        -112
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "0d461815-021f-47ae-9382-cadd56d58f19",
              "name": "channelInfo",
              "type": "object",
              "value": "={{ $json }}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "9ce4f49b-8585-4e6d-b9f2-838387c2bbd1",
      "name": "Code - Extract useful field-3",
      "type": "n8n-nodes-base.code",
      "position": [
        352,
        736
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nconst items = $input.all();\n\nconst posts = items[0].json.data.children;\n\nreturn posts.map(post => {\n  const p = post.data;\n\n\n  let type = \"Link/Image\";\n  if (p.is_video) type = \"Video\";\n  if (p.is_self) type = \"Text/Discussion\";\n\n  return {\n    json: {\n      source: \"Reddit\",\n      community: p.subreddit_name_prefixed,\n      title: p.title,\n      type: type,\n      upvotes: p.ups,\n      comments: p.num_comments,\n      upvote_ratio: p.upvote_ratio,\n      hotness_score: (p.ups * p.upvote_ratio).toFixed(0),\n      summary: p.selftext ? p.selftext.substring(0, 300) + \"...\" : \"Visual/External Content\",\n      url: `https://www.reddit.com${p.permalink}`\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "07282f3f-e565-4594-bee0-f61825b52609",
      "name": "Code - Extract useful field-4",
      "type": "n8n-nodes-base.code",
      "position": [
        352,
        992
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nconst items = $input.all();\n\nreturn items.map(item => {\n  const i = item.json;\n\n  const primaryHeadline = i.title;\n  \n\n  const relatedHeadlines = i.contentSnippet\n    ? i.contentSnippet.split('\\n').slice(1).map(line => line.trim())\n    : [];\n\n  return {\n    json: {\n      source: \"Google News\",\n      title: primaryHeadline,\n      published: i.pubDate,\n      context: `Related coverage from: ${relatedHeadlines.join(' | ')}`,\n      link: i.link\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "7bf9379f-5eca-49b8-a5aa-07bcf6faf7c3",
      "name": "Code - Extract useful field-1",
      "type": "n8n-nodes-base.code",
      "position": [
        208,
        -112
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\nconst items = $input.all();\n\nreturn items.map(item => {\n  const channel = item.json.brandingSettings.channel;\n  \n  const cleanKeywords = channel.keywords ? channel.keywords.replace(/\"/g, '').split(' ').filter(k => k).join(', ') : '';\n\n  return {\n    json: {\n      id: item.json.id,\n      title: channel.title,\n      description: channel.description,\n      keywords: cleanKeywords\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "d505ebc7-3682-4cd7-bf30-d1e12cfcd4b7",
      "name": "Code - Extract useful field-2",
      "type": "n8n-nodes-base.code",
      "position": [
        208,
        208
      ],
      "parameters": {
        "jsCode": "// Loop over input items and add a new field called 'myNewField' to the JSON of each one\n\nconst items = $input.all();\n\nconst videoIds = items.map(item => item.json.id.videoId);\n\nreturn {\n  videoIds: videoIds.join(',')\n};"
      },
      "typeVersion": 2
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "e0646e32-03c8-4cea-ac97-9ebe43a9a99e",
  "connections": {
    "Merge": {
      "main": [
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "AI Channel Pattern Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get a video": {
      "main": [
        [
          {
            "node": "Insert -  Into Channel Video Stat",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get a channel": {
      "main": [
        [
          {
            "node": "Code - Extract useful field-1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many videos": {
      "main": [
        [
          {
            "node": "Code - Extract useful field-2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Format output": {
      "main": [
        [
          {
            "node": "Insert -  Into Channel Profile Analysis Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI \u2013 Virality Scoring Engine",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Code - Format output-2": {
      "main": [
        [
          {
            "node": "Insert -  Into Video  Recommendation Table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenRouter Chat Model1": {
      "ai_languageModel": [
        [
          {
            "node": "AI Channel Pattern Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Fetch \u2013 News RSS (30)": {
      "main": [
        [
          {
            "node": "Code - Extract useful field-4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get \u2013 Channel Profile": {
      "main": [
        [
          {
            "node": "Normalize \u2013 Channel Profile Objects",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate -  Channel Stat": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Aggregate \u2013 RSS Objects": {
      "main": [
        [
          {
            "node": "Merge \u2013 All Trend Sources",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Fetch \u2013 Reddit Hot (50)": {
      "main": [
        [
          {
            "node": "Code - Extract useful field-3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate \u2013 Sources Data": {
      "main": [
        [
          {
            "node": "AI \u2013 Virality Scoring Engine",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get - Previous Video Stats": {
      "main": [
        [
          {
            "node": "Aggregate \u2013 Previous Video Stats Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge \u2013 All Sources Data": {
      "main": [
        [
          {
            "node": "Aggregate \u2013 Sources Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Channel Pattern Analysis": {
      "main": [
        [
          {
            "node": "Code - Format output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge \u2013 All Trend Sources": {
      "main": [
        [
          {
            "node": "Aggregate \u2013 Trends Objects",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate \u2013 Reddit Objects": {
      "main": [
        [
          {
            "node": "Merge \u2013 All Trend Sources",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate \u2013 Trends Objects": {
      "main": [
        [
          {
            "node": "Merge \u2013 All Sources Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger \u2013 Daily Trend Scan": {
      "main": [
        [
          {
            "node": "Fetch \u2013 News RSS (30)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Fetch \u2013 Reddit Hot (50)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get \u2013 Channel Profile",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get - Previous Video Stats",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get - Previous Video Stats Analysis  Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Extract useful field-1": {
      "main": [
        [
          {
            "node": "Insert -  Into Channel Profile",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Extract useful field-2": {
      "main": [
        [
          {
            "node": "Get a video",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Extract useful field-3": {
      "main": [
        [
          {
            "node": "Aggregate \u2013 Reddit Objects",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code - Extract useful field-4": {
      "main": [
        [
          {
            "node": "Aggregate \u2013 RSS Objects",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI \u2013 Virality Scoring Engine": {
      "main": [
        [
          {
            "node": "Code - Format output-2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert -  Into Channel Profile": {
      "main": [
        [
          {
            "node": "Normalize \u2013 Channel Profile Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert -  Into Channel Video Stat": {
      "main": [
        [
          {
            "node": "Aggregate -  Channel Stat",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize \u2013 Channel Profile Data": {
      "main": [
        [
          {
            "node": "Merge",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Recommended Videos To Telegram": {
      "main": [
        []
      ]
    },
    "Normalize \u2013 Channel Profile Objects": {
      "main": [
        [
          {
            "node": "Merge \u2013 All Sources Data",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Aggregate \u2013 Previous Video Stats Data": {
      "main": [
        [
          {
            "node": "Merge \u2013 All Sources Data",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Insert -  Into Video  Recommendation Table": {
      "main": [
        [
          {
            "node": "Send Recommended Videos To Telegram",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Trigger \u2013 Weekly Intelligence Extraction": {
      "main": [
        [
          {
            "node": "Get a channel",
            "type": "main",
            "index": 0
          },
          {
            "node": "Get many videos",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get - Previous Video Stats Analysis  Report": {
      "main": [
        [
          {
            "node": "Normalize \u2013 Previous Video Stats Analysis  Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize \u2013 Previous Video Stats Analysis  Report": {
      "main": [
        [
          {
            "node": "Merge \u2013 All Sources Data",
            "type": "main",
            "index": 3
          }
        ]
      ]
    }
  }
}