{
  "id": "Q7da5PYBhv0ge1Wp",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Zoho CRM - Deal health Predictor",
  "tags": [],
  "nodes": [
    {
      "id": "704f9656-2cdb-4608-8eb3-bb2078964d71",
      "name": "Fetch Active Deals From Zoho",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        1696,
        -128
      ],
      "parameters": {
        "url": "=https://www.zohoapis.com/crm/v2/Deals/search?criteria=(Stage:in:Qualification,Negotiation,Proposal,Demo,Value Proposition)",
        "options": {},
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "zohoOAuth2Api"
      },
      "credentials": {
        "zohoOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3,
      "alwaysOutputData": true
    },
    {
      "id": "67b758e8-7694-4d90-a8b8-75d550dfd423",
      "name": "Google Gemini Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        2576,
        96
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "googlePalmApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "b882e979-9b36-4f37-a32f-1850029900b1",
      "name": "Structured Output Parser",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        2848,
        96
      ],
      "parameters": {
        "jsonSchemaExample": "{\n  \"health_score\": \"0-100\",\n  \"risk_level\": \"Low | Medium | High\",\n  \"top_reasons\": [\"...\",\"...\",\"...\"],\n  \"recommended_actions\": [\"...\",\"...\",\"...\"],\n  \"suggested_message\": \"Short 40-word personalized message\"\n}"
      },
      "typeVersion": 1.3
    },
    {
      "id": "40da79d9-bd89-4a9a-9275-803b2996dc77",
      "name": "Filter stalled Deals",
      "type": "n8n-nodes-base.if",
      "position": [
        2352,
        -128
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "1cc5e57a-3d20-40da-9342-d62a6bbc1b11",
              "operator": {
                "type": "number",
                "operation": "gte"
              },
              "leftValue": "={{ $json.inactivity_days ||  0}}",
              "rightValue": 2
            }
          ]
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "da50d8e8-4ffa-4e1d-82b7-9e079dfe1be0",
      "name": "Weekly Deal Health Scan Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        1152,
        -128
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "weeks",
              "triggerAtDay": [
                1
              ],
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "1fc91135-1836-4106-b1da-f9817a49d61c",
      "name": "Split Deals Into Individual Items",
      "type": "n8n-nodes-base.splitOut",
      "position": [
        1936,
        -128
      ],
      "parameters": {
        "options": {},
        "fieldToSplitOut": "data"
      },
      "typeVersion": 1
    },
    {
      "id": "5d48d758-5590-4b42-acb8-4d466f36a388",
      "name": "Calculate Deal Metrics - Deal Inactivitu and Stage Age",
      "type": "n8n-nodes-base.code",
      "position": [
        2144,
        -128
      ],
      "parameters": {
        "jsCode": "const now = new Date();\nconst out = [];\n\nfor (const item of items) {\n  const deal = item.json;\n\n  // Inactivity\n  let inactivity = deal.Last_Activity_Time\n    ? Math.floor((now - new Date(deal.Last_Activity_Time)) / (1000*60*60*24))\n    : null;\n\n  // Stage age\n  let stageStart = deal.Stage_Span || deal.Stage_Start_Time || null;\n  let stage_days = stageStart\n    ? Math.floor((now - new Date(stageStart)) / (1000*60*60*24))\n    : null;\n\n  // Deal age\n  let deal_age = deal.Created_Time\n    ? Math.floor((now - new Date(deal.Created_Time)) / (1000*60*60*24))\n    : null;\n\n  out.push({\n    json: {\n      ...deal,\n      inactivity_days: inactivity,\n      stage_days,\n      deal_age\n    }\n  });\n}\n\nreturn out;\n"
      },
      "typeVersion": 2
    },
    {
      "id": "c4a4367e-4a55-4e5a-9b33-d89c046253e3",
      "name": "AI Deal Health Scoring",
      "type": "@n8n/n8n-nodes-langchain.chainLlm",
      "position": [
        2640,
        -144
      ],
      "parameters": {
        "text": "=You score the health of CRM deals.\n \nInput:\n\n- Stage: {{$json.Stage}}\n\n- Inactivity days: {{$json.inactivity_days}}\n\n- Stage days: {{$json.stage_days}}\n\n- Deal age: {{$json.deal_age}}\n\n- Amount: {{$json.Amount}}\n\n- Last activity: {{$json.Last_Activity_Time}}\n\n- Expected close date: {{ $json.Closing_Date }}\n \nOutput JSON only:\n\n{\n\n  \"health_score\": 0-100,\n\n  \"risk_level\": \"Low | Medium | High\",\n\n  \"top_reasons\": [\"...\",\"...\",\"...\"],\n\n  \"recommended_actions\": [\"...\",\"...\",\"...\"],\n\n  \"suggested_message\": \"Short 40-word personalized message\"\n\n}\n\n ",
        "batching": {},
        "promptType": "define",
        "hasOutputParser": true
      },
      "typeVersion": 1.7
    },
    {
      "id": "745af4fe-40a0-446b-8eab-80326d38327c",
      "name": "Is Deal At-Risk?",
      "type": "n8n-nodes-base.if",
      "position": [
        3008,
        -144
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 2,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "09ecc8e6-356c-4147-97e3-c27d77166c08",
              "operator": {
                "type": "number",
                "operation": "lt"
              },
              "leftValue": "={{ $json.output.health_score }}",
              "rightValue": 60
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.2
    },
    {
      "id": "753161e4-d0f3-4f9f-8d11-218ff20f90b3",
      "name": "Send At-Risk Alert Email",
      "type": "n8n-nodes-base.gmail",
      "position": [
        3376,
        -224
      ],
      "parameters": {
        "sendTo": "={{ $('Calculate Deal Metrics - Deal Inactivitu and Stage Age').item.json.Owner.email }}",
        "message": "= *Deal At-Risk Alert*  \n\nDeal: {{ $('Calculate Deal Metrics - Deal Inactivitu and Stage Age').item.json.Deal_Name }}\nStage: {{ $('Calculate Deal Metrics - Deal Inactivitu and Stage Age').item.json.Stage }}\nScore: {{ $json.output.health_score }}\n\nReasons: {{ $json.output.top_reasons }}\n\nActions Recommended: {{ $json.output.recommended_actions }}\n\nSuggested Message: {{ $json.output.suggested_message }}\n",
        "options": {},
        "subject": "Deal At-Risk Alert",
        "emailType": "text"
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "ab6d2993-36f1-4afd-ba00-1fb53bcd018c",
      "name": "Create At-Risk Task (Zoho CRM)",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        3632,
        -224
      ],
      "parameters": {
        "url": "https://www.zohoapis.com/crm/v2/Tasks",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"data\": [\n    {\n      \"Subject\": \"AI Alert : At-Risk Deal\",\n      \"Due_Date\": \"{{ $now.plus({ days: 3 }).toISODate() }}\",\n      \"Status\": \"Not Started\",\n      \"Priority\": \"High\",\n      \"$se_module\": \"Deals\",\n      \"What_Id\": \"{{ $('Calculate Deal Metrics - Deal Inactivitu and Stage Age').item.json.id }}\",\n      \"Description\": \"Deal: {{ $('Calculate Deal Metrics - Deal Inactivitu and Stage Age').item.json.Deal_Name }} Stage: {{ $('Calculate Deal Metrics - Deal Inactivitu and Stage Age').item.json.Stage }} Score:{{ $('AI Deal Health Scoring').item.json.output.health_score }}  Recommendations: Last Activity: {{ $('Calculate Deal Metrics - Deal Inactivitu and Stage Age').item.json.Last_Activity_Time }}\"\n    }\n  ],\n  \"trigger\": [\n    \"workflow\"\n  ]\n}\n",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "zohoOAuth2Api"
      },
      "credentials": {
        "zohoOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "7d960baa-daae-4c69-856a-92e0b0450354",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        480,
        -720
      ],
      "parameters": {
        "width": 560,
        "height": 528,
        "content": "## Zoho CRM \u2013 Deal Health Predictor (Overview)\n**How it works** \nThis workflow runs weekly and checks all open deals in Zoho CRM to detect those showing stall risks. Deals are split and evaluated one-by-one. Each deal gets metrics like inactivity age and stage age. Only stalled deals continue to AI scoring (Gemini). For each stalled deal, an AI-generated health score and risk level (0\u2013100) determines if the deal needs attention. If the score is below the risk threshold, the system alerts the responsible rep via email and automatically creates a high-priority CRM task linked to that deal.\n\n**Setup steps**\n1. Update the Zoho OAuth2 credentials in the fetch/task nodes.\n\n2. Confirm all stage names match Zoho exactly.\n\n3. Confirm inactivity/stage thresholds match business rules.\n\n4. Update the Gmail credential + sender address.\n\n5. Replace fallback email logic with deal owner email field from Zoho.\n\n6. Test with a single record before enabling scheduling.\n\n7. Enable workflow when reviewed and approved by the sales team."
      },
      "typeVersion": 1
    },
    {
      "id": "b82aca67-f520-4e31-81a4-a5eab7313427",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1088,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 256,
        "height": 320,
        "content": "## Weekly Scan Trigger\nRuns every week to score active deals and flag those at risk."
      },
      "typeVersion": 1
    },
    {
      "id": "aee190cd-7593-4932-aca3-f7b05e4ec949",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1392,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 1120,
        "height": 320,
        "content": "## Data Load & Stalling Filter\nGrabs open CRM deals \u2192 enriches with inactivity metrics \u2192 only stalled deals move forward."
      },
      "typeVersion": 1
    },
    {
      "id": "28b36966-bbb3-4866-b604-3b8f9188996d",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2576,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 336,
        "height": 320,
        "content": "## AI Risk Evaluation\nGemini assigns risk score + actionable recommendations."
      },
      "typeVersion": 1
    },
    {
      "id": "17323a03-aef4-4344-b918-600120aee625",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2944,
        -320
      ],
      "parameters": {
        "color": 7,
        "width": 896,
        "height": 352,
        "content": "## Alerts & CRM Actions\nIf health score < threshold \u2192 notify rep + create high-priority CRM task.\n"
      },
      "typeVersion": 1
    },
    {
      "id": "f7bfdc37-5b3e-41c5-9733-de65683b86e3",
      "name": "Edit Fields",
      "type": "n8n-nodes-base.set",
      "position": [
        1472,
        -128
      ],
      "parameters": {
        "options": {},
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "369f5d29-d357-4128-a496-e320c9c9a015",
  "connections": {
    "Edit Fields": {
      "main": [
        [
          {
            "node": "Fetch Active Deals From Zoho",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Is Deal At-Risk?": {
      "main": [
        [
          {
            "node": "Send At-Risk Alert Email",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter stalled Deals": {
      "main": [
        [
          {
            "node": "AI Deal Health Scoring",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Deal Health Scoring": {
      "main": [
        [
          {
            "node": "Is Deal At-Risk?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Deal Health Scoring",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Send At-Risk Alert Email": {
      "main": [
        [
          {
            "node": "Create At-Risk Task (Zoho CRM)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Structured Output Parser": {
      "ai_outputParser": [
        [
          {
            "node": "AI Deal Health Scoring",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Active Deals From Zoho": {
      "main": [
        [
          {
            "node": "Split Deals Into Individual Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Weekly Deal Health Scan Trigger": {
      "main": [
        [
          {
            "node": "Edit Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Deals Into Individual Items": {
      "main": [
        [
          {
            "node": "Calculate Deal Metrics - Deal Inactivitu and Stage Age",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Deal Metrics - Deal Inactivitu and Stage Age": {
      "main": [
        [
          {
            "node": "Filter stalled Deals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}