All Templates
Revenue Operations • Advanced

Automated ICP Classification & CRM Enrichment

Scheduled n8n pipeline that enriches and classifies HubSpot companies against your ICP with evidence-based scoring, confidence levels, and full audit logging.

0

Interactive Workflow

Powered by n8n.io

How it works

Overview

A working n8n implementation of an evidence-based ICP classification pipeline. It runs on a schedule, pulls unclassified HubSpot companies, checks their enrichment state, branches between existing CRM data and Apollo enrichment, gathers web intelligence, runs a custom ICP scoring engine in JavaScript, and writes the classification - with confidence and matched evidence - back into HubSpot.

This is the working counterpart to the Target ICP Classification & VIP Lead Notification blueprint.

The flow

  1. Trigger - A schedule node runs the pipeline every 6 hours.
  2. Fetch - HubSpot search returns a batch of companies with a domain that have no target_icp and are not currently being processed.
  3. Lock - Each company is marked processing_icp = true before any enrichment starts, so parallel runs never touch the same record.
  4. Branch - If HubSpot already marks the company enriched, the workflow uses CRM data plus web intelligence. If not, it enriches via Apollo first.
  5. Evidence - Website/search intelligence adds a company summary; the code layer normalizes everything into one evidence record.
  6. Classify - Three JavaScript classification engines (Apollo+Exa path, HubSpot path, Exa path) score the company against ICP segments: Online Casino Operators, Platform Providers, CRM/Retention, iGaming Affiliates, Game/Slot Providers, and Investors.
  7. Gate & verify - A mandatory iGaming-context gate and negative/hard-exclusion signals block weak classifications; ambiguous results route to manual review.
  8. Update - Classified companies are written back to HubSpot with target_icp, confidence, score, matched keywords, and reason.
  9. Audit - Every result is appended to Google Sheets (or n8n data tables) for traceability.

At a glance: the CRM stops being a manual spreadsheet and becomes a repeatable, explainable classification pipeline - with enrichment spend used only where it is actually needed.

How to use

What you need

  • HubSpot - a private app token with Company read/write scope. Custom company properties used by this workflow: target_icp, processing_icp, hs_is_enriched, plus the icp_* fields the classifier writes.
  • Apollo - an API key. Open the HTTP Request4 node and set the x-api-key header value to your key (currently a placeholder - never commit real keys into workflow JSON).
  • Google Sheets - an OAuth2 connection. The document IDs were cleared for privacy: select your own sheet in each Append row in sheet node (or replace them with n8n Data Table nodes).
  • Exa (community node n8n-nodes-exa-official) - an API key for web intelligence. The workflow also includes SearXNG-compatible HTTP nodes pointing at a self-hosted search instance - point them at your own instance.

Import & setup

  1. Download the workflow JSON and import it into n8n.
  2. n8n will ask you to map credentials - connect your own HubSpot, Google Sheets, and Exa credentials (none are bundled).
  3. Put your Apollo API key in the x-api-key header of HTTP Request4.
  4. Point the four Google Sheets nodes at your own audit sheets.
  5. Create the HubSpot custom properties listed above if they don't exist yet.
  6. Activate the workflow - it will process up to 10 unclassified companies every 6 hours.

Notes

  • The schedule is set to every 6 hours (reconciled from the original export, which had conflicting settings).
  • The search/HTTP nodes reference a self-hosted search endpoint (search.uptune.io) - replace it with your own SearXNG/Exa setup, or keep the Exa community node path.
  • Security: this public template has credentials and private document IDs stripped. Rotate any key that was previously stored inside a workflow.
  • Read the full design behind this workflow in the Target ICP Classification & VIP Lead Notification blueprint.

Ready to use?

Import into n8n

Copy the workflow JSON below and paste it directly onto your n8n canvas.

Ctrl + V to paste in n8n
View raw JSON
{
  "name": "Target ICP Analysis (Company)",
  "nodes": [
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "hoursInterval": 6
            }
          ]
        }
      },
      "id": "070e16dc-1547-481b-88b0-9934f1ffbe21",
      "name": "⏰ Schedule Trigger1",
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.2,
      "position": [
        -2016,
        2144
      ],
      "notes": "Runs every 6 hours. Can also be triggered manually or via webhook."
    },
    {
      "parameters": {
        "authentication": "appToken",
        "resource": "company",
        "operation": "get",
        "companyId": {
          "__rl": true,
          "value": "={{ $json.companyId }}",
          "mode": "id"
        },
        "additionalFields": {}
      },
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.2,
      "position": [
        -1120,
        2144
      ],
      "id": "53599372-d544-4bea-bff0-495bd80389ba",
      "name": "Get a company1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "157ca031-8c00-4e9c-962d-ff5750536835",
              "leftValue": "={{ $('Split Out1').item.json.properties.hs_is_enriched }}",
              "rightValue": "true",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "looseTypeValidation": "={{ false }}",
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -896,
        2144
      ],
      "id": "42674363-445f-40fb-ad9b-44148ced4a95",
      "name": "If3"
    },
    {
      "parameters": {
        "url": "https://api.apollo.io/api/v1/organizations/enrich",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "domain",
              "value": "={{ $('If3').item.json.properties.domain.value }}"
            },
            {
              "name": "linkedin_url",
              "value": "={{ $('If3').item.json.properties.linkedin_company_page.value }}"
            },
            {
              "name": "name",
              "value": "={{ $('If3').item.json.properties.name.value }}"
            },
            {
              "name": "website",
              "value": "={{ $('If3').item.json.properties.domain.value }}"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Cache-Control",
              "value": "no-cache"
            },
            {
              "name": "accept",
              "value": "application/json"
            },
            {
              "name": "x-api-key",
              "value": "REPLACE_WITH_YOUR_APOLLO_API_KEY"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {}
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        224,
        2336
      ],
      "id": "3e497c25-b19c-48ee-9fd7-081cce051cce",
      "name": "HTTP Request4"
    },
    {
      "parameters": {
        "authentication": "appToken",
        "resource": "company",
        "operation": "update",
        "companyId": {
          "__rl": true,
          "value": "={{ $('Website Filter (Hubspot)1').item.json.companyId }}",
          "mode": "id"
        },
        "updateFields": {
          "customPropertiesUi": {
            "customPropertiesValues": [
              {
                "property": "target_icp",
                "value": "={{ $('Classify ICP (Hubspot)1').item.json.target_icp_marker }}"
              },
              {
                "property": "processing_icp",
                "value": "true"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.2,
      "position": [
        672,
        1856
      ],
      "id": "e8f6d2fc-dfa8-4242-b2fe-2a92a48c72ce",
      "name": "Update a company4"
    },
    {
      "parameters": {
        "jsCode": "// n8n Code node\n// Mode: Run Once for All Items\n// Purpose: Strictly classify Apollo + Exa-enriched company records into ICP segments\n//\n// Output ICP markers:\n// - ICP 1 (Online Casino Operators)\n// - ICP 2 (Platform Providers)\n// - ICP 3 (CRM / Retention)\n// - ICP 4 (iGaming Affiliates)\n// - ICP 5 (Game / Slot Providers)\n// - ICP 6 (iGaming Investors)\n\nconst DEBUG_EVIDENCE = true;\nconst CLASSIFICATION_VERSION = 'apollo-exa-icp-v1.3-all-target-icps';\n\nconst STRONG_EVIDENCE_FIELDS = new Set([\n  'name',\n  'account_name',\n  'short_description',\n  'description',\n  'keywords',\n  'exa_title',\n  'exa_summary',\n  'exa_text',\n  'exa_content'\n]);\n\nconst SUPPORTING_ONLY_FIELDS = new Set([\n  'industry',\n  'industries',\n  'secondary_industries',\n  'industry_tag_hash',\n  'technology_names',\n  'current_technologies',\n  'website_url',\n  'primary_domain',\n  'domain',\n  'linkedin_url',\n  'twitter_url',\n  'facebook_url',\n  'country'\n]);\n\nconst MANDATORY_IGAMING_CONTEXT_KEYWORDS = [\n  'casino',\n  'online casino',\n  'gambling',\n  'online gambling',\n  'sportsbook',\n  'betting',\n  'sports betting',\n  'igaming',\n  'i gaming',\n  'real money gaming',\n  'real money',\n  'rmg',\n  'slots',\n  'slot games',\n  'live casino',\n  'poker',\n  'jackpot',\n  'bet',\n  'odds',\n  'wager',\n  'lottery',\n  'lotto',\n  'esports betting'\n];\n\nconst GLOBAL_FALSE_POSITIVE_EXCLUSIONS = [\n  'board game',\n  'tabletop game',\n  'toy company',\n  'children games'\n];\n\nconst AFFILIATE_MEDIA_REVIEW_SIGNALS = [\n  'affiliate',\n  'affiliate marketing',\n  'lead generation',\n  'comparison site',\n  'casino reviews',\n  'sports betting reviews',\n  'betting reviews',\n  'review site',\n  'media company',\n  'publishing',\n  'publisher',\n  'traffic acquisition',\n  'performance marketing',\n  'seo',\n  'content marketing',\n  'partner network'\n];\n\nconst ICP_DEFINITIONS = [\n  {\n    icpNumber: 'ICP 1',\n    icpMarker: 'ICP 1 (Online Casino Operators)',\n    segment: 'Online Casino Operators',\n    keywordMatchGroup: 'Operator Keywords',\n    minScore: 6,\n    minStrongCoreMatches: 1,\n    genericCoreTerms: ['casino', 'gambling', 'igaming', 'i gaming', 'bet', 'lottery'],\n\n    coreKeywords: [\n      'online casino',\n      'casino operator',\n      'online casino operator',\n      'gambling operator',\n      'online gambling',\n      'sportsbook',\n      'sportsbook operator',\n      'betting',\n      'betting operator',\n      'online betting',\n      'sports betting',\n      'real money gaming',\n      'real money deposit',\n      'rmg',\n      'slots',\n      'slot games',\n      'live casino',\n      'poker',\n      'jackpot',\n      'daily jackpot',\n      'odds',\n      'betting odds',\n      'wager',\n      'lottery operator',\n      'lottery',\n      'lotto'\n    ],\n\n    productSignals: [\n      'licensed operator',\n      'betting license',\n      'gaming license',\n      'player account',\n      'player wallet',\n      'deposit',\n      'withdrawal',\n      'deposit methods',\n      'withdrawal methods',\n      'kyc verification',\n      'wagering requirements',\n      'bonus terms',\n      'live betting',\n      'casino lobby',\n      'game providers',\n      'rng games',\n      'live dealer',\n      'vip program',\n      'loyalty rewards',\n      'responsible gambling',\n      'responsible gaming',\n      'responsible play',\n      'player protection',\n      'player safety',\n      'bet slip',\n      'cash out',\n      'cashout',\n      'payment methods',\n      'mobile app',\n      'players',\n      'b2c'\n    ],\n\n    supportingIndustries: [\n      'gambling',\n      'gambling casinos',\n      'gambling and casinos',\n      'gambling & casinos',\n      'casino',\n      'casinos',\n      'igaming operators',\n      'i gaming operators',\n      'lottery',\n      'other gambling industries'\n    ],\n\n    negativeSignals: [\n      'b2b',\n      'platform provider',\n      'software provider',\n      'gaming software',\n      'casino software',\n      'white label',\n      'white label casino',\n      'turnkey casino',\n      'turnkey solution',\n      'api integration',\n      'game aggregation',\n      'content aggregation',\n      'operator clients',\n      'platform partners',\n      'integration partners',\n      'custom software',\n      'software development',\n      'product development',\n      'igaming solutions',\n      'casino solution',\n      'sportsbook platform',\n      'game studio',\n      'slot developer',\n      'game provider',\n      'investment firm',\n      'venture capital',\n      ...AFFILIATE_MEDIA_REVIEW_SIGNALS\n    ],\n\n    hardExclusions: [\n      'resort',\n      'hotel',\n      'hospitality',\n      'spa',\n      'entertainment complex',\n      'physical casino',\n      'land based',\n      'land-based',\n      'venue',\n      'conference',\n      ...GLOBAL_FALSE_POSITIVE_EXCLUSIONS\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 2',\n    icpMarker: 'ICP 2 (Platform Providers)',\n    segment: 'Platform Providers',\n    keywordMatchGroup: 'Platform Keywords',\n    minScore: 6,\n    minStrongCoreMatches: 1,\n    genericCoreTerms: [],\n\n    coreKeywords: [\n      'white label casino',\n      'white label igaming',\n      'igaming platform',\n      'i gaming platform',\n      'casino platform',\n      'turnkey casino',\n      'turnkey igaming',\n      'sportsbook platform',\n      'gaming platform provider',\n      'game aggregation platform',\n      'aggregation platform',\n      'casino solution',\n      'casino software',\n      'gaming software',\n      'operator platform',\n      'api gaming platform',\n      'igaming solutions',\n      'i gaming solutions',\n      'sportsbook solution',\n      'sportsbook software',\n      'betting platform',\n      'betting software',\n      'esports betting platform',\n      'betting data',\n      'official esports data',\n      'official game data',\n      'official telemetry feeds',\n      'data platform for betting',\n      'services for betting operators',\n      'services for the esports betting industry'\n    ],\n\n    productSignals: [\n      'white label solution',\n      'turnkey solution',\n      'gaming platform',\n      'platform provider',\n      'software provider',\n      'api integration',\n      'api documentation',\n      'game aggregation',\n      'content aggregation',\n      'sportsbook engine',\n      'casino engine',\n      'operator dashboard',\n      'back office system',\n      'backoffice',\n      'back office',\n      'player management system',\n      'wallet integration',\n      'kyc integration',\n      'payment gateway integration',\n      'risk management tools',\n      'multi brand',\n      'multi-brand',\n      'multi tenant',\n      'multi-tenant',\n      'operator clients',\n      'platform partners',\n      'integration partners',\n      'b2b gaming',\n      'b2b igaming',\n      'b2b',\n      'data api',\n      'data apis',\n      'data feeds',\n      'data distribution',\n      'official data',\n      'real-time data',\n      'predictive analytics',\n      'custom software',\n      'software development',\n      'product development',\n      'product creation',\n      'technology company',\n      'tech solutions',\n      'digital solutions'\n    ],\n\n    supportingIndustries: [\n      'information technology',\n      'information technology and services',\n      'information technology & services',\n      'computer software',\n      'enterprise software',\n      'saas',\n      'software',\n      'software development',\n      'technology',\n      'it services',\n      'it consulting',\n      'gaming software',\n      'internet'\n    ],\n\n    negativeSignals: [\n      'casino operator',\n      'online casino operator',\n      'sportsbook operator',\n      'betting operator',\n      'gambling operator',\n      'public gaming operator',\n      'b2c operator',\n      'affiliate',\n      'review site',\n      'investment firm',\n      'venture capital'\n    ],\n\n    hardExclusions: [\n      ...GLOBAL_FALSE_POSITIVE_EXCLUSIONS\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 3',\n    icpMarker: 'ICP 3 (CRM)',\n    segment: 'CRM / Retention',\n    keywordMatchGroup: 'CRM Keywords',\n    minScore: 6,\n    minStrongCoreMatches: 1,\n    genericCoreTerms: [],\n\n    coreKeywords: [\n      'igaming crm',\n      'i gaming crm',\n      'casino crm',\n      'sportsbook crm',\n      'gaming crm',\n      'player retention',\n      'player engagement',\n      'loyalty platform',\n      'marketing automation casino',\n      'gaming crm platform',\n      'customer retention gaming',\n      'bonus engine',\n      'campaign management gaming',\n      'player lifecycle',\n      'player engagement platform',\n      'retention platform for igaming',\n      'crm for igaming operators'\n    ],\n\n    productSignals: [\n      'player segmentation',\n      'customer segmentation',\n      'campaign automation',\n      'campaign management',\n      'reward engine',\n      'event based messaging',\n      'event-based messaging',\n      'real time triggers',\n      'real-time triggers',\n      'player journeys',\n      'churn prevention',\n      'behavior tracking',\n      'customer data platform',\n      'cdp',\n      'reactivation campaigns',\n      'retention campaigns',\n      'push notifications',\n      'sms',\n      'email',\n      'multi channel messaging',\n      'multi-channel messaging',\n      'bonus management',\n      'loyalty rewards',\n      'retention',\n      'customer retention',\n      'marketing automation',\n      'lifecycle marketing'\n    ],\n\n    supportingIndustries: [\n      'computer software',\n      'saas',\n      'marketing',\n      'advertising',\n      'crm',\n      'marketing automation',\n      'customer retention',\n      'email marketing'\n    ],\n\n    negativeSignals: [\n      'casino operator',\n      'online casino operator',\n      'sportsbook operator',\n      'betting operator',\n      'gambling operator',\n      'public gaming operator',\n      'b2c operator',\n      'affiliate',\n      'review site'\n    ],\n\n    hardExclusions: [\n      ...GLOBAL_FALSE_POSITIVE_EXCLUSIONS\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 4',\n    icpMarker: 'ICP 4 (iGaming Affiliates)',\n    segment: 'iGaming Affiliates',\n    keywordMatchGroup: 'Affiliate Keywords',\n    minScore: 6,\n    minStrongCoreMatches: 1,\n    genericCoreTerms: ['affiliate'],\n\n    coreKeywords: [\n      'igaming affiliate',\n      'casino affiliate',\n      'sports betting affiliate',\n      'betting affiliate',\n      'gambling affiliate',\n      'affiliate network',\n      'affiliate marketing',\n      'lead generation for betting',\n      'casino comparison',\n      'casino reviews',\n      'sports betting reviews',\n      'betting reviews',\n      'bonus comparison',\n      'odds comparison',\n      'review site',\n      'comparison site',\n      'gambling media',\n      'igaming media',\n      'betting media',\n      'casino media'\n    ],\n\n    productSignals: [\n      'traffic acquisition',\n      'performance marketing',\n      'seo',\n      'content marketing',\n      'publisher',\n      'publishing',\n      'partner network',\n      'affiliate program',\n      'lead generation',\n      'player acquisition',\n      'casino bonus',\n      'bonus codes',\n      'betting tips',\n      'odds comparison',\n      'operator reviews',\n      'bookmaker reviews'\n    ],\n\n    supportingIndustries: [\n      'marketing',\n      'advertising',\n      'media',\n      'publishing',\n      'internet',\n      'gambling',\n      'casino',\n      'sports betting',\n      'igaming'\n    ],\n\n    negativeSignals: [\n      'casino operator',\n      'sportsbook operator',\n      'platform provider',\n      'white label casino',\n      'casino software',\n      'game studio',\n      'slot developer',\n      'investment firm',\n      'venture capital'\n    ],\n\n    hardExclusions: [\n      ...GLOBAL_FALSE_POSITIVE_EXCLUSIONS\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 5',\n    icpMarker: 'ICP 5 (Game / Slot Providers)',\n    segment: 'Game / Slot Providers',\n    keywordMatchGroup: 'Game Provider Keywords',\n    minScore: 6,\n    minStrongCoreMatches: 1,\n    genericCoreTerms: ['game provider', 'game studio'],\n\n    coreKeywords: [\n      'casino game provider',\n      'slot provider',\n      'slot game provider',\n      'slot developer',\n      'slot game developer',\n      'casino game developer',\n      'online casino games',\n      'casino games',\n      'slot games',\n      'slots provider',\n      'game studio',\n      'igaming studio',\n      'live casino provider',\n      'live dealer provider',\n      'rng games',\n      'instant games',\n      'crash games',\n      'table games',\n      'game aggregation',\n      'game content provider',\n      'casino content provider',\n      'gaming content provider'\n    ],\n\n    productSignals: [\n      'game portfolio',\n      'slots portfolio',\n      'game catalog',\n      'casino content',\n      'html5 games',\n      'rng',\n      'random number generator',\n      'live dealer',\n      'blackjack',\n      'roulette',\n      'baccarat',\n      'crash game',\n      'provably fair',\n      'game math',\n      'game mechanics',\n      'operator integration',\n      'casino operators',\n      'regulated markets',\n      'certified games',\n      'game certification'\n    ],\n\n    supportingIndustries: [\n      'computer games',\n      'gaming software',\n      'software',\n      'technology',\n      'igaming',\n      'casino',\n      'gambling'\n    ],\n\n    negativeSignals: [\n      'casino operator',\n      'sportsbook operator',\n      'affiliate',\n      'review site',\n      'investment firm',\n      'venture capital'\n    ],\n\n    hardExclusions: [\n      'console game',\n      'pc game',\n      'mobile game studio',\n      'video game studio',\n      'video games',\n      ...GLOBAL_FALSE_POSITIVE_EXCLUSIONS\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 6',\n    icpMarker: 'ICP 6 (iGaming Investors)',\n    segment: 'iGaming Investors',\n    keywordMatchGroup: 'Investor Keywords',\n    minScore: 6,\n    minStrongCoreMatches: 1,\n    genericCoreTerms: ['investor'],\n\n    coreKeywords: [\n      'igaming investor',\n      'gaming investor',\n      'gambling investor',\n      'casino investor',\n      'sports betting investor',\n      'venture capital',\n      'vc fund',\n      'investment firm',\n      'private equity',\n      'family office',\n      'angel investor',\n      'seed investor',\n      'early stage investor',\n      'growth investor',\n      'invests in igaming',\n      'invests in gambling',\n      'invests in sports betting',\n      'invests in casino',\n      'gaming venture capital',\n      'betting investment'\n    ],\n\n    productSignals: [\n      'portfolio companies',\n      'investment portfolio',\n      'fund',\n      'funding',\n      'seed round',\n      'series a',\n      'series b',\n      'growth capital',\n      'minority investment',\n      'acquisition',\n      'merger',\n      'm&a',\n      'strategic investment',\n      'backed companies',\n      'portfolio includes',\n      'investor in'\n    ],\n\n    supportingIndustries: [\n      'venture capital',\n      'private equity',\n      'investment management',\n      'financial services',\n      'family office',\n      'capital markets',\n      'gambling',\n      'igaming',\n      'sports betting',\n      'casino'\n    ],\n\n    negativeSignals: [\n      'casino operator',\n      'sportsbook operator',\n      'platform provider',\n      'casino software',\n      'affiliate',\n      'review site',\n      'game studio',\n      'slot developer'\n    ],\n\n    hardExclusions: [\n      ...GLOBAL_FALSE_POSITIVE_EXCLUSIONS\n    ]\n  }\n];\n\nconst FIELD_WEIGHTS = {\n  name: 0.9,\n  account_name: 0.7,\n\n  short_description: 1.45,\n  description: 1.35,\n  keywords: 1.3,\n\n  exa_title: 1.25,\n  exa_summary: 1.45,\n  exa_text: 1.25,\n  exa_content: 1.25,\n\n  industry: 0.45,\n  industries: 0.45,\n  secondary_industries: 0.35,\n  industry_tag_hash: 0.35,\n\n  technology_names: 0.25,\n  current_technologies: 0.25,\n\n  website_url: 0.2,\n  primary_domain: 0.2,\n  domain: 0.2,\n\n  linkedin_url: 0.15,\n  twitter_url: 0.1,\n  facebook_url: 0.1,\n\n  country: 0.05\n};\n\nconst SCORE_WEIGHTS = {\n  core: 5,\n  productSignal: 2.5,\n  supportingIndustry: 1,\n  negativeSignalPenalty: 3.5,\n  hardExclusionPenalty: 10\n};\n\nfunction toArray(value) {\n  if (value === undefined || value === null) return [];\n\n  if (Array.isArray(value)) {\n    return value\n      .flatMap(v => toArray(v))\n      .filter(v => v !== undefined && v !== null && String(v).trim() !== '');\n  }\n\n  if (typeof value === 'object') return [];\n\n  return String(value)\n    .split(/[;,|]/g)\n    .map(v => v.trim())\n    .filter(Boolean);\n}\n\nfunction objectKeys(value) {\n  if (!value || typeof value !== 'object' || Array.isArray(value)) return [];\n  return Object.keys(value);\n}\n\nfunction currentTechnologyTerms(currentTechnologies) {\n  if (!Array.isArray(currentTechnologies)) return [];\n\n  const terms = [];\n\n  for (const tech of currentTechnologies) {\n    if (!tech || typeof tech !== 'object') continue;\n\n    if (tech.name) terms.push(tech.name);\n    if (tech.category) terms.push(tech.category);\n    if (tech.uid) terms.push(tech.uid);\n  }\n\n  return terms.filter(Boolean);\n}\n\nfunction cleanDomain(value) {\n  const raw = Array.isArray(value) ? value[0] : String(value || '');\n  if (!raw) return '';\n\n  return raw\n    .replace(/^https?:\\/\\//i, '')\n    .replace(/^www\\./i, '')\n    .split('/')[0]\n    .trim()\n    .toLowerCase();\n}\n\nfunction normalizeText(value) {\n  const text = Array.isArray(value) ? value.join(' ') : String(value || '');\n\n  return text\n    .normalize('NFD')\n    .replace(/[\\u0300-\\u036f]/g, '')\n    .toLowerCase()\n    .replace(/&/g, ' and ')\n    .replace(/[’']/g, '')\n    .replace(/[_/|;,:()[\\]{}+]+/g, ' ')\n    .replace(/[–—-]/g, ' ')\n    .replace(/\\s+/g, ' ')\n    .trim();\n}\n\nfunction escapeRegExp(str) {\n  return String(str).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nconst patternCache = new Map();\n\nfunction termRegex(term) {\n  const normalized = normalizeText(term);\n  if (!normalized) return null;\n\n  if (!patternCache.has(normalized)) {\n    const body = escapeRegExp(normalized).replace(/\\s+/g, '\\\\s+');\n\n    patternCache.set(\n      normalized,\n      new RegExp(`(^|[^a-z0-9])${body}($|[^a-z0-9])`, 'i')\n    );\n  }\n\n  return patternCache.get(normalized);\n}\n\nfunction findMatches(terms, normalizedFields) {\n  const matches = [];\n  const seenTerms = new Set();\n\n  for (const term of terms || []) {\n    const regex = termRegex(term);\n    if (!regex) continue;\n\n    const normalizedTerm = normalizeText(term);\n    if (seenTerms.has(normalizedTerm)) continue;\n\n    for (const [field, text] of Object.entries(normalizedFields)) {\n      if (!text || !regex.test(text)) continue;\n\n      matches.push({\n        term,\n        normalizedTerm,\n        field,\n        fieldWeight: FIELD_WEIGHTS[field] || 1,\n        isStrongField: STRONG_EVIDENCE_FIELDS.has(field),\n        isSupportingOnlyField: SUPPORTING_ONLY_FIELDS.has(field)\n      });\n\n      seenTerms.add(normalizedTerm);\n      break;\n    }\n  }\n\n  return matches;\n}\n\nfunction weightedScore(matches, baseWeight) {\n  return matches.reduce((total, match) => {\n    return total + baseWeight * match.fieldWeight;\n  }, 0);\n}\n\nfunction topTerms(matches, limit = 8) {\n  return (matches || []).map(m => m.term).slice(0, limit).join(', ');\n}\n\nfunction strongMatches(matches) {\n  return (matches || []).filter(m => m.isStrongField);\n}\n\nfunction hasHighPrecisionCoreMatch(matches, genericCoreTerms = []) {\n  const generic = new Set((genericCoreTerms || []).map(t => normalizeText(t)));\n  return (matches || []).some(match => !generic.has(match.normalizedTerm));\n}\n\nfunction buildReason(best, second, needsManualReview, gate) {\n  const context = topTerms(gate.strongMandatoryContextMatches, 4);\n\n  const core = best.strongCoreMatches\n    .map(m => `${m.term} (${m.field})`)\n    .slice(0, 3)\n    .join(', ');\n\n  const signals = best.strongSignalMatches\n    .map(m => `${m.term} (${m.field})`)\n    .slice(0, 3)\n    .join(', ');\n\n  const support = best.industryMatches\n    .map(m => `${m.term} (${m.field})`)\n    .slice(0, 2)\n    .join(', ');\n\n  const negative = best.negativeMatches\n    .map(m => `${m.term} (${m.field})`)\n    .slice(0, 2)\n    .join(', ');\n\n  let reason = `Matched ${best.icpMarker}`;\n\n  if (context) {\n    reason += ` after mandatory iGaming context gate passed from strong evidence fields: ${context}`;\n  }\n\n  if (core) {\n    reason += `; segment core keywords: ${core}`;\n  }\n\n  if (signals) {\n    reason += `; product signals: ${signals}`;\n  }\n\n  if (support) {\n    reason += `; supporting context: ${support}`;\n  }\n\n  if (negative) {\n    reason += `; negative signals considered: ${negative}`;\n  }\n\n  if (needsManualReview && second) {\n    reason += `; close score with ${second.icpMarker}, so manual review is recommended`;\n  }\n\n  return reason + '.';\n}\n\nfunction notClassifiedResponse(reason, results = [], gate = {}) {\n  const second = results?.[1];\n\n  return {\n    target_icp_marker: 'Not Classified',\n    target_icp_number: '',\n    target_icp_name: 'Not Classified',\n\n    icp_segment: 'Not Classified',\n    keyword_match_group: '',\n    classification_confidence: 'Low',\n    classification_score: 0,\n    classification_reason: reason,\n\n    strict_gate_passed: false,\n    mandatory_context_match: topTerms(gate.mandatoryContextMatches || [], 8),\n    strong_mandatory_context_match: topTerms(gate.strongMandatoryContextMatches || [], 8),\n    weak_mandatory_context_match: topTerms(gate.weakMandatoryContextMatches || [], 8),\n\n    matched_core_keywords: '',\n    strong_core_keywords: '',\n    product_signal_match: '',\n    strong_product_signal_match: '',\n    supporting_industry_match: '',\n    negative_signal_match: '',\n    hard_exclusion_match: topTerms(gate.globalFalsePositiveMatches || [], 8),\n\n    needs_manual_review: false,\n    second_best_segment: second?.icpMarker || '',\n    second_best_score: second?.score || 0,\n\n    _all_scores: Object.fromEntries((results || []).map(r => [r.icpMarker, r.score])),\n    _debug_evidence: DEBUG_EVIDENCE ? { gate, results } : undefined\n  };\n}\n\nfunction classify(normalizedFields) {\n  const mandatoryContextMatches = findMatches(\n    MANDATORY_IGAMING_CONTEXT_KEYWORDS,\n    normalizedFields\n  );\n\n  const strongMandatoryContextMatches = strongMatches(mandatoryContextMatches);\n\n  const weakMandatoryContextMatches = mandatoryContextMatches.filter(\n    m => !m.isStrongField\n  );\n\n  const globalFalsePositiveMatches = findMatches(\n    GLOBAL_FALSE_POSITIVE_EXCLUSIONS,\n    normalizedFields\n  );\n\n  const gate = {\n    mandatoryContextMatches,\n    strongMandatoryContextMatches,\n    weakMandatoryContextMatches,\n    globalFalsePositiveMatches,\n    hasMandatoryIgamingContext: strongMandatoryContextMatches.length > 0\n  };\n\n  if (!gate.hasMandatoryIgamingContext) {\n    return notClassifiedResponse(\n      'Mandatory iGaming context gate failed. No casino, gambling, betting, sportsbook, iGaming, RMG, slots, live casino, poker, jackpot, bet, odds, wager, lottery, or esports betting keywords were found in strong evidence fields. Industry, domain, website, and technology fields are supporting only and cannot classify the company by themselves.',\n      [],\n      gate\n    );\n  }\n\n  const results = ICP_DEFINITIONS.map((icp) => {\n    const coreMatches = findMatches(icp.coreKeywords, normalizedFields);\n    const signalMatches = findMatches(icp.productSignals, normalizedFields);\n    const industryMatches = findMatches(icp.supportingIndustries, normalizedFields);\n    const negativeMatches = findMatches(icp.negativeSignals, normalizedFields);\n    const hardExclusionMatches = findMatches(icp.hardExclusions, normalizedFields);\n\n    const strongCoreMatches = strongMatches(coreMatches);\n    const strongSignalMatches = strongMatches(signalMatches);\n\n    const hasHighPrecisionCore = hasHighPrecisionCoreMatch(\n      strongCoreMatches,\n      icp.genericCoreTerms\n    );\n\n    const hasEnoughStrongCore =\n      strongCoreMatches.length >= icp.minStrongCoreMatches;\n\n    const hasOnlyGenericCore =\n      strongCoreMatches.length > 0 && !hasHighPrecisionCore;\n\n    const genericCoreIsSupported =\n      !hasOnlyGenericCore ||\n      strongCoreMatches.length >= 2 ||\n      strongSignalMatches.length >= 1;\n\n    const hasRequiredSegmentEvidence =\n      hasEnoughStrongCore && genericCoreIsSupported;\n\n    const hasBlockingHardExclusion =\n      hardExclusionMatches.length > 0;\n\n    const evidenceScore =\n      weightedScore(coreMatches, SCORE_WEIGHTS.core) +\n      weightedScore(signalMatches, SCORE_WEIGHTS.productSignal);\n\n    const supportScore =\n      weightedScore(industryMatches, SCORE_WEIGHTS.supportingIndustry);\n\n    const negativePenalty =\n      weightedScore(negativeMatches, SCORE_WEIGHTS.negativeSignalPenalty);\n\n    const hardExclusionPenalty =\n      weightedScore(hardExclusionMatches, SCORE_WEIGHTS.hardExclusionPenalty);\n\n    let score = Math.max(\n      0,\n      evidenceScore + supportScore - negativePenalty - hardExclusionPenalty\n    );\n\n    if (!hasRequiredSegmentEvidence || hasBlockingHardExclusion) {\n      score = 0;\n    }\n\n    return {\n      icpNumber: icp.icpNumber,\n      icpMarker: icp.icpMarker,\n      segment: icp.segment,\n      keywordMatchGroup: icp.keywordMatchGroup,\n      minScore: icp.minScore,\n      score: Number(score.toFixed(2)),\n\n      coreMatches,\n      strongCoreMatches,\n      signalMatches,\n      strongSignalMatches,\n      industryMatches,\n      negativeMatches,\n      hardExclusionMatches,\n\n      mandatoryContextMatches,\n      strongMandatoryContextMatches,\n      weakMandatoryContextMatches,\n\n      hasHighPrecisionCore,\n      hasOnlyGenericCore,\n      hasRequiredSegmentEvidence,\n      hasBlockingHardExclusion,\n      strictGatePassed:\n        gate.hasMandatoryIgamingContext &&\n        hasRequiredSegmentEvidence &&\n        !hasBlockingHardExclusion\n    };\n  }).sort((a, b) => b.score - a.score);\n\n  const best = results[0];\n  const second = results[1];\n\n  if (!best || best.score < best.minScore || !best.strictGatePassed) {\n    return notClassifiedResponse(\n      'Mandatory iGaming context was found in strong evidence fields, but no ICP segment reached the minimum score with its own required strong segment keywords. Generic software, platform, CRM, marketing, technology, industry, website, domain, or technology terms were not enough to classify the company.',\n      results,\n      gate\n    );\n  }\n\n  const scoreGap = best.score - (second?.score || 0);\n\n  const hasWeakEvidenceProfile =\n    best.strongCoreMatches.length === 1 &&\n    best.strongSignalMatches.length === 0;\n\n  const needsManualReview =\n    (\n      best.score >= best.minScore &&\n      second &&\n      second.score >= second.minScore &&\n      scoreGap <= 3\n    ) ||\n    hasWeakEvidenceProfile;\n\n  let confidence = 'Low';\n\n  if (\n    best.score >= 18 &&\n    scoreGap >= 5 &&\n    !needsManualReview &&\n    (\n      best.strongCoreMatches.length >= 2 ||\n      best.strongSignalMatches.length >= 2\n    )\n  ) {\n    confidence = 'High';\n  } else if (\n    best.score >= 9 &&\n    scoreGap >= 3\n  ) {\n    confidence = 'Medium';\n  }\n\n  if (needsManualReview) {\n    confidence = 'Low';\n  }\n\n  return {\n    target_icp_marker: best.icpMarker,\n    target_icp_number: best.icpNumber,\n    target_icp_name: best.segment,\n\n    icp_segment: best.icpMarker,\n    keyword_match_group: best.keywordMatchGroup,\n    classification_confidence: confidence,\n    classification_score: best.score,\n    classification_reason: buildReason(best, second, needsManualReview, gate),\n\n    strict_gate_passed: true,\n    mandatory_context_match: topTerms(best.mandatoryContextMatches, 8),\n    strong_mandatory_context_match: topTerms(best.strongMandatoryContextMatches, 8),\n    weak_mandatory_context_match: topTerms(best.weakMandatoryContextMatches, 8),\n\n    matched_core_keywords: topTerms(best.coreMatches),\n    strong_core_keywords: topTerms(best.strongCoreMatches),\n    product_signal_match: topTerms(best.signalMatches),\n    strong_product_signal_match: topTerms(best.strongSignalMatches),\n    supporting_industry_match: topTerms(best.industryMatches, 5),\n    negative_signal_match: topTerms(best.negativeMatches, 5),\n    hard_exclusion_match: topTerms(best.hardExclusionMatches, 5),\n\n    needs_manual_review: needsManualReview,\n    second_best_segment: second?.icpMarker || '',\n    second_best_score: second?.score || 0,\n\n    _all_scores: Object.fromEntries(results.map(r => [r.icpMarker, r.score])),\n    _debug_evidence: DEBUG_EVIDENCE ? { gate, results } : undefined\n  };\n}\n\nfunction getApolloPayloads(json) {\n  const root = json?.body || json;\n  if (!root) return [];\n\n  if (Array.isArray(root)) return root.filter(Boolean);\n\n  if (Array.isArray(root.organizations)) return root.organizations.filter(Boolean);\n  if (Array.isArray(root.accounts)) return root.accounts.filter(Boolean);\n  if (Array.isArray(root.companies)) return root.companies.filter(Boolean);\n\n  if (Array.isArray(root.body?.organizations)) return root.body.organizations.filter(Boolean);\n  if (Array.isArray(root.body?.accounts)) return root.body.accounts.filter(Boolean);\n  if (Array.isArray(root.body?.companies)) return root.body.companies.filter(Boolean);\n\n  // Do not blindly split root.results, because Exa may also return results.\n  // Only treat results as Apollo company results if they contain organization-like fields.\n  if (\n    Array.isArray(root.results) &&\n    root.results.some(r =>\n      r?.organization ||\n      r?.account ||\n      r?.primary_domain ||\n      r?.website_url ||\n      r?.name\n    )\n  ) {\n    return root.results.filter(Boolean);\n  }\n\n  return [root];\n}\n\nfunction extractOrganization(payload) {\n  if (!payload || typeof payload !== 'object') return {};\n\n  if (payload.organization && typeof payload.organization === 'object') {\n    return payload.organization;\n  }\n\n  if (\n    payload.account?.organization &&\n    typeof payload.account.organization === 'object'\n  ) {\n    return payload.account.organization;\n  }\n\n  return payload;\n}\n\nfunction collectExaStrings(value, depth = 0) {\n  if (value === undefined || value === null || depth > 4) return [];\n\n  if (typeof value === 'string') {\n    const trimmed = value.trim();\n    return trimmed ? [trimmed] : [];\n  }\n\n  if (Array.isArray(value)) {\n    return value.flatMap(v => collectExaStrings(v, depth + 1));\n  }\n\n  if (typeof value === 'object') {\n    const preferredKeys = [\n      'title',\n      'summary',\n      'text',\n      'content',\n      'contents',\n      'extract',\n      'description',\n      'snippet',\n      'highlights',\n      'results'\n    ];\n\n    const strings = [];\n\n    for (const key of preferredKeys) {\n      if (value[key] !== undefined) {\n        strings.push(...collectExaStrings(value[key], depth + 1));\n      }\n    }\n\n    return strings;\n  }\n\n  return [];\n}\n\nfunction extractExaContent(payload) {\n  const possibleExaSources = [\n    payload.exa,\n    payload.exa_result,\n    payload.exa_results,\n    payload.exa_content,\n    payload.content,\n    payload.contents,\n    payload.result,\n    payload.results,\n    payload.body?.content,\n    payload.body?.contents,\n    payload.body?.results,\n    payload\n  ];\n\n  const title = [\n    payload.title,\n    payload.exa?.title,\n    payload.result?.title,\n    payload.results?.[0]?.title\n  ].filter(Boolean).join(' ');\n\n  const summary = [\n    payload.summary,\n    payload.exa_summary,\n    payload.exa?.summary,\n    payload.result?.summary,\n    payload.results?.[0]?.summary\n  ].filter(Boolean).join(' ');\n\n  const allText = possibleExaSources\n    .flatMap(source => collectExaStrings(source))\n    .join(' ')\n    .slice(0, 25000);\n\n  return {\n    exa_title: title,\n    exa_summary: summary,\n    exa_text: allText,\n    exa_content: allText\n  };\n}\n\nfunction mapApolloCompany(payload) {\n  const org = extractOrganization(payload);\n  const account = org.account || payload.account || {};\n  const exa = extractExaContent(payload);\n\n  const technologyNames = toArray(org.technology_names);\n  const currentTechnologies = currentTechnologyTerms(org.current_technologies);\n\n  const keywords = [\n    ...toArray(org.keywords),\n    ...toArray(org.industry_keywords),\n    ...toArray(org.tags),\n    ...toArray(payload.keywords)\n  ];\n\n  const industries = [\n    ...toArray(org.industries),\n    org.industry,\n    payload.industry\n  ].filter(Boolean);\n\n  const secondaryIndustries = [\n    ...toArray(org.secondary_industries),\n    ...toArray(payload.secondary_industries)\n  ];\n\n  const industryTagHash = [\n    ...objectKeys(org.industry_tag_hash),\n    ...objectKeys(payload.industry_tag_hash)\n  ];\n\n  const company = {\n    apollo_id: org.id || payload.id || '',\n    apollo_account_id: org.account_id || account.id || '',\n\n    hubspot_id:\n      account.hubspot_id ||\n      org.hubspot_id ||\n      payload.hubspot_id ||\n      payload.hubspotId ||\n      '',\n\n    company_name: org.name || account.name || payload.name || '',\n    account_name: account.name || '',\n\n    website:\n      org.website_url ||\n      org.website ||\n      account.website_url ||\n      payload.website_url ||\n      payload.website ||\n      payload.url ||\n      '',\n\n    domain: cleanDomain(\n      org.primary_domain ||\n      account.domain ||\n      org.domain ||\n      org.website_url ||\n      account.website_url ||\n      payload.primary_domain ||\n      payload.domain ||\n      payload.website_url ||\n      payload.url ||\n      ''\n    ),\n\n    linkedin_url: org.linkedin_url || account.linkedin_url || payload.linkedin_url || '',\n    twitter_url: org.twitter_url || account.twitter_url || payload.twitter_url || '',\n    facebook_url: org.facebook_url || account.facebook_url || payload.facebook_url || '',\n\n    short_description:\n      org.short_description ||\n      org.description ||\n      org.seo_description ||\n      payload.short_description ||\n      payload.description ||\n      '',\n\n    industry: org.industry || payload.industry || '',\n    industries,\n    secondary_industries: secondaryIndustries,\n    industry_tag_hash: industryTagHash,\n\n    keywords,\n    technology_names: technologyNames,\n    current_technologies: currentTechnologies,\n\n    country:\n      org.country ||\n      account.country ||\n      org.organization_country ||\n      payload.country ||\n      '',\n\n    city: org.city || account.city || payload.city || '',\n    estimated_num_employees: org.estimated_num_employees || payload.estimated_num_employees || '',\n    annual_revenue: org.annual_revenue || org.organization_revenue || payload.annual_revenue || '',\n    annual_revenue_printed:\n      org.annual_revenue_printed ||\n      org.organization_revenue_printed ||\n      payload.annual_revenue_printed ||\n      '',\n\n    latest_funding_stage: org.latest_funding_stage || payload.latest_funding_stage || '',\n    latest_funding_round_date: org.latest_funding_round_date || payload.latest_funding_round_date || '',\n\n    ...exa\n  };\n\n  const normalizedFields = {\n    name: normalizeText(company.company_name),\n    account_name: normalizeText(company.account_name),\n\n    short_description: normalizeText(company.short_description),\n    description: normalizeText(company.short_description),\n    keywords: normalizeText(company.keywords),\n\n    exa_title: normalizeText(company.exa_title),\n    exa_summary: normalizeText(company.exa_summary),\n    exa_text: normalizeText(company.exa_text),\n    exa_content: normalizeText(company.exa_content),\n\n    industry: normalizeText(company.industry),\n    industries: normalizeText(company.industries),\n    secondary_industries: normalizeText(company.secondary_industries),\n    industry_tag_hash: normalizeText(company.industry_tag_hash),\n\n    technology_names: normalizeText(company.technology_names),\n    current_technologies: normalizeText(company.current_technologies),\n\n    website_url: normalizeText(company.website),\n    primary_domain: normalizeText(company.domain),\n    domain: normalizeText(company.domain),\n\n    linkedin_url: normalizeText(company.linkedin_url),\n    twitter_url: normalizeText(company.twitter_url),\n    facebook_url: normalizeText(company.facebook_url),\n\n    country: normalizeText(company.country)\n  };\n\n  const hasAnyCompanyData =\n    company.company_name ||\n    company.domain ||\n    company.website ||\n    company.short_description ||\n    company.exa_text ||\n    company.keywords.length > 0 ||\n    company.industries.length > 0;\n\n  if (!hasAnyCompanyData) return null;\n\n  const classification = classify(normalizedFields);\n\n  return {\n    source_system: 'Apollo + Exa',\n    classification_version: CLASSIFICATION_VERSION,\n\n    apollo_id: String(company.apollo_id || ''),\n    apollo_account_id: String(company.apollo_account_id || ''),\n    hubspot_id: String(company.hubspot_id || ''),\n\n    company_name: company.company_name,\n    domain: company.domain,\n    website: company.website,\n    linkedin_url: company.linkedin_url,\n\n    country: company.country,\n    city: company.city,\n    estimated_num_employees: company.estimated_num_employees,\n    annual_revenue: company.annual_revenue,\n    annual_revenue_printed: company.annual_revenue_printed,\n    latest_funding_stage: company.latest_funding_stage,\n    latest_funding_round_date: company.latest_funding_round_date,\n\n    source_industry: company.industry,\n    source_industries: company.industries.join(', '),\n    source_secondary_industries: company.secondary_industries.join(', '),\n    source_keywords_sample: company.keywords.slice(0, 20).join(', '),\n    source_technologies_sample: [\n      ...company.technology_names,\n      ...company.current_technologies\n    ].slice(0, 20).join(', '),\n\n    exa_title_sample: company.exa_title.slice(0, 300),\n    exa_summary_sample: company.exa_summary.slice(0, 800),\n    exa_text_sample: company.exa_text.slice(0, 1200),\n\n    ...classification,\n\n    hubspot_update_properties: {\n      target_icp_marker: classification.target_icp_marker,\n      target_icp_number: classification.target_icp_number,\n      target_icp_name: classification.target_icp_name,\n\n      icp_segment: classification.target_icp_marker,\n\n      icp_confidence: classification.classification_confidence,\n      icp_score: classification.classification_score,\n      icp_reason: classification.classification_reason,\n\n      icp_strict_gate_passed: classification.strict_gate_passed ? 'true' : 'false',\n      icp_mandatory_context: classification.mandatory_context_match,\n      icp_strong_mandatory_context: classification.strong_mandatory_context_match,\n      icp_weak_mandatory_context: classification.weak_mandatory_context_match,\n\n      icp_core_keywords: classification.matched_core_keywords,\n      icp_strong_core_keywords: classification.strong_core_keywords,\n      icp_product_signals: classification.product_signal_match,\n      icp_strong_product_signals: classification.strong_product_signal_match,\n      icp_supporting_industries: classification.supporting_industry_match,\n      icp_negative_signals: classification.negative_signal_match,\n      icp_hard_exclusions: classification.hard_exclusion_match,\n\n      icp_needs_manual_review: classification.needs_manual_review ? 'true' : 'false',\n      icp_last_classified_at: new Date().toISOString(),\n      icp_classification_version: CLASSIFICATION_VERSION\n    }\n  };\n}\n\nconst output = [];\n\nfor (const item of $input.all()) {\n  const payloads = getApolloPayloads(item.json);\n\n  for (const payload of payloads) {\n    const mapped = mapApolloCompany(payload);\n    if (!mapped) continue;\n\n    output.push({\n      json: mapped\n    });\n  }\n}\n\nreturn output;"
      },
      "id": "2c2b1f06-2b2d-4c45-aeda-46dd4fbabc1b",
      "name": "Classify ICP (Apollo)1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        448,
        2336
      ],
      "notes": "Scores each company against all 3 ICP definitions using keyword + signal matching. Returns segment, confidence, and matched terms."
    },
    {
      "parameters": {
        "jsCode": "// n8n Code Node\n// HubSpot ICP Classification + Company Summary Intelligence\n// Version: hubspot-icp-v2.6-final-taxonomy-with-hubspot-id\n//\n// Final ICP taxonomy:\n// - ICP 1 (Online Casino Operators)\n// - ICP 2 (Platform Providers)\n// - ICP 3 (CRM)\n// - ICP 4 (iGaming Affiliates)\n// - ICP 5 (Game / Slot Providers)\n// - ICP 7 (Investors)\n// - Not Classified\n\nconst CLASSIFICATION_VERSION = 'hubspot-icp-v2.6-final-taxonomy-with-hubspot-id';\n\n// --------------------------------------------------\n// Helpers\n// --------------------------------------------------\n\nfunction toText(value) {\n  if (value === null || value === undefined) return '';\n\n  if (Array.isArray(value)) {\n    return value.map(toText).join(' ');\n  }\n\n  if (typeof value === 'object') {\n    if (value.value !== undefined && value.value !== null) {\n      return toText(value.value);\n    }\n\n    return Object.values(value).map(toText).join(' ');\n  }\n\n  return String(value);\n}\n\nfunction normalizeText(value) {\n  return toText(value)\n    .toLowerCase()\n    .replace(/&/g, ' and ')\n    .replace(/[_\\-\\/|]+/g, ' ')\n    .replace(/[^\\p{L}\\p{N}\\s.]/gu, ' ')\n    .replace(/\\s+/g, ' ')\n    .trim();\n}\n\nfunction compactText(value) {\n  return normalizeText(value).replace(/\\s+/g, '');\n}\n\nfunction unique(arr) {\n  return [...new Set(arr.filter(Boolean))];\n}\n\nfunction escapeRegex(str) {\n  return String(str).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction hasTerm(text, term) {\n  const normalizedText = normalizeText(text);\n  const normalizedTerm = normalizeText(term);\n\n  if (!normalizedText || !normalizedTerm) return false;\n\n  const boundaryPattern = new RegExp(\n    `(^|[^a-z0-9])${escapeRegex(normalizedTerm)}([^a-z0-9]|$)`,\n    'i'\n  );\n\n  if (boundaryPattern.test(normalizedText)) return true;\n\n  if (\n    normalizedTerm.includes(' ') &&\n    normalizedTerm.replace(/\\s+/g, '').length >= 8\n  ) {\n    return compactText(normalizedText).includes(compactText(normalizedTerm));\n  }\n\n  return false;\n}\n\nfunction getFieldValue(json, possibleNames) {\n  for (const name of possibleNames) {\n    if (json[name] !== undefined && json[name] !== null && json[name] !== '') {\n      return toText(json[name]);\n    }\n\n    if (\n      json.properties &&\n      json.properties[name] !== undefined &&\n      json.properties[name] !== null &&\n      json.properties[name] !== ''\n    ) {\n      return toText(json.properties[name]);\n    }\n\n    if (\n      json.properties &&\n      json.properties[name] &&\n      json.properties[name].value !== undefined &&\n      json.properties[name].value !== null &&\n      json.properties[name].value !== ''\n    ) {\n      return toText(json.properties[name].value);\n    }\n  }\n\n  return '';\n}\n\nfunction getHubSpotId(json) {\n  return (\n    getFieldValue(json, [\n      'hubspot_id',\n      'hubspotId',\n      'hs_object_id',\n      'companyId',\n      'company_id',\n      'id',\n    ]) ||\n    toText(json?.id) ||\n    toText(json?.properties?.hs_object_id?.value) ||\n    toText(json?.properties?.hs_object_id) ||\n    ''\n  );\n}\n\nfunction matchTerms(fields, terms) {\n  const matches = [];\n\n  for (const term of terms) {\n    for (const field of fields) {\n      if (!field.value) continue;\n\n      if (hasTerm(field.value, term)) {\n        matches.push({\n          term,\n          field: field.name,\n          fieldWeight: field.weight,\n          evidenceStrength: field.evidenceStrength,\n        });\n      }\n    }\n  }\n\n  return matches;\n}\n\nfunction scoreMatches(matches, multiplier = 1, cap = 999) {\n  const score = matches.reduce((sum, match) => {\n    return sum + match.fieldWeight * multiplier;\n  }, 0);\n\n  return Math.min(Number(score.toFixed(2)), cap);\n}\n\nfunction termsFromMatches(matches) {\n  return unique((matches || []).map(match => match.term));\n}\n\nfunction hasAny(matches) {\n  return Array.isArray(matches) && matches.length > 0;\n}\n\nfunction strongMatches(matches) {\n  return (matches || []).filter(match => match.evidenceStrength === 'strong');\n}\n\nfunction hasStrong(matches) {\n  return strongMatches(matches).length > 0;\n}\n\nfunction hasTermInMatches(matches, terms) {\n  const normalizedTerms = terms.map(normalizeText);\n\n  return (matches || []).some(match => {\n    return normalizedTerms.includes(normalizeText(match.term));\n  });\n}\n\nfunction buildReason(parts) {\n  const cleanParts = parts.filter(Boolean);\n\n  if (cleanParts.length === 0) {\n    return 'No classification reason generated.';\n  }\n\n  return cleanParts.join('; ') + '.';\n}\n\nfunction truncateText(text, maxLength = 4000) {\n  const clean = toText(text).replace(/\\s+/g, ' ').trim();\n\n  if (clean.length <= maxLength) return clean;\n\n  return clean.slice(0, maxLength).trim() + '...';\n}\n\n// --------------------------------------------------\n// Broad iGaming Context Gate\n// --------------------------------------------------\n\nconst IGAMING_CONTEXT_TERMS = [\n  'casino',\n  'online casino',\n  'gambling',\n  'gambling and casino',\n  'gambling casinos',\n  'online gambling',\n  'betting',\n  'sports betting',\n  'sportsbook',\n  'igaming',\n  'i gaming',\n  'real money gaming',\n  'real money',\n  'rmg',\n  'slots',\n  'slot games',\n  'live casino',\n  'live betting',\n  'poker',\n  'jackpot',\n  'wager',\n  'odds',\n  'lottery',\n  'lotto',\n  'keno',\n];\n\nconst GAMING_INVESTOR_CONTEXT_TERMS = [\n  'igaming investment',\n  'gaming investment',\n  'gambling investment',\n  'sports betting investment',\n  'casino investment',\n  'gambling technology investment',\n  'igaming investor',\n  'gaming investor',\n  'gambling investor',\n  'sports betting investor',\n  'casino investor',\n  'gaming fund',\n  'gambling fund',\n  'sports betting fund',\n  'gaming technology investor',\n  'gambling technology investor',\n  'b2b saas investor',\n  'vertical saas investor',\n  'software investor',\n];\n\nconst PUBLISHER_MEDIA_OTHER_TERMS = [\n  'publisher',\n  'media company',\n  'sports publisher',\n  'sports media',\n  'news',\n  'sports news',\n  'football news',\n  'sports scores',\n  'live scores',\n  'content publisher',\n  'blog',\n  'magazine',\n  'esports',\n  'e sports',\n];\n\nconst AFFILIATE_TRACKING_TOOL_TERMS = [\n  'affiliate tracking',\n  'affiliate tracking software',\n  'affiliate management software',\n  'affiliate management platform',\n  'affiliate tracking platform',\n  'partner tracking software',\n  'tracking platform',\n  'tracking system',\n];\n\nconst ASSOCIATION_REGULATORY_TERMS = [\n  'association',\n  'trade association',\n  'industry association',\n  'regulator',\n  'regulatory body',\n  'advisory council',\n  'members',\n  'membership',\n  'how to become a member',\n  'represents operators',\n  'representing operators',\n  'legal framework',\n  'gambling regulations',\n  'licensing terms',\n  'press releases',\n];\n\n// --------------------------------------------------\n// ICP Segment Definitions\n// --------------------------------------------------\n\nconst SEGMENTS = [\n  {\n    number: 'ICP 7',\n    name: 'Investors',\n    marker: 'ICP 7 (Investors)',\n    priority: 100,\n    minScore: 8,\n    core: [\n      'venture capital',\n      'vc',\n      'private equity',\n      'family office',\n      'strategic investment',\n      'growth equity',\n      'investment management',\n      'investment firm',\n      'investment fund',\n      'strategic investor',\n      'angel investor',\n      'gaming investment',\n      'sports betting investment',\n      'igaming investment',\n      'gambling technology investment',\n      'igaming investor',\n      'gaming investor',\n      'gambling investor',\n      'sports betting investor',\n      'casino investor',\n      'gaming fund',\n      'gambling fund',\n      'sports betting fund',\n      'portfolio companies',\n    ],\n    industry: [\n      'venture capital',\n      'private equity',\n      'family office',\n      'investment management',\n      'investment firm',\n      'financial services',\n    ],\n    signals: [\n      'portfolio',\n      'investor',\n      'investment',\n      'fund',\n      'growth equity',\n      'strategic investor',\n      'angel investor',\n      'portfolio companies',\n      'investment portfolio',\n      'seed round',\n      'series a',\n      'series b',\n      'growth capital',\n      'backed companies',\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'game developer',\n      'game studio',\n      'affiliate marketing',\n      'casino affiliate',\n      'platform provider',\n      'crm platform',\n    ],\n  },\n\n  {\n    number: 'ICP 4',\n    name: 'iGaming Affiliates',\n    marker: 'ICP 4 (iGaming Affiliates)',\n    priority: 95,\n    minScore: 8,\n    core: [\n      'affiliate marketing',\n      'performance marketing',\n      'casino affiliate',\n      'igaming affiliate',\n      'i gaming affiliate',\n      'sportsbook affiliate',\n      'betting affiliate',\n      'gambling affiliate',\n      'online casino affiliate',\n      'sports betting affiliate',\n      'affiliate network',\n      'affiliate partner',\n      'affiliate program',\n      'casino partners',\n      'betting partners',\n      'sportsbook partners',\n      'traffic partner',\n      'player referrals',\n      'lead generation',\n      'player acquisition',\n      'cpa',\n      'revshare',\n      'revenue share',\n      'lifetime revenue share',\n      'hybrid deals',\n      'ftd',\n      'ndc',\n      'media buying',\n      'casino review',\n      'casino reviews',\n      'betting review',\n      'betting reviews',\n      'sports betting reviews',\n      'comparison site',\n      'casino comparison',\n      'bonus comparison',\n      'odds comparison',\n      'lowest cpa',\n      'highest quality players',\n    ],\n    industry: [\n      'affiliate marketing',\n      'performance marketing',\n      'marketing and advertising',\n      'gambling and casino',\n      'online gambling',\n      'sports betting',\n      'igaming',\n      'i gaming',\n    ],\n    signals: [\n      'affiliate',\n      'cpa',\n      'revshare',\n      'revenue share',\n      'ftd',\n      'ndc',\n      'traffic',\n      'lead generation',\n      'player acquisition',\n      'referrals',\n      'comparison',\n      'reviews',\n      'bonus codes',\n      'bookmaker reviews',\n      'operator reviews',\n    ],\n    negative: [\n      'affiliate tracking software',\n      'affiliate management software',\n      'affiliate tracking platform',\n      'casino operator',\n      'sportsbook operator',\n      'platform provider',\n      'white label platform',\n      'game developer',\n      'game studio',\n      'venture capital',\n      'private equity',\n      'family office',\n    ],\n  },\n\n  {\n    number: 'ICP 5',\n    name: 'Game / Slot Providers',\n    marker: 'ICP 5 (Game / Slot Providers)',\n    priority: 90,\n    minScore: 8,\n    core: [\n      'game developer',\n      'game development',\n      'casino game developer',\n      'slot game developer',\n      'casino game studio',\n      'igaming studio',\n      'i gaming studio',\n      'game studio',\n      'slot studio',\n      'game provider',\n      'casino game provider',\n      'slot provider',\n      'slot game provider',\n      'slots provider',\n      'gaming content provider',\n      'game content provider',\n      'casino content provider',\n      'rng provider',\n      'rng games',\n      'real money games provider',\n      'table games provider',\n      'instant games provider',\n      'crash games provider',\n      'scratch games provider',\n      'virtual sports provider',\n      'game portfolio',\n      'games portfolio',\n      'proprietary games',\n      'develops casino games',\n      'develops slot games',\n      'live casino games provider',\n      'live casino provider',\n      'live dealer provider',\n    ],\n    industry: [\n      'game development',\n      'gaming software',\n      'computer games',\n      'gambling and casino',\n      'online gambling',\n      'igaming',\n      'i gaming',\n    ],\n    signals: [\n      'game studio',\n      'studio',\n      'provider',\n      'rng',\n      'table games',\n      'instant games',\n      'crash games',\n      'game portfolio',\n      'games portfolio',\n      'casino content',\n      'game catalog',\n      'html5 games',\n      'live dealer',\n      'blackjack',\n      'roulette',\n      'baccarat',\n      'certified games',\n      'regulated markets',\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'affiliate marketing',\n      'casino affiliate',\n      'venture capital',\n      'private equity',\n      'family office',\n      'crm platform',\n      'marketing automation',\n      'login',\n      'register',\n      'deposit',\n      'withdrawal',\n      'bettor',\n      'players',\n    ],\n  },\n\n  {\n    number: 'ICP 3',\n    name: 'CRM',\n    marker: 'ICP 3 (CRM)',\n    priority: 85,\n    minScore: 8,\n    core: [\n      'igaming crm',\n      'i gaming crm',\n      'gaming crm',\n      'casino crm',\n      'sportsbook crm',\n      'crm platform',\n      'player retention',\n      'player engagement',\n      'loyalty platform',\n      'marketing automation',\n      'casino marketing automation',\n      'marketing automation casino',\n      'gaming bonus engine',\n      'campaign management',\n      'campaign management gaming',\n      'player lifecycle',\n      'player segmentation',\n      'customer segmentation',\n      'lifecycle marketing',\n      'campaign automation',\n      'real time triggers',\n      'real-time triggers',\n      'event based messaging',\n      'event-based messaging',\n      'bonus engine',\n      'reward engine',\n      'loyalty engine',\n      'player journeys',\n      'multi channel messaging',\n      'multi-channel messaging',\n      'email sms push notifications',\n      'retention campaigns',\n      'reactivation campaigns',\n      'churn prevention',\n      'behavior tracking',\n      'customer data platform',\n      'cdp gaming',\n      'player engagement platform',\n      'retention platform for igaming',\n      'crm for igaming operators',\n      'customer retention gaming',\n    ],\n    industry: [\n      'computer software',\n      'saas',\n      'marketing and advertising',\n      'marketing automation',\n      'crm',\n      'customer retention',\n      'email marketing',\n    ],\n    signals: [\n      'retention',\n      'engagement',\n      'loyalty',\n      'automation',\n      'segmentation',\n      'campaign',\n      'crm',\n      'cdp',\n      'churn',\n      'reactivation',\n      'lifecycle',\n      'bonus management',\n      'push notifications',\n      'sms',\n      'email',\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'affiliate marketing',\n      'casino affiliate',\n      'game developer',\n      'game studio',\n      'venture capital',\n      'private equity',\n      'family office',\n    ],\n  },\n\n  {\n    number: 'ICP 2',\n    name: 'Platform Providers',\n    marker: 'ICP 2 (Platform Providers)',\n    priority: 80,\n    minScore: 8,\n    core: [\n      'white label',\n      'white label casino',\n      'white label igaming',\n      'igaming platform',\n      'i gaming platform',\n      'casino platform',\n      'turnkey casino',\n      'turnkey solution',\n      'turnkey igaming',\n      'sportsbook platform',\n      'gaming platform',\n      'platform provider',\n      'aggregation platform',\n      'game aggregation platform',\n      'casino solution',\n      'operator platform',\n      'api gaming platform',\n      'casino platform provider',\n      'white label solution',\n      'api integration',\n      'api documentation',\n      'game aggregation',\n      'gaming aggregation platform',\n      'content aggregation',\n      'casino aggregation',\n      'sportsbook engine',\n      'casino engine',\n      'back office system',\n      'backoffice',\n      'operator dashboard',\n      'multi brand support',\n      'multi tenant platform',\n      'multi-brand',\n      'multi-tenant',\n      'player management system',\n      'player account management',\n      'pam',\n      'wallet integration',\n      'payment gateway integration',\n      'kyc integration',\n      'risk management tools',\n      'b2b gaming',\n      'b2b igaming',\n      'b2b support',\n      'operator clients',\n      'platform partners',\n      'casino software platform',\n      'casino software',\n      'online casino software',\n      'sportsbook software',\n      'betting platform',\n      'betting software',\n      'proprietary technology platforms',\n      'payments and licensing',\n      'website hosting and monitoring',\n      'data platform for betting',\n      'official esports data',\n      'official game data',\n      'official telemetry feeds',\n      'services for betting operators',\n      'services for the esports betting industry',\n    ],\n    industry: [\n      'information technology and services',\n      'computer software',\n      'software',\n      'saas',\n      'igaming technology',\n      'gambling technology',\n      'gaming software',\n      'internet',\n      'technology',\n    ],\n    signals: [\n      'white label',\n      'turnkey',\n      'api',\n      'platform',\n      'aggregation',\n      'operator dashboard',\n      'back office',\n      'backoffice',\n      'multi tenant',\n      'b2b',\n      'software platform',\n      'licensing',\n      'operator clients',\n      'integration partners',\n      'platform partners',\n      'data feeds',\n      'data api',\n      'real-time data',\n      'predictive analytics',\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'affiliate marketing',\n      'casino affiliate',\n      'game developer',\n      'game studio',\n      'slot game developer',\n      'casino game developer',\n      'venture capital',\n      'private equity',\n      'family office',\n      'affiliate tracking software',\n      'affiliate management platform',\n    ],\n  },\n\n  {\n    number: 'ICP 1',\n    name: 'Online Casino Operators',\n    marker: 'ICP 1 (Online Casino Operators)',\n    priority: 60,\n    minScore: 8,\n    core: [\n      'casino operator',\n      'licensed operator',\n      'betting operator',\n      'sportsbook operator',\n      'online casino operator',\n      'gaming license',\n      'gambling license',\n      'betting license',\n      'license number',\n      'licensed by',\n      'real money operator',\n      'deposit',\n      'withdrawal',\n      'players',\n      'player account',\n      'player wallet',\n      'wallet',\n      'deposit methods',\n      'withdrawal methods',\n      'kyc verification',\n      'account verification',\n      'bonus terms',\n      'wagering requirements',\n      'betting odds',\n      'odds',\n      'betslip',\n      'bet slip',\n      'place bet',\n      'live betting',\n      'casino lobby',\n      'vip program',\n      'vip club',\n      'loyalty rewards',\n      'responsible gambling',\n      'responsible gaming',\n      'payment methods',\n      'currency support',\n      'lottery',\n      'lotto',\n      'keno',\n      'register',\n      'login',\n      'sign up',\n      'online casino',\n      'sports betting',\n      'live casino',\n      'slots',\n      'poker',\n      'jackpot',\n    ],\n    industry: [\n      'gambling and casino',\n      'gambling casinos',\n      'gambling',\n      'casino',\n      'casinos',\n      'entertainment',\n      'igaming operators',\n      'i gaming operators',\n      'online gambling',\n      'lottery',\n    ],\n    signals: [\n      'players',\n      'player account',\n      'deposit',\n      'withdrawal',\n      'casino lobby',\n      'responsible gambling',\n      'responsible gaming',\n      'bonus terms',\n      'live betting',\n      'licensed operator',\n      'operator',\n      'lottery',\n      'lotto',\n      'jackpot',\n      'sports betting',\n      'online casino',\n      'live casino',\n      'slots',\n      'odds',\n      'payment methods',\n      'cash out',\n      'cashout',\n      'vip program',\n    ],\n    negative: [\n      'affiliate marketing',\n      'casino affiliate',\n      'igaming affiliate',\n      'sportsbook affiliate',\n      'performance marketing',\n      'game developer',\n      'game development',\n      'game studio',\n      'slot game developer',\n      'casino game developer',\n      'platform provider',\n      'white label',\n      'turnkey platform',\n      'crm platform',\n      'marketing automation',\n      'venture capital',\n      'private equity',\n      'family office',\n      'investment firm',\n      'media company',\n      'publisher',\n      'news',\n      'esports',\n      'association',\n      'trade association',\n      'industry association',\n    ],\n  },\n];\n\n// --------------------------------------------------\n// Company Summary Business Model Intelligence\n// --------------------------------------------------\n\nfunction buildCompanySummaryIntelligence(companySummary) {\n  const fields = [\n    {\n      name: 'company_summary',\n      value: companySummary,\n      weight: 2.0,\n      evidenceStrength: 'strong',\n    },\n  ];\n\n  const scores = {};\n\n  for (const segment of SEGMENTS) {\n    const coreMatches = matchTerms(fields, segment.core);\n    const signalMatches = matchTerms(fields, segment.signals);\n    const industryMatches = matchTerms(fields, segment.industry);\n    const negativeMatches = matchTerms(fields, segment.negative);\n\n    let score = 0;\n\n    score += scoreMatches(coreMatches, 6, 36);\n    score += scoreMatches(signalMatches, 4, 20);\n    score += scoreMatches(industryMatches, 2, 10);\n    score -= scoreMatches(negativeMatches, 3, 20);\n\n    scores[segment.number] = {\n      icpNumber: segment.number,\n      icpMarker: segment.marker,\n      segment: segment.name,\n      score: Number(score.toFixed(2)),\n      coreMatches,\n      signalMatches,\n      industryMatches,\n      negativeMatches,\n    };\n  }\n\n  const best = Object.values(scores).sort((a, b) => b.score - a.score)[0];\n\n  let detectedBusinessModel = 'unknown';\n  let suggestedIcp = 'Not Classified';\n  let confidence = 'Low';\n\n  if (best && best.score >= 18) {\n    suggestedIcp = best.icpNumber;\n    confidence = 'High';\n  } else if (best && best.score >= 10) {\n    suggestedIcp = best.icpNumber;\n    confidence = 'Medium';\n  }\n\n  if (suggestedIcp === 'ICP 1') detectedBusinessModel = 'operator';\n  if (suggestedIcp === 'ICP 2') detectedBusinessModel = 'platform_provider';\n  if (suggestedIcp === 'ICP 3') detectedBusinessModel = 'crm';\n  if (suggestedIcp === 'ICP 4') detectedBusinessModel = 'affiliate';\n  if (suggestedIcp === 'ICP 5') detectedBusinessModel = 'game_slot_provider';\n  if (suggestedIcp === 'ICP 7') detectedBusinessModel = 'investor';\n\n  return {\n    detected_business_model: detectedBusinessModel,\n    suggested_icp: suggestedIcp,\n    confidence,\n    scores,\n    best,\n  };\n}\n\n// --------------------------------------------------\n// Main Classification Function\n// --------------------------------------------------\n\nfunction classifyCompany(json) {\n  const companyName = getFieldValue(json, [\n    'company_name',\n    'name',\n    'hs_name',\n  ]);\n\n  const domain = getFieldValue(json, [\n    'domain',\n    'website_domain',\n  ]);\n\n  const website = getFieldValue(json, [\n    'website',\n    'hs_website_url',\n    'url',\n  ]);\n\n  const description = getFieldValue(json, [\n    'description',\n    'company_description',\n    'about',\n    'linkedinbio',\n    'linkedin_bio',\n    'linkedin_company_description',\n  ]);\n\n  const industry = getFieldValue(json, [\n    'industry',\n    'source_industry',\n    'hs_industry',\n  ]);\n\n  const industryGroup = getFieldValue(json, [\n    'source_industry_group',\n    'industry_group',\n    'hs_industry_group',\n  ]);\n\n  const sourcePlatform = getFieldValue(json, [\n    'source_platform',\n    'platform',\n    'detected_platform',\n  ]);\n\n  const sourceCrm = getFieldValue(json, [\n    'source_crm',\n    'crm',\n    'detected_crm',\n  ]);\n\n  const keywords = getFieldValue(json, [\n    'source_keywords_sample',\n    'keywords',\n    'detected_keywords',\n    'scraped_keywords',\n  ]);\n\n  const tags = getFieldValue(json, [\n    'source_industry_tags_sample',\n    'industry_tags',\n    'source_industries',\n    'source_secondary_industries',\n    'tags',\n  ]);\n\n  const technologies = getFieldValue(json, [\n    'source_technologies_sample',\n    'technologies',\n    'web_technologies',\n  ]);\n\n  const existingScrapedText = getFieldValue(json, [\n    'scraped_text',\n    'homepage_text',\n    'about_text',\n    'products_text',\n    'page_text',\n  ]);\n\n  const companySummary = truncateText(getFieldValue(json, [\n    'company_summary',\n    'exa_company_summary',\n    'website_company_summary',\n  ]));\n\n  const summaryIntel = buildCompanySummaryIntelligence(companySummary);\n\n  const fields = [\n    {\n      name: 'company_name',\n      value: companyName,\n      weight: 0.6,\n      evidenceStrength: 'weak',\n    },\n    {\n      name: 'domain',\n      value: domain,\n      weight: 0.2,\n      evidenceStrength: 'weak',\n    },\n    {\n      name: 'website',\n      value: website,\n      weight: 0.2,\n      evidenceStrength: 'weak',\n    },\n    {\n      name: 'description',\n      value: description,\n      weight: 1.5,\n      evidenceStrength: 'strong',\n    },\n    {\n      name: 'company_summary',\n      value: companySummary,\n      weight: 2.0,\n      evidenceStrength: 'strong',\n    },\n    {\n      name: 'source_industry',\n      value: industry,\n      weight: 1.0,\n      evidenceStrength: 'strong',\n    },\n    {\n      name: 'source_industry_group',\n      value: industryGroup,\n      weight: 1.1,\n      evidenceStrength: 'strong',\n    },\n    {\n      name: 'source_keywords_sample',\n      value: keywords,\n      weight: 1.35,\n      evidenceStrength: 'strong',\n    },\n    {\n      name: 'source_industry_tags_sample',\n      value: tags,\n      weight: 1.1,\n      evidenceStrength: 'strong',\n    },\n    {\n      name: 'source_platform',\n      value: sourcePlatform,\n      weight: 0.35,\n      evidenceStrength: 'weak',\n    },\n    {\n      name: 'source_crm',\n      value: sourceCrm,\n      weight: 0.35,\n      evidenceStrength: 'weak',\n    },\n    {\n      name: 'source_technologies_sample',\n      value: technologies,\n      weight: 0.25,\n      evidenceStrength: 'weak',\n    },\n    {\n      name: 'existing_scraped_text',\n      value: existingScrapedText,\n      weight: 1.2,\n      evidenceStrength: 'strong',\n    },\n  ];\n\n  const igamingContextMatches = matchTerms(fields, IGAMING_CONTEXT_TERMS);\n  const gamingInvestorContextMatches = matchTerms(fields, GAMING_INVESTOR_CONTEXT_TERMS);\n  const publisherMediaMatches = matchTerms(fields, PUBLISHER_MEDIA_OTHER_TERMS);\n  const affiliateTrackingToolMatches = matchTerms(fields, AFFILIATE_TRACKING_TOOL_TERMS);\n  const associationRegulatoryMatches = matchTerms(fields, ASSOCIATION_REGULATORY_TERMS);\n\n  const hasIgamingContext = hasAny(igamingContextMatches);\n  const hasStrongIgamingContext = hasStrong(igamingContextMatches);\n  const hasGamingInvestorContext = hasAny(gamingInvestorContextMatches);\n\n  const hasPublisherMediaSignal = hasStrong(publisherMediaMatches);\n  const hasAffiliateTrackingToolSignal = hasStrong(affiliateTrackingToolMatches);\n  const hasAssociationRegulatorySignal = hasStrong(associationRegulatoryMatches);\n\n  const operatorIndustryFallback =\n    hasIgamingContext &&\n    (\n      hasTerm(industry, 'gambling casinos') ||\n      hasTerm(industry, 'gambling') ||\n      hasTerm(industry, 'gambling and casino') ||\n      hasTerm(industryGroup, 'igaming operators') ||\n      hasTerm(industryGroup, 'online gambling') ||\n      summaryIntel.detected_business_model === 'operator'\n    );\n\n  const results = [];\n\n  for (const segment of SEGMENTS) {\n    const coreMatches = matchTerms(fields, segment.core);\n    const signalMatches = matchTerms(fields, segment.signals);\n    const industryMatches = matchTerms(fields, segment.industry);\n    const negativeMatches = matchTerms(fields, segment.negative);\n\n    const strongCoreMatches = strongMatches(coreMatches);\n    const strongSignalMatches = strongMatches(signalMatches);\n    const strongNegativeMatches = strongMatches(negativeMatches);\n\n    let score = 0;\n\n    score += scoreMatches(strongCoreMatches, 6, 42);\n\n    const weakCoreMatches = coreMatches.filter(\n      match => match.evidenceStrength !== 'strong'\n    );\n\n    score += scoreMatches(weakCoreMatches, 1.5, 6);\n    score += scoreMatches(strongSignalMatches, 4, 24);\n\n    const weakSignalMatches = signalMatches.filter(\n      match => match.evidenceStrength !== 'strong'\n    );\n\n    score += scoreMatches(weakSignalMatches, 1, 5);\n    score += scoreMatches(industryMatches, 2, 12);\n\n    if (summaryIntel.suggested_icp === segment.number) {\n      if (summaryIntel.confidence === 'High') score += 12;\n      if (summaryIntel.confidence === 'Medium') score += 7;\n      if (summaryIntel.confidence === 'Low') score += 2;\n    }\n\n    if (segment.number !== 'ICP 7' && hasIgamingContext) {\n      score += scoreMatches(igamingContextMatches, 0.35, 4);\n    }\n\n    score -= scoreMatches(strongNegativeMatches, 3, 24);\n\n    if (\n      hasPublisherMediaSignal &&\n      !hasStrong(coreMatches) &&\n      ['ICP 1', 'ICP 2', 'ICP 3'].includes(segment.number)\n    ) {\n      score -= 10;\n    }\n\n    if (segment.number === 'ICP 4' && hasAffiliateTrackingToolSignal) {\n      score -= 15;\n    }\n\n    if (\n      hasAssociationRegulatorySignal &&\n      ['ICP 1', 'ICP 2', 'ICP 3', 'ICP 4', 'ICP 5'].includes(segment.number)\n    ) {\n      score -= 12;\n    }\n\n    let hasRequiredEvidence = false;\n\n    if (segment.number === 'ICP 7') {\n      hasRequiredEvidence =\n        hasStrong(coreMatches) &&\n        (\n          hasGamingInvestorContext ||\n          hasIgamingContext ||\n          summaryIntel.detected_business_model === 'investor'\n        );\n\n      if (\n        hasGamingInvestorContext ||\n        summaryIntel.detected_business_model === 'investor'\n      ) {\n        score += 6;\n      }\n\n      if (\n        !hasGamingInvestorContext &&\n        !hasIgamingContext &&\n        summaryIntel.detected_business_model !== 'investor'\n      ) {\n        score -= 8;\n      }\n    }\n\n    else if (segment.number === 'ICP 4') {\n      const hasExplicitAffiliateEvidence =\n        hasTermInMatches(coreMatches, [\n          'casino affiliate',\n          'igaming affiliate',\n          'i gaming affiliate',\n          'sportsbook affiliate',\n          'betting affiliate',\n          'gambling affiliate',\n          'online casino affiliate',\n          'sports betting affiliate',\n          'casino review',\n          'casino reviews',\n          'betting review',\n          'betting reviews',\n          'sports betting reviews',\n          'comparison site',\n          'casino comparison',\n          'bonus comparison',\n          'odds comparison',\n          'cpa',\n          'revshare',\n          'revenue share',\n        ]) ||\n        summaryIntel.detected_business_model === 'affiliate';\n\n      hasRequiredEvidence =\n        hasIgamingContext &&\n        hasExplicitAffiliateEvidence &&\n        !hasAffiliateTrackingToolSignal;\n    }\n\n    else if (segment.number === 'ICP 5') {\n      const hasExplicitGameProviderEvidence =\n        hasTermInMatches(coreMatches, [\n          'game developer',\n          'game development',\n          'casino game developer',\n          'slot game developer',\n          'casino game studio',\n          'igaming studio',\n          'i gaming studio',\n          'game studio',\n          'slot studio',\n          'game provider',\n          'casino game provider',\n          'slot provider',\n          'slot game provider',\n          'slots provider',\n          'gaming content provider',\n          'game content provider',\n          'casino content provider',\n          'rng provider',\n          'game portfolio',\n          'games portfolio',\n          'proprietary games',\n          'develops casino games',\n          'develops slot games',\n          'live casino games provider',\n          'live casino provider',\n          'live dealer provider',\n        ]) ||\n        summaryIntel.detected_business_model === 'game_slot_provider';\n\n      hasRequiredEvidence =\n        hasIgamingContext &&\n        hasExplicitGameProviderEvidence;\n    }\n\n    else if (segment.number === 'ICP 3') {\n      const hasExplicitGamingCrm =\n        hasTermInMatches(coreMatches, [\n          'igaming crm',\n          'i gaming crm',\n          'gaming crm',\n          'casino crm',\n          'sportsbook crm',\n          'player retention',\n          'player engagement',\n          'player lifecycle',\n          'casino marketing automation',\n          'marketing automation casino',\n          'gaming bonus engine',\n          'player engagement platform',\n          'customer engagement',\n          'retention platform for igaming',\n          'crm for igaming operators',\n          'customer retention gaming',\n        ]) ||\n        summaryIntel.detected_business_model === 'crm';\n\n      hasRequiredEvidence =\n        hasIgamingContext &&\n        (\n          hasExplicitGamingCrm ||\n          (hasStrong(coreMatches) && hasStrongIgamingContext)\n        );\n    }\n\n    else if (segment.number === 'ICP 2') {\n      const hasExplicitPlatform =\n        hasTermInMatches(coreMatches, [\n          'igaming platform',\n          'i gaming platform',\n          'casino platform',\n          'sportsbook platform',\n          'white label casino',\n          'white label igaming',\n          'turnkey casino',\n          'turnkey igaming',\n          'casino platform provider',\n          'api gaming platform',\n          'casino software platform',\n          'casino software',\n          'online casino software',\n          'sportsbook software',\n          'betting platform',\n          'betting software',\n          'gaming aggregation platform',\n          'game aggregation platform',\n          'player account management',\n          'pam',\n          'proprietary technology platforms',\n          'payments and licensing',\n          'data platform for betting',\n          'official esports data',\n          'official game data',\n          'services for betting operators',\n        ]) ||\n        summaryIntel.detected_business_model === 'platform_provider';\n\n      hasRequiredEvidence =\n        hasIgamingContext &&\n        (\n          hasExplicitPlatform ||\n          (hasStrong(coreMatches) && hasStrongIgamingContext)\n        );\n    }\n\n    else if (segment.number === 'ICP 1') {\n      const hasSpecificOperatorEvidence =\n        hasStrong(coreMatches) ||\n        hasStrong(signalMatches) ||\n        summaryIntel.detected_business_model === 'operator';\n\n      const otherSegmentStrongEvidence = hasStrong(matchTerms(fields, [\n        ...SEGMENTS.find(s => s.number === 'ICP 4').core,\n        ...SEGMENTS.find(s => s.number === 'ICP 5').core,\n        ...SEGMENTS.find(s => s.number === 'ICP 7').core,\n        ...SEGMENTS.find(s => s.number === 'ICP 3').core,\n        ...SEGMENTS.find(s => s.number === 'ICP 2').core,\n      ]));\n\n      hasRequiredEvidence =\n        hasIgamingContext &&\n        !hasAssociationRegulatorySignal &&\n        (\n          hasSpecificOperatorEvidence ||\n          (\n            operatorIndustryFallback &&\n            !otherSegmentStrongEvidence &&\n            !hasPublisherMediaSignal &&\n            !hasAffiliateTrackingToolSignal\n          )\n        );\n\n      if (\n        operatorIndustryFallback &&\n        !hasSpecificOperatorEvidence &&\n        !hasPublisherMediaSignal &&\n        !hasAffiliateTrackingToolSignal &&\n        !hasAssociationRegulatorySignal\n      ) {\n        score += 5;\n      }\n    }\n\n    score = Math.max(0, score);\n\n    const strictGatePassed =\n      hasRequiredEvidence &&\n      score >= segment.minScore;\n\n    results.push({\n      icpNumber: segment.number,\n      icpMarker: segment.marker,\n      segment: segment.name,\n      priority: segment.priority,\n      minScore: segment.minScore,\n      score: Number(score.toFixed(2)),\n      coreMatches,\n      strongCoreMatches,\n      signalMatches,\n      strongSignalMatches,\n      industryMatches,\n      negativeMatches,\n      strongNegativeMatches,\n      hasRequiredEvidence,\n      strictGatePassed,\n    });\n  }\n\n  const passingResults = results\n    .filter(result => result.strictGatePassed)\n    .sort((a, b) => {\n      if (b.priority !== a.priority) return b.priority - a.priority;\n      return b.score - a.score;\n    });\n\n  const selected = passingResults[0];\n\n  if (!selected) {\n    const bestResult = [...results].sort((a, b) => b.score - a.score)[0];\n\n    const reasonParts = [];\n\n    if (!hasIgamingContext && !hasGamingInvestorContext) {\n      reasonParts.push('No strong iGaming or gaming-investor context found');\n    }\n\n    if (hasIgamingContext) {\n      reasonParts.push(\n        `iGaming context found: ${termsFromMatches(igamingContextMatches).slice(0, 8).join(', ')}`\n      );\n    }\n\n    if (companySummary) {\n      reasonParts.push(\n        'Company summary was checked, but no target ICP segment had enough specific business-model evidence'\n      );\n    }\n\n    if (hasPublisherMediaSignal) {\n      reasonParts.push(\n        `publisher/media signals found: ${termsFromMatches(publisherMediaMatches).slice(0, 5).join(', ')}`\n      );\n    }\n\n    if (hasAffiliateTrackingToolSignal) {\n      reasonParts.push(\n        `affiliate tracking/tooling signals found: ${termsFromMatches(affiliateTrackingToolMatches).slice(0, 5).join(', ')}`\n      );\n    }\n\n    if (hasAssociationRegulatorySignal) {\n      reasonParts.push(\n        `association/regulatory signals found: ${termsFromMatches(associationRegulatoryMatches).slice(0, 5).join(', ')}`\n      );\n    }\n\n    reasonParts.push(\n      'Classified as Not Classified because no target ICP passed the strict evidence gate'\n    );\n\n    return {\n      target_icp_marker: 'Not Classified',\n      target_icp_number: '',\n      target_icp_name: 'Not Classified',\n      icp_segment: 'Not Classified',\n      keyword_match_group: 'Not Classified',\n      classification_confidence: 'Low',\n      classification_score: 0,\n      classification_reason: buildReason(reasonParts),\n      matched_core_keywords: '',\n      product_signal_match: '',\n      supporting_industry_match: '',\n      negative_signal_match: '',\n      hard_exclusion_match: termsFromMatches([\n        ...publisherMediaMatches,\n        ...affiliateTrackingToolMatches,\n        ...associationRegulatoryMatches,\n      ]).join(', '),\n      needs_manual_review: false,\n      second_best_segment: bestResult?.icpMarker || '',\n      second_best_score: bestResult?.score || 0,\n      strict_gate_passed: false,\n      mandatory_context_match: termsFromMatches(igamingContextMatches).join(', '),\n      company_summary: companySummary,\n      company_summary_detected_model: summaryIntel.detected_business_model,\n      company_summary_suggested_icp: summaryIntel.suggested_icp,\n      company_summary_confidence: summaryIntel.confidence,\n      classification_version: CLASSIFICATION_VERSION,\n      _all_scores: Object.fromEntries(results.map(r => [r.icpMarker, r.score])),\n      _debug_evidence: {\n        gate: {\n          hasIgamingContext,\n          hasStrongIgamingContext,\n          igamingContextMatches,\n          hasGamingInvestorContext,\n          gamingInvestorContextMatches,\n          hasPublisherMediaSignal,\n          publisherMediaMatches,\n          hasAffiliateTrackingToolSignal,\n          affiliateTrackingToolMatches,\n          hasAssociationRegulatorySignal,\n          associationRegulatoryMatches,\n        },\n        companySummaryIntel: summaryIntel,\n        results,\n      },\n    };\n  }\n\n  let confidence = 'Medium';\n\n  if (selected.score >= 30 || summaryIntel.confidence === 'High') {\n    confidence = 'High';\n  } else if (selected.score < 12) {\n    confidence = 'Low';\n  }\n\n  const secondBest = results\n    .filter(result => result.icpMarker !== selected.icpMarker)\n    .sort((a, b) => b.score - a.score)[0];\n\n  const coreTerms = termsFromMatches(selected.coreMatches);\n  const signalTerms = termsFromMatches(selected.signalMatches);\n  const industryTerms = termsFromMatches(selected.industryMatches);\n  const negativeTerms = termsFromMatches(selected.negativeMatches);\n  const mandatoryTerms = termsFromMatches(igamingContextMatches);\n\n  const reasonParts = [\n    `Matched ${selected.icpMarker}`,\n  ];\n\n  if (mandatoryTerms.length) {\n    reasonParts.push(`iGaming context: ${mandatoryTerms.slice(0, 8).join(', ')}`);\n  }\n\n  if (coreTerms.length) {\n    reasonParts.push(`specific ICP keywords: ${coreTerms.slice(0, 10).join(', ')}`);\n  }\n\n  if (signalTerms.length) {\n    reasonParts.push(`supporting product/business signals: ${signalTerms.slice(0, 8).join(', ')}`);\n  }\n\n  if (industryTerms.length) {\n    reasonParts.push(`supporting industry/context: ${industryTerms.slice(0, 8).join(', ')}`);\n  }\n\n  if (summaryIntel.detected_business_model !== 'unknown') {\n    reasonParts.push(\n      `company summary detected business model: ${summaryIntel.detected_business_model} with ${summaryIntel.confidence} confidence`\n    );\n  }\n\n  if (negativeTerms.length) {\n    reasonParts.push(\n      `negative signals found but outweighed: ${negativeTerms.slice(0, 8).join(', ')}`\n    );\n  }\n\n  return {\n    target_icp_marker: selected.icpMarker,\n    target_icp_number: selected.icpNumber,\n    target_icp_name: selected.segment,\n    icp_segment: selected.icpMarker,\n    keyword_match_group: `${selected.segment} Keywords`,\n    classification_confidence: confidence,\n    classification_score: selected.score,\n    classification_reason: buildReason(reasonParts),\n    matched_core_keywords: coreTerms.join(', '),\n    product_signal_match: signalTerms.join(', '),\n    supporting_industry_match: industryTerms.join(', '),\n    negative_signal_match: negativeTerms.join(', '),\n    hard_exclusion_match: termsFromMatches([\n      ...publisherMediaMatches,\n      ...affiliateTrackingToolMatches,\n      ...associationRegulatoryMatches,\n    ]).join(', '),\n    needs_manual_review: confidence === 'Low',\n    second_best_segment: secondBest?.icpMarker || '',\n    second_best_score: secondBest?.score || 0,\n    strict_gate_passed: true,\n    mandatory_context_match: mandatoryTerms.join(', '),\n    company_summary: companySummary,\n    company_summary_detected_model: summaryIntel.detected_business_model,\n    company_summary_suggested_icp: summaryIntel.suggested_icp,\n    company_summary_confidence: summaryIntel.confidence,\n    classification_version: CLASSIFICATION_VERSION,\n    _all_scores: Object.fromEntries(results.map(r => [r.icpMarker, r.score])),\n    _debug_evidence: {\n      gate: {\n        hasIgamingContext,\n        hasStrongIgamingContext,\n        igamingContextMatches,\n        hasGamingInvestorContext,\n        gamingInvestorContextMatches,\n        hasPublisherMediaSignal,\n        publisherMediaMatches,\n        hasAffiliateTrackingToolSignal,\n        affiliateTrackingToolMatches,\n        hasAssociationRegulatorySignal,\n        associationRegulatoryMatches,\n      },\n      companySummaryIntel: summaryIntel,\n      selected,\n      results,\n    },\n  };\n}\n\n// --------------------------------------------------\n// n8n Execution\n// --------------------------------------------------\n\nconst items = $input.all();\n\nreturn items.map((item, index) => {\n  const summaryJson = item.json || {};\n\n  // --- FIX: MERGE HUBSPOT DATA WITH SUMMARY ---\n  // Because the SearXNG HTTP Request overwrites the item data with its search results,\n  // we need to pull the original HubSpot company data from the previous Filter node \n  // so the classifier actually knows what company it is scoring.\n  let hubspotJson = {};\n  try {\n    // Try to link to the exact item running in this branch/loop\n    hubspotJson = $('Website Filter (Hubspot)1').item.json || {};\n  } catch (e) {\n    // Fallback to the first item if running outside a loop\n    hubspotJson = $('Website Filter (Hubspot)1').first().json || {};\n  }\n\n  // Combine both so the classification function can read both \n  // the HubSpot properties AND the new SearXNG summary\n  const mergedJson = {\n    ...hubspotJson,\n    company_summary: summaryJson.company_summary || ''\n  };\n  // --------------------------------------------\n\n  const hubspotId = getHubSpotId(mergedJson);\n  const classification = classifyCompany(mergedJson);\n\n  const targetIcpAnalysis = {\n    hubspot_id: hubspotId,\n    result: classification.target_icp_marker,\n    icp_number: classification.target_icp_number,\n    icp_name: classification.target_icp_name,\n    confidence: classification.classification_confidence,\n    score: classification.classification_score,\n    reason: classification.classification_reason,\n    matched_keywords: classification.matched_core_keywords,\n    product_signals: classification.product_signal_match,\n    supporting_industries: classification.supporting_industry_match,\n    negative_signals: classification.negative_signal_match,\n    hard_exclusions: classification.hard_exclusion_match,\n    strict_gate_passed: classification.strict_gate_passed,\n    needs_manual_review: classification.needs_manual_review,\n    second_best_segment: classification.second_best_segment,\n    second_best_score: classification.second_best_score,\n  };\n\n  const hubspotUpdateProperties = {\n    hubspot_id: hubspotId,\n\n    target_icp_marker: classification.target_icp_marker,\n    target_icp_number: classification.target_icp_number,\n    target_icp_name: classification.target_icp_name,\n    icp_segment: classification.icp_segment,\n\n    icp_confidence: classification.classification_confidence,\n    icp_score: classification.classification_score,\n    icp_reason: classification.classification_reason,\n\n    icp_core_keywords: classification.matched_core_keywords,\n    icp_product_signals: classification.product_signal_match,\n    icp_supporting_industries: classification.supporting_industry_match,\n    icp_negative_signals: classification.negative_signal_match,\n    icp_hard_exclusions: classification.hard_exclusion_match,\n\n    icp_needs_manual_review: String(classification.needs_manual_review),\n    icp_strict_gate_passed: String(classification.strict_gate_passed),\n    icp_mandatory_context: classification.mandatory_context_match,\n\n    icp_company_summary: classification.company_summary,\n    icp_company_summary_model: classification.company_summary_detected_model,\n    icp_company_summary_suggested_icp: classification.company_summary_suggested_icp,\n    icp_company_summary_confidence: classification.company_summary_confidence,\n\n    icp_last_classified_at: new Date().toISOString(),\n    icp_classification_version: CLASSIFICATION_VERSION,\n  };\n\n  return {\n    json: {\n      ...mergedJson, // Returns the full combined data so subsequent nodes have it\n\n      hubspot_id: hubspotId,\n      company_id: hubspotId,\n\n      company_summary: classification.company_summary,\n\n      target_icp_analysis: targetIcpAnalysis,\n\n      target_icp_marker: classification.target_icp_marker,\n      target_icp_number: classification.target_icp_number,\n      target_icp_name: classification.target_icp_name,\n      icp_segment: classification.icp_segment,\n      keyword_match_group: classification.keyword_match_group,\n\n      classification_confidence: classification.classification_confidence,\n      classification_score: classification.classification_score,\n      classification_reason: classification.classification_reason,\n\n      matched_core_keywords: classification.matched_core_keywords,\n      product_signal_match: classification.product_signal_match,\n      supporting_industry_match: classification.supporting_industry_match,\n      negative_signal_match: classification.negative_signal_match,\n      hard_exclusion_match: classification.hard_exclusion_match,\n\n      needs_manual_review: classification.needs_manual_review,\n      second_best_segment: classification.second_best_segment,\n      second_best_score: classification.second_best_score,\n\n      strict_gate_passed: classification.strict_gate_passed,\n      mandatory_context_match: classification.mandatory_context_match,\n      classification_version: classification.classification_version,\n\n      company_summary_detected_model: classification.company_summary_detected_model,\n      company_summary_suggested_icp: classification.company_summary_suggested_icp,\n      company_summary_confidence: classification.company_summary_confidence,\n\n      _all_scores: classification._all_scores,\n      _debug_evidence: classification._debug_evidence,\n\n      hubspot_update_properties: hubspotUpdateProperties,\n    },\n  };\n});"
      },
      "id": "1dfdd109-a8a8-49b1-a616-1fbe5053b33c",
      "name": "Classify ICP (Hubspot)1",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        0,
        1952
      ],
      "notes": "Scores each company against all 3 ICP definitions using keyword + signal matching. Returns segment, confidence, and matched terms."
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "sheetName": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [],
          "schema": [
            {
              "id": "company_summary",
              "displayName": "company_summary",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_marker",
              "displayName": "target_icp_marker",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_number",
              "displayName": "target_icp_number",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_name",
              "displayName": "target_icp_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "icp_segment",
              "displayName": "icp_segment",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "keyword_match_group",
              "displayName": "keyword_match_group",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_confidence",
              "displayName": "classification_confidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_score",
              "displayName": "classification_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_reason",
              "displayName": "classification_reason",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "matched_core_keywords",
              "displayName": "matched_core_keywords",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "product_signal_match",
              "displayName": "product_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "supporting_industry_match",
              "displayName": "supporting_industry_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "negative_signal_match",
              "displayName": "negative_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "hard_exclusion_match",
              "displayName": "hard_exclusion_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "needs_manual_review",
              "displayName": "needs_manual_review",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "second_best_segment",
              "displayName": "second_best_segment",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "second_best_score",
              "displayName": "second_best_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strict_gate_passed",
              "displayName": "strict_gate_passed",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "mandatory_context_match",
              "displayName": "mandatory_context_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_version",
              "displayName": "classification_version",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "company_summary_detected_model",
              "displayName": "company_summary_detected_model",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "company_summary_suggested_icp",
              "displayName": "company_summary_suggested_icp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "company_summary_confidence",
              "displayName": "company_summary_confidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "_all_scores",
              "displayName": "_all_scores",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "_debug_evidence",
              "displayName": "_debug_evidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "hubspot_update_properties",
              "displayName": "hubspot_update_properties",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "useAppend": true
        }
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        224,
        1952
      ],
      "id": "54428637-14b6-41df-9280-7c653c699615",
      "name": "Append row in sheet4"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "sheetName": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [],
          "schema": [
            {
              "id": "source_system",
              "displayName": "source_system",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_version",
              "displayName": "classification_version",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "apollo_id",
              "displayName": "apollo_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "apollo_account_id",
              "displayName": "apollo_account_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "hubspot_id",
              "displayName": "hubspot_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "company_name",
              "displayName": "company_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "domain",
              "displayName": "domain",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "website",
              "displayName": "website",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "linkedin_url",
              "displayName": "linkedin_url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "country",
              "displayName": "country",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "city",
              "displayName": "city",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "estimated_num_employees",
              "displayName": "estimated_num_employees",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "annual_revenue",
              "displayName": "annual_revenue",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "annual_revenue_printed",
              "displayName": "annual_revenue_printed",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "latest_funding_stage",
              "displayName": "latest_funding_stage",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "latest_funding_round_date",
              "displayName": "latest_funding_round_date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_industry",
              "displayName": "source_industry",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_industries",
              "displayName": "source_industries",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_secondary_industries",
              "displayName": "source_secondary_industries",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_keywords_sample",
              "displayName": "source_keywords_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_technologies_sample",
              "displayName": "source_technologies_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "exa_title_sample",
              "displayName": "exa_title_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "exa_summary_sample",
              "displayName": "exa_summary_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "exa_text_sample",
              "displayName": "exa_text_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_marker",
              "displayName": "target_icp_marker",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_number",
              "displayName": "target_icp_number",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_name",
              "displayName": "target_icp_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "icp_segment",
              "displayName": "icp_segment",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "keyword_match_group",
              "displayName": "keyword_match_group",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_confidence",
              "displayName": "classification_confidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_score",
              "displayName": "classification_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_reason",
              "displayName": "classification_reason",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strict_gate_passed",
              "displayName": "strict_gate_passed",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "mandatory_context_match",
              "displayName": "mandatory_context_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strong_mandatory_context_match",
              "displayName": "strong_mandatory_context_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "weak_mandatory_context_match",
              "displayName": "weak_mandatory_context_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "matched_core_keywords",
              "displayName": "matched_core_keywords",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strong_core_keywords",
              "displayName": "strong_core_keywords",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "product_signal_match",
              "displayName": "product_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strong_product_signal_match",
              "displayName": "strong_product_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "supporting_industry_match",
              "displayName": "supporting_industry_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "negative_signal_match",
              "displayName": "negative_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "hard_exclusion_match",
              "displayName": "hard_exclusion_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "needs_manual_review",
              "displayName": "needs_manual_review",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "second_best_segment",
              "displayName": "second_best_segment",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "second_best_score",
              "displayName": "second_best_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "_all_scores",
              "displayName": "_all_scores",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "_debug_evidence",
              "displayName": "_debug_evidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "hubspot_update_properties",
              "displayName": "hubspot_update_properties",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        672,
        2336
      ],
      "id": "a2f5884f-9869-48be-baf5-e5d52ff30e8f",
      "name": "Append row in sheet5"
    },
    {
      "parameters": {
        "authentication": "appToken",
        "resource": "company",
        "operation": "update",
        "companyId": {
          "__rl": true,
          "value": "={{ $('Append row in sheet5').item.json.hubspot_id }}",
          "mode": "id"
        },
        "updateFields": {
          "customPropertiesUi": {
            "customPropertiesValues": [
              {
                "property": "target_icp",
                "value": "={{ $json.icp_segment }}"
              },
              {
                "property": "processing_icp",
                "value": "true"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.2,
      "position": [
        1120,
        2240
      ],
      "id": "4c4d6b05-1b03-4183-a73a-7fb77f2b3b3a",
      "name": "Update a company (Apollo)1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "f52b323c-3a30-432b-97d2-d3385ec07cc0",
              "leftValue": "={{ $json.properties.domain.value }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.3,
      "position": [
        -672,
        2336
      ],
      "id": "61f0ab5b-dfbc-4313-879e-a7505937ce6d",
      "name": "Website Filter (Apollo)1"
    },
    {
      "parameters": {
        "jsCode": "// n8n Code Node\n// SearXNG Output Cleaner\n\nfunction toText(value) {\n  if (value === null || value === undefined) return '';\n  if (Array.isArray(value)) return value.map(toText).join(' ');\n  if (typeof value === 'object') return Object.values(value).map(toText).join(' ');\n  return String(value);\n}\n\nfunction cleanText(text) {\n  return toText(text)\n    .replace(/\\s+/g, ' ')\n    .replace(/\\n+/g, ' ')\n    .trim();\n}\n\nfunction truncate(text, maxLength = 2000) {\n  const clean = cleanText(text);\n  if (clean.length <= maxLength) return clean;\n  return clean.slice(0, maxLength).trim() + '...';\n}\n\nfunction isLowQualityPage(text) {\n  const clean = cleanText(text).toLowerCase();\n\n  const lowQualityTerms = [\n    'website maintenance',\n    'under maintenance',\n    'scheduled maintenance',\n    'under construction',\n    'coming soon',\n    'access denied',\n    'enable javascript',\n    'temporarily unavailable',\n    'something went wrong',\n    'try again later',\n    'hoppla något gick fel',\n    'captcha',\n    'security check'\n  ];\n\n  return lowQualityTerms.some(term => clean.includes(term));\n}\n\nfunction extractCompanySummary(json) {\n  const results = Array.isArray(json.results) ? json.results : [];\n  const unresponsive = Array.isArray(json.unresponsive_engines) ? json.unresponsive_engines : [];\n\n  // If NO engines returned results, check if we were entirely rate-limited\n  if (results.length === 0) {\n    const isRateLimited = unresponsive.some(engine => \n      engine[1].includes('too many requests') || \n      engine[1].includes('CAPTCHA')\n    );\n    if (isRateLimited) {\n      return \"ERROR: SearXNG was fully rate-limited or blocked by CAPTCHAs.\";\n    }\n    return '';\n  }\n\n  // Iterate through the successful results to find a good snippet\n  for (const result of results) {\n    const pageTitle = cleanText(result.title || '');\n    const pageContent = cleanText(result.content || ''); // SearXNG uses 'content' instead of 'text'\n\n    // Threshold lowered to 50 because search snippets are shorter than full website text\n    if (pageContent && !isLowQualityPage(pageContent) && pageContent.length > 50) {\n      return truncate(`${pageTitle}. ${pageContent}`, 1000);\n    }\n  }\n\n  // Fallback: If individual snippets are too short, combine the top 3\n  const combinedSnippets = results\n    .slice(0, 3)\n    .filter(r => r.content && !isLowQualityPage(cleanText(r.content)))\n    .map(r => `${cleanText(r.title || '')}: ${cleanText(r.content)}`);\n\n  if (combinedSnippets.length > 0) {\n    return truncate(combinedSnippets.join(' | '), 1000);\n  }\n\n  return '';\n}\n\nreturn $input.all().map(item => {\n  const companySummary = extractCompanySummary(item.json || {});\n\n  return {\n    json: {\n      company_summary: companySummary,\n    },\n  };\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -224,
        1952
      ],
      "id": "e51fb6dc-91c3-43ea-b1d0-7ef5a7deb5d9",
      "name": "EXA Summary Cleanup (Hubspot)1"
    },
    {
      "parameters": {
        "jsCode": "// n8n Code Node\n// SearXNG Output Cleaner - Company Summary Only\n\nfunction toText(value) {\n  if (value === null || value === undefined) return '';\n  if (Array.isArray(value)) return value.map(toText).join(' ');\n  if (typeof value === 'object') return Object.values(value).map(toText).join(' ');\n  return String(value);\n}\n\nfunction cleanText(text) {\n  return toText(text)\n    .replace(/\\s+/g, ' ')\n    .replace(/\\n+/g, ' ')\n    .trim();\n}\n\nfunction truncate(text, maxLength = 2000) {\n  const clean = cleanText(text);\n  if (clean.length <= maxLength) return clean;\n  return clean.slice(0, maxLength).trim() + '...';\n}\n\nfunction isLowQualityPage(text) {\n  const clean = cleanText(text).toLowerCase();\n\n  const lowQualityTerms = [\n    'website maintenance',\n    'under maintenance',\n    'scheduled maintenance',\n    'under construction',\n    'coming soon',\n    'access denied',\n    'enable javascript',\n    'temporarily unavailable',\n    'something went wrong',\n    'try again later',\n    'hoppla något gick fel',\n  ];\n\n  return lowQualityTerms.some(term => clean.includes(term));\n}\n\nfunction extractCompanySummary(json) {\n  // SearXNG returns its output in a 'results' array\n  const results = Array.isArray(json.results) ? json.results : [];\n\n  if (results.length === 0) {\n    return '';\n  }\n\n  // Iterate through results to find the first high-quality snippet\n  for (const result of results) {\n    const pageTitle = cleanText(result.title || '');\n    const pageContent = cleanText(result.content || ''); // SearXNG uses 'content' instead of 'text'\n\n    // Lowered threshold from 150 to 50 because search snippets are typically shorter than full page text\n    if (pageContent && !isLowQualityPage(pageContent) && pageContent.length > 50) {\n      return truncate(`${pageTitle}. ${pageContent}`, 1000);\n    }\n  }\n\n  // Fallback: If no single snippet passed the length test but valid results exist, \n  // combine the top 3 valid snippets to create a summary.\n  const combinedSnippets = results\n    .slice(0, 3)\n    .filter(r => r.content && !isLowQualityPage(cleanText(r.content)))\n    .map(r => `${cleanText(r.title || '')}: ${cleanText(r.content)}`);\n\n  if (combinedSnippets.length > 0) {\n    return truncate(combinedSnippets.join(' | '), 1000);\n  }\n\n  return '';\n}\n\nreturn $input.all().map(item => {\n  const companySummary = extractCompanySummary(item.json || {});\n\n  return {\n    json: {\n      company_summary: companySummary,\n    },\n  };\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        0,
        2336
      ],
      "id": "fcc96fca-2e81-4776-b971-95f64219e593",
      "name": "EXA Summary Cleanup (Apollo)1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "0caf25ac-5df6-415c-a149-af007c7fc8d4",
              "leftValue": "={{ $json.properties.website.value }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "exists",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.3,
      "position": [
        -672,
        1952
      ],
      "id": "7f740558-57af-43e9-a0ec-baf3c6ff6f1b",
      "name": "Website Filter (Hubspot)1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "a9a8d401-4894-423e-9252-ac7acb791b15",
              "leftValue": "={{ $json.target_icp_marker }}",
              "rightValue": "Not Classified",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        448,
        1952
      ],
      "id": "6eed780b-c2e7-4f13-81ca-79b5c08a76ad",
      "name": "If4"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "8d3ef975-72c2-4149-8b7c-a37e32c7e1f7",
              "leftValue": "={{ $json.target_icp_marker }}",
              "rightValue": "Not Classified",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              }
            },
            {
              "id": "be9744fe-33b5-4949-aee4-36f60a6303bd",
              "leftValue": "={{ $json.hubspot_id }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        896,
        2336
      ],
      "id": "fa1dcb58-f27a-40d0-841c-637b1585c4a0",
      "name": "If5"
    },
    {
      "parameters": {
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "ClassificationReason": "={{ $json.classification_reason }}",
            "HubspotID": "={{ $('Website Filter (Hubspot)1').item.json.companyId }}",
            "Website": "={{ $('Get a company1').item.json.properties.website.value }}",
            "exa_summary": "={{ $('Append row in sheet4').item.json.company_summary }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "HubspotID",
              "displayName": "HubspotID",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "ClassificationReason",
              "displayName": "ClassificationReason",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "Website",
              "displayName": "Website",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "Keywords",
              "displayName": "Keywords",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "exa_title",
              "displayName": "exa_title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": true
            },
            {
              "id": "exa_summary",
              "displayName": "exa_summary",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        672,
        2048
      ],
      "id": "3909c399-0061-4c32-ae3c-bc778c346d0b",
      "name": "Insert row2"
    },
    {
      "parameters": {
        "dataTableId": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "HubspotID": "={{ $json.hubspot_id }}",
            "ClassificationReason": "={{ $json.classification_reason }}",
            "Website": "={{ $json.website }}",
            "Keywords": "={{ $json.source_keywords_sample }}",
            "exa_title": "={{ $json.exa_title_sample }}",
            "exa_summary": "={{ $json.exa_summary_sample }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "HubspotID",
              "displayName": "HubspotID",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "ClassificationReason",
              "displayName": "ClassificationReason",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "Website",
              "displayName": "Website",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "Keywords",
              "displayName": "Keywords",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "exa_title",
              "displayName": "exa_title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            },
            {
              "id": "exa_summary",
              "displayName": "exa_summary",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "readOnly": false,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "optimizeBulk": false
        }
      },
      "type": "n8n-nodes-base.dataTable",
      "typeVersion": 1.1,
      "position": [
        1120,
        2432
      ],
      "id": "248d571f-164d-4d9b-89c0-c32f269de0b0",
      "name": "Insert row3"
    },
    {
      "parameters": {
        "query": "={{ $json.Website }}",
        "additionalFields": {},
        "contentsOptions": {
          "highlights": true,
          "summary": true
        },
        "requestOptions": {}
      },
      "type": "n8n-nodes-exa-official.exa",
      "typeVersion": 1,
      "position": [
        896,
        2048
      ],
      "id": "14608159-b44c-4e1d-8b9d-607590c279ef",
      "name": "Search the web1"
    },
    {
      "parameters": {
        "jsCode": "// n8n Code node\n// Mode: Run Once for All Items\n// Purpose: Optimized ICP identification from Exa JSON results\n// Version: exa-target-icp-v1.4-strict-business-model\n\nconst CLASSIFICATION_VERSION = 'exa-target-icp-v1.4-strict-business-model';\nconst DEBUG_EVIDENCE = true;\n\n// --------------------------------------------------\n// Helpers\n// --------------------------------------------------\n\nfunction toText(value) {\n  if (value === null || value === undefined) return '';\n\n  if (Array.isArray(value)) {\n    return value.map(toText).join(' ');\n  }\n\n  if (typeof value === 'object') {\n    return Object.values(value).map(toText).join(' ');\n  }\n\n  return String(value);\n}\n\nfunction normalizeText(value) {\n  return toText(value)\n    .normalize('NFD')\n    .replace(/[\\u0300-\\u036f]/g, '')\n    .toLowerCase()\n    .replace(/&/g, ' and ')\n    .replace(/[’']/g, '')\n    .replace(/[_/|;,:()[\\]{}+]+/g, ' ')\n    .replace(/[–—-]/g, ' ')\n    .replace(/\\s+/g, ' ')\n    .trim();\n}\n\nfunction compactText(value) {\n  return normalizeText(value).replace(/\\s+/g, '');\n}\n\nfunction escapeRegex(str) {\n  return String(str).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction hasTerm(text, term) {\n  const normalizedText = normalizeText(text);\n  const normalizedTerm = normalizeText(term);\n\n  if (!normalizedText || !normalizedTerm) return false;\n\n  const pattern = new RegExp(\n    `(^|[^a-z0-9])${escapeRegex(normalizedTerm).replace(/\\s+/g, '\\\\s+')}($|[^a-z0-9])`,\n    'i'\n  );\n\n  if (pattern.test(normalizedText)) return true;\n\n  // Handles messy phrases like \"white label casinoiGaming platformcasino platform\"\n  if (normalizedTerm.includes(' ') && normalizedTerm.replace(/\\s+/g, '').length >= 8) {\n    return compactText(normalizedText).includes(compactText(normalizedTerm));\n  }\n\n  return false;\n}\n\nfunction findTerms(text, terms) {\n  return [...new Set((terms || []).filter(term => hasTerm(text, term)))];\n}\n\nfunction scoreTerms(text, terms, weight = 1) {\n  return findTerms(text, terms).length * weight;\n}\n\nfunction getDomain(url) {\n  const raw = String(url || '').trim();\n\n  if (!raw) return '';\n\n  try {\n    const normalized = raw.startsWith('http://') || raw.startsWith('https://')\n      ? raw\n      : `https://${raw}`;\n\n    return new URL(normalized).hostname.replace(/^www\\./, '').toLowerCase();\n  } catch {\n    return raw\n      .replace(/^https?:\\/\\//i, '')\n      .replace(/^www\\./i, '')\n      .split('/')[0]\n      .trim()\n      .toLowerCase();\n  }\n}\n\nfunction rootDomain(domain) {\n  const clean = getDomain(domain);\n  const parts = clean.split('.').filter(Boolean);\n\n  if (parts.length <= 2) return clean;\n\n  return parts.slice(-2).join('.');\n}\n\nfunction isLikelyUtilityPage(url, title) {\n  const text = normalizeText(`${url} ${title}`);\n\n  const utilityTerms = [\n    'login',\n    'log in',\n    'register',\n    'create account',\n    'contact',\n    'privacy',\n    'terms',\n    'cookie',\n    'careers',\n    'jobs',\n    'lost password',\n    'user login',\n    'user register'\n  ];\n\n  return utilityTerms.some(term => hasTerm(text, term));\n}\n\nfunction extractCompanyNameFromTitle(title) {\n  const clean = String(title || '').trim();\n\n  if (!clean) return '';\n\n  return clean\n    .split('|')[0]\n    .split('-')[0]\n    .trim();\n}\n\nfunction cleanSummaryText(text, maxLength = 20000) {\n  return toText(text)\n    .replace(/\\s+/g, ' ')\n    .trim()\n    .slice(0, maxLength);\n}\n\n// --------------------------------------------------\n// Business-model gates\n// --------------------------------------------------\n\nconst IGAMING_CONTEXT_TERMS = [\n  'casino',\n  'online casino',\n  'gambling',\n  'online gambling',\n  'sportsbook',\n  'betting',\n  'sports betting',\n  'igaming',\n  'i gaming',\n  'real money gaming',\n  'real money',\n  'rmg',\n  'slots',\n  'slot games',\n  'live casino',\n  'poker',\n  'jackpot',\n  'odds',\n  'wager',\n  'lottery',\n  'lotto',\n  'esports betting'\n];\n\nconst ASSOCIATION_EXCLUSION_TERMS = [\n  'association',\n  'trade association',\n  'industry association',\n  'represent gambling businesses',\n  'represents operators',\n  'protects members',\n  'members of the association',\n  'how to become a member',\n  'membership',\n  'advocacy',\n  'regulatory',\n  'regulation',\n  'legal framework',\n  'authorities',\n  'advisory council',\n  'industry body',\n  'press releases',\n  'responsible gambling projects'\n];\n\nconst GENERIC_AGENCY_EXCLUSION_TERMS = [\n  'internet marketing',\n  'digital marketing',\n  'performance marketing',\n  'seo',\n  'paid media',\n  'web design',\n  'web development',\n  'content marketing',\n  'conversion optimization',\n  'marketing agency',\n  'advertising agency',\n  'saas development',\n  'custom saas',\n  'software development',\n  'crypto consulting',\n  'cryptocurrency consulting',\n  'on chain product strategy',\n  'custody consulting'\n];\n\nconst CRYPTO_FINANCE_EXCLUSION_TERMS = [\n  'crypto investing',\n  'cryptocurrency investing',\n  'crypto broker',\n  'regulated broker',\n  'stocks',\n  'etfs',\n  'precious metals',\n  'trade cryptos',\n  'buy and sell crypto',\n  'investment platform',\n  'broker platform',\n  'staking',\n  'savings plans',\n  'wallets',\n  'aml compliance'\n];\n\nconst EDUCATION_EXCLUSION_TERMS = [\n  'university',\n  'public university',\n  'degrees',\n  'campus',\n  'students',\n  'study options',\n  'teaching',\n  'research',\n  'education'\n];\n\nconst ECOMMERCE_HOME_EXCLUSION_TERMS = [\n  'home plans',\n  'house plans',\n  'cabin plans',\n  'digital art',\n  'designer paint',\n  'shoppe',\n  'collections',\n  'products'\n];\n\nconst NON_TARGET_EXCLUSION_GROUPS = [\n  {\n    label: 'Association / Regulatory Body',\n    terms: ASSOCIATION_EXCLUSION_TERMS\n  },\n  {\n    label: 'Generic Marketing / SaaS / Crypto Consulting Agency',\n    terms: GENERIC_AGENCY_EXCLUSION_TERMS\n  },\n  {\n    label: 'Crypto / Financial Investment Platform',\n    terms: CRYPTO_FINANCE_EXCLUSION_TERMS\n  },\n  {\n    label: 'Education / University',\n    terms: EDUCATION_EXCLUSION_TERMS\n  },\n  {\n    label: 'Ecommerce / Home Plans',\n    terms: ECOMMERCE_HOME_EXCLUSION_TERMS\n  }\n];\n\n// --------------------------------------------------\n// ICP definitions\n// --------------------------------------------------\n\nconst ICP_DEFINITIONS = [\n  {\n    icpNumber: 'ICP 1',\n    icpMarker: 'ICP 1 (Online Casino Operators)',\n    segment: 'Online Casino Operators',\n    minScore: 10,\n    core: [\n      'online casino operator',\n      'casino operator',\n      'sportsbook operator',\n      'betting operator',\n      'gambling operator',\n      'licensed operator',\n      'licensed gambling operator',\n      'licensed casino operator',\n      'licensed betting operator',\n      'online casino',\n      'sportsbook',\n      'sports betting',\n      'online betting',\n      'real money gaming',\n      'real money casino',\n      'live casino',\n      'casino lobby',\n      'place bet',\n      'bet slip',\n      'betslip'\n    ],\n    signals: [\n      'deposit',\n      'withdrawal',\n      'deposit methods',\n      'withdrawal methods',\n      'player account',\n      'player wallet',\n      'register',\n      'sign up',\n      'login',\n      'bonus terms',\n      'wagering requirements',\n      'responsible gambling',\n      'responsible gaming',\n      'payment methods',\n      'cash out',\n      'cashout',\n      'vip program',\n      'odds',\n      'jackpot',\n      'slots',\n      'poker'\n    ],\n    negative: [\n      'association',\n      'represents operators',\n      'platform provider',\n      'white label',\n      'software provider',\n      'affiliate',\n      'review site',\n      'game provider',\n      'game studio',\n      'investment firm',\n      'venture capital'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 2',\n    icpMarker: 'ICP 2 (Platform Providers)',\n    segment: 'Platform Providers',\n    minScore: 10,\n    core: [\n      'white label casino',\n      'white label igaming',\n      'igaming platform',\n      'casino platform',\n      'sportsbook platform',\n      'turnkey casino',\n      'turnkey igaming',\n      'casino software',\n      'sportsbook software',\n      'betting software',\n      'operator platform',\n      'game aggregation platform',\n      'aggregation platform',\n      'casino solution',\n      'igaming solutions',\n      'sportsbook solution',\n      'api gaming platform',\n      'services for betting operators',\n      'data platform for betting',\n      'official esports data',\n      'official game data'\n    ],\n    signals: [\n      'api integration',\n      'api documentation',\n      'operator dashboard',\n      'back office',\n      'backoffice',\n      'sportsbook engine',\n      'casino engine',\n      'wallet integration',\n      'kyc integration',\n      'payment gateway integration',\n      'risk management tools',\n      'multi brand',\n      'multi tenant',\n      'b2b igaming',\n      'operator clients',\n      'platform partners',\n      'integration partners'\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'association',\n      'affiliate',\n      'review site',\n      'investment firm',\n      'venture capital'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 3',\n    icpMarker: 'ICP 3 (CRM / Retention)',\n    segment: 'CRM / Retention',\n    minScore: 10,\n    core: [\n      'igaming crm',\n      'casino crm',\n      'sportsbook crm',\n      'gaming crm',\n      'player retention',\n      'player engagement',\n      'player lifecycle',\n      'loyalty platform',\n      'bonus engine',\n      'campaign management gaming',\n      'marketing automation casino',\n      'crm for igaming operators',\n      'retention platform for igaming'\n    ],\n    signals: [\n      'player segmentation',\n      'campaign automation',\n      'reward engine',\n      'real time triggers',\n      'event based messaging',\n      'player journeys',\n      'churn prevention',\n      'reactivation campaigns',\n      'retention campaigns',\n      'bonus management',\n      'multi channel messaging',\n      'push notifications',\n      'sms',\n      'email'\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'affiliate',\n      'review site',\n      'game provider',\n      'investment firm'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 4',\n    icpMarker: 'ICP 4 (iGaming Affiliates)',\n    segment: 'iGaming Affiliates',\n    minScore: 10,\n    core: [\n      'igaming affiliate',\n      'casino affiliate',\n      'sports betting affiliate',\n      'betting affiliate',\n      'gambling affiliate',\n      'online casino affiliate',\n      'affiliate network',\n      'affiliate program',\n      'casino comparison',\n      'casino reviews',\n      'sports betting reviews',\n      'betting reviews',\n      'bonus comparison',\n      'odds comparison',\n      'review site',\n      'comparison site',\n      'gambling media',\n      'igaming media',\n      'betting media'\n    ],\n    signals: [\n      'traffic acquisition',\n      'player acquisition',\n      'lead generation',\n      'cpa',\n      'revshare',\n      'revenue share',\n      'bonus codes',\n      'betting tips',\n      'operator reviews',\n      'bookmaker reviews',\n      'performance marketing'\n    ],\n    negative: [\n      'affiliate tracking software',\n      'affiliate management software',\n      'casino operator',\n      'sportsbook operator',\n      'platform provider',\n      'game provider',\n      'investment firm'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 5',\n    icpMarker: 'ICP 5 (Game / Slot Providers)',\n    segment: 'Game / Slot Providers',\n    minScore: 10,\n    core: [\n      'casino game provider',\n      'slot provider',\n      'slot game provider',\n      'slot developer',\n      'slot game developer',\n      'casino game developer',\n      'game content provider',\n      'casino content provider',\n      'online casino games',\n      'casino games',\n      'slot games',\n      'slots provider',\n      'igaming studio',\n      'live casino provider',\n      'live dealer provider',\n      'rng games',\n      'instant games',\n      'crash games',\n      'table games'\n    ],\n    signals: [\n      'game portfolio',\n      'slots portfolio',\n      'game catalog',\n      'casino content',\n      'html5 games',\n      'rng',\n      'random number generator',\n      'live dealer',\n      'blackjack',\n      'roulette',\n      'baccarat',\n      'provably fair',\n      'game mechanics',\n      'operator integration',\n      'regulated markets',\n      'certified games'\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'affiliate',\n      'review site',\n      'investment firm',\n      'venture capital'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 6',\n    icpMarker: 'ICP 6 (iGaming Investors)',\n    segment: 'iGaming Investors',\n    minScore: 10,\n    core: [\n      'igaming investor',\n      'gambling investor',\n      'casino investor',\n      'sports betting investor',\n      'gaming venture capital',\n      'betting investment',\n      'igaming investment',\n      'gambling investment',\n      'sports betting investment',\n      'casino investment',\n      'invests in igaming',\n      'invests in gambling',\n      'invests in sports betting',\n      'invests in casino'\n    ],\n    signals: [\n      'venture capital',\n      'vc fund',\n      'investment firm',\n      'private equity',\n      'family office',\n      'portfolio companies',\n      'investment portfolio',\n      'seed round',\n      'series a',\n      'growth capital',\n      'strategic investment',\n      'backed companies',\n      'portfolio includes'\n    ],\n    negative: [\n      'crypto broker',\n      'stocks',\n      'etfs',\n      'regulated broker',\n      'casino operator',\n      'sportsbook operator',\n      'platform provider',\n      'affiliate',\n      'review site',\n      'game studio'\n    ]\n  }\n];\n\n// --------------------------------------------------\n// Exa extraction\n// --------------------------------------------------\n\nfunction extractExaPayloads(json) {\n  const root = json?.body || json;\n\n  if (!root) return [];\n\n  if (Array.isArray(root)) return root;\n\n  if (Array.isArray(root.results)) return [root];\n\n  return [root];\n}\n\nfunction resultText(result) {\n  return cleanSummaryText([\n    result.title,\n    result.summary,\n    result.text,\n    Array.isArray(result.highlights) ? result.highlights.join(' ') : ''\n  ].join(' '));\n}\n\nfunction buildCompanyEvidence(payload) {\n  const results = Array.isArray(payload.results) ? payload.results : [];\n\n  const firstUsefulResult =\n    results.find(r => r?.url && !isLikelyUtilityPage(r.url, r.title)) ||\n    results[0] ||\n    {};\n\n  const inferredCompanyName =\n    payload.company_name ||\n    payload.name ||\n    extractCompanyNameFromTitle(firstUsefulResult.title) ||\n    '';\n\n  const officialDomain =\n    rootDomain(\n      payload.domain ||\n      payload.primary_domain ||\n      payload.website ||\n      payload.website_url ||\n      firstUsefulResult.url ||\n      ''\n    );\n\n  const officialResults = [];\n  const thirdPartyResults = [];\n  const ignoredResults = [];\n\n  for (const result of results) {\n    const domain = rootDomain(result.url || result.id || '');\n\n    const isOfficial =\n      officialDomain &&\n      domain &&\n      domain === officialDomain;\n\n    const isUtility = isLikelyUtilityPage(result.url, result.title);\n\n    const row = {\n      title: result.title || '',\n      url: result.url || result.id || '',\n      domain,\n      text: resultText(result),\n      summary: result.summary || ''\n    };\n\n    if (isUtility) {\n      ignoredResults.push(row);\n    } else if (isOfficial) {\n      officialResults.push(row);\n    } else {\n      thirdPartyResults.push(row);\n    }\n  }\n\n  const officialText = cleanSummaryText(\n    officialResults.map(r => r.text).join(' '),\n    30000\n  );\n\n  const thirdPartyText = cleanSummaryText(\n    thirdPartyResults.map(r => r.text).join(' '),\n    12000\n  );\n\n  const ignoredText = cleanSummaryText(\n    ignoredResults.map(r => r.text).join(' '),\n    5000\n  );\n\n  const companySummary = cleanSummaryText(\n    [\n      `Company: ${inferredCompanyName}`,\n      `Official domain: ${officialDomain}`,\n      officialResults.slice(0, 3).map(r => r.summary || r.text).join(' ')\n    ].join(' '),\n    6000\n  );\n\n  return {\n    inferredCompanyName,\n    officialDomain,\n    officialResults,\n    thirdPartyResults,\n    ignoredResults,\n    companySummary,\n    officialText,\n    thirdPartyText,\n    ignoredText,\n    strongText: cleanSummaryText([companySummary, officialText].join(' '), 35000),\n    weakText: cleanSummaryText(thirdPartyText, 12000),\n    allText: cleanSummaryText([companySummary, officialText, thirdPartyText].join(' '), 45000)\n  };\n}\n\n// --------------------------------------------------\n// Classification\n// --------------------------------------------------\n\nfunction detectNonTargetBusinessModel(evidence) {\n  const strongText = evidence.strongText;\n  const weakText = evidence.weakText;\n  const allText = evidence.allText;\n\n  const matches = [];\n\n  for (const group of NON_TARGET_EXCLUSION_GROUPS) {\n    const strongMatches = findTerms(strongText, group.terms);\n    const weakMatches = findTerms(weakText, group.terms);\n\n    const score =\n      strongMatches.length * 2 +\n      weakMatches.length;\n\n    if (score >= 2) {\n      matches.push({\n        label: group.label,\n        score,\n        strongMatches,\n        weakMatches\n      });\n    }\n  }\n\n  matches.sort((a, b) => b.score - a.score);\n\n  const iGamingMatches = findTerms(strongText, IGAMING_CONTEXT_TERMS);\n\n  return {\n    hasNonTargetBusinessModel: matches.length > 0,\n    topNonTargetModel: matches[0] || null,\n    allNonTargetMatches: matches,\n    iGamingMatches\n  };\n}\n\nfunction classifyIcp(evidence) {\n  const strongText = evidence.strongText;\n  const weakText = evidence.weakText;\n  const allText = evidence.allText;\n\n  const iGamingContextStrong = findTerms(strongText, IGAMING_CONTEXT_TERMS);\n  const iGamingContextWeak = findTerms(weakText, IGAMING_CONTEXT_TERMS);\n\n  const nonTarget = detectNonTargetBusinessModel(evidence);\n\n  // Hard stop: fully unrelated companies should not classify.\n  if (iGamingContextStrong.length === 0) {\n    return {\n      target_icp_marker: 'Not Classified',\n      target_icp_number: '',\n      target_icp_name: 'Not Classified',\n      icp_segment: 'Not Classified',\n      classification_confidence: 'Low',\n      classification_score: 0,\n      classification_reason:\n        'No strong iGaming, casino, gambling, sportsbook, betting, lottery, or real-money gaming context was found in official Exa evidence.',\n      strict_gate_passed: false,\n      non_target_business_model: nonTarget.topNonTargetModel?.label || '',\n      mandatory_context_match: iGamingContextWeak.join(', '),\n      matched_core_keywords: '',\n      product_signal_match: '',\n      negative_signal_match: '',\n      needs_manual_review: false,\n      _debug_evidence: DEBUG_EVIDENCE ? { nonTarget, iGamingContextStrong, iGamingContextWeak } : undefined\n    };\n  }\n\n  // Hard stop: Rombet-style association / regulatory / member organization.\n  if (\n    nonTarget.topNonTargetModel &&\n    nonTarget.topNonTargetModel.label === 'Association / Regulatory Body'\n  ) {\n    return {\n      target_icp_marker: 'Not Classified',\n      target_icp_number: '',\n      target_icp_name: 'Not Classified',\n      icp_segment: 'Not Classified',\n      classification_confidence: 'Low',\n      classification_score: 0,\n      classification_reason:\n        `Strong iGaming context was found, but the company appears to be an association, regulatory body, or member organization rather than a direct target ICP. Matched: ${nonTarget.topNonTargetModel.strongMatches.join(', ')}.`,\n      strict_gate_passed: false,\n      non_target_business_model: nonTarget.topNonTargetModel.label,\n      mandatory_context_match: iGamingContextStrong.join(', '),\n      matched_core_keywords: '',\n      product_signal_match: '',\n      negative_signal_match: '',\n      needs_manual_review: true,\n      _debug_evidence: DEBUG_EVIDENCE ? { nonTarget, iGamingContextStrong, iGamingContextWeak } : undefined\n    };\n  }\n\n  const results = ICP_DEFINITIONS.map(segment => {\n    const strongCore = findTerms(strongText, segment.core);\n    const weakCore = findTerms(weakText, segment.core);\n\n    const strongSignals = findTerms(strongText, segment.signals);\n    const weakSignals = findTerms(weakText, segment.signals);\n\n    const strongNegative = findTerms(strongText, segment.negative);\n    const weakNegative = findTerms(weakText, segment.negative);\n\n    let score = 0;\n\n    score += strongCore.length * 7;\n    score += weakCore.length * 2;\n    score += strongSignals.length * 4;\n    score += weakSignals.length * 1;\n    score -= strongNegative.length * 5;\n    score -= weakNegative.length * 2;\n\n    // Segment-specific extra precision rules.\n    const hasStrongCore = strongCore.length > 0;\n    const hasStrongSignal = strongSignals.length > 0;\n\n    let segmentGatePassed = hasStrongCore;\n\n    // Investors must have explicit iGaming/gambling/betting investment language.\n    if (segment.icpNumber === 'ICP 6') {\n      const investorSpecificContext = findTerms(strongText, [\n        'igaming investment',\n        'gambling investment',\n        'sports betting investment',\n        'casino investment',\n        'igaming investor',\n        'gambling investor',\n        'sports betting investor',\n        'casino investor',\n        'invests in igaming',\n        'invests in gambling',\n        'invests in sports betting',\n        'invests in casino'\n      ]);\n\n      segmentGatePassed = investorSpecificContext.length > 0;\n    }\n\n    // Affiliates must be iGaming-specific, not generic affiliate marketing.\n    if (segment.icpNumber === 'ICP 4') {\n      const affiliateSpecificContext = findTerms(strongText, [\n        'igaming affiliate',\n        'casino affiliate',\n        'sports betting affiliate',\n        'betting affiliate',\n        'gambling affiliate',\n        'casino reviews',\n        'sports betting reviews',\n        'betting reviews',\n        'casino comparison',\n        'bonus comparison',\n        'odds comparison'\n      ]);\n\n      segmentGatePassed = affiliateSpecificContext.length > 0;\n    }\n\n    // Operators need either strong operator core OR multiple player/product signals.\n    if (segment.icpNumber === 'ICP 1') {\n      segmentGatePassed =\n        hasStrongCore ||\n        strongSignals.length >= 3;\n    }\n\n    if (!segmentGatePassed) {\n      score = 0;\n    }\n\n    score = Math.max(0, score);\n\n    return {\n      ...segment,\n      score,\n      strongCore,\n      weakCore,\n      strongSignals,\n      weakSignals,\n      strongNegative,\n      weakNegative,\n      segmentGatePassed\n    };\n  }).sort((a, b) => b.score - a.score);\n\n  const best = results[0];\n  const second = results[1];\n\n  if (!best || best.score < best.minScore || !best.segmentGatePassed) {\n    return {\n      target_icp_marker: 'Not Classified',\n      target_icp_number: '',\n      target_icp_name: 'Not Classified',\n      icp_segment: 'Not Classified',\n      classification_confidence: 'Low',\n      classification_score: 0,\n      classification_reason:\n        'Mandatory iGaming context was found, but no ICP segment had enough strong official evidence to classify safely.',\n      strict_gate_passed: true,\n      non_target_business_model: nonTarget.topNonTargetModel?.label || '',\n      mandatory_context_match: iGamingContextStrong.join(', '),\n      matched_core_keywords: '',\n      product_signal_match: '',\n      negative_signal_match: '',\n      needs_manual_review: true,\n      second_best_segment: second?.icpMarker || '',\n      second_best_score: second?.score || 0,\n      _all_scores: Object.fromEntries(results.map(r => [r.icpMarker, r.score])),\n      _debug_evidence: DEBUG_EVIDENCE ? { results, nonTarget, iGamingContextStrong, iGamingContextWeak } : undefined\n    };\n  }\n\n  const scoreGap = best.score - (second?.score || 0);\n\n  const needsManualReview =\n    best.score < 18 ||\n    scoreGap < 5 ||\n    best.strongCore.length === 1 && best.strongSignals.length === 0;\n\n  let confidence = 'Low';\n\n  if (!needsManualReview && best.score >= 24 && scoreGap >= 8) {\n    confidence = 'High';\n  } else if (best.score >= 14 && scoreGap >= 4) {\n    confidence = 'Medium';\n  }\n\n  const reasonParts = [\n    `Matched ${best.icpMarker}`,\n    `mandatory context: ${iGamingContextStrong.slice(0, 6).join(', ')}`,\n    `strong core: ${best.strongCore.slice(0, 6).join(', ') || 'none'}`,\n    `strong signals: ${best.strongSignals.slice(0, 6).join(', ') || 'none'}`\n  ];\n\n  if (best.strongNegative.length > 0) {\n    reasonParts.push(`negative signals considered: ${best.strongNegative.slice(0, 4).join(', ')}`);\n  }\n\n  if (needsManualReview) {\n    reasonParts.push('manual review recommended because evidence is not strong enough for automatic update');\n  }\n\n  return {\n    target_icp_marker: best.icpMarker,\n    target_icp_number: best.icpNumber,\n    target_icp_name: best.segment,\n    icp_segment: best.icpMarker,\n    classification_confidence: confidence,\n    classification_score: best.score,\n    classification_reason: reasonParts.join('; ') + '.',\n\n    strict_gate_passed: true,\n    non_target_business_model: nonTarget.topNonTargetModel?.label || '',\n    mandatory_context_match: iGamingContextStrong.join(', '),\n    matched_core_keywords: best.strongCore.join(', '),\n    product_signal_match: best.strongSignals.join(', '),\n    negative_signal_match: best.strongNegative.join(', '),\n\n    needs_manual_review: needsManualReview,\n    second_best_segment: second?.icpMarker || '',\n    second_best_score: second?.score || 0,\n    _all_scores: Object.fromEntries(results.map(r => [r.icpMarker, r.score])),\n    _debug_evidence: DEBUG_EVIDENCE ? { results, nonTarget, iGamingContextStrong, iGamingContextWeak } : undefined\n  };\n}\n\n// --------------------------------------------------\n// Main execution\n// --------------------------------------------------\n\nconst output = [];\n\nfor (const item of $input.all()) {\n  const payloads = extractExaPayloads(item.json);\n\n  for (const payload of payloads) {\n    const evidence = buildCompanyEvidence(payload);\n    const classification = classifyIcp(evidence);\n\n    output.push({\n      json: {\n        source_system: 'Exa',\n        classification_version: CLASSIFICATION_VERSION,\n\n        request_id: payload.requestId || payload.request_id || '',\n        company_name: evidence.inferredCompanyName,\n        domain: evidence.officialDomain,\n\n        official_result_count: evidence.officialResults.length,\n        third_party_result_count: evidence.thirdPartyResults.length,\n        ignored_result_count: evidence.ignoredResults.length,\n\n        company_summary: evidence.companySummary,\n        official_text_sample: evidence.officialText.slice(0, 1200),\n        third_party_text_sample: evidence.weakText.slice(0, 800),\n\n        ...classification,\n\n        hubspot_update_properties: {\n          target_icp_marker: classification.target_icp_marker,\n          target_icp_number: classification.target_icp_number,\n          target_icp_name: classification.target_icp_name,\n          icp_segment: classification.icp_segment,\n\n          icp_confidence: classification.classification_confidence,\n          icp_score: classification.classification_score,\n          icp_reason: classification.classification_reason,\n\n          icp_strict_gate_passed: classification.strict_gate_passed ? 'true' : 'false',\n          icp_mandatory_context: classification.mandatory_context_match,\n          icp_core_keywords: classification.matched_core_keywords,\n          icp_product_signals: classification.product_signal_match,\n          icp_negative_signals: classification.negative_signal_match,\n          icp_needs_manual_review: classification.needs_manual_review ? 'true' : 'false',\n\n          icp_non_target_business_model: classification.non_target_business_model,\n          icp_last_classified_at: new Date().toISOString(),\n          icp_classification_version: CLASSIFICATION_VERSION\n        }\n      }\n    });\n  }\n}\n\nreturn output;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1792,
        2432
      ],
      "id": "806a36a3-e6a3-4e79-88b1-f89006390151",
      "name": "Code in JavaScript2"
    },
    {
      "parameters": {
        "jsCode": "// n8n Code node\n// Mode: Run Once for All Items\n// Purpose: Optimized ICP identification from Exa JSON results\n// Version: exa-target-icp-v1.4-strict-business-model\n\nconst CLASSIFICATION_VERSION = 'exa-target-icp-v1.4-strict-business-model';\nconst DEBUG_EVIDENCE = true;\n\n// --------------------------------------------------\n// Helpers\n// --------------------------------------------------\n\nfunction toText(value) {\n  if (value === null || value === undefined) return '';\n\n  if (Array.isArray(value)) {\n    return value.map(toText).join(' ');\n  }\n\n  if (typeof value === 'object') {\n    return Object.values(value).map(toText).join(' ');\n  }\n\n  return String(value);\n}\n\nfunction normalizeText(value) {\n  return toText(value)\n    .normalize('NFD')\n    .replace(/[\\u0300-\\u036f]/g, '')\n    .toLowerCase()\n    .replace(/&/g, ' and ')\n    .replace(/[’']/g, '')\n    .replace(/[_/|;,:()[\\]{}+]+/g, ' ')\n    .replace(/[–—-]/g, ' ')\n    .replace(/\\s+/g, ' ')\n    .trim();\n}\n\nfunction compactText(value) {\n  return normalizeText(value).replace(/\\s+/g, '');\n}\n\nfunction escapeRegex(str) {\n  return String(str).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction hasTerm(text, term) {\n  const normalizedText = normalizeText(text);\n  const normalizedTerm = normalizeText(term);\n\n  if (!normalizedText || !normalizedTerm) return false;\n\n  const pattern = new RegExp(\n    `(^|[^a-z0-9])${escapeRegex(normalizedTerm).replace(/\\s+/g, '\\\\s+')}($|[^a-z0-9])`,\n    'i'\n  );\n\n  if (pattern.test(normalizedText)) return true;\n\n  // Handles messy phrases like \"white label casinoiGaming platformcasino platform\"\n  if (normalizedTerm.includes(' ') && normalizedTerm.replace(/\\s+/g, '').length >= 8) {\n    return compactText(normalizedText).includes(compactText(normalizedTerm));\n  }\n\n  return false;\n}\n\nfunction findTerms(text, terms) {\n  return [...new Set((terms || []).filter(term => hasTerm(text, term)))];\n}\n\nfunction scoreTerms(text, terms, weight = 1) {\n  return findTerms(text, terms).length * weight;\n}\n\nfunction getDomain(url) {\n  const raw = String(url || '').trim();\n\n  if (!raw) return '';\n\n  try {\n    const normalized = raw.startsWith('http://') || raw.startsWith('https://')\n      ? raw\n      : `https://${raw}`;\n\n    return new URL(normalized).hostname.replace(/^www\\./, '').toLowerCase();\n  } catch {\n    return raw\n      .replace(/^https?:\\/\\//i, '')\n      .replace(/^www\\./i, '')\n      .split('/')[0]\n      .trim()\n      .toLowerCase();\n  }\n}\n\nfunction rootDomain(domain) {\n  const clean = getDomain(domain);\n  const parts = clean.split('.').filter(Boolean);\n\n  if (parts.length <= 2) return clean;\n\n  return parts.slice(-2).join('.');\n}\n\nfunction isLikelyUtilityPage(url, title) {\n  const text = normalizeText(`${url} ${title}`);\n\n  const utilityTerms = [\n    'login',\n    'log in',\n    'register',\n    'create account',\n    'contact',\n    'privacy',\n    'terms',\n    'cookie',\n    'careers',\n    'jobs',\n    'lost password',\n    'user login',\n    'user register'\n  ];\n\n  return utilityTerms.some(term => hasTerm(text, term));\n}\n\nfunction extractCompanyNameFromTitle(title) {\n  const clean = String(title || '').trim();\n\n  if (!clean) return '';\n\n  return clean\n    .split('|')[0]\n    .split('-')[0]\n    .trim();\n}\n\nfunction cleanSummaryText(text, maxLength = 20000) {\n  return toText(text)\n    .replace(/\\s+/g, ' ')\n    .trim()\n    .slice(0, maxLength);\n}\n\n// --------------------------------------------------\n// Business-model gates\n// --------------------------------------------------\n\nconst IGAMING_CONTEXT_TERMS = [\n  'casino',\n  'online casino',\n  'gambling',\n  'online gambling',\n  'sportsbook',\n  'betting',\n  'sports betting',\n  'igaming',\n  'i gaming',\n  'real money gaming',\n  'real money',\n  'rmg',\n  'slots',\n  'slot games',\n  'live casino',\n  'poker',\n  'jackpot',\n  'odds',\n  'wager',\n  'lottery',\n  'lotto',\n  'esports betting'\n];\n\nconst ASSOCIATION_EXCLUSION_TERMS = [\n  'association',\n  'trade association',\n  'industry association',\n  'represent gambling businesses',\n  'represents operators',\n  'protects members',\n  'members of the association',\n  'how to become a member',\n  'membership',\n  'advocacy',\n  'regulatory',\n  'regulation',\n  'legal framework',\n  'authorities',\n  'advisory council',\n  'industry body',\n  'press releases',\n  'responsible gambling projects'\n];\n\nconst GENERIC_AGENCY_EXCLUSION_TERMS = [\n  'internet marketing',\n  'digital marketing',\n  'performance marketing',\n  'seo',\n  'paid media',\n  'web design',\n  'web development',\n  'content marketing',\n  'conversion optimization',\n  'marketing agency',\n  'advertising agency',\n  'saas development',\n  'custom saas',\n  'software development',\n  'crypto consulting',\n  'cryptocurrency consulting',\n  'on chain product strategy',\n  'custody consulting'\n];\n\nconst CRYPTO_FINANCE_EXCLUSION_TERMS = [\n  'crypto investing',\n  'cryptocurrency investing',\n  'crypto broker',\n  'regulated broker',\n  'stocks',\n  'etfs',\n  'precious metals',\n  'trade cryptos',\n  'buy and sell crypto',\n  'investment platform',\n  'broker platform',\n  'staking',\n  'savings plans',\n  'wallets',\n  'aml compliance'\n];\n\nconst EDUCATION_EXCLUSION_TERMS = [\n  'university',\n  'public university',\n  'degrees',\n  'campus',\n  'students',\n  'study options',\n  'teaching',\n  'research',\n  'education'\n];\n\nconst ECOMMERCE_HOME_EXCLUSION_TERMS = [\n  'home plans',\n  'house plans',\n  'cabin plans',\n  'digital art',\n  'designer paint',\n  'shoppe',\n  'collections',\n  'products'\n];\n\nconst NON_TARGET_EXCLUSION_GROUPS = [\n  {\n    label: 'Association / Regulatory Body',\n    terms: ASSOCIATION_EXCLUSION_TERMS\n  },\n  {\n    label: 'Generic Marketing / SaaS / Crypto Consulting Agency',\n    terms: GENERIC_AGENCY_EXCLUSION_TERMS\n  },\n  {\n    label: 'Crypto / Financial Investment Platform',\n    terms: CRYPTO_FINANCE_EXCLUSION_TERMS\n  },\n  {\n    label: 'Education / University',\n    terms: EDUCATION_EXCLUSION_TERMS\n  },\n  {\n    label: 'Ecommerce / Home Plans',\n    terms: ECOMMERCE_HOME_EXCLUSION_TERMS\n  }\n];\n\n// --------------------------------------------------\n// ICP definitions\n// --------------------------------------------------\n\nconst ICP_DEFINITIONS = [\n  {\n    icpNumber: 'ICP 1',\n    icpMarker: 'ICP 1 (Online Casino Operators)',\n    segment: 'Online Casino Operators',\n    minScore: 10,\n    core: [\n      'online casino operator',\n      'casino operator',\n      'sportsbook operator',\n      'betting operator',\n      'gambling operator',\n      'licensed operator',\n      'licensed gambling operator',\n      'licensed casino operator',\n      'licensed betting operator',\n      'online casino',\n      'sportsbook',\n      'sports betting',\n      'online betting',\n      'real money gaming',\n      'real money casino',\n      'live casino',\n      'casino lobby',\n      'place bet',\n      'bet slip',\n      'betslip'\n    ],\n    signals: [\n      'deposit',\n      'withdrawal',\n      'deposit methods',\n      'withdrawal methods',\n      'player account',\n      'player wallet',\n      'register',\n      'sign up',\n      'login',\n      'bonus terms',\n      'wagering requirements',\n      'responsible gambling',\n      'responsible gaming',\n      'payment methods',\n      'cash out',\n      'cashout',\n      'vip program',\n      'odds',\n      'jackpot',\n      'slots',\n      'poker'\n    ],\n    negative: [\n      'association',\n      'represents operators',\n      'platform provider',\n      'white label',\n      'software provider',\n      'affiliate',\n      'review site',\n      'game provider',\n      'game studio',\n      'investment firm',\n      'venture capital'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 2',\n    icpMarker: 'ICP 2 (Platform Providers)',\n    segment: 'Platform Providers',\n    minScore: 10,\n    core: [\n      'white label casino',\n      'white label igaming',\n      'igaming platform',\n      'casino platform',\n      'sportsbook platform',\n      'turnkey casino',\n      'turnkey igaming',\n      'casino software',\n      'sportsbook software',\n      'betting software',\n      'operator platform',\n      'game aggregation platform',\n      'aggregation platform',\n      'casino solution',\n      'igaming solutions',\n      'sportsbook solution',\n      'api gaming platform',\n      'services for betting operators',\n      'data platform for betting',\n      'official esports data',\n      'official game data'\n    ],\n    signals: [\n      'api integration',\n      'api documentation',\n      'operator dashboard',\n      'back office',\n      'backoffice',\n      'sportsbook engine',\n      'casino engine',\n      'wallet integration',\n      'kyc integration',\n      'payment gateway integration',\n      'risk management tools',\n      'multi brand',\n      'multi tenant',\n      'b2b igaming',\n      'operator clients',\n      'platform partners',\n      'integration partners'\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'association',\n      'affiliate',\n      'review site',\n      'investment firm',\n      'venture capital'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 3',\n    icpMarker: 'ICP 3 (CRM / Retention)',\n    segment: 'CRM / Retention',\n    minScore: 10,\n    core: [\n      'igaming crm',\n      'casino crm',\n      'sportsbook crm',\n      'gaming crm',\n      'player retention',\n      'player engagement',\n      'player lifecycle',\n      'loyalty platform',\n      'bonus engine',\n      'campaign management gaming',\n      'marketing automation casino',\n      'crm for igaming operators',\n      'retention platform for igaming'\n    ],\n    signals: [\n      'player segmentation',\n      'campaign automation',\n      'reward engine',\n      'real time triggers',\n      'event based messaging',\n      'player journeys',\n      'churn prevention',\n      'reactivation campaigns',\n      'retention campaigns',\n      'bonus management',\n      'multi channel messaging',\n      'push notifications',\n      'sms',\n      'email'\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'affiliate',\n      'review site',\n      'game provider',\n      'investment firm'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 4',\n    icpMarker: 'ICP 4 (iGaming Affiliates)',\n    segment: 'iGaming Affiliates',\n    minScore: 10,\n    core: [\n      'igaming affiliate',\n      'casino affiliate',\n      'sports betting affiliate',\n      'betting affiliate',\n      'gambling affiliate',\n      'online casino affiliate',\n      'affiliate network',\n      'affiliate program',\n      'casino comparison',\n      'casino reviews',\n      'sports betting reviews',\n      'betting reviews',\n      'bonus comparison',\n      'odds comparison',\n      'review site',\n      'comparison site',\n      'gambling media',\n      'igaming media',\n      'betting media'\n    ],\n    signals: [\n      'traffic acquisition',\n      'player acquisition',\n      'lead generation',\n      'cpa',\n      'revshare',\n      'revenue share',\n      'bonus codes',\n      'betting tips',\n      'operator reviews',\n      'bookmaker reviews',\n      'performance marketing'\n    ],\n    negative: [\n      'affiliate tracking software',\n      'affiliate management software',\n      'casino operator',\n      'sportsbook operator',\n      'platform provider',\n      'game provider',\n      'investment firm'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 5',\n    icpMarker: 'ICP 5 (Game / Slot Providers)',\n    segment: 'Game / Slot Providers',\n    minScore: 10,\n    core: [\n      'casino game provider',\n      'slot provider',\n      'slot game provider',\n      'slot developer',\n      'slot game developer',\n      'casino game developer',\n      'game content provider',\n      'casino content provider',\n      'online casino games',\n      'casino games',\n      'slot games',\n      'slots provider',\n      'igaming studio',\n      'live casino provider',\n      'live dealer provider',\n      'rng games',\n      'instant games',\n      'crash games',\n      'table games'\n    ],\n    signals: [\n      'game portfolio',\n      'slots portfolio',\n      'game catalog',\n      'casino content',\n      'html5 games',\n      'rng',\n      'random number generator',\n      'live dealer',\n      'blackjack',\n      'roulette',\n      'baccarat',\n      'provably fair',\n      'game mechanics',\n      'operator integration',\n      'regulated markets',\n      'certified games'\n    ],\n    negative: [\n      'casino operator',\n      'sportsbook operator',\n      'affiliate',\n      'review site',\n      'investment firm',\n      'venture capital'\n    ]\n  },\n\n  {\n    icpNumber: 'ICP 6',\n    icpMarker: 'ICP 6 (iGaming Investors)',\n    segment: 'iGaming Investors',\n    minScore: 10,\n    core: [\n      'igaming investor',\n      'gambling investor',\n      'casino investor',\n      'sports betting investor',\n      'gaming venture capital',\n      'betting investment',\n      'igaming investment',\n      'gambling investment',\n      'sports betting investment',\n      'casino investment',\n      'invests in igaming',\n      'invests in gambling',\n      'invests in sports betting',\n      'invests in casino'\n    ],\n    signals: [\n      'venture capital',\n      'vc fund',\n      'investment firm',\n      'private equity',\n      'family office',\n      'portfolio companies',\n      'investment portfolio',\n      'seed round',\n      'series a',\n      'growth capital',\n      'strategic investment',\n      'backed companies',\n      'portfolio includes'\n    ],\n    negative: [\n      'crypto broker',\n      'stocks',\n      'etfs',\n      'regulated broker',\n      'casino operator',\n      'sportsbook operator',\n      'platform provider',\n      'affiliate',\n      'review site',\n      'game studio'\n    ]\n  }\n];\n\n// --------------------------------------------------\n// Exa extraction\n// --------------------------------------------------\n\nfunction extractExaPayloads(json) {\n  const root = json?.body || json;\n\n  if (!root) return [];\n\n  if (Array.isArray(root)) return root;\n\n  if (Array.isArray(root.results)) return [root];\n\n  return [root];\n}\n\nfunction resultText(result) {\n  return cleanSummaryText([\n    result.title,\n    result.summary,\n    result.text,\n    Array.isArray(result.highlights) ? result.highlights.join(' ') : ''\n  ].join(' '));\n}\n\nfunction buildCompanyEvidence(payload) {\n  const results = Array.isArray(payload.results) ? payload.results : [];\n\n  const firstUsefulResult =\n    results.find(r => r?.url && !isLikelyUtilityPage(r.url, r.title)) ||\n    results[0] ||\n    {};\n\n  const inferredCompanyName =\n    payload.company_name ||\n    payload.name ||\n    extractCompanyNameFromTitle(firstUsefulResult.title) ||\n    '';\n\n  const officialDomain =\n    rootDomain(\n      payload.domain ||\n      payload.primary_domain ||\n      payload.website ||\n      payload.website_url ||\n      firstUsefulResult.url ||\n      ''\n    );\n\n  const officialResults = [];\n  const thirdPartyResults = [];\n  const ignoredResults = [];\n\n  for (const result of results) {\n    const domain = rootDomain(result.url || result.id || '');\n\n    const isOfficial =\n      officialDomain &&\n      domain &&\n      domain === officialDomain;\n\n    const isUtility = isLikelyUtilityPage(result.url, result.title);\n\n    const row = {\n      title: result.title || '',\n      url: result.url || result.id || '',\n      domain,\n      text: resultText(result),\n      summary: result.summary || ''\n    };\n\n    if (isUtility) {\n      ignoredResults.push(row);\n    } else if (isOfficial) {\n      officialResults.push(row);\n    } else {\n      thirdPartyResults.push(row);\n    }\n  }\n\n  const officialText = cleanSummaryText(\n    officialResults.map(r => r.text).join(' '),\n    30000\n  );\n\n  const thirdPartyText = cleanSummaryText(\n    thirdPartyResults.map(r => r.text).join(' '),\n    12000\n  );\n\n  const ignoredText = cleanSummaryText(\n    ignoredResults.map(r => r.text).join(' '),\n    5000\n  );\n\n  const companySummary = cleanSummaryText(\n    [\n      `Company: ${inferredCompanyName}`,\n      `Official domain: ${officialDomain}`,\n      officialResults.slice(0, 3).map(r => r.summary || r.text).join(' ')\n    ].join(' '),\n    6000\n  );\n\n  return {\n    inferredCompanyName,\n    officialDomain,\n    officialResults,\n    thirdPartyResults,\n    ignoredResults,\n    companySummary,\n    officialText,\n    thirdPartyText,\n    ignoredText,\n    strongText: cleanSummaryText([companySummary, officialText].join(' '), 35000),\n    weakText: cleanSummaryText(thirdPartyText, 12000),\n    allText: cleanSummaryText([companySummary, officialText, thirdPartyText].join(' '), 45000)\n  };\n}\n\n// --------------------------------------------------\n// Classification\n// --------------------------------------------------\n\nfunction detectNonTargetBusinessModel(evidence) {\n  const strongText = evidence.strongText;\n  const weakText = evidence.weakText;\n  const allText = evidence.allText;\n\n  const matches = [];\n\n  for (const group of NON_TARGET_EXCLUSION_GROUPS) {\n    const strongMatches = findTerms(strongText, group.terms);\n    const weakMatches = findTerms(weakText, group.terms);\n\n    const score =\n      strongMatches.length * 2 +\n      weakMatches.length;\n\n    if (score >= 2) {\n      matches.push({\n        label: group.label,\n        score,\n        strongMatches,\n        weakMatches\n      });\n    }\n  }\n\n  matches.sort((a, b) => b.score - a.score);\n\n  const iGamingMatches = findTerms(strongText, IGAMING_CONTEXT_TERMS);\n\n  return {\n    hasNonTargetBusinessModel: matches.length > 0,\n    topNonTargetModel: matches[0] || null,\n    allNonTargetMatches: matches,\n    iGamingMatches\n  };\n}\n\nfunction classifyIcp(evidence) {\n  const strongText = evidence.strongText;\n  const weakText = evidence.weakText;\n  const allText = evidence.allText;\n\n  const iGamingContextStrong = findTerms(strongText, IGAMING_CONTEXT_TERMS);\n  const iGamingContextWeak = findTerms(weakText, IGAMING_CONTEXT_TERMS);\n\n  const nonTarget = detectNonTargetBusinessModel(evidence);\n\n  // Hard stop: fully unrelated companies should not classify.\n  if (iGamingContextStrong.length === 0) {\n    return {\n      target_icp_marker: 'Not Classified',\n      target_icp_number: '',\n      target_icp_name: 'Not Classified',\n      icp_segment: 'Not Classified',\n      classification_confidence: 'Low',\n      classification_score: 0,\n      classification_reason:\n        'No strong iGaming, casino, gambling, sportsbook, betting, lottery, or real-money gaming context was found in official Exa evidence.',\n      strict_gate_passed: false,\n      non_target_business_model: nonTarget.topNonTargetModel?.label || '',\n      mandatory_context_match: iGamingContextWeak.join(', '),\n      matched_core_keywords: '',\n      product_signal_match: '',\n      negative_signal_match: '',\n      needs_manual_review: false,\n      _debug_evidence: DEBUG_EVIDENCE ? { nonTarget, iGamingContextStrong, iGamingContextWeak } : undefined\n    };\n  }\n\n  // Hard stop: Rombet-style association / regulatory / member organization.\n  if (\n    nonTarget.topNonTargetModel &&\n    nonTarget.topNonTargetModel.label === 'Association / Regulatory Body'\n  ) {\n    return {\n      target_icp_marker: 'Not Classified',\n      target_icp_number: '',\n      target_icp_name: 'Not Classified',\n      icp_segment: 'Not Classified',\n      classification_confidence: 'Low',\n      classification_score: 0,\n      classification_reason:\n        `Strong iGaming context was found, but the company appears to be an association, regulatory body, or member organization rather than a direct target ICP. Matched: ${nonTarget.topNonTargetModel.strongMatches.join(', ')}.`,\n      strict_gate_passed: false,\n      non_target_business_model: nonTarget.topNonTargetModel.label,\n      mandatory_context_match: iGamingContextStrong.join(', '),\n      matched_core_keywords: '',\n      product_signal_match: '',\n      negative_signal_match: '',\n      needs_manual_review: true,\n      _debug_evidence: DEBUG_EVIDENCE ? { nonTarget, iGamingContextStrong, iGamingContextWeak } : undefined\n    };\n  }\n\n  const results = ICP_DEFINITIONS.map(segment => {\n    const strongCore = findTerms(strongText, segment.core);\n    const weakCore = findTerms(weakText, segment.core);\n\n    const strongSignals = findTerms(strongText, segment.signals);\n    const weakSignals = findTerms(weakText, segment.signals);\n\n    const strongNegative = findTerms(strongText, segment.negative);\n    const weakNegative = findTerms(weakText, segment.negative);\n\n    let score = 0;\n\n    score += strongCore.length * 7;\n    score += weakCore.length * 2;\n    score += strongSignals.length * 4;\n    score += weakSignals.length * 1;\n    score -= strongNegative.length * 5;\n    score -= weakNegative.length * 2;\n\n    // Segment-specific extra precision rules.\n    const hasStrongCore = strongCore.length > 0;\n    const hasStrongSignal = strongSignals.length > 0;\n\n    let segmentGatePassed = hasStrongCore;\n\n    // Investors must have explicit iGaming/gambling/betting investment language.\n    if (segment.icpNumber === 'ICP 6') {\n      const investorSpecificContext = findTerms(strongText, [\n        'igaming investment',\n        'gambling investment',\n        'sports betting investment',\n        'casino investment',\n        'igaming investor',\n        'gambling investor',\n        'sports betting investor',\n        'casino investor',\n        'invests in igaming',\n        'invests in gambling',\n        'invests in sports betting',\n        'invests in casino'\n      ]);\n\n      segmentGatePassed = investorSpecificContext.length > 0;\n    }\n\n    // Affiliates must be iGaming-specific, not generic affiliate marketing.\n    if (segment.icpNumber === 'ICP 4') {\n      const affiliateSpecificContext = findTerms(strongText, [\n        'igaming affiliate',\n        'casino affiliate',\n        'sports betting affiliate',\n        'betting affiliate',\n        'gambling affiliate',\n        'casino reviews',\n        'sports betting reviews',\n        'betting reviews',\n        'casino comparison',\n        'bonus comparison',\n        'odds comparison'\n      ]);\n\n      segmentGatePassed = affiliateSpecificContext.length > 0;\n    }\n\n    // Operators need either strong operator core OR multiple player/product signals.\n    if (segment.icpNumber === 'ICP 1') {\n      segmentGatePassed =\n        hasStrongCore ||\n        strongSignals.length >= 3;\n    }\n\n    if (!segmentGatePassed) {\n      score = 0;\n    }\n\n    score = Math.max(0, score);\n\n    return {\n      ...segment,\n      score,\n      strongCore,\n      weakCore,\n      strongSignals,\n      weakSignals,\n      strongNegative,\n      weakNegative,\n      segmentGatePassed\n    };\n  }).sort((a, b) => b.score - a.score);\n\n  const best = results[0];\n  const second = results[1];\n\n  if (!best || best.score < best.minScore || !best.segmentGatePassed) {\n    return {\n      target_icp_marker: 'Not Classified',\n      target_icp_number: '',\n      target_icp_name: 'Not Classified',\n      icp_segment: 'Not Classified',\n      classification_confidence: 'Low',\n      classification_score: 0,\n      classification_reason:\n        'Mandatory iGaming context was found, but no ICP segment had enough strong official evidence to classify safely.',\n      strict_gate_passed: true,\n      non_target_business_model: nonTarget.topNonTargetModel?.label || '',\n      mandatory_context_match: iGamingContextStrong.join(', '),\n      matched_core_keywords: '',\n      product_signal_match: '',\n      negative_signal_match: '',\n      needs_manual_review: true,\n      second_best_segment: second?.icpMarker || '',\n      second_best_score: second?.score || 0,\n      _all_scores: Object.fromEntries(results.map(r => [r.icpMarker, r.score])),\n      _debug_evidence: DEBUG_EVIDENCE ? { results, nonTarget, iGamingContextStrong, iGamingContextWeak } : undefined\n    };\n  }\n\n  const scoreGap = best.score - (second?.score || 0);\n\n  const needsManualReview =\n    best.score < 18 ||\n    scoreGap < 5 ||\n    best.strongCore.length === 1 && best.strongSignals.length === 0;\n\n  let confidence = 'Low';\n\n  if (!needsManualReview && best.score >= 24 && scoreGap >= 8) {\n    confidence = 'High';\n  } else if (best.score >= 14 && scoreGap >= 4) {\n    confidence = 'Medium';\n  }\n\n  const reasonParts = [\n    `Matched ${best.icpMarker}`,\n    `mandatory context: ${iGamingContextStrong.slice(0, 6).join(', ')}`,\n    `strong core: ${best.strongCore.slice(0, 6).join(', ') || 'none'}`,\n    `strong signals: ${best.strongSignals.slice(0, 6).join(', ') || 'none'}`\n  ];\n\n  if (best.strongNegative.length > 0) {\n    reasonParts.push(`negative signals considered: ${best.strongNegative.slice(0, 4).join(', ')}`);\n  }\n\n  if (needsManualReview) {\n    reasonParts.push('manual review recommended because evidence is not strong enough for automatic update');\n  }\n\n  return {\n    target_icp_marker: best.icpMarker,\n    target_icp_number: best.icpNumber,\n    target_icp_name: best.segment,\n    icp_segment: best.icpMarker,\n    classification_confidence: confidence,\n    classification_score: best.score,\n    classification_reason: reasonParts.join('; ') + '.',\n\n    strict_gate_passed: true,\n    non_target_business_model: nonTarget.topNonTargetModel?.label || '',\n    mandatory_context_match: iGamingContextStrong.join(', '),\n    matched_core_keywords: best.strongCore.join(', '),\n    product_signal_match: best.strongSignals.join(', '),\n    negative_signal_match: best.strongNegative.join(', '),\n\n    needs_manual_review: needsManualReview,\n    second_best_segment: second?.icpMarker || '',\n    second_best_score: second?.score || 0,\n    _all_scores: Object.fromEntries(results.map(r => [r.icpMarker, r.score])),\n    _debug_evidence: DEBUG_EVIDENCE ? { results, nonTarget, iGamingContextStrong, iGamingContextWeak } : undefined\n  };\n}\n\n// --------------------------------------------------\n// Main execution\n// --------------------------------------------------\n\nconst output = [];\n\nfor (const item of $input.all()) {\n  const payloads = extractExaPayloads(item.json);\n\n  for (const payload of payloads) {\n    const evidence = buildCompanyEvidence(payload);\n    const classification = classifyIcp(evidence);\n\n    output.push({\n      json: {\n        source_system: 'Exa',\n        classification_version: CLASSIFICATION_VERSION,\n\n        request_id: payload.requestId || payload.request_id || '',\n        company_name: evidence.inferredCompanyName,\n        domain: evidence.officialDomain,\n\n        official_result_count: evidence.officialResults.length,\n        third_party_result_count: evidence.thirdPartyResults.length,\n        ignored_result_count: evidence.ignoredResults.length,\n\n        company_summary: evidence.companySummary,\n        official_text_sample: evidence.officialText.slice(0, 1200),\n        third_party_text_sample: evidence.weakText.slice(0, 800),\n\n        ...classification,\n\n        hubspot_update_properties: {\n          target_icp_marker: classification.target_icp_marker,\n          target_icp_number: classification.target_icp_number,\n          target_icp_name: classification.target_icp_name,\n          icp_segment: classification.icp_segment,\n\n          icp_confidence: classification.classification_confidence,\n          icp_score: classification.classification_score,\n          icp_reason: classification.classification_reason,\n\n          icp_strict_gate_passed: classification.strict_gate_passed ? 'true' : 'false',\n          icp_mandatory_context: classification.mandatory_context_match,\n          icp_core_keywords: classification.matched_core_keywords,\n          icp_product_signals: classification.product_signal_match,\n          icp_negative_signals: classification.negative_signal_match,\n          icp_needs_manual_review: classification.needs_manual_review ? 'true' : 'false',\n\n          icp_non_target_business_model: classification.non_target_business_model,\n          icp_last_classified_at: new Date().toISOString(),\n          icp_classification_version: CLASSIFICATION_VERSION\n        }\n      }\n    });\n  }\n}\n\nreturn output;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1120,
        2048
      ],
      "id": "11eb1b62-7805-40ec-994f-308fba795ad7",
      "name": "Code in JavaScript3"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "sheetName": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "defineBelow",
          "value": {
            "company_summary": "={{ $json.company_summary }}",
            "target_icp_marker": "={{ $json.target_icp_marker }}",
            "target_icp_number": "={{ $json.target_icp_number }}",
            "target_icp_name": "={{ $json.target_icp_name }}",
            "icp_segment": "={{ $json.icp_segment }}",
            "classification_confidence": "={{ $json.classification_confidence }}",
            "classification_score": "={{ $json.classification_score }}",
            "company_name": "={{ $json.company_name }}",
            "classification_reason": "={{ $json.classification_reason }}"
          },
          "matchingColumns": [],
          "schema": [
            {
              "id": "company_summary",
              "displayName": "company_summary",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_marker",
              "displayName": "target_icp_marker",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_number",
              "displayName": "target_icp_number",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_name",
              "displayName": "target_icp_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "icp_segment",
              "displayName": "icp_segment",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "keyword_match_group",
              "displayName": "keyword_match_group",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_confidence",
              "displayName": "classification_confidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_score",
              "displayName": "classification_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_reason",
              "displayName": "classification_reason",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "matched_core_keywords",
              "displayName": "matched_core_keywords",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "product_signal_match",
              "displayName": "product_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "supporting_industry_match",
              "displayName": "supporting_industry_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "negative_signal_match",
              "displayName": "negative_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "hard_exclusion_match",
              "displayName": "hard_exclusion_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "needs_manual_review",
              "displayName": "needs_manual_review",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "second_best_segment",
              "displayName": "second_best_segment",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "second_best_score",
              "displayName": "second_best_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "strict_gate_passed",
              "displayName": "strict_gate_passed",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "mandatory_context_match",
              "displayName": "mandatory_context_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "classification_version",
              "displayName": "classification_version",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "company_summary_detected_model",
              "displayName": "company_summary_detected_model",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "company_summary_suggested_icp",
              "displayName": "company_summary_suggested_icp",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "company_summary_confidence",
              "displayName": "company_summary_confidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "_all_scores",
              "displayName": "_all_scores",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "_debug_evidence",
              "displayName": "_debug_evidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "hubspot_update_properties",
              "displayName": "hubspot_update_properties",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "target_icp_analysis",
              "displayName": "target_icp_analysis",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "hubspot_id",
              "displayName": "hubspot_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "company_id",
              "displayName": "company_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "source_system",
              "displayName": "source_system",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "request_id",
              "displayName": "request_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "company_name",
              "displayName": "company_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "domain",
              "displayName": "domain",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "official_result_count",
              "displayName": "official_result_count",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "third_party_result_count",
              "displayName": "third_party_result_count",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "ignored_result_count",
              "displayName": "ignored_result_count",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "official_text_sample",
              "displayName": "official_text_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "third_party_text_sample",
              "displayName": "third_party_text_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            },
            {
              "id": "non_target_business_model",
              "displayName": "non_target_business_model",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "useAppend": true
        }
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        1344,
        2048
      ],
      "id": "38d77f9a-7707-466a-a4ef-3635eb47a113",
      "name": "Append row in sheet6"
    },
    {
      "parameters": {
        "operation": "append",
        "documentId": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "sheetName": {
          "__rl": true,
          "value": "",
          "mode": "list"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [],
          "schema": [
            {
              "id": "source_system",
              "displayName": "source_system",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_version",
              "displayName": "classification_version",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "apollo_id",
              "displayName": "apollo_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "apollo_account_id",
              "displayName": "apollo_account_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "hubspot_id",
              "displayName": "hubspot_id",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "company_name",
              "displayName": "company_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "domain",
              "displayName": "domain",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "website",
              "displayName": "website",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "linkedin_url",
              "displayName": "linkedin_url",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "country",
              "displayName": "country",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "city",
              "displayName": "city",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "estimated_num_employees",
              "displayName": "estimated_num_employees",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "annual_revenue",
              "displayName": "annual_revenue",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "annual_revenue_printed",
              "displayName": "annual_revenue_printed",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "latest_funding_stage",
              "displayName": "latest_funding_stage",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "latest_funding_round_date",
              "displayName": "latest_funding_round_date",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_industry",
              "displayName": "source_industry",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_industries",
              "displayName": "source_industries",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_secondary_industries",
              "displayName": "source_secondary_industries",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_keywords_sample",
              "displayName": "source_keywords_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "source_technologies_sample",
              "displayName": "source_technologies_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "exa_title_sample",
              "displayName": "exa_title_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "exa_summary_sample",
              "displayName": "exa_summary_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "exa_text_sample",
              "displayName": "exa_text_sample",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_marker",
              "displayName": "target_icp_marker",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_number",
              "displayName": "target_icp_number",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "target_icp_name",
              "displayName": "target_icp_name",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "icp_segment",
              "displayName": "icp_segment",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "keyword_match_group",
              "displayName": "keyword_match_group",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_confidence",
              "displayName": "classification_confidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_score",
              "displayName": "classification_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "classification_reason",
              "displayName": "classification_reason",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strict_gate_passed",
              "displayName": "strict_gate_passed",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "mandatory_context_match",
              "displayName": "mandatory_context_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strong_mandatory_context_match",
              "displayName": "strong_mandatory_context_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "weak_mandatory_context_match",
              "displayName": "weak_mandatory_context_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "matched_core_keywords",
              "displayName": "matched_core_keywords",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strong_core_keywords",
              "displayName": "strong_core_keywords",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "product_signal_match",
              "displayName": "product_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "strong_product_signal_match",
              "displayName": "strong_product_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "supporting_industry_match",
              "displayName": "supporting_industry_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "negative_signal_match",
              "displayName": "negative_signal_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "hard_exclusion_match",
              "displayName": "hard_exclusion_match",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "needs_manual_review",
              "displayName": "needs_manual_review",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "second_best_segment",
              "displayName": "second_best_segment",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "second_best_score",
              "displayName": "second_best_score",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "_all_scores",
              "displayName": "_all_scores",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "_debug_evidence",
              "displayName": "_debug_evidence",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            },
            {
              "id": "hubspot_update_properties",
              "displayName": "hubspot_update_properties",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true,
              "removed": false
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.7,
      "position": [
        2016,
        2432
      ],
      "id": "e7ed9734-9df0-4f13-b5c1-ab25b7e0ba5e",
      "name": "Append row in sheet7"
    },
    {
      "parameters": {
        "authentication": "appToken",
        "resource": "company",
        "operation": "update",
        "companyId": {
          "__rl": true,
          "value": "={{ $('Website Filter (Hubspot)1').item.json.companyId }}",
          "mode": "id"
        },
        "updateFields": {
          "customPropertiesUi": {
            "customPropertiesValues": [
              {
                "property": "target_icp",
                "value": "={{ $json.target_icp_marker }}"
              },
              {
                "property": "processing_icp",
                "value": "true"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.2,
      "position": [
        1792,
        2048
      ],
      "id": "3fffed75-7194-4c1f-80fb-21cbba44b741",
      "name": "Update a company5"
    },
    {
      "parameters": {
        "authentication": "appToken",
        "resource": "company",
        "operation": "update",
        "companyId": {
          "__rl": true,
          "value": "={{ $('If5').item.json.hubspot_id }}",
          "mode": "id"
        },
        "updateFields": {
          "customPropertiesUi": {
            "customPropertiesValues": [
              {
                "property": "target_icp",
                "value": "={{ $('Code in JavaScript2').item.json.target_icp_marker }}"
              },
              {
                "property": "processing_icp",
                "value": "true"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.2,
      "position": [
        2464,
        2432
      ],
      "id": "d31bc944-2643-464b-a0cb-b58bf5cf9e80",
      "name": "Update a company6"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "873bde39-a5cd-4d21-8fd9-127c7c025ccf",
              "leftValue": "={{ $('If5').item.json.hubspot_id }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.3,
      "position": [
        2240,
        2432
      ],
      "id": "18740832-fbe2-4fe4-8b75-fcfd2ed75b9f",
      "name": "Filter3"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "19949893-4765-4aea-b4b3-e398bf6b111f",
              "leftValue": "",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "equals",
                "name": "filter.operator.equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.3,
      "position": [
        1568,
        2048
      ],
      "id": "867b2e22-ec96-4315-8038-9f4d8125f317",
      "name": "Filter4"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.hubapi.com/crm/v3/objects/companies/search",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "hubspotAppToken",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "{\n  \"filterGroups\": [\n    {\n      \"filters\": [\n        {\n          \"propertyName\": \"target_icp\",\n          \"operator\": \"NOT_HAS_PROPERTY\"\n        },\n        {\n          \"propertyName\": \"domain\",\n          \"operator\": \"HAS_PROPERTY\"\n        },\n        {\n          \"propertyName\": \"processing_icp\",\n          \"operator\": \"NOT_HAS_PROPERTY\"\n        }\n      ]\n    },\n    {\n      \"filters\": [\n        {\n          \"propertyName\": \"target_icp\",\n          \"operator\": \"NOT_HAS_PROPERTY\"\n        },\n        {\n          \"propertyName\": \"domain\",\n          \"operator\": \"HAS_PROPERTY\"\n        },\n        {\n          \"propertyName\": \"processing_icp\",\n          \"operator\": \"EQ\",\n          \"value\": \"false\"\n        }\n      ]\n    }\n  ],\n  \"properties\": [\n    \"hs_object_id\",\n    \"createdate\",\n    \"name\",\n    \"domain\",\n    \"website\",\n    \"linkedin_company_page\",\n    \"hs_is_enriched\",\n    \"target_icp\",\n    \"processing_icp\",\n    \"icp_classification_version\",\n    \"icp_last_classified_at\",\n    \"icp_needs_manual_review\",\n    \"icp_processing_status\"\n  ],\n  \"sorts\": [\n    {\n      \"propertyName\": \"createdate\",\n      \"direction\": \"ASCENDING\"\n    }\n  ],\n  \"limit\": 10\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        -1792,
        2144
      ],
      "id": "8195a7e6-6efd-4922-bfd5-96a5b90c7ff9",
      "name": "Hubspot Get Companies (Not Classified)",
      "executeOnce": false
    },
    {
      "parameters": {
        "fieldToSplitOut": "results",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        -1568,
        2144
      ],
      "id": "74f4149d-bc21-428e-a111-a2cea11851b1",
      "name": "Split Out1"
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "35c6123d-f092-4323-bafc-d84591bab00c",
              "leftValue": "={{ $json.Website }}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.filter",
      "typeVersion": 2.3,
      "position": [
        1344,
        2432
      ],
      "id": "6e04de50-fec1-4542-983f-e4cf6b1c6a72",
      "name": "Filter5"
    },
    {
      "parameters": {
        "authentication": "appToken",
        "resource": "company",
        "operation": "update",
        "companyId": {
          "__rl": true,
          "value": "={{ $json.id }}",
          "mode": "id"
        },
        "updateFields": {
          "customPropertiesUi": {
            "customPropertiesValues": [
              {
                "property": "processing_icp",
                "value": "true"
              }
            ]
          }
        }
      },
      "type": "n8n-nodes-base.hubspot",
      "typeVersion": 2.2,
      "position": [
        -1344,
        2144
      ],
      "id": "5a108cdf-de18-4d17-a123-5da64c5334b9",
      "name": "Update a company7"
    },
    {
      "parameters": {
        "url": "https://search.uptune.io/search",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $('Split Out1').item.json.properties.website }}"
            },
            {
              "name": "format",
              "value": "json"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [
        -448,
        2336
      ],
      "id": "e59c327c-1d59-48f6-8cc5-aa89879deb36",
      "name": "HTTP Request5",
      "retryOnFail": true,
      "maxTries": 5,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "url": "https://search.uptune.io/search",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $json.Website }}"
            },
            {
              "name": "format",
              "value": "json"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [
        1568,
        2432
      ],
      "id": "54af9c76-72ec-4fdd-b0d0-5f9053e87b23",
      "name": "HTTP Request6",
      "retryOnFail": true,
      "maxTries": 5,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "url": "https://search.uptune.io/search",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "q",
              "value": "={{ $('Split Out1').item.json.properties.website }}"
            },
            {
              "name": "format",
              "value": "json"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.5,
      "position": [
        -448,
        1952
      ],
      "id": "83354747-31a3-47fb-8707-643515d40969",
      "name": "HTTP Request7",
      "retryOnFail": true,
      "maxTries": 5,
      "waitBetweenTries": 5000
    },
    {
      "parameters": {
        "query": "={{ $json.query }}",
        "searchType": "=auto",
        "numResults": 3,
        "contents": {},
        "options": {}
      },
      "type": "n8n-nodes-exa-official.exa",
      "typeVersion": 2,
      "position": [
        -224,
        2336
      ],
      "id": "c419267e-88cf-4c8a-975f-86879b741c50",
      "name": "Search the web"
    }
  ],
  "pinData": {
    "⏰ Schedule Trigger1": [
      {
        "json": {
          "timestamp": "2026-07-04T08:10:36.006+00:00",
          "Readable date": "July 4th 2026, 8:10:36 am",
          "Readable time": "8:10:36 am",
          "Day of week": "Saturday",
          "Year": "2026",
          "Month": "July",
          "Day of month": "04",
          "Hour": "08",
          "Minute": "10",
          "Second": "36",
          "Timezone": "UTC (UTC+00:00)"
        },
        "pairedItem": {
          "item": 0
        }
      }
    ]
  },
  "connections": {
    "⏰ Schedule Trigger1": {
      "main": [
        [
          {
            "node": "Hubspot Get Companies (Not Classified)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get a company1": {
      "main": [
        [
          {
            "node": "If3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If3": {
      "main": [
        [
          {
            "node": "Website Filter (Hubspot)1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Website Filter (Apollo)1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request4": {
      "main": [
        [
          {
            "node": "Classify ICP (Apollo)1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify ICP (Apollo)1": {
      "main": [
        [
          {
            "node": "Append row in sheet5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Classify ICP (Hubspot)1": {
      "main": [
        [
          {
            "node": "Append row in sheet4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet4": {
      "main": [
        [
          {
            "node": "If4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet5": {
      "main": [
        [
          {
            "node": "If5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Website Filter (Apollo)1": {
      "main": [
        [
          {
            "node": "HTTP Request5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "EXA Summary Cleanup (Hubspot)1": {
      "main": [
        [
          {
            "node": "Classify ICP (Hubspot)1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "EXA Summary Cleanup (Apollo)1": {
      "main": [
        [
          {
            "node": "HTTP Request4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Website Filter (Hubspot)1": {
      "main": [
        [
          {
            "node": "HTTP Request7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If4": {
      "main": [
        [
          {
            "node": "Update a company4",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Insert row2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If5": {
      "main": [
        [
          {
            "node": "Update a company (Apollo)1",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Insert row3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert row2": {
      "main": [
        [
          {
            "node": "Search the web1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert row3": {
      "main": [
        [
          {
            "node": "Filter5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search the web1": {
      "main": [
        [
          {
            "node": "Code in JavaScript3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript2": {
      "main": [
        [
          {
            "node": "Append row in sheet7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript3": {
      "main": [
        [
          {
            "node": "Append row in sheet6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet6": {
      "main": [
        [
          {
            "node": "Filter4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append row in sheet7": {
      "main": [
        [
          {
            "node": "Filter3",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter3": {
      "main": [
        [
          {
            "node": "Update a company6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter4": {
      "main": [
        [
          {
            "node": "Update a company5",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Hubspot Get Companies (Not Classified)": {
      "main": [
        [
          {
            "node": "Split Out1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out1": {
      "main": [
        [
          {
            "node": "Update a company7",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter5": {
      "main": [
        [
          {
            "node": "HTTP Request6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update a company7": {
      "main": [
        [
          {
            "node": "Get a company1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request5": {
      "main": [
        [
          {
            "node": "Search the web",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request6": {
      "main": [
        [
          {
            "node": "Code in JavaScript2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTTP Request7": {
      "main": [
        [
          {
            "node": "EXA Summary Cleanup (Hubspot)1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Search the web": {
      "main": [
        [
          {
            "node": "EXA Summary Cleanup (Apollo)1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": true,
    "timeSavedMode": "fixed",
    "callerPolicy": "workflowsFromSameOwner"
  },
  "nodeGroups": [],
  "tags": []
}