Supported on: Android SDK 1.0.33+
You can A/B test this survey with no extra code — create an experiment on it in the Console and the SDK serves the assigned variant automatically. See Servable Surface Experiments.
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")
The SDK uses the foreground Activity captured at configure time to launch its internal SurveyActivity. If the survey ID is unknown or the config hasn’t loaded, the call is a no-op and an SDK log line explains why.
Module Access
val surveys = AppDNA.surveys
Module Methods
| Method | Signature | Description |
|---|
present | present(surveyId: String) | Present a survey by ID |
setDelegate | setDelegate(delegate: AppDNASurveyDelegate?) | Set a delegate for survey lifecycle callbacks |
8 Question Types
| 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 | List of selected strings |
free_text | Text input field | Free-form string |
likert (alias scale) | Numeric scale with optional left/right anchor labels | Integer in configured range |
Question types and their content are defined entirely in the Console. The SDK renders them automatically based on the survey configuration.
Smart Review Prompting
The SDK supports a two-step review-prompt flow: an in-app screener routes happy users to the Google In-App Review dialog and unhappy users to a feedback form. Configure the prompt in the Console under Feedback → Review Prompts and target it like any other survey — the SDK presents it automatically when trigger conditions match.
AppDNASurveyDelegate
All 3 methods on this delegate fire from SurveyManager alongside the analytics events. Register your delegate via AppDNA.surveys.setDelegate(...).
onSurveyPresented(surveyId) — fires when the survey view appears (alongside the survey_shown event).
onSurveyCompleted(surveyId, responses) — fires when the user submits the final question. responses is a List<SurveyResponse> (one entry per answered question with questionId + the raw answer), suitable for forwarding to your own analytics or CRM.
onSurveyDismissed(surveyId) — fires when the user closes the survey before completing it (back button, swipe-to-dismiss, outside tap).
Implement the delegate to capture survey responses and lifecycle events:
interface AppDNASurveyDelegate {
fun onSurveyPresented(surveyId: String)
fun onSurveyCompleted(surveyId: String, responses: List<SurveyResponse>)
fun onSurveyDismissed(surveyId: String)
}
SurveyResponse
| Property | Type | Description |
|---|
questionId | String | Identifier for the question |
answer | Any | The raw answer — Int for NPS/CSAT/rating/Likert, String for free-text/single-choice, List<String> for multi-choice, Boolean for yes-no |
metadata | Map<String, Any>? | Optional per-question metadata (question type, timing, etc.) |
Cast answer to the type matching the question (see Question Types).
Example Implementation
import ai.appdna.sdk.AppDNA
import ai.appdna.sdk.AppDNASurveyDelegate
import ai.appdna.sdk.SurveyResponse
class FeedbackHandler : AppDNASurveyDelegate {
override fun onSurveyPresented(surveyId: String) {
Log.d("Survey", "Survey shown: $surveyId")
}
override fun onSurveyCompleted(surveyId: String, responses: List<SurveyResponse>) {
for (response in responses) {
when (val a = response.answer) {
is Int -> {
// NPS / CSAT / rating / likert
if (response.questionId == "nps_question") {
if (a >= 9) showReferralPrompt() // Promoter
else if (a <= 6) showSupportLink() // Detractor
}
}
is String -> Log.d("Survey", "Feedback: $a")
is List<*> -> Log.d("Survey", "Multi-select: $a")
is Boolean -> Log.d("Survey", "Yes/No: $a")
}
}
}
override fun onSurveyDismissed(surveyId: String) {
Log.d("Survey", "Survey dismissed: $surveyId")
}
private fun showReferralPrompt() { /* ... */ }
private fun showSupportLink() { /* ... */ }
}
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, 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_shown | A survey is displayed |
survey_question_answered | User answers an individual question |
survey_completed | User submits the final answer |
survey_dismissed | Survey is closed without completing |
survey_followup_prompt_review | Smart Review prompt routed the user to the Google Play review dialog |
survey_followup_feedback_form | Smart Review prompt routed the user to a feedback form |
survey_followup_winback | A win-back follow-up was triggered after a low-rating response |
survey_feedback_submitted | User submits the in-app feedback form |
feedback_form_submitted | Standalone feedback form submitted |
feedback_form_dismissed | Standalone feedback form dismissed |
Full Example
import ai.appdna.sdk.AppDNA
import ai.appdna.sdk.AppDNASurveyDelegate
import ai.appdna.sdk.SurveyResponse
class FeedbackManager : AppDNASurveyDelegate {
init {
AppDNA.surveys.setDelegate(this)
}
/** Present NPS survey after a key moment */
fun askForFeedback() {
AppDNA.surveys.present("nps_q1_2026")
}
// MARK: AppDNASurveyDelegate
override fun onSurveyPresented(surveyId: String) {
// Survey is visible
}
override fun onSurveyCompleted(surveyId: String, responses: List<SurveyResponse>) {
// React to feedback
val nps = responses.firstOrNull { it.questionId == "nps_question" }
val score = nps?.answer as? Int ?: return
when {
score >= 9 -> showReferralPrompt()
score <= 6 -> showSupportLink()
}
}
override fun onSurveyDismissed(surveyId: String) {
// User dismissed without responding
}
private fun showReferralPrompt() { /* ... */ }
private fun showSupportLink() { /* ... */ }
}
Surveys are created in the Console under Feedback > Surveys. Trigger-based surveys appear automatically — manual presentation with present() is for precise control over timing.