Berlin Tech Meetup: The Future of Relational Foundation Models, Systems, and Real-World Applications

Register now:
PyG/Use Case11 min read

Lead Scoring: HeteroConv on B2B CRM Graphs

Sales teams waste 50% of their time on leads that never convert. Traditional scoring uses individual lead attributes. Here is how to build a GNN that scores leads using the full CRM graph: account relationships, engagement patterns, and industry signals.

PyTorch Geometric

TL;DR

  • 1B2B lead scoring is a graph classification problem. Leads exist in context: their company, colleagues, engagement history, and industry peers all carry predictive signal.
  • 2HeteroConv models the heterogeneous CRM schema (contacts, companies, activities, opportunities) with type-specific transformations per relationship type.
  • 3On RelBench benchmarks, GNNs achieve 75.83 AUROC vs 62.44 for flat-table LightGBM. Account-level and industry-level signals drive the improvement.
  • 4The PyG model is ~35 lines, but integrating with Salesforce/HubSpot, maintaining real-time scoring, and handling CRM data quality add significant engineering.
  • 5KumoRFM scores leads with one PQL query (76.71 AUROC zero-shot), connecting directly to your CRM and capturing account-level buying signals automatically.

The business problem

B2B sales teams spend 50% of their time on leads that never convert. With average deal sizes of $25K-$500K and sales cycles of 3-12 months, misallocating rep time is extraordinarily expensive. A good lead scoring model routes the right leads to the right reps at the right time, directly increasing pipeline velocity and close rates.

Traditional lead scoring assigns points based on individual attributes: job title (+10), company size >1000 (+15), downloaded whitepaper (+5). These rules are static, manually maintained, and ignore the relational context. A VP of Engineering at a company where three other employees already use your product is fundamentally different from a VP at a greenfield account, but both score the same.

Why flat ML fails

  • No account context: A lead is part of a buying committee. Multiple engaged contacts at the same account is a much stronger signal than one engaged contact. Flat models see each lead independently.
  • No industry signal: When a category leader adopts your product, their competitors often follow. This peer-influence pattern is a graph signal.
  • No champion detection: The “champion” (internal advocate) is often not the decision-maker. GNNs can identify champion patterns by looking at engagement depth across the account graph.
  • Temporal blindness: Engagement velocity (3 meetings in 2 weeks vs 3 meetings in 6 months) is a critical signal that flat features compress into a single count.

The relational schema

schema.txt
Node types:
  Contact    (id, title, department, seniority)
  Company    (id, industry, size, revenue, tech_stack)
  Activity   (id, type, timestamp, duration, sentiment)
  Opportunity (id, stage, amount, close_date)

Edge types:
  Contact   --[works_at]-->     Company
  Contact   --[had_activity]--> Activity  (timestamp)
  Activity  --[related_to]-->   Opportunity
  Company   --[industry_peer]--> Company
  Company   --[similar_to]-->   Company  (tech_overlap)

Four node types capture the full B2B context: who the lead is, where they work, what they've done, and how their company relates to your existing customers.

PyG architecture: HeteroConv for CRM data

lead_scoring_model.py
import torch
import torch.nn.functional as F
from torch_geometric.nn import HeteroConv, SAGEConv, Linear

class LeadScoringGNN(torch.nn.Module):
    def __init__(self, hidden_dim=64):
        super().__init__()
        self.contact_lin = Linear(-1, hidden_dim)
        self.company_lin = Linear(-1, hidden_dim)
        self.activity_lin = Linear(-1, hidden_dim)
        self.opp_lin = Linear(-1, hidden_dim)

        self.conv1 = HeteroConv({
            ('contact', 'works_at', 'company'): SAGEConv(
                hidden_dim, hidden_dim),
            ('contact', 'had_activity', 'activity'): SAGEConv(
                hidden_dim, hidden_dim),
            ('activity', 'related_to', 'opportunity'): SAGEConv(
                hidden_dim, hidden_dim),
            ('company', 'industry_peer', 'company'): SAGEConv(
                hidden_dim, hidden_dim),
        }, aggr='sum')

        self.conv2 = HeteroConv({
            ('contact', 'works_at', 'company'): SAGEConv(
                hidden_dim, hidden_dim),
            ('contact', 'had_activity', 'activity'): SAGEConv(
                hidden_dim, hidden_dim),
            ('activity', 'related_to', 'opportunity'): SAGEConv(
                hidden_dim, hidden_dim),
            ('company', 'industry_peer', 'company'): SAGEConv(
                hidden_dim, hidden_dim),
        }, aggr='sum')

        self.classifier = torch.nn.Sequential(
            Linear(hidden_dim, 32),
            torch.nn.ReLU(),
            Linear(32, 1),
        )

    def forward(self, x_dict, edge_index_dict):
        x_dict['contact'] = self.contact_lin(x_dict['contact'])
        x_dict['company'] = self.company_lin(x_dict['company'])
        x_dict['activity'] = self.activity_lin(x_dict['activity'])
        x_dict['opportunity'] = self.opp_lin(x_dict['opportunity'])

        x_dict = {k: F.relu(v) for k, v in
                  self.conv1(x_dict, edge_index_dict).items()}
        x_dict = self.conv2(x_dict, edge_index_dict)

        return torch.sigmoid(
            self.classifier(x_dict['contact']).squeeze(-1))

HeteroConv with SAGEConv per edge type. Two hops let each contact aggregate company context, industry signals, and engagement patterns from colleagues.

Training considerations

  • Label definition: Define conversion as “opportunity created within 90 days” or “closed-won within 180 days.” The choice depends on your sales cycle length.
  • CRM data quality: CRM data is notoriously incomplete. Missing activities, outdated contacts, and duplicate companies degrade model performance. Clean data before building the graph.
  • Temporal leakage: Only use activities and opportunities that occurred before the prediction date. Future engagement is not available at scoring time.
  • Class balance: B2B conversion rates are typically 1-5%. Use focal loss or weighted sampling to handle the imbalance.

Expected performance

  • Rule-based scoring: ~50 AUROC
  • LightGBM (flat-table): 62.44 AUROC
  • GNN (HeteroConv): 75.83 AUROC
  • KumoRFM (zero-shot): 76.71 AUROC

Or use KumoRFM in one line

KumoRFM PQL
PREDICT will_convert FOR contact
USING contact, company, activity, opportunity

One PQL query. KumoRFM connects to your CRM, constructs the heterogeneous graph, and scores every lead with account-level context.

KumoRFM replaces graph construction, feature engineering, model training, and CRM data cleaning with a single query. It captures account-level buying signals, industry peer influence, and engagement velocity automatically.

Frequently asked questions

Why use GNNs for lead scoring instead of traditional scoring models?

Traditional lead scoring uses individual lead attributes (title, company size, engagement score). GNNs see the lead in context: their company's existing relationship with you, their colleagues who already converted, their industry peers' adoption patterns. A VP at a company where three directors already use your product is a very different lead than a VP at a greenfield account.

What CRM data feeds the lead scoring graph?

Contacts, companies, opportunities, activities (emails, meetings, demos), and product usage data. The graph connects contacts to their companies, companies to their industry peers, contacts to activities, and activities to opportunities. Each connection adds predictive signal.

How does the graph capture account-level buying signals?

Multiple contacts at the same company aggregate into an account-level signal through message passing. If a company has 5 contacts who attended webinars and 2 who requested demos, the GNN propagates this engagement pattern to the account node, making all contacts at that account score higher.

Can GNN lead scoring work with sparse CRM data?

Yes. GNNs are especially valuable with sparse data because they borrow signal from the network. A new contact with no engagement history can still score well if their company, title, and industry match patterns of past converters. The graph provides context that individual features cannot.

How does KumoRFM improve B2B lead scoring?

KumoRFM connects directly to your CRM database, auto-constructs the contact-company-activity graph, and predicts conversion probability with one PQL query. It captures account-level signals, industry patterns, and temporal engagement trends without manual feature engineering.

Learn more about graph ML

PyTorch Geometric is the open-source foundation for graph neural networks. Explore more layers, concepts, and production patterns.