Skip to main content
Supported on: iOS SDK 1.0.61+
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")

Module Access

let surveys = AppDNA.surveys

Module Methods

MethodSignatureDescription
presentpresent(_ surveyId: String)Present a survey manually
setDelegatesetDelegate(_ delegate: AppDNASurveyDelegate?)Set a delegate for survey callbacks

8 Question Types

Surveys support the following question types, configured in the Console:
TypeDisplayResponse
nps0-10 numeric scaleInteger 0-10
csat1-5 satisfaction scaleInteger 1-5
ratingStar ratingInteger 1-5
emoji_scaleEmoji optionsSelected emoji value
yes_noBinary choiceBoolean
single_choiceRadio button optionsSelected option string
multi_choiceCheckbox optionsArray of selected strings
free_textText input fieldFree-form string
Question types and their content are defined entirely in the Console. The SDK renders them automatically based on the survey configuration.

AppDNASurveyDelegate

All 3 methods on this delegate fire from SurveyManager alongside the existing 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 the public [SurveyResponse] array (one entry per answered question with questionId + answer), 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).
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())

Rich Media

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

EventTrigger
survey_presentedA survey is displayed
survey_response_submittedUser submits a survey response
survey_dismissedSurvey 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.