Supported on: iOS SDK
1.0.61+ · Android SDK 1.0.33+ · Flutter SDK 1.0.3+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
present returns once the survey request has been dispatched to the native SDK. Whether the survey actually appears depends on the survey’s status, audience, and trigger rules configured in the Console — the SDK fires the survey_shown analytics event (and your delegate’s onSurveyPresented callback) when it does. If you need to confirm that a survey was shown to the user, observe the delegate rather than the return value.
Module Access
Module Methods
9 Question Types
Surveys support the following question types, configured in the Console:Question types and their content are defined entirely in the Console. The SDK renders them automatically based on the survey configuration.
scale is an accepted alias for likert, and scale_config for likert_config — both SDKs
read either spelling, because questions were stored under the older one before likert became
authorable. The Console writes the canonical names, so a survey created today uses likert and
likert_config.A max above 10 is refused at authoring time: the scale draws as one un-scrolling row of
fixed-width buttons, so a wider range would run off the edge of a phone. A min greater than
max is read as the range the other way round rather than drawing nothing.Question configuration
Each type reads its own config object on the question. Everything is optional; an unset value takes the default below.The emoji scale is read in order. The first entry is the worst and the last the best, and that
order is what sentiment routing uses — see Follow-up actions. A scale of any
length works.
Conditional questions
A question can carry ashow_if naming an EARLIER question and the answers that reveal it:
- Unanswered means hidden. If the question it references has not been answered yet, the conditional question is not shown.
- A blank
question_idmeans no condition. A half-configuredshow_ifshows the question rather than hiding it — otherwise a survey could render with nothing in it at all.
When a survey appears
trigger_rules on the survey decides this; no code is needed for a triggered survey.
Presenting with
present(...) from your own code ignores all of this except the survey’s own
status and audience.
Follow-up actions
When a survey completes, the SDK classifies the FIRST answer aspositive, negative or
neutral, and runs the matching branch of follow_up_actions.
A numeric type whose answer is NOT a number falls through to the emoji row, so a
csat survey
whose first question is an emoji scale is classified by that scale rather than coming back
neutral. An answer that is neither a number nor a member of the scale is always neutral.
Each branch is { action, message }:
Appearance
appearance on the survey:
appearance.theme may be a flat object, or { "light": { … }, "dark": { … } } — in the second
form the active variant is sparse-merged over the other, so a dark theme only needs the keys it
changes.
Plus the rich-media keys in the next section.
AppDNASurveyDelegate
All 3 methods on this delegate fire from the native survey pipeline alongside the existing analytics events. Register your delegate viaAppDNA.surveys.setDelegate(...).
onSurveyPresented(surveyId)— fires when the survey view appears (alongside thesurvey_shownevent).onSurveyCompleted(surveyId, responses)— fires when the user submits the final question.responsesis aList<Map<String, dynamic>>where each entry is an answer map of the shape{'questionId': String, 'answer': dynamic}, suitable for forwarding to your own analytics or CRM.onSurveyDismissed(surveyId)— fires when the user closes the survey before completing it (X button, swipe-to-dismiss, outside tap).
Response Shape
Theresponses list passed to onSurveyCompleted holds one answer map per answered question, each of the shape {'questionId': String, 'answer': dynamic}. The answer value type follows the question type:
Rich Media
Survey questions support rich media content configured in the Console:Option icons are not authorable.
choice_config.options[] accepts an icon through the API
and the survey editor has no control for it, so it cannot be set from the Console; it renders on
iOS and not on Android. Treat choice options as { id, label } until that is resolved.Auto-Tracked Events
Every event whose name beginssurvey_ carries survey_id. The two feedback_form_*
events are emitted by the form itself and carry only the fields named below.
feedback_form_submitted / feedback_form_dismissed come from the survey follow-up form — the
one follow_up_actions opens. There is no separate standalone form.reason on the dismissal is user (the Cancel button; on Android also a back press or a
tap outside the dialog) or presenter_released (the host navigated away and the form went with it —
a form the user never saw, which would otherwise be counted as one they closed).Full Example
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.
