{
  "id": "PLACEHOLDER_WORKFLOW_ID",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Deal Conversion Probability Predictor with AI Behavioral Scoring",
  "tags": [],
  "nodes": [
    {
      "id": "80b1b86d-a3df-43a0-ade1-080db9031e32",
      "name": "Schedule Trigger",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1680,
        304
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 16
            }
          ]
        }
      },
      "typeVersion": 1.2
    },
    {
      "id": "08d0258d-0f54-4cab-beff-491eacab485b",
      "name": "Get Active Deals from HubSpot",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        -1456,
        304
      ],
      "parameters": {
        "filters": {
          "propertiesCollection": {
            "propertiesValues": {
              "properties": [
                "dealname",
                "amount",
                "dealstage",
                "closedate",
                "hs_all_owner_ids",
                "createdate",
                "notes_last_contacted",
                "num_associated_contacts",
                "hs_lastmodifieddate"
              ]
            }
          }
        },
        "resource": "deal",
        "operation": "getAll",
        "returnAll": true,
        "authentication": "appToken"
      },
      "credentials": {
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "196dfb80-88d3-4457-8453-dea03d1788da",
      "name": "Filter Alerts Needed",
      "type": "n8n-nodes-base.if",
      "position": [
        688,
        240
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 1,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "alert_condition",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.needsImmediateAttention }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "b0aa889e-7a3b-4052-a61c-a4e16921da72",
      "name": "Send Slack Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        912,
        176
      ],
      "parameters": {
        "text": "=\ud83c\udfaf *Deal Alert: High-Risk Opportunity*\n\n*Conversion Probability:* {{ $json.conversionProbability }}% ({{ $json.riskLevel.toUpperCase() }} RISK)\n*Deal Health:* {{ $json.dealHealthTrend }}\n*Confidence Level:* {{ $json.confidenceLevel }}\n*Alert Priority:* {{ $json.alertPriority }}\n*Immediate Action Required:* {{ $json.immediateActionRequired ? 'Yes' : 'No' }}\n\n*\ud83d\udcca Behavioral Scores:*\n\u2022 Behavioral Score: {{ $json.behavioralScore }}/100\n\u2022 Engagement Quality: {{ $json.engagementQuality }}/25\n\u2022 Momentum: {{ $json.momentum }}/25\n\u2022 Stakeholder Involvement: {{ $json.stakeholderInvolvement }}/25\n\u2022 Timeline Progress: {{ $json.timelineProgress }}/25\n\n*\ud83d\udcc9 Key Risk Factors:*\n{{ $json.riskFactors.map((risk, i) => `${i + 1}. ${risk}`).join('\\n') }}\n\n*\u2705 Positive Signals:*\n{{ $json.positiveSignals.map((signal, i) => `${i + 1}. ${signal}`).join('\\n') }}\n\n*\ud83d\udca1 Recommended Actions:*\n{{ $json.recommendedActions.map((action, i) => `${i + 1}. ${action}`).join('\\n') }}\n\n*\ud83d\udcde Next Best Engagement:*\n\u2022 Type: {{ $json.nextEngagementType }}\n\u2022 Timing: {{ $json.nextEngagementTiming }}\n\u2022 Focus: {{ $json.nextEngagementFocus }}\n\u2022 Goal: {{ $json.nextEngagementGoal }}\n\n*\ud83d\udcc5 Predicted Close Date:* {{ $json.predictedCloseDate }}\n\n\u26a0\ufe0f *This deal is {{ $json.isStalled ? 'stalled and' : '' }} {{ $json.isHighRisk ? 'high risk' : 'active' }} and needs immediate attention.*",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_SLACK_CHANNEL_ID",
          "cachedResultName": "general"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "27f41d75-f36d-48db-9da0-0815709534f5",
      "name": "If",
      "type": "n8n-nodes-base.if",
      "position": [
        -1008,
        304
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "74c429f7-17ae-4818-a450-220ecb363b4a",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.isActive }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "be3eb10a-0890-4f34-a468-a4b27893f1da",
      "name": "Loop Over Items",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -784,
        304
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "8846cf43-0f6f-4027-9fc7-7e2ec0c5451e",
      "name": "HTTP Request",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        -560,
        48
      ],
      "parameters": {
        "url": "=https://api.hubapi.com/crm/v3/objects/deals/{{ $json.dealId }}/associations/engagements",
        "options": {},
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Authorization",
              "value": "Bearer YOUR_TOKEN_HERE"
            }
          ]
        }
      },
      "typeVersion": 4.3
    },
    {
      "id": "6a74e2bd-4537-4a48-8cde-49fc9b1c656f",
      "name": "Get an engagement",
      "type": "n8n-nodes-base.hubspot",
      "position": [
        -336,
        48
      ],
      "parameters": {
        "resource": "engagement",
        "operation": "get",
        "engagementId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.results[0].id }}"
        },
        "authentication": "appToken"
      },
      "credentials": {
        "hubspotAppToken": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.2
    },
    {
      "id": "bf6ee2f3-42b8-4404-a239-afd2f9ba2b3f",
      "name": "AI Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        112,
        48
      ],
      "parameters": {
        "text": "=You are an expert sales data scientist specializing in deal conversion probability analysis and behavioral scoring.\n\nAnalyze the following deal and engagement data to predict conversion probability and identify behavioral signals.\n\n=== DEAL INFORMATION ===\nDeal ID: {{ $json.dealId }}\nDeal Name: {{ $('Loop Over Items').item.json.dealName }}\nDeal Value: ${{ $('Loop Over Items').item.json.amount }}\nCurrent Stage: {{ $('Loop Over Items').item.json.dealStage }}\nCreated Date: {{ $('Loop Over Items').item.json.createDate }}\nExpected Close Date: {{ $('Loop Over Items').item.json.closeDate }}\nDeal Age: {{ $('Loop Over Items').item.json.dealAgeDays }} days\nNumber of Contacts: {{ $('Loop Over Items').item.json.numAssociatedContacts }}\n\n=== ENGAGEMENT METRICS ===\nRecent Engagement Type: {{ $json.type }}\nRecent Engagement Date: {{ $json.timestamp }}\n\n=== ENGAGEMENT DETAILS ===\nTitle: {{ $json.title }}\nContent: {{ $json.body }}\nInternal Notes: {{ $json.internalNotes }}\nMeeting Duration: {{ $json.meetingEndTime - $json.meetingStartTime }} (if applicable)\n\n=== BEHAVIORAL SIGNALS TO ANALYZE ===\n1. **Engagement Frequency**: How often is the prospect engaging?\n2. **Response Time**: How quickly do they respond?\n3. **Engagement Quality**: Are meetings happening? Are they substantive?\n4. **Momentum**: Is activity increasing or decreasing?\n5. **Stakeholder Involvement**: Multiple contacts engaged?\n6. **Content Depth**: Are discussions getting more detailed/technical?\n7. **Timeline Adherence**: Is deal progressing as expected?\n8. **Objection Patterns**: Any recurring concerns or hesitations?\n\n=== SCORING CRITERIA ===\n**POSITIVE SIGNALS (+points):**\n- Multiple stakeholders engaged (+15)\n- Recent meetings scheduled (+20)\n- Technical/detailed discussions (+15)\n- Quick response times (+10)\n- Increasing engagement frequency (+15)\n- Budget discussions initiated (+20)\n- Decision-maker involvement (+25)\n- Contract/legal discussions (+30)\n- Reference requests (+20)\n\n**NEGATIVE SIGNALS (-points):**\n- No activity >14 days (-25)\n- Missed meetings (-15)\n- Postponed meetings (-10)\n- Vague/brief responses (-10)\n- Decreasing engagement (-20)\n- Objections not addressed (-15)\n- Single stakeholder only (-10)\n- No progress in 30+ days (-30)\n- Price objections recurring (-20)\n\n**NEUTRAL SIGNALS (monitor):**\n- Regular but unchanged cadence\n- Information gathering phase\n- Internal approval processes\n\n=== YOUR ANALYSIS TASK ===\n\nProvide a structured analysis in this EXACT format:\n\n**CONVERSION PROBABILITY: [X]%**\n\n**CONFIDENCE LEVEL: [High/Medium/Low]**\n[Explain why you're confident or uncertain in this prediction]\n\n**BEHAVIORAL SCORE: [X]/100**\nBreakdown:\n- Engagement Quality: [X]/25\n- Momentum: [X]/25\n- Stakeholder Involvement: [X]/25\n- Timeline Progress: [X]/25\n\n**RISK LEVEL: [Green/Yellow/Red/Critical]**\n- Green: >70% probability, healthy progression\n- Yellow: 40-70% probability, needs attention\n- Red: 20-40% probability, at risk\n- Critical: <20% probability, immediate intervention needed\n\n**KEY POSITIVE SIGNALS DETECTED:**\n1. [Signal and impact]\n2. [Signal and impact]\n3. [Signal and impact]\n\n**KEY RISK FACTORS DETECTED:**\n1. [Risk and impact]\n2. [Risk and impact]\n3. [Risk and impact]\n\n**BEHAVIORAL INSIGHTS:**\n[2-3 sentences about prospect's engagement patterns and what they reveal about intent]\n\n**DEAL HEALTH TREND: [Improving/Stable/Declining/Stalled]**\n[Explain the trend based on recent activities]\n\n**IMMEDIATE ACTION REQUIRED: [Yes/No]**\n[If Yes, explain why urgent attention is needed]\n\n**TOP 3 RECOMMENDED ACTIONS:**\n1. [Specific, actionable step with reasoning]\n2. [Specific, actionable step with reasoning]\n3. [Specific, actionable step with reasoning]\n\n**OPTIMAL NEXT ENGAGEMENT:**\n- Type: [Email/Call/Meeting/Demo]\n- Timing: [When - be specific]\n- Message Focus: [What to discuss]\n- Goal: [What outcome to achieve]\n\n**FORECASTING RECOMMENDATION:**\n- Commit/Best Case/Pipeline/Omit: [Choice]\n- Reasoning: [Why this forecast category]\n\n**PREDICTED CLOSE DATE: [Date]**\n[Based on current momentum and typical sales cycle]\n\n**ALERT PRIORITY: [P0-Critical / P1-High / P2-Medium / P3-Low]**\n\nBe data-driven, specific, and actionable. Consider industry benchmarks where typical B2B deals close in 30-90 days with 5-10 touchpoints.",
        "options": {},
        "promptType": "define"
      },
      "typeVersion": 3
    },
    {
      "id": "2d214070-e8a5-45e5-96c0-d088fa4ade35",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        192,
        272
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4o-mini"
        },
        "options": {},
        "builtInTools": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "485f544f-82e9-400f-bddd-d1a43b36729b",
      "name": "Append or update row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1136,
        336
      ],
      "parameters": {
        "columns": {
          "value": {
            "dealName": "={{ $('Loop Over Items').item.json.dealName }}",
            "momentum": "={{ $('Filter Alerts Needed').item.json.momentum }}",
            "isStalled": "={{ $('Filter Alerts Needed').item.json.isStalled }}",
            "riskLevel": "={{ $('Filter Alerts Needed').item.json.riskLevel }}",
            "isHighRisk": "={{ $('Filter Alerts Needed').item.json.isHighRisk }}",
            "riskFactors": "={{ $('Filter Alerts Needed').item.json.riskFactors[0] }}\n{{ $('Filter Alerts Needed').item.json.riskFactors[1] }}\n{{ $('Filter Alerts Needed').item.json.riskFactors[2] }}",
            "summaryText": "={{ $('Filter Alerts Needed').item.json.summaryText }}",
            "fullAnalysis": "={{ $('Filter Alerts Needed').item.json.fullAnalysis }}",
            "alertPriority": "={{ $('Filter Alerts Needed').item.json.alertPriority }}",
            "lowProbability": "={{ $('Filter Alerts Needed').item.json.lowProbability }}",
            "behavioralScore": "={{ $('Filter Alerts Needed').item.json.behavioralScore }}",
            "confidenceLevel": "={{ $('Filter Alerts Needed').item.json.confidenceLevel }}",
            "dealHealthTrend": "={{ $('Filter Alerts Needed').item.json.dealHealthTrend }}",
            "positiveSignals": "={{ $('Filter Alerts Needed').item.json.positiveSignals[0] }}\n{{ $('Filter Alerts Needed').item.json.positiveSignals[1] }}\n{{ $('Filter Alerts Needed').item.json.positiveSignals[2] }}",
            "timelineProgress": "={{ $('Filter Alerts Needed').item.json.timelineProgress }}",
            "analysisTimestamp": "={{ $('Filter Alerts Needed').item.json.analysisTimestamp }}",
            "engagementQuality": "={{ $('Filter Alerts Needed').item.json.engagementQuality }}",
            "behavioralInsights": "={{ $('Filter Alerts Needed').item.json.behavioralInsights }}",
            "nextEngagementGoal": "={{ $('Filter Alerts Needed').item.json.nextEngagementGoal }}",
            "nextEngagementType": "={{ $('Filter Alerts Needed').item.json.nextEngagementType }}",
            "predictedCloseDate": "={{ $('Filter Alerts Needed').item.json.predictedCloseDate }}",
            "recommendedActions": "={{ $('Filter Alerts Needed').item.json.recommendedActions[0] }}\n{{ $('Filter Alerts Needed').item.json.recommendedActions[1] }}\n{{ $('Filter Alerts Needed').item.json.recommendedActions[2] }}",
            "confidenceReasoning": "={{ $('Filter Alerts Needed').item.json.confidenceReasoning }}",
            "nextEngagementFocus": "={{ $('Filter Alerts Needed').item.json.nextEngagementFocus }}",
            "forecastingReasoning": "={{ $('Filter Alerts Needed').item.json.forecastingReasoning }}",
            "nextEngagementTiming": "={{ $('Filter Alerts Needed').item.json.nextEngagementTiming }}",
            "conversionProbability": "={{ $('Filter Alerts Needed').item.json.conversionProbability }}",
            "stakeholderInvolvement": "={{ $('Filter Alerts Needed').item.json.stakeholderInvolvement }}",
            "immediateActionRequired": "={{ $('Filter Alerts Needed').item.json.immediateActionRequired }}",
            "needsImmediateAttention": "={{ $('Filter Alerts Needed').item.json.needsImmediateAttention }}",
            "forecastingRecommendation": "={{ $('Filter Alerts Needed').item.json.forecastingRecommendation }}"
          },
          "schema": [
            {
              "id": "dealName",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "dealName",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "conversionProbability",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "conversionProbability",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "confidenceLevel",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "confidenceLevel",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "confidenceReasoning",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "confidenceReasoning",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "behavioralScore",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "behavioralScore",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "engagementQuality",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "engagementQuality",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "momentum",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "momentum",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "stakeholderInvolvement",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "stakeholderInvolvement",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "timelineProgress",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timelineProgress",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "riskLevel",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "riskLevel",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "dealHealthTrend",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "dealHealthTrend",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "immediateActionRequired",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "immediateActionRequired",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "positiveSignals",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "positiveSignals",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "riskFactors",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "riskFactors",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "behavioralInsights",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "behavioralInsights",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "recommendedActions",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "recommendedActions",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nextEngagementType",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "nextEngagementType",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nextEngagementTiming",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "nextEngagementTiming",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nextEngagementFocus",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "nextEngagementFocus",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "nextEngagementGoal",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "nextEngagementGoal",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "forecastingRecommendation",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "forecastingRecommendation",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "forecastingReasoning",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "forecastingReasoning",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "predictedCloseDate",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "predictedCloseDate",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "alertPriority",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "alertPriority",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "summaryText",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "summaryText",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "fullAnalysis",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "fullAnalysis",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "analysisTimestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "analysisTimestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "isHighRisk",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "isHighRisk",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "needsImmediateAttention",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "needsImmediateAttention",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "isStalled",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "isStalled",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "lowProbability",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "lowProbability",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "dealName"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "YOUR_GOOGLE_SHEET_ID",
          "cachedResultName": "Deal Analysis Results"
        }
      },
      "credentials": {
        "googleSheetsOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "0e163fc0-a59c-4a40-bbde-657028bd38a6",
      "name": "Extracts Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -112,
        48
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst formattedEngagements = [];\n\nfor (const item of items) {\n  const eng = item.json.engagement;\n  const meta = item.json.metadata || {};\n  const assoc = item.json.associations || {};\n  \n  // Base engagement data\n  const engagementData = {\n    // Core IDs\n    engagementId: eng.id,\n    portalId: eng.portalId,\n    dealId: assoc.dealIds?.[0] || null,\n    \n    // Type and Status\n    type: eng.type,\n    active: eng.active,\n    \n    // Timestamps\n    createdAt: new Date(eng.createdAt).toISOString(),\n    lastUpdated: new Date(eng.lastUpdated).toISOString(),\n    timestamp: new Date(eng.timestamp * 1000).toISOString(),\n    \n    // Content - All available text fields\n    title: meta.title || '',\n    body: meta.body || '',\n    bodyPreview: eng.bodyPreview || '',\n    bodyPreviewHtml: eng.bodyPreviewHtml || '',\n    bodyPreviewIsTruncated: eng.bodyPreviewIsTruncated || false,\n    \n    // Internal Notes (Important!)\n    internalNotes: meta.internalMeetingNotes || meta.internalNotes || '',\n    \n    // Associations\n    contactIds: assoc.contactIds || [],\n    companyIds: assoc.companyIds || [],\n    dealIds: assoc.dealIds || [],\n    ownerIds: assoc.ownerIds || [],\n    ticketIds: assoc.ticketIds || [],\n    \n    // Attachments\n    attachments: item.json.attachments || [],\n    hasAttachments: (item.json.attachments || []).length > 0,\n    \n    // Days calculation\n    daysSinceEngagement: Math.floor((Date.now() - eng.timestamp * 1000) / (1000 * 60 * 60 * 24))\n  };\n  \n  // Type-specific metadata\n  if (eng.type === 'MEETING') {\n    engagementData.meetingStartTime = meta.startTime ? new Date(meta.startTime * 1000).toISOString() : null;\n    engagementData.meetingEndTime = meta.endTime ? new Date(meta.endTime * 1000).toISOString() : null;\n    engagementData.meetingSource = meta.source || '';\n    engagementData.guestEmails = meta.guestEmails || [];\n    engagementData.attendeeOwnerIds = meta.attendeeOwnerIds || [];\n  }\n  \n  if (eng.type === 'CALL') {\n    engagementData.callDuration = meta.durationMilliseconds || 0;\n    engagementData.callStatus = meta.status || '';\n    engagementData.callDisposition = meta.disposition || '';\n    engagementData.recordingUrl = meta.recordingUrl || '';\n  }\n  \n  if (eng.type === 'EMAIL') {\n    engagementData.emailSubject = meta.subject || '';\n    engagementData.emailFrom = meta.from || {};\n    engagementData.emailTo = meta.to || [];\n    engagementData.emailCc = meta.cc || [];\n    engagementData.emailBcc = meta.bcc || [];\n    engagementData.emailStatus = meta.status || '';\n  }\n  \n  if (eng.type === 'NOTE') {\n    engagementData.noteBody = meta.body || eng.bodyPreview || '';\n  }\n  \n  if (eng.type === 'TASK') {\n    engagementData.taskSubject = meta.subject || '';\n    engagementData.taskStatus = meta.status || '';\n    engagementData.taskPriority = meta.priority || '';\n    engagementData.taskType = meta.taskType || '';\n    engagementData.forObjectType = meta.forObjectType || '';\n  }\n  \n  formattedEngagements.push({ json: engagementData });\n}\n\nreturn formattedEngagements;"
      },
      "typeVersion": 2
    },
    {
      "id": "fe234e65-d95a-40dc-a3e3-037715499d9d",
      "name": "Format Data",
      "type": "n8n-nodes-base.code",
      "position": [
        464,
        48
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst results = [];\n\nfor (const item of items) {\n  const aiOutput = item.json.output || item.json.response || item.json.text || '';\n  \n  // Helper function to extract value after a pattern with null safety\n  const extract = (pattern, defaultValue = null) => {\n    try {\n      const match = aiOutput.match(pattern);\n      return match && match[1] ? match[1].trim() : defaultValue;\n    } catch (e) {\n      return defaultValue;\n    }\n  };\n  \n  // Helper function to extract number\n  const extractNumber = (pattern, defaultValue = null) => {\n    try {\n      const match = aiOutput.match(pattern);\n      return match && match[1] ? parseInt(match[1]) : defaultValue;\n    } catch (e) {\n      return defaultValue;\n    }\n  };\n  \n  // Helper function to extract list items\n  const extractList = (startPattern, endPattern) => {\n    try {\n      const regex = new RegExp(`${startPattern}([\\\\s\\\\S]*?)${endPattern}`, 'i');\n      const match = aiOutput.match(regex);\n      if (!match || !match[1]) return [];\n      \n      return match[1]\n        .split(/\\n/)\n        .filter(line => line.trim().match(/^\\d+\\./))\n        .map(line => line.replace(/^\\d+\\.\\s*/, '').trim())\n        .filter(item => item.length > 0);\n    } catch (e) {\n      return [];\n    }\n  };\n  \n  // Extract all metrics\n  const parsedData = {\n    // Core Metrics\n    conversionProbability: extractNumber(/CONVERSION PROBABILITY:\\s*(\\d+)%/i),\n    confidenceLevel: extract(/CONFIDENCE LEVEL:\\s*(High|Medium|Low)/i),\n    confidenceReasoning: extract(/CONFIDENCE LEVEL:.*?\\n(.*?)(?=\\n\\n\\*\\*)/is),\n    \n    // Behavioral Score\n    behavioralScore: extractNumber(/BEHAVIORAL SCORE:\\s*(\\d+)\\/100/i),\n    engagementQuality: extractNumber(/Engagement Quality:\\s*(\\d+)\\/25/i),\n    momentum: extractNumber(/Momentum:\\s*(\\d+)\\/25/i),\n    stakeholderInvolvement: extractNumber(/Stakeholder Involvement:\\s*(\\d+)\\/25/i),\n    timelineProgress: extractNumber(/Timeline Progress:\\s*(\\d+)\\/25/i),\n    \n    // Risk Assessment\n    riskLevel: extract(/RISK LEVEL:\\s*(Green|Yellow|Red|Critical)/i),\n    dealHealthTrend: extract(/DEAL HEALTH TREND:\\s*(Improving|Stable|Declining|Stalled)/i),\n    immediateActionRequired: extract(/IMMEDIATE ACTION REQUIRED:\\s*(Yes|No)/i) === 'Yes',\n    \n    // Signals\n    positiveSignals: extractList('KEY POSITIVE SIGNALS DETECTED:', 'KEY RISK FACTORS'),\n    riskFactors: extractList('KEY RISK FACTORS DETECTED:', 'BEHAVIORAL INSIGHTS'),\n    \n    // Insights\n    behavioralInsights: extract(/BEHAVIORAL INSIGHTS:\\s*(.*?)(?=\\n\\n\\*\\*)/is),\n    \n    // Actions\n    recommendedActions: extractList('TOP 3 RECOMMENDED ACTIONS:', 'OPTIMAL NEXT ENGAGEMENT'),\n    \n    // Next Engagement\n    nextEngagementType: extract(/Type:\\s*(Email|Call|Meeting|Demo)/i),\n    nextEngagementTiming: extract(/Timing:\\s*(.*?)(?=\\n)/i),\n    nextEngagementFocus: extract(/Message Focus:\\s*(.*?)(?=\\n)/i),\n    nextEngagementGoal: extract(/Goal:\\s*(.*?)(?=\\n)/i),\n    \n    // Forecasting\n    forecastingRecommendation: extract(/FORECASTING RECOMMENDATION:\\s*(Commit|Best Case|Pipeline|Omit)/i),\n    forecastingReasoning: extract(/Reasoning:\\s*(.*?)(?=\\n\\n\\*\\*)/is),\n    \n    // Predictions\n    predictedCloseDate: extract(/PREDICTED CLOSE DATE:\\s*(\\d{4}-\\d{2}-\\d{2})/i),\n    alertPriority: extract(/ALERT PRIORITY:\\s*(P0-Critical|P1-High|P2-Medium|P3-Low)/i),\n    \n    // Summary\n    summaryText: extract(/Summary:\\s*(.*?)$/is),\n    \n    // Full response for reference\n    fullAnalysis: aiOutput,\n    \n    // Metadata\n    analysisTimestamp: new Date().toISOString()\n  };\n  \n  // Derived flags for workflows (with null safety)\n  parsedData.isHighRisk = parsedData.riskLevel === 'Red' || parsedData.riskLevel === 'Critical';\n  parsedData.needsImmediateAttention = parsedData.immediateActionRequired === true;\n  parsedData.isStalled = parsedData.dealHealthTrend === 'Stalled';\n  parsedData.lowProbability = parsedData.conversionProbability !== null && parsedData.conversionProbability < 50;\n  \n  // Add original deal data if available\n  if (item.json.dealData) {\n    parsedData.dealId = item.json.dealData.dealId;\n    parsedData.dealName = item.json.dealData.dealName;\n    parsedData.dealAmount = item.json.dealData.amount;\n    parsedData.dealStage = item.json.dealData.dealStage;\n    parsedData.ownerId = item.json.dealData.ownerId;\n  }\n  \n  results.push({ json: parsedData });\n}\n\nreturn results;"
      },
      "typeVersion": 2
    },
    {
      "id": "3e7a538d-58b2-44af-bf17-dfbac1d18469",
      "name": "Formatting Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -1232,
        304
      ],
      "parameters": {
        "jsCode": "const items = $input.all();\nconst filteredDeals = [];\n\n// Loop through each item (each item is already a deal)\nfor (const item of items) {\n  const deal = item.json;\n  const props = deal.properties;\n  \n  // Get associations\n  const contactIds = deal.associations?.associatedVids || [];\n  const companyIds = deal.associations?.associatedCompanyIds || [];\n  \n  // Extract only important fields\n  const filteredDeal = {\n    dealId: deal.dealId,\n    portalId: deal.portalId,\n    dealName: props.dealname?.value || 'Unnamed Deal',\n    amount: parseFloat(props.amount?.value || 0),\n    dealStage: props.dealstage?.value || 'unknown',\n    createDate: props.createdate?.value ? new Date(parseInt(props.createdate.value)).toISOString() : null,\n    closeDate: props.closedate?.value ? new Date(parseInt(props.closedate.value)).toISOString() : null,\n    lastModifiedDate: props.hs_lastmodifieddate?.value ? new Date(parseInt(props.hs_lastmodifieddate.value)).toISOString() : null,\n    lastContactedDate: props.notes_last_contacted?.value ? new Date(parseInt(props.notes_last_contacted.value)).toISOString() : null,\n    numAssociatedContacts: parseInt(props.num_associated_contacts?.value || 0),\n    daysSinceActivity: props.notes_last_contacted?.value ? \n      Math.floor((Date.now() - parseInt(props.notes_last_contacted.value)) / (1000 * 60 * 60 * 24)) :\n      (props.hs_lastmodifieddate?.value ? \n        Math.floor((Date.now() - parseInt(props.hs_lastmodifieddate.value)) / (1000 * 60 * 60 * 24)) : 999),\n    dealAgeDays: props.createdate?.value ? \n      Math.floor((Date.now() - parseInt(props.createdate.value)) / (1000 * 60 * 60 * 24)) : 0,\n    isDeleted: deal.isDeleted || false,\n    isClosed: ['closedwon', 'closedlost'].includes(props.dealstage?.value?.toLowerCase()),\n    isActive: !['closedwon', 'closedlost'].includes(props.dealstage?.value?.toLowerCase())\n  };\n  \n  // Add ownerId only if it exists\n  if (props.hs_all_owner_ids?.value) {\n    filteredDeal.ownerId = props.hs_all_owner_ids.value;\n  }\n  \n  // Add contact IDs dynamically (only non-null)\n  contactIds.forEach((contactId, index) => {\n    if (contactId) {\n      filteredDeal[`contactId${index + 1}`] = contactId;\n    }\n  });\n  if (contactIds.length > 0) {\n    filteredDeal.totalContacts = contactIds.length;\n  }\n  \n  // Add company IDs dynamically (only non-null)\n  companyIds.forEach((companyId, index) => {\n    if (companyId) {\n      filteredDeal[`companyId${index + 1}`] = companyId;\n    }\n  });\n  if (companyIds.length > 0) {\n    filteredDeal.totalCompanies = companyIds.length;\n  }\n  \n  filteredDeals.push({ json: filteredDeal });\n}\n\nreturn filteredDeals;"
      },
      "typeVersion": 2
    },
    {
      "id": "f7cb917b-9d3d-4bec-a56f-8c17badedb29",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2336,
        -128
      ],
      "parameters": {
        "width": 544,
        "height": 720,
        "content": "# AI-Powered HubSpot Deal Risk Monitoring\n\nThis workflow automatically reviews your active HubSpot deals, analyzes recent engagement activity using AI, and alerts your sales team when deals show signs of risk or stagnation. All analysis results are logged to Google Sheets for tracking and forecasting.\n\n## How this workflow works\n\n- Runs on a schedule to monitor your sales pipeline\n- Collects active deal data from HubSpot\n- Enriches each deal with recent engagement activity\n- Uses AI to predict conversion probability and deal health\n- Flags high-risk or stalled deals\n- Sends detailed alerts to Slack\n- Stores structured analysis results in Google Sheets\n\n## Setup steps\n\n1. Connect your HubSpot account  \n2. Connect your OpenAI account  \n3. Connect your Slack account  \n4. Connect your Google Sheets account  \n5. Replace example IDs (Slack channel, Google Sheet) with your own  \n6. Activate the workflow"
      },
      "typeVersion": 1
    },
    {
      "id": "c798ed58-be4c-463e-8d82-a332bee7ca61",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1776,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 720,
        "height": 720,
        "content": "### Step 1 \u2013 Trigger and collect active deals  \nThe workflow runs everyday at 4PM using a Schedule Trigger.  \nIt fetches all active (non-closed) deals from HubSpot and formats key fields such as deal value, stage, age, contacts, and last activity date."
      },
      "typeVersion": 1
    },
    {
      "id": "9477eebb-9801-460a-aad8-0abfb20abd89",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1040,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 1072,
        "height": 720,
        "content": "### Step 2 \u2013 Enrich deals with engagement data  \nEach deal is processed individually to retrieve associated engagements (emails, calls, meetings, notes).  \nEngagement data is normalized and enriched with timestamps, content, and internal notes to provide full context for analysis."
      },
      "typeVersion": 1
    },
    {
      "id": "df557527-a2ea-4339-9928-f54604e83be8",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        48,
        -128
      ],
      "parameters": {
        "color": 7,
        "width": 1264,
        "height": 720,
        "content": "## Step 3 \u2013 Analyze deals and notify team\n\nUses AI to evaluate deal health and conversion probability, identify risks and recommended actions, and determine urgency.  \nHigh-risk or stalled deals trigger Slack alerts and are logged in Google Sheets for tracking and forecasting."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "PLACEHOLDER_VERSION_ID",
  "connections": {
    "If": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Agent": {
      "main": [
        [
          {
            "node": "Format Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Data": {
      "main": [
        [
          {
            "node": "Filter Alerts Needed",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request": {
      "main": [
        [
          {
            "node": "Get an engagement",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extracts Data": {
      "main": [
        [
          {
            "node": "AI Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Formatting Data": {
      "main": [
        [
          {
            "node": "If",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop Over Items": {
      "main": [
        [],
        [
          {
            "node": "HTTP Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Get Active Deals from HubSpot",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Slack Alert": {
      "main": [
        [
          {
            "node": "Append or update row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get an engagement": {
      "main": [
        [
          {
            "node": "Extracts Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Filter Alerts Needed": {
      "main": [
        [
          {
            "node": "Send Slack Alert",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append or update row in sheet": {
      "main": [
        [
          {
            "node": "Loop Over Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Active Deals from HubSpot": {
      "main": [
        [
          {
            "node": "Formatting Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}