The surveys module lets you collect user feedback through in-app surveys. Surveys can trigger automatically based on events (like in-app messages) or be presented manually from your code.
How It Works
Surveys are configured in the Console with content, question types, and trigger rules. Like in-app messages, they can appear automatically when trigger conditions are met — no code required for trigger-based surveys.
Present a Survey Manually
AppDNA.surveys.present("nps_q1_2026")
Module Access
let surveys = AppDNA.surveys
Module Methods
| Method | Signature | Description |
|---|
present | present(_ surveyId: String) | Present a survey manually |
setDelegate | setDelegate(_ delegate: AppDNASurveyDelegate?) | Set a delegate for survey callbacks |
8 Question Types
Surveys support the following question types, configured in the Console:
| Type | Display | Response |
|---|
nps | 0-10 numeric scale | Integer 0-10 |
csat | 1-5 satisfaction scale | Integer 1-5 |
rating | Star rating | Integer 1-5 |
emoji_scale | Emoji options | Selected emoji value |
yes_no | Binary choice | Boolean |
single_choice | Radio button options | Selected option string |
multi_choice | Checkbox options | Array of selected strings |
free_text | Text input field | Free-form string |
Question types and their content are defined entirely in the Console. The SDK renders them automatically based on the survey configuration.
AppDNASurveyDelegate
Implement the delegate to capture survey responses and lifecycle events:
protocol AppDNASurveyDelegate {
func onSurveyPresented(surveyId: String)
func onSurveyCompleted(surveyId: String, responses: [SurveyResponse])
func onSurveyDismissed(surveyId: String)
}
SurveyResponse
struct SurveyResponse {
let questionId: String
let answer: Any // String, Int, [String], Bool depending on question type
}
Example Implementation
class FeedbackHandler: AppDNASurveyDelegate {
func onSurveyPresented(surveyId: String) {
print("Survey shown: \(surveyId)")
}
func onSurveyCompleted(surveyId: String, responses: [SurveyResponse]) {
for response in responses {
if let score = response.answer as? Int {
if score >= 9 {
// Promoter -- show referral prompt
showReferralPrompt()
} else if score <= 6 {
// Detractor -- show support link
showSupportLink()
}
} else if let feedback = response.answer as? String {
print("User feedback: \(feedback)")
}
}
}
func onSurveyDismissed(surveyId: String) {
print("Survey dismissed: \(surveyId)")
}
}
AppDNA.surveys.setDelegate(FeedbackHandler())
Survey questions support rich media content configured in the Console:
- Header images — add images above survey questions
- Icons in options — use icon references in choice options (Lucide, SF Symbols, Material, or emoji)
- Thank-you animations — Lottie or confetti effects on survey completion
- Haptic feedback — triggered on option selection and submission
See the Rich Media guide for details on supported formats.
Auto-Tracked Events
| Event | Trigger |
|---|
survey_presented | A survey is displayed |
survey_response_submitted | User submits a survey response |
survey_dismissed | Survey is closed without completing |
Full Example
import AppDNASDK
class FeedbackManager: AppDNASurveyDelegate {
init() {
AppDNA.surveys.setDelegate(self)
}
/// Present NPS survey after a key moment
func askForFeedback() {
AppDNA.surveys.present("nps_q1_2026")
}
// MARK: - AppDNASurveyDelegate
func onSurveyPresented(surveyId: String) {
// Survey is visible
}
func onSurveyCompleted(surveyId: String, responses: [SurveyResponse]) {
// React to feedback
if let nps = responses.first(where: { $0.questionId == "nps_question" }),
let score = nps.answer as? Int {
if score >= 9 {
showReferralPrompt()
} else if score <= 6 {
showSupportLink()
}
}
}
func onSurveyDismissed(surveyId: String) {
// User dismissed without responding
}
}
Surveys are created in the Console under Feedback > Surveys. Trigger-based surveys appear automatically — manual presentation with present() is for cases where you want precise control over timing.