CRM · Health Tourism
EHT CRM: WhatsApp, ad spend and AI on one pipeline
A microservice CRM. Sales conversations running over the WhatsApp Business API, real deal data written back to Google and Meta, conversation analysis, and a RAG-based AI call centre.
- Company
- EHT
- Role
- Our own company · end to end
- Industry
- CRM · Health Tourism
- Date
Challenge
The entire sale ran over WhatsApp but was recorded nowhere. Ad platforms were optimising for "form submitted" with no knowledge of whether a sale ever closed, so budget flowed to the campaign that produced forms rather than the one that produced patients. Consultant conversation quality could only be measured if someone read the threads by hand — which meant it was not measured.
Approach
We split the system into messaging, ads, attribution, analysis and AI services instead of one application, and made the communication between them event-driven. WhatsApp Cloud API webhooks pass through a single messaging gateway. When a deal closes, that fact is written back to Google and Meta as an offline conversion — so the ad algorithm optimises for closed deals rather than form count. Conversation analysis and the RAG-based call centre run as a separate service with an explicit human-handoff rule.
Starting position
EHT is a team that sells entirely over WhatsApp. A patient arrives from an ad, writes to a consultant, the conversation runs for days, and in the end they either come or they do not.
That model had three blind spots, and each one fed the others.
The conversation existed nowhere. The thread on the consultant’s phone was that person’s data, not the company’s. When a consultant left, the history left with them. Two consultants writing to the same patient, or a patient going unanswered for days, was something nobody could see.
Ad platforms were optimising for the wrong thing. Meta and Google work to deliver the event you report to them as cheaply as possible. If the reported event is “form submitted”, the system gets very good at finding people who submit forms and never buy. The campaign producing cheap forms looked bright in the report; the one producing patients looked dim.
Conversation quality was not measured. How quickly a consultant replied, how they handled an objection, whether they nailed down a next step — all of it could only be known if someone sat down and read the threads. Nobody did.
Decisions
Why microservices
Microservices are not a correct decision by default; the distributed-systems cost they introduce is real. Here they were chosen on three concrete grounds.
The load profiles are very different. The messaging gateway takes sudden, high webhook traffic during campaign hours; the analysis service runs batch jobs overnight; the AI service makes long, expensive calls. Keeping them in one process meant scaling all of them for the most expensive component.
A failure boundary was required. When the model provider slows down or an ad API hits its quota, WhatsApp messages have to keep flowing. A message not arriving is a lost patient; a delayed report can wait.
External APIs move to their own rhythm. The WhatsApp Cloud API, the Meta Marketing API and the Google Ads API each have their own rate limits, credential cycles and breaking version changes. Isolating each one in its own service stops a single provider’s change from halting the whole system.
Services communicate over RabbitMQ, event-driven. Each service has its own PostgreSQL schema; there are no writes to a shared database. The price is eventual consistency: when a deal closes, it can take seconds to appear on the reporting screen. Measured against the pace of a sales conversation, that is an acceptable delay.
The messaging gateway
WhatsApp Cloud API webhooks land on a single service whose only job is to receive the message, verify it, turn it into an event and publish it.
The details that matter:
- Repeated delivery. Meta can send the same webhook more than once. Every message is deduplicated on its
wamid; the second delivery is dropped silently. - No ordering guarantee. Messages may not arrive in the order they were sent. The conversation timeline is built from the message’s own timestamp, not from webhook order.
- The 24-hour rule. Free-form text cannot be sent more than 24 hours after the customer’s last message; only pre-approved templates may be used. That rule is built into the system: when the window closes, the interface disables the free-text field and offers approved templates. The consultant is not expected to memorise it.
- Template management. Pending, approved and rejected templates are tracked in the system, and a rejected template is blocked from use.
Consultants work from a single shared inbox: assignment, handover, tagging, internal notes, and protection against two people replying at once. The number now lives in the company’s system rather than on someone’s phone.
Attribution: the real point
This is the part of the system that produces the most value.
The chain is built like this:
- Click-to-WhatsApp ads drop the user straight into a chat and carry a referral payload with the first message — which ad, which campaign. That payload is written to the contact record the moment the conversation opens.
- Meta lead forms arrive by webhook; the form id and campaign details are attached to the same contact record.
- Web forms carry
gclidand UTM parameters; the phone number is normalised to E.164 and matched against the existing record. - When a consultant marks the deal won, an event is published.
- The attribution service catches that event and writes the offline conversion back: to Google Ads by
gclid, and to Meta through the Conversions API with hashed contact details. The value field carries the deal amount, not a form count.
After that step, what the ad algorithm optimises for changes. The panel no longer says “forms at 500 lira”; it says which campaign produced how many deals.
The trade-off here is latency: the deal closes days later, and the conversion is written back then. Ad platforms tolerate that delay up to a point. To compensate, intermediate signals are also sent — qualified conversation, appointment booked — so the algorithm is not left entirely blind.
On personal data the rule is firm: fields going to Meta and Google are hashed on the server rather than on the client, and raw phone numbers and email addresses never leave the system.
Conversation analysis
Every closed conversation enters the analysis queue. What gets evaluated is measurable and defined in advance:
- First response time, and average response time across the conversation.
- Whether the qualifying questions were asked.
- How the objection was handled.
- Whether a next step was made concrete — appointment, date, payment step.
- Sentiment trajectory, and where the conversation broke down.
The real risk here is treating a language model’s score as a metric in itself. We took two precautions. First, there is a fixed, human-labelled evaluation set; when the model or the prompt changes, scores are re-measured against it. Second, scores are not written directly onto a consultant’s scorecard — low-scoring conversations go into a human review queue. The model is a filter here, not a judge.
The AI call centre and RAG
The repeat rate on common questions is high: price range, process, accommodation, recovery timeline, payment options. We built a layer to handle them.
The knowledge base is made of price lists, process documents and clinic policies. It is chunked, embedded and held in pgvector. Retrieval is not pure vector search but a hybrid with keyword search, followed by a reranking step. The reason is practical: on price questions the model tends to retrieve the semantically close but wrong package line — the keyword component corrects that.
Three rules govern answer generation:
- No answer without a source. The model answers only from the retrieved passages; with no grounding, it does not answer.
- Handoff below the threshold. Any conversation under the confidence threshold is passed to a consultant without the user noticing. The handoff rate is not a hidden number — it is one of the system’s headline metrics.
- The medical domain is closed. Questions about eligibility, diagnosis, medication and outcome promises are never left to the model; they go straight to a person. In healthcare, a language model being convincingly wrong is not an acceptable risk.
On the voice side, speech is transcribed, passes through the same retrieval path, and the answer is returned as speech. It uses the same knowledge base and the same handoff rules as the text side — we do not maintain two sources of truth.
Delivery
Observability
In a distributed system the most expensive thing is not being able to find where a request was lost. The path a WhatsApp message takes from webhook to inbox to attribution service is traced through a single correlation id. Queues have dead-letter handling; an event that cannot be processed is not dropped, it waits to be inspected.
Identity and deduplication
The same person can enter as three separate records: web form, Meta lead form, WhatsApp. Phone numbers are normalised to E.164 and merge rules work from that. A wrong merge is more expensive than leaving two records apart, so uncertain matches are not merged automatically — they are surfaced as suggestions.
Cost
The AI layer is a measurable expense. Token consumption per conversation is reported per service; analysis jobs run in batch on a cheaper model while live answers use a stronger one. Answers to frequently repeated questions are cached.
Measurement
We did not put numbers on this page. When the measurement period closes, these are the metrics that go here:
- Cost per deal by campaign — before and after offline conversion write-back.
- The distribution of first response time; the long tail, not the average.
- The AI layer’s handoff rate, and the conversion difference after handoff.
- Answer accuracy on the evaluation set — stated with the number of questions and the grading method.
- AI cost per conversation against the consultant hours saved.
Outcome
Ad spend and closed deals are linked through a single identity, and campaign performance is now discussed in deal value rather than form count. All WhatsApp traffic is recorded and searchable; consultant conversations are scored across the whole population rather than a sample. The AI layer answers only above its confidence threshold, hands off below it, and never enters the medical advice space. The measurement period for campaign-level cost comparison is still open.
Do you have an idea, or a product that has stalled?
Let us scope it in a short call. In the first conversation we cover the technical approach and an estimated budget range.
Or write directly: info@boygantech.com