Create and distribute surveys from the CLI.
Surveys
Collect feedback from your users with in-app surveys. AscendKit supports three survey types: NPS (Net Promoter Score) for loyalty measurement, CSAT (Customer Satisfaction) for experience ratings, and custom surveys for any question format using SurveyJS.
Surveys integrate with the rest of AscendKit — distribute them through journeys, trigger webhooks on submission, and track completion analytics with per-user funnels (sent, opened, submitted).
Note: The CLI handles survey-level operations (create, distribute, view analytics). Question-level editing is also available through the portal UI.
Which survey type should you use?
The three types are not interchangeable, and picking the wrong one produces data you cannot act on.
| NPS | CSAT | Custom | |
|---|---|---|---|
| Asks | "How likely are you to recommend us?" | "How satisfied were you with X?" | Whatever you define |
| Scale | 0–10 | Typically 1–5 | Any SurveyJS question type |
| Measures | Overall loyalty, tracked over time | Satisfaction with one interaction | Anything |
| Send when | Periodically — quarterly is common | Right after the interaction | When you have a specific question |
| Benchmarkable | Yes, across the industry | Somewhat | No |
| Pre-configured | Yes | Yes | No — starts empty |
NPS answers "is this getting better or worse?" Its value is the trend, not any single number, so it needs consistent timing and a stable audience. Sending it only to happy users destroys the comparison you were trying to build.
CSAT answers "did that specific thing work?" It must arrive close to the interaction — a satisfaction question about onboarding sent three weeks later measures memory rather than experience.
Custom is for questions you already know you want to ask. If you are unsure what to ask, a custom survey will produce vague answers; start with CSAT on a specific moment instead.
How the NPS score is calculated
Responses group into three bands, and the score is the percentage of promoters minus the percentage of detractors. Passives count toward the total but not toward either side.
| Response | Band | Effect on score |
|---|---|---|
| 9–10 | Promoter | Increases |
| 7–8 | Passive | Dilutes only |
| 0–6 | Detractor | Decreases |
The result ranges from -100 to +100, so a positive score means promoters outnumber detractors. Because passives dilute without counting, a survey with many 7s and 8s produces a score near zero even with no unhappy users — which is why the trend matters more than the absolute value.
Create a survey
ascendkit survey create --name "Q1 NPS Survey" --type nps
ascendkit survey create --name "Onboarding CSAT" --type csat
ascendkit survey create --name "Feature Feedback" --type custom
NPS and CSAT surveys come with standard questions pre-configured. Custom surveys start empty.
List surveys
ascendkit survey list
Shows all surveys with their status: needs questions, draft, active, or collecting responses.
Export/import definition JSON
Export current definition:
ascendkit survey definition export srv_abc123 --out survey-definition.json
Edit survey-definition.json, then import it:
ascendkit survey definition import srv_abc123 --in survey-definition.json
definition import updates only the definition field. It does not mutate slug, name, or status.
Activate and distribute
ascendkit survey update srv_abc123 --status active
ascendkit survey distribute srv_abc123 --users usr_001,usr_002,usr_003
Distribution creates personalized links per user for tracking (sent, opened, submitted).
Because invitations address usr_ records directly, there is no contact list to export into a survey tool and no reconciliation between a survey vendor's idea of a user and your own. Responses attach to the same profile as that user's auth and email history, so a detractor score is queryable next to when they signed up and which emails they opened.
Distributing through a journey
Distributing manually by user ID works for a one-off. For anything recurring, trigger the survey from a journey instead — a CSAT three days after onboarding completes, or an NPS at 90 days on the account.
The distinction matters for the same reason it does with campaigns: a manually distributed survey sends on your clock, while a journey-distributed survey sends on each user's. For CSAT, which must arrive close to the interaction it asks about, the user's clock is the only correct one.
View results
ascendkit survey invitation list srv_abc123
ascendkit survey analytics srv_abc123
Analytics shows the funnel (sent -> opened -> submitted), conversion rates, and NPS score for NPS surveys.
Delete a survey
ascendkit survey remove srv_abc123
Deletes the survey and all associated invitations and responses.
Question operations
ascendkit survey question list srv_abc123
ascendkit survey question add srv_abc123 --type text --title "What should we improve?"
ascendkit survey question update srv_abc123 feedback --title "Anything we should improve?"
ascendkit survey question remove srv_abc123 feedback
ascendkit survey question reorder srv_abc123 --order nps_score,feedback
Note: Question
--typecannot be changed on an existing question. To change the type, remove the question and re-add it. Theupdatecommand will return an error if--typeis passed.
Troubleshooting
The survey shows "needs questions" and will not activate
Custom surveys start empty and cannot be activated until at least one question exists. NPS and CSAT surveys arrive pre-configured and do not hit this.
Add a question with survey question add, or export the definition, edit it, and import it back.
definition import did not change the survey name or status
Working as intended. definition import updates only the definition field and deliberately leaves slug, name, and status alone, so a definition file cannot silently activate a survey or rename it.
Use ascendkit survey update srv_abc123 --status active to change status.
Updating a question type returns an error
Question --type is immutable. Changing it would invalidate responses already collected against the old type.
Remove the question and add it again with the new type. Do this before distribution, since removing a question discards its responses.
Invitations show as sent but never opened
Opens are tracked by the personalized link, so an unopened invitation is usually an email delivery problem rather than a survey problem.
Check that your sending domain is verified, then look at the email delivery logs. If delivery succeeded but opens stayed at zero, the invitation is likely landing in spam — see Email.
The NPS score looks wrong for the responses received
Most often passives. A set of responses clustered at 7 and 8 produces a score near zero, because passives count toward the denominator without contributing to either side.
Check the band breakdown in survey analytics rather than reading the headline score alone.