CRM Updates
Every call, agreed next step, and follow-up task written back to your CRM — so the record stays complete without adding work for your reps.
Catch clients before they quietly drift away
In a business built on repeat orders, clients rarely leave with a cancellation. They just go quiet. The calls get shorter, the orders get smaller, and one day you realise a client you counted on has been buying from someone else for months.
Nobody decided to lose them. There was no moment to react to. By the time the drop shows up in the numbers, the client is already gone, and winning them back costs far more than keeping them would have.
The signs are there long before the orders stop, spread across calls no one has time to review: a rising number of objections, a competitor mentioned more often, a warmer client turning transactional, contact that used to be weekly slowing to monthly.
Sales Signals watches for these signals across every client’s calls and surfaces the ones that are cooling, while there is still time to act, an incentive, a call from the manager, a reason to keep ordering from you.
Example: Customer Sentiment Trend serves as an early-warning indicator of satisfaction decline, churn risk, or emerging operational issues. Thresholds are automatically adjusted to indicate significant changes in tone.
Because this kind of churn is invisible, it is easy to underestimate. The calculator below gives a rough sense of the gross margin quietly at risk each year, and how much of it earlier warning could recover.
countryData = FileAttachment("/data/salary-by-country.csv").csv({ typed: true })
fmtMoney = (value, row) =>
new Intl.NumberFormat(row.locale, {maximumFractionDigits: 0}).format(Math.round(value)) + " " + row.sym
renderResult = (rows) => html`<div class="calc-result">
${rows.map(r => html`<div class="calc-result-row ${r.total ? 'calc-result-total' : ''}">
<span>${r.label}</span><span>${r.value}</span>
</div>`)}
</div>`
// Persist a value to a cookie shared across the site (1-year expiry).
// Used to carry calculator inputs (country, reps, calls/day) into the contact form.
setSSCookie = (name, value) => {
document.cookie = "salessignals-" + name + "=" + encodeURIComponent(value) +
";path=/;max-age=" + (60*60*24*365) + ";SameSite=Lax";
}viewof countryCode = Inputs.select(
countryData.map(d => d.code),
{
label: "Country",
format: code => countryData.find(d => d.code === code).name
}
)
viewof reps = Inputs.number({label: "Number of reps", value: 5, min: 1, step: 1})
viewof grossMargin = Inputs.number({label: "Annual gross margin", min: 0, step: 10000})
viewof churnRate = Inputs.range([5, 40], {label: "Clients drifting per year (%)", value: 20, step: 1})
viewof recoverable = Inputs.range([5, 50], {label: "Recoverable with early warning (%)", value: 20, step: 1})// Pre-fill gross margin from country + team size (hidden salary logic):
// fully-loaded annual sales cost × 5. User can override.
{
row; reps; // recompute when either changes
const gm = Math.round(row.salary * (1 + row.oncost/100) * 12 * reps * 5 / 10000) * 10000;
const gEl = viewof grossMargin;
gEl.value = gm;
gEl.dispatchEvent(new Event("input", {bubbles: true}));
}Figures are approximate. Gross margin is estimated from team size and typical sales economics; drift and recovery rates vary widely by business. Adjust every field to your situation.
Even recovering a fraction of what quietly drifts away pays for Sales Signals many times over.
You see a client cooling while you can still do something about it. The manager gets a reason to make a call, offer an incentive, or simply check in, before the client has quietly moved on. Retention stops being something you measure after the fact and becomes something you can act on.
The clearest way to understand Sales Signals is to see what it surfaces from your team’s actual conversations. We will set it up with your existing phone system; there is nothing to install, and nothing changes for your reps.