Skip to content
Product · Sales

A pipeline that fills itself from real usage.

HAL's CRM is deliberately small: companies, contacts, deals, stages. Its edge is what flows in — every identify call, chat, and product event is already attached.

The records

  • Company — the account. Domain, industry, notes, health signals, and its deals. Its stage and deal value mirror its main deal, so anything that reads a company's stage keeps working.
  • Deal — one sale with a company: new business, an expansion, or a renewal. Each has a stage, amount, owner, expected close date, next step, the people involved with their role, and a lost reason when it is lost.
  • Contact — a person. Emails, tags, notes, and links to one or many companies.
  • Visitor — a browsing session. Anonymous until identified, then attached to a contact.

The full ownership rules — which record holds which field, and what happens on identify — are in CRM data model.

How data enters

There are four inlets, and they all converge on the same records:

  • Widget identify — HalWidget.identify() from your site. The most common path: signed-in users appear in CRM automatically.
  • Server-side identify — POST /api/widget/identify from your backend.
  • Public API — /api/v1/contacts, /api/v1/companies and /api/v1/deals with an API key. For billing webhooks, data warehouse sync, and integrations.
  • Dashboard — manual entry and CSV import with duplicate merging.

Stages

Stages are fully custom per project: name, color, order, and probability. A stage at 100% marks a deal won and one at 0% marks it lost. The board shows deals as cards with column totals — one-time, MRR, or ARR semantics per your sales currency setting — and flags deals past their close date, with an overdue next step, or untouched for two weeks.

Product signals respect stage precedence: writes from the widget advance deals forward in your stage order but never backward, unless the write explicitly requests exact mode. Manual moves from the dashboard always win. Details in CRM data model.

Deals and deal values

Create deals from the board, a company, the API (/api/v1/deals), or MCP. Widget and company writes — HalWidget.setStage(), HalWidget.setDeal({ deal_value: 1800 }), deal_value / stage_id on companies — move the company's main deal, and a company entering the pipeline gets one. A customer who comes back after a lost deal gets a new deal, so each sale keeps its own record. Amounts roll up into board totals, win rate, sales cycle and revenue reporting. Interpretation (one-time vs MRR vs ARR) is a project setting so totals mean one thing.

Health signals

Define rules — "no conversation in 14 days", "usage dropped below X", "open ticket + trial ending" — and HAL surfaces a "needs attention" state on the company.

Attribution

Because visitors, contacts, and companies are linked, HAL can trace a revenue line: anonymous visit → identified user → company → stage changes → won. The marketing view reports qualified pipeline and won revenue attributed back to the original touchpoints.