Sales teams often have plenty of company and CRM data, but the harder question is: which accounts should we work now, why, and what should we do next?
I built the GTM Decision Engine to answer that question. The application combines account data, website signals, CRM context, optional ICP fit and data quality to create a prioritized sales action queue.
Instead of only giving every account a score, the engine also recommends the next action, such as Work Now, Research First, Follow Up Existing, Nurture, Expansion, Continue Opportunity, Pause Outreach or Deprioritize.
The goal is simple: turn scattered account information into a clear answer about who sales should work next and why.
Sales teams often work with information spread across CRMs, spreadsheets, enrichment tools and company websites.
Even when all of that information exists, a salesperson may still need to manually answer:
The project brings those checks together into one decision workflow.
The overall flow is:
Account Data → Enrichment → ICP & Data Quality → CRM Context → Scoring → Recommended Action → Prioritized Queue
Users can upload their own CSV or use one of the built-in GTM, HubSpot or Salesforce-style sample datasets.
For each account, the engine can consider company information, website signals, CRM status, previous activity, optional ICP criteria and the completeness of the available data.
The result is not just another score. The system also recommends what sales should do next.
One important part of the project is that the highest account score does not automatically mean Work Now.
The engine also checks what is already happening with the account.
| CRM situation | Possible recommendation |
|---|---|
| There is already an open opportunity | Continue Opportunity |
| The company is already a customer | Expansion |
| The account was contacted recently | Pause Outreach |
| An existing lead has strong fit and evidence | Follow Up Existing |
| A promising new account has strong current signals | Work Now |
This makes the recommendations more realistic because the engine does not treat every company as a completely new prospect.
Users can optionally define an Ideal Customer Profile (ICP) using criteria such as target countries, industries and company size.
The system can then compare accounts against that profile while also considering available website signals such as hiring activity, detected technologies and relevant business signals.
ICP is optional. Accounts are not removed simply because an ICP profile has not been configured.
Another important design choice is how the engine handles missing information. If enrichment is unavailable, the system does not automatically assume that the company is a poor prospect.
Missing information is treated as uncertainty. An interesting account may therefore receive a Research First recommendation instead of being incorrectly deprioritized.
Good GTM decisions depend on good CRM data.
The engine calculates a data confidence score based on the information available for each account, including fields such as domain, website, country, industry and company size.
It also checks for potential duplicate CRM accounts. If multiple records appear to represent the same company or share the same domain, they are flagged for review.
The system does not automatically merge or delete duplicate records. It highlights the issue so that a person can review it safely.
I built the project as a full-stack application with separate components for the frontend, backend API, enrichment, decision logic and database layer.
The user interface is built with Next.js and TypeScript.
The dashboard includes:
The backend is built with Python and FastAPI.
It handles:
Supabase / PostgreSQL is used for analysis history in private/local mode.
The public portfolio deployment runs visitor CSV analyses temporarily and does not store them as persistent analysis history.
The application includes three built-in datasets:
The HubSpot and Salesforce datasets are synthetic and do not contain real customer CRM data.
Their signals are controlled sample inputs, but the actual scoring, ranking, duplicate detection, CRM rules and recommended actions are calculated by the real decision engine.
Visitors can also upload their own CSV. Those accounts can be processed using live website enrichment rather than the built-in sample signal snapshots.
The project separates two related concepts: Account Score and Recommended Action.
The Account Score summarizes evidence such as fit, current signals and available data. The final sales action can also depend on CRM context.
This means a high-scoring account may still receive Continue Opportunity, Expansion or Pause Outreach instead of Work Now.
A high score answers “how interesting is this account?” The recommended action answers “what should sales actually do next?”
Because the project contains business decision rules, I created deterministic evaluation scenarios to verify that those rules behave consistently.
| Validation | Result |
|---|---|
| Deterministic policy scenarios | 35 / 35 passed |
| Policy conformance | 100% |
| Backend tests | 36 passed |
The 100% figure describes policy conformance, not real-world sales prediction accuracy.
It means the implemented rules behaved as designed across the scenarios created to test them.
The most interesting part of this project was not simply building another scoring dashboard.
It was designing the logic that connects:
Fit + Signals + CRM Context + Data Quality → Recommended Sales Action
An account can look attractive but still be the wrong company to contact right now. For example, it may already be an active opportunity, an existing customer or an account that was contacted recently.
The goal of the GTM Decision Engine is therefore not simply to rank companies, but to make the next sales decision clearer, more consistent and easier to act on.
The public version includes the built-in demo datasets and also supports temporary CSV analysis.