{
  "id": "gtmControlTower01",
  "name": "GTM Control Tower - Lead Routing",
  "nodes": [
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "gtm-lead",
        "responseMode": "responseNode",
        "options": {}
      },
      "id": "0e6ad5f7-02c1-44d0-a86e-15d0ed5cb203",
      "name": "Receive CRM Signal",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -700,
        80
      ]
    },
    {
      "parameters": {
        "jsCode": "const body = $json.body ?? $json;\nconst revenue = Number(body.annual_revenue ?? 0);\nconst employees = Number(body.employee_count ?? 0);\nconst score = Math.min(100, Math.round((revenue / 500000) + (employees / 20) + (body.intent_signal ? 25 : 0)));\nconst segment = revenue >= 20000000 ? 'Enterprise' : revenue >= 5000000 ? 'Mid-Market' : 'SMB';\nconst region = body.region ?? 'Central';\nconst owner = `${region.slice(0, 2).toUpperCase()}-${segment === 'Enterprise' ? 'ENT' : segment === 'Mid-Market' ? 'MM' : 'SMB'}`;\nconst eventTimestamp = new Date().toISOString();\nconst leadId = body.lead_id ?? `LEAD-${Date.now()}`;\nreturn [{ json: { ...body, lead_id: leadId, account_id: body.account_id ?? `ACC-${leadId}`, event_id: `${leadId}-${eventTimestamp}`, event_type: 'lead_routed', lifecycle_stage: score >= 70 ? 'mql' : 'lead', event_timestamp: eventTimestamp, score, segment, region, owner_id: owner, route_seconds: 0, is_duplicate: false } }];"
      },
      "id": "d7a6c42e-6637-4fc6-84ef-ae9bb3be1bbb",
      "name": "Normalize, Score & Route",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -450,
        80
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.hubapi.com/crm/objects/2026-03/contacts/batch/upsert",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "hubspotOAuth2Api",
        "sendBody": true,
        "contentType": "json",
        "specifyBody": "json",
        "jsonBody": "={{ { inputs: [{ id: $json.email, idProperty: 'email', objectWriteTraceId: $json.event_id, properties: { firstname: $json.first_name ?? '', lastname: $json.last_name ?? '', company: $json.company ?? '', annualrevenue: String($json.annual_revenue ?? 0), hs_lead_status: $json.score >= 70 ? 'IN_PROGRESS' : 'NEW', lifecyclestage: $json.lifecycle_stage === 'mql' ? 'marketingqualifiedlead' : 'lead', numemployees: $json.employee_count >= 1000 ? '1000+' : $json.employee_count >= 500 ? '500-1000' : $json.employee_count >= 100 ? '100-500' : $json.employee_count >= 50 ? '50-100' : $json.employee_count >= 25 ? '25-50' : $json.employee_count >= 5 ? '5-25' : '1-5' } }] } }}",
        "options": {}
      },
      "id": "49c76290-3a5f-4c33-8823-aac2fb997ee9",
      "name": "Upsert HubSpot Contact",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [
        -190,
        -120
      ],
      "notes": "Primary live CRM path. Uses HubSpot's current contacts batch-upsert API because the bundled HubSpot node still calls a legacy contacts endpoint."
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "operation": "upsert",
        "resource": "lead",
        "externalId": "GTM_Lead_Id__c",
        "externalIdValue": "={{ $json.lead_id }}",
        "company": "={{ $json.company ?? 'Unknown' }}",
        "lastname": "={{ $json.last_name ?? 'Unknown' }}",
        "additionalFields": {
          "email": "={{ $json.email }}",
          "annualRevenue": "={{ $json.annual_revenue }}",
          "numberOfEmployees": "={{ $json.employee_count }}",
          "leadSource": "={{ $json.source ?? 'Web' }}",
          "rating": "={{ $json.score >= 70 ? 'Hot' : 'Warm' }}",
          "customFieldsUi": {
            "customFieldsValues": [
              {
                "fieldId": "GTM_Score__c",
                "value": "={{ $json.score }}"
              },
              {
                "fieldId": "GTM_Segment__c",
                "value": "={{ $json.segment }}"
              },
              {
                "fieldId": "GTM_Routed_Owner__c",
                "value": "={{ $json.owner_id }}"
              },
              {
                "fieldId": "GTM_Last_Routed_At__c",
                "value": "={{ $json.event_timestamp }}"
              }
            ]
          }
        },
        "options": {}
      },
      "id": "c15b7f89-8319-47ec-b687-0306c7dd0d6c",
      "name": "Upsert Salesforce Lead",
      "type": "n8n-nodes-base.salesforce",
      "typeVersion": 1,
      "position": [
        -190,
        180
      ],
      "disabled": true,
      "notes": "Organization-specific custom-field example; intentionally disabled. The verified portable Salesforce path is the query-first CSV connector and does not require GTM_* custom fields."
    },
    {
      "parameters": {
        "authentication": "serviceAccount",
        "operation": "insert",
        "projectId": {
          "mode": "id",
          "value": "__GCP_PROJECT_ID__"
        },
        "datasetId": {
          "mode": "id",
          "value": "__BIGQUERY_SOURCE_DATASET__"
        },
        "tableId": {
          "mode": "id",
          "value": "raw_crm_events"
        },
        "dataMode": "autoMap",
        "options": {
          "ignoreUnknownValues": true
        }
      },
      "id": "75e1691f-11ee-477b-bf4a-7dcb77f1f1be",
      "name": "Append BigQuery Event",
      "type": "n8n-nodes-base.googleBigQuery",
      "typeVersion": 2.1,
      "position": [
        70,
        80
      ],
      "notes": "Bind your own least-privilege BigQuery credential after importing this workflow."
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ { accepted: true, lead_id: $json.lead_id ?? $('Normalize, Score & Route').item.json.lead_id, score: $('Normalize, Score & Route').item.json.score, owner_id: $('Normalize, Score & Route').item.json.owner_id } }}",
        "options": {
          "responseCode": 202
        }
      },
      "id": "848c1bd7-faf1-4ad2-88e0-63f0e39a6d2d",
      "name": "Return Routing Decision",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        330,
        80
      ]
    }
  ],
  "connections": {
    "Receive CRM Signal": {
      "main": [
        [
          {
            "node": "Normalize, Score & Route",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalize, Score & Route": {
      "main": [
        [
          {
            "node": "Upsert HubSpot Contact",
            "type": "main",
            "index": 0
          },
          {
            "node": "Upsert Salesforce Lead",
            "type": "main",
            "index": 0
          },
          {
            "node": "Append BigQuery Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append BigQuery Event": {
      "main": [
        [
          {
            "node": "Return Routing Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true
  },
  "versionId": "8455fc67-af18-4cfb-b76b-ec3d7f32b9ec",
  "meta": {
    "templateCredsSetupCompleted": false
  },
  "tags": []
}