> ## Documentation Index
> Fetch the complete documentation index at: https://docs.appdna.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# React Native Surveys & Feedback

> Collect NPS, CSAT, and custom feedback with 8 question types

<Info>
  **Supported on:** iOS SDK `1.0.61+` · Android SDK `1.0.33+` · React Native SDK `1.0.4+`
</Info>

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

```typescript theme={null}
import { AppDNA } from '@appdna/react-native-sdk';

await AppDNA.surveys.present('nps_q1_2026');
```

`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_presented` 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

```typescript theme={null}
const surveys = AppDNA.surveys;
```

### Module Methods

| Method        | Signature                                    | Description                           |                                               |
| ------------- | -------------------------------------------- | ------------------------------------- | --------------------------------------------- |
| `present`     | `present(surveyId: string): Promise<void>`   | Request that the SDK present a survey |                                               |
| `setDelegate` | \`setDelegate(delegate: AppDNASurveyDelegate | null): void\`                         | Set a delegate for survey lifecycle 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       | List of selected strings |
| `free_text`     | Text input field       | Free-form string         |

<Info>
  Question types and their content are defined entirely in the Console. The SDK renders them automatically based on the survey configuration.
</Info>

## AppDNASurveyDelegate

All 3 methods on this delegate fire from the native survey pipeline 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 a `Record<string, unknown>` keyed by question ID containing the user's answers, 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:

```typescript theme={null}
import { AppDNA, AppDNASurveyDelegate } from '@appdna/react-native-sdk';

const feedbackHandler: AppDNASurveyDelegate = {
  onSurveyPresented(surveyId) {
    console.log(`Survey shown: ${surveyId}`);
  },

  onSurveyCompleted(surveyId, responses) {
    const score = responses.nps_question as number | undefined;
    if (score !== undefined) {
      if (score >= 9) {
        showReferralPrompt();
      } else if (score <= 6) {
        showSupportLink();
      }
    }
    const feedback = responses.free_text_question as string | undefined;
    if (feedback) {
      console.log(`User feedback: ${feedback}`);
    }
  },

  onSurveyDismissed(surveyId) {
    console.log(`Survey dismissed: ${surveyId}`);
  },
};

AppDNA.surveys.setDelegate(feedbackHandler);
```

### Response Shape

The `responses` object passed to `onSurveyCompleted` is keyed by `questionId`. Value types follow the question type:

| Question Type                               | Value Type |
| ------------------------------------------- | ---------- |
| `nps`, `csat`, `rating`                     | `number`   |
| `yes_no`                                    | `boolean`  |
| `single_choice`, `emoji_scale`, `free_text` | `string`   |
| `multi_choice`                              | `string[]` |

## 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](/sdks/react-native/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

```typescript theme={null}
import { AppDNA, AppDNASurveyDelegate } from '@appdna/react-native-sdk';

export class FeedbackManager implements AppDNASurveyDelegate {
  constructor() {
    AppDNA.surveys.setDelegate(this);
  }

  /** Present NPS survey after a key moment */
  async askForFeedback(): Promise<void> {
    await AppDNA.surveys.present('nps_q1_2026');
  }

  onSurveyPresented(surveyId: string): void {
    // Survey is visible
  }

  onSurveyCompleted(surveyId: string, responses: Record<string, unknown>): void {
    const score = responses.nps_question as number | undefined;
    if (score === undefined) return;

    if (score >= 9) {
      showReferralPrompt();
    } else if (score <= 6) {
      showSupportLink();
    }
  }

  onSurveyDismissed(surveyId: string): void {
    // User dismissed without responding
  }
}
```

<Note>
  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.
</Note>
