A 20-person UK SaaS company had been filtering their outbound list by ICP score for 18 months. The score weighted industry vertical, headcount range, and technology stack. Their reps called top-score contacts first. When we pulled their closed-won data for the last 12 months, the top ICP quartile had produced 29% of ARR. The second quartile had produced 51%. ICP score was measuring fit — how closely a prospect matched a profile. It was not measuring close likelihood — how likely a specific prospect was to buy given their behaviour and timing. Those are different models, and the difference was costing the team roughly £200,000 in misallocated calling time per year.
ICP score vs predictive close score: fit and likelihood are different variables, and conflating them wastes rep time
ICP scoring answers: "Does this prospect look like our best customers?" Predictive close scoring answers: "Given this deal's behaviour and timing signals, how likely is it to convert?" These are not the same question. Building dialling priority on ICP score alone ranks prospects by profile match rather than purchase signal.
| Dimension | ICP Score | Predictive Close Score |
|---|---|---|
| Data used | Firmographics — industry, headcount, tech stack | Your own closed-won history + CRM behavioural signals |
| What it measures | Fit with your ideal customer profile | Probability this specific deal closes |
| Training source | Manually defined rubric | Historical closed-won and closed-lost deal records |
| Update frequency | When your ICP definition changes | Quarterly recalibration |
| Best use case | List filtering, territory planning | Rep dialling order, pipeline forecasting |
| Risk | High-fit contacts with no buying intent | Overfitting on data that no longer reflects the market |
| HubSpot implementation | Contact property scoring rules | Custom deal property populated nightly via API |
The team above had a rigorous ICP score that correctly identified companies in the right verticals. But close likelihood correlated with different signals entirely: time from first touch to demo booked, number of stakeholders on the deal record, and stage velocity. None of those signals lived in the ICP model. Fit and likelihood are orthogonal variables; building one model to answer both questions produces an unreliable score for each.
Keep your CRM enrichment and ICP scoring for list building and territory planning. Build a separate predictive model for active pipeline ranking. Use both, not one as a proxy for the other.
The minimum closed-won dataset before a predictive model is reliable: why 150 deals is the floor for UK SMB SaaS
Below 150 closed-won deals with complete CRM data, a gradient-boosted classifier overfits on noise. The model learns the idiosyncrasies of individual reps or individual quarters rather than genuine behavioural predictors of close. That produces scores that look plausible but rank deals incorrectly.
Three constraints define the floor for UK SMB SaaS:
- You need roughly 120 closed-won and 80+ closed-lost records for balanced training data. UK B2B SaaS close rates typically run 20–30%, so 150 closed-won deals implies 450–600 total closed deals in the CRM.
- With deal cycles of 60–90 days, that volume requires 18–24 months of consistently recorded CRM history.
- Clean data means stage timestamps recorded consistently, contact count populated at close, and at least one engagement metric per deal.
Below 100 clean closed deals, build a hand-weighted scoring rule instead. It will not be as accurate, but it will not mislead reps with false confidence scores either.
Feature engineering from HubSpot data: the eight CRM fields that correlate with closed-won in UK B2B
These eight fields consistently show predictive signal across the UK B2B deals we have modelled. All exist natively in HubSpot and can be pulled directly via the Reports export.
- Days from first touch to demo booked — deals where this is below the team median convert at roughly 1.8 times the rate of longer-ramp deals.
- Contacts on deal record — multi-threaded deals (three or more contacts) close at two to three times the rate of single-contact deals in professional services and mid-market SaaS.
- Days in current deal stage vs. historical median — deals moving faster than median for that stage carry meaningfully higher close rates.
- Email reply rate during active sequence — any reply rate above 35% during the nurture sequence is a strong positive signal.
- Outbound call connection rate — whether the contact answered, not whether calls were made.
- Company headcount band — encoded as an ordinal (1–10, 11–50, 51–200, 201+). For most UK SMB SaaS products, the 11–50 band shows the highest close rate.
- Technical contact present — a boolean flag: does the deal record include a technical decision-maker? For SaaS tools with any configuration requirement, this matters significantly.
- ACV vs. median ratio — deals priced at 0.7x–1.3x the team's median ACV close at higher rates than outliers in either direction.
Building a gradient-boosted close probability model on your own historical deal data: the Python implementation
We use scikit-learn's GradientBoostingClassifier over logistic regression because it handles non-linear feature interactions — the combination of multi-threading and fast stage velocity predicts close better than either feature alone, a non-linearity logistic regression cannot capture without manual interaction terms.
import pandas as pd
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import roc_auc_score
import joblib
# Export via HubSpot Reports > Deals, include all closed deals (won + lost)
df = pd.read_csv('hubspot_deals_export.csv')
FEATURES = [
'days_to_demo', # first touch to demo booked
'contacts_on_deal', # stakeholder count (multi-threading signal)
'days_in_current_stage', # stage velocity vs. team median
'email_reply_rate', # % replies during active sequence
'call_connection_rate', # outbound connection rate (not dials)
'headcount_band', # encoded: 1-10=1, 11-50=2, 51-200=3, 201+=4
'technical_contact', # 1 = technical decision-maker on deal, else 0
'acv_vs_median_ratio', # deal ACV / team median closed-won ACV
]
TARGET = 'is_closed_won' # 1 = closed-won, 0 = closed-lost
df = df.dropna(subset=FEATURES + [TARGET])
X, y = df[FEATURES], df[TARGET]
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)
model = GradientBoostingClassifier(
n_estimators=200,
learning_rate=0.05,
max_depth=4,
subsample=0.8,
random_state=42
)
model.fit(X_train_s, y_train)
auc = roc_auc_score(y_test, model.predict_proba(X_test_s)[:, 1])
print(f"AUC-ROC on hold-out: {auc:.3f}")
# Target > 0.72 before deploying scores to rep queue
# Below 0.65: reduce feature set to the five highest from model.feature_importances_
joblib.dump(model, 'close_probability_model.pkl')
joblib.dump(scaler, 'feature_scaler.pkl')
Target AUC-ROC above 0.72 before using the output to influence rep priorities. The scikit-learn gradient boosting documentation covers hyperparameter tuning in depth; the XGBoost library offers a marginal accuracy improvement once the pipeline is stable — the Python API is nearly identical.
For how this score feeds into revenue forecasting, see our post on AI sales forecasting from HubSpot CRM data — a 0.7 probability deal at £50k contributes £35k to the weighted pipeline number.
Deploying the score back into HubSpot: custom properties, workflow triggers, and the rep-facing priority view
Deployment has three components: a custom property, a nightly score push via the HubSpot API, and a workflow trigger that routes deals by score threshold.
Custom property: Create a deal property called close_probability_custom (type: number, 0–100). Keep it separate from HubSpot's native close probability field to run both in parallel during validation.
Score push: Run this snippet nightly via a scheduled job (cron or Make):
import requests
TOKEN = "your-private-app-token"
def update_deal_score(deal_id: int, score: float) -> None:
url = f"https://api.hubapi.com/crm/v3/objects/deals/{deal_id}"
payload = {"properties": {"close_probability_custom": round(score * 100)}}
requests.patch(url, json=payload,
headers={"Authorization": f"Bearer {TOKEN}"})
Workflow trigger: Create a HubSpot workflow that fires when close_probability_custom crosses 70. Action: enrol deal in the "High priority" sequence, assign to senior rep. Below 40: deprioritise or move to nurture cadence.
Rep-facing view: A deal board view sorted by close_probability_custom descending. Reps open this each morning. Highest number at the top, call that one first. No interpretation required.
Model drift and quarterly recalibration: what happens to score accuracy when market conditions or ICP shifts
A model trained on Q4 2024 data drifts as market conditions, ICP definitions, or rep behaviour change. Check AUC-ROC on held-out deals each quarter and retrain when accuracy drops below 0.68.
Common drift triggers:
- ICP expansion or contraction — if you started targeting a new vertical or dropped a segment, the old training data misrepresents your current pipeline.
- Rep or process changes — a new SDR with different call patterns changes the signal value of the call connection rate feature.
- Macro conditions — UK procurement approval timelines lengthened through 2025–2026 in ways that older training data does not reflect.
The recalibration process: pull the last 90 days of closed deals, append them to the training set, retrain, compare AUC, deploy if it improves. Around two hours of engineering time per quarter. The bigger cost is skipping recalibration — a drifted model actively harms rep prioritisation by promoting signals that have stopped predicting close. Alongside recalibration, run CRM pipeline hygiene automation to remove ghost deals from the training set before retraining — stale open deals inflate the closed-lost class and distort feature weights.
Combining predictive close score with engagement score: the two-axis matrix for rep dialling prioritisation
A single score is less useful than two dimensions. Predictive close probability tells you who is likely to convert. Engagement score — email opens, call pickups, website visits in the last 14 days — tells you who is active now. Combining them produces four actionable quadrants:
HIGH CLOSE PROBABILITY
|
Nurture (good fit signal, | Priority dial (high probability
not yet engaged — watch) | + active engagement — call now)
|
LOW ENGAGEMENT ─────────────────┼──────────────────── HIGH ENGAGEMENT
|
Deprioritise (weak signal | Investigate (engaged but lower
in both dimensions) | model confidence — re-qualify)
|
LOW CLOSE PROBABILITY
The "Priority dial" quadrant is where reps should spend 60–70% of their calling time. The "Investigate" quadrant — high engagement but lower predicted probability — is where you find deals that need a changed approach: escalation to a senior AE, a revised proposal, or a competitor displacement conversation. This matrix integrates with HubSpot's deal views using two custom properties on the X and Y axes. See our LinkedIn AI SDR case study for how we applied similar prioritisation logic in outbound sequencing.
What changed in 2025–2026: HubSpot Breeze predictive scoring and Salesforce Einstein lead ranking in 2026
Two developments shifted the scoring tooling landscape over the past 12 months.
HubSpot Breeze Scoring: HubSpot launched Breeze predictive scoring in late 2025, available in Sales Hub Professional and Enterprise tiers. Breeze scores active deals using aggregate signal across HubSpot's customer base rather than your specific deal history. No engineering required — it activates once enabled. According to HubSpot's Breeze AI lead scoring documentation, the model improves as it ingests your deal outcomes. The limitation is the same as any generic baseline: it reflects average buying behaviour across all HubSpot customers, not your specific vertical or UK market timing. On client deployments we have measured, a custom model outperforms Breeze by 8–14 AUC-ROC points once you have 150+ deals.
Salesforce Einstein lead ranking in 2026: Salesforce updated Einstein's methodology in early 2026 to incorporate intent signals from third-party data providers. Salesforce's own documentation on Einstein opportunity scoring is worth reading as an alternative perspective — particularly the section on model transparency and how Einstein surfaces score explanations to reps. The counterpoint to Einstein is cost: advanced scoring requires Sales Cloud Enterprise at £150+ per user per month, which is above most UK SME budgets. For sub-200-person teams, a custom model on a HubSpot export delivers comparable or better accuracy at a fraction of the cost. See our HubSpot vs Salesforce comparison for UK SME outbound AI for the full cost-capability breakdown.
Good / Bad / Ugly: three scoring approaches and their measurable impact on rep dialling order and quota attainment
Here is what each approach produced when we measured rep dialling outcomes and quota attainment across client deployments.
Good: custom gradient-boosted model on own closed-won data
For a 15-person UK professional services firm with 210 closed deals, we deployed the model above. Over six months, the top-score quartile converted at 34% against a team baseline of 18%. Quota attainment rose from 71% to 89%. Hold-out AUC-ROC was 0.76. The biggest surprise: stage velocity was the single highest-importance feature, outranking headcount band and email reply rate.
Bad: ICP score used as dialling priority
The 20-person SaaS team from the opening. Top ICP quartile produced 29% of ARR; second quartile produced 51%. Reps spent 40% of calling time on the lowest-probability contacts. The fix required rebuilding the priority logic and resetting rep expectations — the change management was harder than the technical change.
Ugly: Breeze scoring on a thin pipeline
A client with 62 closed deals activated HubSpot Breeze Scoring in January 2026. Breeze ranked their largest active deal — a £180k professional services opportunity — in the bottom quartile. That deal closed three weeks later. Breeze was training on patterns that did not match the client's enterprise-segment deals. We switched them to a hand-weighted rule covering five features until they reach the 150-deal threshold.
The lesson: do not deploy any automatic scoring tool on a thin pipeline. A model trained on 62 deals will actively mislead reps. Build the simple weighted rule first, graduate to a trained model when the data justifies it.
These qualification signals also feed CRM-based BANT extraction using the same deal-stage data structure.