We use cookies
We use cookies and similar technologies to improve your experience, analyse traffic, and personalise content. You can accept all cookies or reject non-essential ones.
10 Sep 2026
About one customer in eight fills in your survey. Your reports are built on those answers. The other seven tell you nothing — but you already have their data: what they bought, when they last logged in, how often they contacted support, what they clicked. You know what they did. You just don’t know how they felt about it.
This post walks through closing that gap inside SurveyAnalytica, screen by screen: joining the data, engineering the features, training on your survey answers as labels, and scoring the customers who never replied.
About one customer in eight fills in your survey. Your reports are built on those answers.
The other seven tell you nothing. But you already have their data: what they bought, when they last logged in, how often they contacted support, what they clicked. You know what they did. You just don’t know how they felt about it.
That is the gap this closes.
You have this for everyone, all the time. It shows what people did, not how they felt.
Only a small slice answer. But they are the only ones who told you how it felt.
So instead of chasing a higher response rate, use the answers you already have to teach a model what the behaviour means. Then apply it to everyone.
Your survey stops being the report. It becomes the answer key.
Seven steps. Every screen below is real, with the buttons named as you will find them.
Step 01
Workspace ▸ Data ▸ Create Data Hub · Contact Lists ▸ Import Contacts
You need two things. A dataset holds the events: orders, sessions, tickets, clickstream. A contact list holds the people those events belong to. Choose From a flow if the data keeps arriving, or Upload a file for a one-off.
Clickstream has its own door: Connectors Marketplace ▸ Clickstream Publisher ▸ Create Clickstream workflow, then install the SDK — Vanilla JS, Next.js, React, React Native, Flutter or iOS.
Contacts arrive the same two ways: Upload CSV, or a flow that adds them as they show up in your systems. Then set up the fields — this is where the model’s answer gets written later.
| Field ID | Display Label | Type |
|---|---|---|
| plan | Plan | Dropdown |
| tenure_months | Tenure (months) | Number |
| experience_flag | Experience | Dropdown |
Add experience_flag now and leave it empty. Step 07 writes the prediction into it. On this same screen you’ll later filter on it to build a segment.
Step 02
Workspace ▸ Analytics model ▸ Data & Relationships
Drag your sources onto the canvas and connect them. The contact list is the spine: everything joins to it, because it is the one table that agrees on who the customer is.
If you distributed the survey to a contact list, you don’t have to reconcile anything. Each invite carries a session id minted with the contact’s ID, list, email and name attached, so the response comes back stamped with who it came from.
And you usually send a survey about something: an order that just shipped, a ticket that just closed, a delivery that just arrived. Pass that reference through as a custom variable — order ID, ticket number, transaction ID — and it lands on the response too. Same for surveys sent from your own ESP or a link on your site.
So the answer doesn’t come back floating at the customer level. It comes back attached to the exact thing it was about.
So the matching options below are for the systems you don’t control: the order database, the helpdesk export, the spreadsheet from finance. Your feedback data arrives clean.
For those, How to match and Normalize keys sort out the mismatch without a data cleanup project.
customers · contactId · email · plan · tenure_months · experience_flag
csat_responses · contactId · orderId · sid
orders_2026 · orderId · customer_email
Notice the shape: behaviour is filled in for everyone, survey answers only for some. That gap is the whole point. The rows with answers train the model. The rows without are the ones you predict.
This is worth pausing on, because it is the part most survey tools cannot do. A rating that arrives with an order ID on it tells you which order produced it. You are not guessing which of a customer’s forty transactions caused the two-star review — you know, and so does the model.
That gives you two ways to build the training set, and you pick by the question you are asking:
Both are useful and they answer different questions. The first catches a bad experience while it is still fixable. The second tells you who to call this month. You can build both from the same joined view; the rolling up happens in the next step.
Step 03
Analytics ▸ Predictions ▸ Feature Engineering ▸ Open Studio
Pick a transform from the list, or write the expression yourself. The same goes for the label: a raw 0–10 score is hard to predict, but grouped into promoter, passive and detractor it becomes straightforward.
Written comments count too. Word Count and TF-IDF turn the free-text box nobody had time to read into something the model can use.
Step 04
Analytics ▸ Predictions ▸ Model Selection → Data Preparation → Training
The catalogue covers Classification, Regression, Forecasting, Clustering, Image and Text. If you would rather not choose, AI Recommend suggests a model and a target based on your columns.
Step 05
Analytics ▸ Predictions ▸ Results & Comparison ▸ Versions
Look at precision and recall rather than accuracy. Train a second model, compare the two, and press Mark as Live on the one you trust.
| Version | Primary metric | Trained | |
|---|---|---|---|
| v3 · Boosted Tree | 0.91 ROC AUC | today | LIVE |
| v2 · Logistic Reg. | 0.84 ROC AUC | 2 days ago | Mark as Live |
Feature Importance and Confusion Matrix sit under Detailed Metrics.
Step 06
Predictions ▸ Deploy as Agent, then Agents ▸ open the agent ▸ Deploy
Deploying gives you a service that knows which inputs it needs and what it returns. The generated code is yours to edit, so you can add whatever output your team actually wants.
Declare experience_flag on the Output Schema tab so it appears in the flow designer.
Do the conversion here, once. Put the 0.7 cut-off inside nine separate automations instead, and retraining the model quietly makes all nine wrong.
Step 07
Flows ▸ Design ▸ Trigger, then Add Component
So start the flow when the thing happens. Clickstream for what people do on your site or app. Webhook for your order or helpdesk system. Survey Response when feedback arrives. Contact List when a profile changes.
The AI Agent node calls your model. Condition then sends different customers down different paths.
Drag a node from Add Component, drop it on the canvas, connect it. A Condition splits the path; everything under a branch runs only for the records that matched it.
The same three pieces handle inbound. When a customer writes to you on WhatsApp, email or a web form, a Message Channel trigger starts the flow. The model reads their message along with everything you already know about them, and the branch decides whether this needs a person or can be answered right away.
Same trigger, model and condition, pointed at a different signal. An at-risk customer who writes in reaches a person. Everyone else gets an answer straight away.
Write the field to the list first via Manage Fields ▸ Add Custom Field, then filter on it in Advanced Filters and press Create Dynamic List — the segment re-evaluates on every send.
Keep a Schedule trigger for things that really are slow: contract renewals, tenure, a monthly sweep of anyone the event stream never touched. Fast signals on the event, slow signals on a timer. What you want to avoid is an urgent signal sitting in an overnight job.
A prediction is a guess, not a quote. The model thinks this customer is unhappy. The customer never said so. Keep the two apart in your reports, and never tell someone you know how they feel.
This is also why you keep asking. New answers are how you check the model is still right. And when a model goes wrong, it goes wrong quietly: the scores keep arriving, everyone keeps trusting them, and fewer and fewer real answers come in to catch it.
No comments yet. Be the first to comment!