{
  "id": "E8ovE16hzVEEVJCU",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Instagram Profile Analyser Orchestrator",
  "tags": [],
  "nodes": [
    {
      "id": "b041c3c8-8d45-4777-9339-8c399184d2cd",
      "name": "Webhook (From Lovable)",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -2208,
        -64
      ],
      "parameters": {
        "path": "analyze-profile",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2
    },
    {
      "id": "058c7890-ec0c-49d7-804d-3696c0ca732a",
      "name": "Check Cache (<24h)",
      "type": "n8n-nodes-base.supabase",
      "position": [
        -1984,
        -64
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "updated_at",
              "keyValue": "={{ $now.minus({ hours: 24 }).toISO() }}",
              "condition": "gt"
            }
          ]
        },
        "tableId": "reports",
        "matchType": "allFilters",
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1,
      "alwaysOutputData": true
    },
    {
      "id": "797e0e0f-4eb6-4adc-b12e-3fcfbcd1653d",
      "name": "Return Cached Report",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        -1696,
        -208
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ $json.analysis_report }}"
      },
      "typeVersion": 1
    },
    {
      "id": "bbf841e7-42be-41e0-9402-a99c5a0aaab3",
      "name": "JS Prune Payload",
      "type": "n8n-nodes-base.code",
      "position": [
        -1056,
        16
      ],
      "parameters": {
        "jsCode": "// Grab all incoming items safely using n8n's modern syntax\nconst allItems = $input.all();\nconst posts = allItems.map(item => item.json);\n\n// Safety check: If empty, stop gracefully\nif (!posts.length) {\n  return [{ json: { error: 'No data returned' } }];\n}\n\n// Extract username from the first post's URL\nconst profile = posts[0].inputUrl \n  ? { username: posts[0].inputUrl.split('/').filter(Boolean).pop() } \n  : { username: 'Unknown' };\n\n// Map through the posts and keep only what the AI needs\nconst cleanedPosts = posts.map(p => ({\n  id: p.id,\n  type: p.type,\n  caption: p.caption || '',\n  likesCount: p.likesCount || 0,\n  commentsCount: p.commentsCount || 0,\n  videoViewCount: p.videoViewCount || 0,\n  timestamp: p.timestamp,\n  hashtags: p.hashtags || []\n}));\n\n// Output the bundled package as a single item for the AI nodes\nreturn [{\n  json: {\n    username: profile.username,\n    raw_posts_summary: cleanedPosts\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "b1b1a6bb-75fc-48d0-a179-dbbf5a274491",
      "name": "Merge AI Sub-Reports",
      "type": "n8n-nodes-base.merge",
      "position": [
        -560,
        64
      ],
      "parameters": {
        "numberInputs": 3
      },
      "typeVersion": 3
    },
    {
      "id": "cabea658-0458-4e4b-b4b2-15af74620c02",
      "name": "Compile Final Report Object",
      "type": "n8n-nodes-base.code",
      "position": [
        -416,
        80
      ],
      "parameters": {
        "jsCode": "const allData = $input.all();\n\n// Safely grab the username from the very first node using .first()\nconst username = $('Webhook (From Lovable)').first().json.body.username;\n\n// Safely grab the scraped posts from your JS Prune Payload node\nconst scrapedData = $('JS Prune Payload').first().json.raw_posts_summary || [];\n\n// Extract the 3 AI reports\nconst nicheReport = allData[0].json.content?.parts?.[0]?.text || allData[0].json.text || \"\";\nconst contentReport = allData[1].json.content?.parts?.[0]?.text || allData[1].json.text || \"\";\nconst engagementReport = allData[2].json.content?.parts?.[0]?.text || allData[2].json.text || \"\";\n\n// Combine the AI reports into one JSON object\nconst combinedReport = {\n  niche_analysis: nicheReport,\n  content_strategy: contentReport,\n  engagement_actions: engagementReport\n};\n\n// Output exactly what Supabase needs\nreturn [{\n  json: {\n    username: username,\n    scraped_data: scrapedData,\n    analysis_report: combinedReport\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "f5b35b6d-d53c-4ea9-a6bb-4c40c00a7d14",
      "name": "Upsert to Supabase",
      "type": "n8n-nodes-base.supabase",
      "position": [
        16,
        64
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "username",
              "keyValue": "={{ $json.username }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "reports",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "analysis_report",
              "fieldValue": "={{ $json.analysis_report }}"
            },
            {
              "fieldId": "scraped_data",
              "fieldValue": "={{ $json.scraped_data }}"
            }
          ]
        },
        "operation": "update"
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8a2e1118-836a-4c65-a64f-7cfa66650e52",
      "name": "Return Fresh Report",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        192,
        64
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={{ $json.analysis_report }}"
      },
      "typeVersion": 1
    },
    {
      "id": "17b7e21c-dbe8-44a8-8cdc-473d604a4aa5",
      "name": "AI Niche & Frequency1",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        -880,
        -128
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-3.1-flash-lite",
          "cachedResultName": "models/gemini-3.1-flash-lite"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Analyze this profile data for @{{ $json.username }}. Identify profile overview, core niche, posting frequency patterns, and best performing post times:\n\n{{ JSON.stringify($json.raw_posts_summary) }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "dcf9f13b-3109-4eb1-8693-64dee1a1aeb5",
      "name": "AI Content & Strategy1",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        -880,
        64
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-3.1-flash-lite",
          "cachedResultName": "models/gemini-3.1-flash-lite"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Analyze content strategy for @{{ $json.username }}. Breakdown themes, format distribution (Reels vs Carousels), caption tones, and hashtag usage strategy:\n\n{{ JSON.stringify($json.raw_posts_summary) }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "0feec70a-aede-487b-b7c6-61b2d92a3838",
      "name": "AI Engagement & Actions1",
      "type": "@n8n/n8n-nodes-langchain.googleGemini",
      "position": [
        -880,
        272
      ],
      "parameters": {
        "modelId": {
          "__rl": true,
          "mode": "list",
          "value": "models/gemini-3.1-flash-lite",
          "cachedResultName": "models/gemini-3.1-flash-lite"
        },
        "options": {},
        "messages": {
          "values": [
            {
              "content": "=Calculate total engagement insights for @{{ $json.username }}. Extract performance analysis on top posts, list 5 hyper-actionable growth recommendations, and point out missing content gaps:\n\n{{ JSON.stringify($json.raw_posts_summary) }}"
            }
          ]
        },
        "builtInTools": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "36c21645-fb21-4df3-bd33-eb9fb04c8dc7",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -1776,
        -64
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "cb266e93-930c-4cd9-baa9-241416770ea4",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Webhook (From Lovable)').item.json.body.username }}",
              "rightValue": "={{ $json.username }}"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "b20b734d-17ab-4c54-8cf9-dabe3287239c",
      "name": "Run an Actor and get dataset",
      "type": "@apify/n8n-nodes-apify.apify",
      "position": [
        -1264,
        16
      ],
      "parameters": {
        "actorId": {
          "__rl": true,
          "mode": "list",
          "value": "shu8hvrXbJbY3Eb9W",
          "cachedResultUrl": "https://console.apify.com/actors/shu8hvrXbJbY3Eb9W/input",
          "cachedResultName": "Instagram Scraper (apify/instagram-scraper)"
        },
        "operation": "Run actor and get dataset",
        "customBody": "={\n  \"directUrls\": [\n    \"https://www.instagram.com/{{ $('Webhook (From Lovable)').first().json.body.username.replace('@', '') }}/\"\n  ],\n  \"resultsType\": \"posts\",\n  \"resultsLimit\": 5\n}"
      },
      "credentials": {
        "apifyApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8f923965-834f-4ec6-b29b-10c30ef9f1b7",
      "name": "Aggregate",
      "type": "n8n-nodes-base.aggregate",
      "position": [
        -1536,
        0
      ],
      "parameters": {
        "options": {},
        "aggregate": "aggregateAllItemData"
      },
      "typeVersion": 1
    },
    {
      "id": "49b6351b-01a0-4efc-b905-66e0402475ba",
      "name": "If1",
      "type": "n8n-nodes-base.if",
      "position": [
        -160,
        80
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "ba7f4d10-5c70-4aa0-b73e-13c0fc3d8d5a",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Webhook (From Lovable)').item.json.body.username }}",
              "rightValue": "={{ $json.username }}"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b84a11c2-6e40-4dc3-8035-6679f50283b6",
      "name": "Upsert to Supabase1",
      "type": "n8n-nodes-base.supabase",
      "position": [
        16,
        224
      ],
      "parameters": {
        "tableId": "reports",
        "fieldsUi": {
          "fieldValues": [
            {
              "fieldId": "username",
              "fieldValue": "={{ $json.username }}"
            },
            {
              "fieldId": "analysis_report",
              "fieldValue": "={{ $json.analysis_report }}"
            },
            {
              "fieldId": "scraped_data",
              "fieldValue": "={{ $json.scraped_data }}"
            }
          ]
        }
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "79aaf227-f77b-4981-b31f-7a5777806e44",
      "name": "Get many rows",
      "type": "n8n-nodes-base.supabase",
      "position": [
        -288,
        80
      ],
      "parameters": {
        "filters": {
          "conditions": [
            {
              "keyName": "username",
              "keyValue": "={{ $json.username }}",
              "condition": "eq"
            }
          ]
        },
        "tableId": "reports",
        "operation": "getAll",
        "returnAll": true
      },
      "credentials": {
        "supabaseApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "47167401-5af3-4b7c-abd5-be31d9b6cd52",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2288,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 688,
        "height": 432,
        "content": "Intercepts incoming webhook. Queries Supabase for existing reports generated strictly within the last 24 hours to minimize redundant scraping and API costs."
      },
      "typeVersion": 1
    },
    {
      "id": "7a150d35-e6d0-43d5-96c3-28f5a0987864",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1584,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 640,
        "height": 544,
        "content": "Triggers if cache is empty or expired. Sanitizes input payload, constructs direct URL, and runs Apify Instagram scraper to extract raw posts."
      },
      "typeVersion": 1
    },
    {
      "id": "7089f736-df47-43a1-a601-3e6248d7b0a8",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -928,
        -288
      ],
      "parameters": {
        "color": 7,
        "width": 1312,
        "height": 736,
        "content": "Distributes scraped dataset across three parallel Gemini agents for specialized analysis. Merges outputs into a unified JSON object, upserts to Supabase to refresh the cache, and responds to the frontend."
      },
      "typeVersion": 1
    },
    {
      "id": "bf207171-d435-430c-acb7-ea20b9c8b372",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2752,
        -304
      ],
      "parameters": {
        "width": 448,
        "height": 528,
        "content": "Instagram Profile Analyser (Zero-Manual-Intervention Pipeline)\n\nCache Control: Intercepts the frontend webhook and queries Supabase for existing reports (generated within the last 24 hours) to minimize redundant scraping and optimize API costs.\n\nLive Scraping: If the cache is empty or expired, the pipeline sanitizes the input payload and triggers the Apify scraper to extract raw Instagram posts.\n\nAgentic AI Analysis: Distributes the scraped dataset across 3 parallel Gemini agents for specialized analysis (Niche, Content Strategy, and Engagement).\n\nCompile & Upsert: Merges the AI sub-reports into a unified JSON object, cleanly upserts the new data to Supabase to refresh the cache, and routes the final payload back to the frontend UI."
      },
      "typeVersion": 1
    }
  ],
  "active": true,
  "settings": {
    "timezone": "Asia/Kolkata",
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "timeSavedMode": "fixed",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "b78d37d6-ed10-4f98-91b5-ea06d06d5103",
  "nodeGroups": [],
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Return Cached Report",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Aggregate",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If1": {
      "main": [
        [
          {
            "node": "Upsert to Supabase",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Upsert to Supabase1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate": {
      "main": [
        [
          {
            "node": "Run an Actor and get dataset",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get many rows": {
      "main": [
        [
          {
            "node": "If1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "JS Prune Payload": {
      "main": [
        [
          {
            "node": "AI Niche & Frequency1",
            "type": "main",
            "index": 0
          },
          {
            "node": "AI Content & Strategy1",
            "type": "main",
            "index": 0
          },
          {
            "node": "AI Engagement & Actions1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Cache (<24h)": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert to Supabase": {
      "main": [
        [
          {
            "node": "Return Fresh Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Upsert to Supabase1": {
      "main": [
        [
          {
            "node": "Return Fresh Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge AI Sub-Reports": {
      "main": [
        [
          {
            "node": "Compile Final Report Object",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Niche & Frequency1": {
      "main": [
        [
          {
            "node": "Merge AI Sub-Reports",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Content & Strategy1": {
      "main": [
        [
          {
            "node": "Merge AI Sub-Reports",
            "type": "main",
            "index": 1
          }
        ]
      ]
    },
    "Webhook (From Lovable)": {
      "main": [
        [
          {
            "node": "Check Cache (<24h)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Engagement & Actions1": {
      "main": [
        [
          {
            "node": "Merge AI Sub-Reports",
            "type": "main",
            "index": 2
          }
        ]
      ]
    },
    "Compile Final Report Object": {
      "main": [
        [
          {
            "node": "Get many rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Run an Actor and get dataset": {
      "main": [
        [
          {
            "node": "JS Prune Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}