|
| 1 | +--- |
| 2 | +title: Configure User Feedback |
| 3 | +sidebar_order: 6900 |
| 4 | +description: "Learn about general User Feedback configuration fields." |
| 5 | +--- |
| 6 | + |
| 7 | +## User Feedback Widget |
| 8 | + |
| 9 | +The User Feedback Widget offers many customization options, and if the available options are insufficient, you can [use your own UI](#bring-your-own-widget). |
| 10 | +The widget is a custom button that opens the form, a custom AlertDialog that allows users to submit feedback. |
| 11 | + |
| 12 | +### Hooks |
| 13 | + |
| 14 | +There are hooks available so you can react when the user opens or closes the form, successfully submits it, or an error is triggered: |
| 15 | + |
| 16 | +| Hook | Type | Description | |
| 17 | +| ----------------- | ------------------------- | ------------------------------------------------------------------------ | |
| 18 | +| `onFormOpen` | `() -> Void` | Called when the feedback form is opened. | |
| 19 | +| `onFormClose` | `() -> Void` | Called when the feedback form is closed. | |
| 20 | +| `onSubmitSuccess` | `(Feedback) -> Void` | Called when feedback is successfully submitted via the prepared form. | |
| 21 | +| `onSubmitError` | `(Feedback) -> Void` | Called when there is an error submitting feedback via the prepared form. | |
| 22 | + |
| 23 | +`onSubmitSuccess` and `onSubmitError` forward the feedback object that was submitted, which contains the following properties: |
| 24 | + |
| 25 | +- `message`: The message the user entered in the feedback form. |
| 26 | +- `name`: The name the user entered in the feedback form. |
| 27 | +- `contactEmail`: The email the user entered in the feedback form. |
| 28 | + |
| 29 | +Example: |
| 30 | + |
| 31 | +```java |
| 32 | +SentryAndroid.init(context, options -> { |
| 33 | + options.getFeedbackOptions().setOnFormOpen(() -> System.out.println("Form opened")); |
| 34 | + options.getFeedbackOptions().setOnFormClose(() -> System.out.println("Form closed")); |
| 35 | + options.getFeedbackOptions().setOnSubmitSuccess((feedback) -> System.out.println("Feedback submitted successfully: " + feedback.toString())); |
| 36 | + options.getFeedbackOptions().setOnSubmitError((feedback) -> System.out.println("Failed to submit feedback: " + feedback.toString())); |
| 37 | +}); |
| 38 | +``` |
| 39 | +```kotlin |
| 40 | +SentryAndroid.init(this) { options -> |
| 41 | + options.feedbackOptions.onFormOpen = Runnable { println("Form opened") } |
| 42 | + options.feedbackOptions.onFormClose = Runnable { println("Form closed") } |
| 43 | + options.feedbackOptions.onSubmitSuccess = SentryFeedbackOptions.SentryFeedbackCallback { |
| 44 | + println("Feedback submitted successfully: $it") |
| 45 | + } |
| 46 | + options.feedbackOptions.onSubmitError = SentryFeedbackOptions.SentryFeedbackCallback { |
| 47 | + println("Failed to submit feedback: $it") |
| 48 | + } |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +### Widget |
| 53 | + |
| 54 | +The widget is a custom button that opens the feedback form. As such, you can treat it like any View, customizing it through its XML attributes or programmatically. |
| 55 | +The default attributes of the widget are: |
| 56 | + |
| 57 | +| Attribute | Default Value | |
| 58 | +| -------------------------- | ------------------------------------------- | |
| 59 | +| `android:drawablePadding` | `4dp` | |
| 60 | +| `android:drawableStart` | `@drawable/baseline_campaign_24` | |
| 61 | +| `android:textAllCaps` | `false` | |
| 62 | +| `android:background` | `@drawable/oval_button_ripple_background` | |
| 63 | +| `android:padding` | `12dp` | |
| 64 | +| `android:textColor` | `?android:attr/colorForeground` | |
| 65 | +| `android:text` | `"Report a Bug"` | |
| 66 | + |
| 67 | +Example: |
| 68 | +```xml {filename:myLayout.xml} |
| 69 | +<?xml version="1.0" encoding="utf-8"?> |
| 70 | +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
| 71 | + android:layout_width="match_parent" |
| 72 | + android:layout_height="match_parent" |
| 73 | + android:orientation="vertical"> |
| 74 | + |
| 75 | + <io.sentry.android.core.SentryUserFeedbackButton |
| 76 | + android:layout_width="wrap_content" |
| 77 | + android:layout_height="wrap_content"/> |
| 78 | +</LinearLayout> |
| 79 | +``` |
| 80 | +```java |
| 81 | +import io.sentry.android.core.SentryUserFeedbackButton; |
| 82 | + |
| 83 | +SentryUserFeedbackButton widget = new SentryUserFeedbackButton(context); |
| 84 | +``` |
| 85 | +```kotlin |
| 86 | +import io.sentry.android.core.SentryUserFeedbackButton |
| 87 | + |
| 88 | +val widget = SentryUserFeedbackButton(context) |
| 89 | +``` |
| 90 | + |
| 91 | +### Form Configuration |
| 92 | + |
| 93 | +You can customize which form elements are shown, whether they are required, and even prefill some info, in `SentryOptions.SentryFeedbackOptions`: |
| 94 | + |
| 95 | +| Option | Type | Default | Description | |
| 96 | +| ----------------------------- | -------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | |
| 97 | +| `showBranding` | `Bool` | `true` | Displays the Sentry logo inside the form | |
| 98 | +| `isNameRequired` | `Bool` | `false` | Requires the name field on the feedback form to be filled in. | |
| 99 | +| `showName` | `Bool` | `true` | Displays the name field on the feedback form. Ignored if `isNameRequired` is `true`. | |
| 100 | +| `isEmailRequired` | `Bool` | `false` | Requires the email field on the feedback form to be filled in. | |
| 101 | +| `showEmail` | `Bool` | `true` | Displays the email field on the feedback form. Ignored if `isEmailRequired` is `true`. | |
| 102 | +| `useSentryUser` | `Bool` | `true` | Sets the `email` and `name` fields to the corresponding Sentry SDK user fields that were called with `SentrySDK.setUser`. | |
| 103 | + |
| 104 | +Example: |
| 105 | + |
| 106 | +```xml {filename:AndroidManifest.xml} |
| 107 | +<application> |
| 108 | + <meta-data android:name="io.sentry.feedback.is-name-required" android:value="true" /> |
| 109 | + <meta-data android:name="io.sentry.feedback.show-name" android:value="false" /> |
| 110 | + <meta-data android:name="io.sentry.feedback.is-email-required" android:value="false" /> |
| 111 | + <meta-data android:name="io.sentry.feedback.show-email" android:value="false" /> |
| 112 | + <meta-data android:name="io.sentry.feedback.use-sentry-user" android:value="false" /> |
| 113 | + <meta-data android:name="io.sentry.feedback.show-branding" android:value="false" /> |
| 114 | +</application> |
| 115 | +``` |
| 116 | +```java |
| 117 | +SentryAndroid.init(context, options -> { |
| 118 | + options.getFeedbackOptions().setNameRequired(true); |
| 119 | + options.getFeedbackOptions().setShowName(false); |
| 120 | + options.getFeedbackOptions().setEmailRequired(true); |
| 121 | + options.getFeedbackOptions().setShowEmail(false); |
| 122 | + options.getFeedbackOptions().setUseSentryUser(false); |
| 123 | + options.getFeedbackOptions().setShowBranding(false); |
| 124 | +}); |
| 125 | +``` |
| 126 | +```kotlin |
| 127 | +SentryAndroid.init(this) { options -> |
| 128 | + options.feedbackOptions.isNameRequired = true |
| 129 | + options.feedbackOptions.isShowName = false |
| 130 | + options.feedbackOptions.isEmailRequired = true |
| 131 | + options.feedbackOptions.isShowEmail = false |
| 132 | + options.feedbackOptions.isUseSentryUser = false |
| 133 | + options.feedbackOptions.isShowBranding = false |
| 134 | +} |
| 135 | +``` |
| 136 | + |
| 137 | +### Form Label Customization |
| 138 | + |
| 139 | +You can customize the labels and placeholders used in the form. |
| 140 | +Note: manifest options are not supported here, due to internationalization: |
| 141 | + |
| 142 | +| Option | Type | Default | Description | |
| 143 | +| ----------------------------- | -------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- | |
| 144 | +| `formTitle` | `String` | `"Report a Bug"` | The title of the feedback form. | |
| 145 | +| `messageLabel` | `String` | `"Description"` | The label of the feedback description input field. | |
| 146 | +| `messagePlaceholder` | `String` | `"What's the bug? What did you expect?"` | The placeholder in the feedback description input field. | |
| 147 | +| `isRequiredLabel` | `String` | `" (Required)"` | The text to attach to the title label for a required field. | |
| 148 | +| `successMessageText` | `String` | `"Thank you for your report!"` | The message displayed after a successful feedback submission. | |
| 149 | +| `nameLabel` | `String` | `"Name"` | The label next to the name input field. | |
| 150 | +| `namePlaceholder` | `String` | `"Your Name"` | The placeholder in the name input field. | |
| 151 | +| `emailLabel` | `String` | `"Email"` | The label next to the email input field. | |
| 152 | +| `emailPlaceholder` | `String` | `"your.email@example.org"` | The placeholder in the email input field. | |
| 153 | +| `submitButtonLabel` | `String` | `"Send Bug Report"` | The label of the submit button. | |
| 154 | +| `cancelButtonLabel` | `String` | `"Cancel"` | The label of the cancel button. | |
| 155 | + |
| 156 | +Example: |
| 157 | + |
| 158 | +```java |
| 159 | +SentryAndroid.init(context, options -> { |
| 160 | + options.getFeedbackOptions().setFormTitle("We want to hear from you!"); |
| 161 | + options.getFeedbackOptions().setMessageLabel("Feedback"); |
| 162 | + options.getFeedbackOptions().setMessagePlaceholder("Type your feedback"); |
| 163 | + options.getFeedbackOptions().setIsRequiredLabel(" *"); |
| 164 | + options.getFeedbackOptions().setSuccessMessageText("Thanks for the feedback!"); |
| 165 | + options.getFeedbackOptions().setNameLabel("Full Name"); |
| 166 | + options.getFeedbackOptions().setNamePlaceholder("Type your full name"); |
| 167 | + options.getFeedbackOptions().setEmailLabel("Email Address"); |
| 168 | + options.getFeedbackOptions().setEmailPlaceholder("Type your email"); |
| 169 | + options.getFeedbackOptions().setSubmitButtonLabel("Submit"); |
| 170 | + options.getFeedbackOptions().setCancelButtonLabel("Back"); |
| 171 | +}); |
| 172 | +``` |
| 173 | +```kotlin |
| 174 | +SentryAndroid.init(this) { options -> |
| 175 | + options.feedbackOptions.formTitle = "We want to hear from you!" |
| 176 | + options.feedbackOptions.messageLabel = "Feedback" |
| 177 | + options.feedbackOptions.messagePlaceholder = "Type your feedback" |
| 178 | + options.feedbackOptions.isRequiredLabel = " *" |
| 179 | + options.feedbackOptions.successMessageText = "Thanks for the feedback!" |
| 180 | + options.feedbackOptions.nameLabel = "Full Name" |
| 181 | + options.feedbackOptions.namePlaceholder = "Type your full name" |
| 182 | + options.feedbackOptions.emailLabel = "Email Address" |
| 183 | + options.feedbackOptions.emailPlaceholder = "Type your email" |
| 184 | + options.feedbackOptions.submitButtonLabel = "Submit" |
| 185 | + options.feedbackOptions.cancelButtonLabel = "Back" |
| 186 | +} |
| 187 | +``` |
| 188 | + |
| 189 | +### Theme Customization |
| 190 | + |
| 191 | +The User Feedback form integrates with the app theme by default, and can be customized with a custom xml style. |
| 192 | +Here are the attributes used by the form: |
| 193 | + |
| 194 | +| Android style attribute | Description | |
| 195 | +| --------------------------------- | ----------------------------------------------------------- | |
| 196 | +| `android:windowTitleStyle` | Style of the feedback dialog title | |
| 197 | +| `android:textColor` | Color of title, cancel button text, and non-editable texts. | |
| 198 | +| `android:editTextColor` | Color of editable texts. | |
| 199 | +| `android:textColorHint` | Color of the hint of editable texts. | |
| 200 | +| `android:textColorPrimaryInverse` | Color of the send button text. | |
| 201 | +| `android:colorPrimary` | Background color of the send button. | |
| 202 | +| `android:colorBackground` | Background color of the cancel button. | |
| 203 | +| `android:colorForeground` | Color tint of the image logo. | |
| 204 | + |
| 205 | +The theme used by the form is the one set in the application theme as the `android:dialogTheme`. |
| 206 | +A custom theme can be also set when instantiating it: |
| 207 | + |
| 208 | +```java |
| 209 | +SentryUserFeedbackDialog dialog = new SentryUserFeedbackDialog.Builder(context, R.style.MyAppDialogTheme).create(); |
| 210 | +``` |
| 211 | +```kotlin |
| 212 | +val dialog = SentryUserFeedbackDialog.Builder(context, R.style.MyAppDialogTheme).create() |
| 213 | +``` |
| 214 | + |
| 215 | +Here is an example of how the feedback form can be customized: |
| 216 | + |
| 217 | +```xml {filename:styles.xml} |
| 218 | +<!-- Application theme. --> |
| 219 | +<style name="MyAppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> |
| 220 | + <!-- ... Current theme customizations ... --> |
| 221 | + |
| 222 | + <!-- Set a dialog theme if not already done. --> |
| 223 | + <item name="android:dialogTheme">@style/MyAppDialogTheme</item> |
| 224 | +</style> |
| 225 | + |
| 226 | +<!-- Edit application dialog theme. --> |
| 227 | +<style name="MyAppDialogTheme" parent="Theme.MaterialComponents.DayNight.Dialog"> |
| 228 | + <!-- Set the style of the feedback dialog title. --> |
| 229 | + <item name="android:windowTitleStyle">@style/FeedbackFormTitleStyle</item> |
| 230 | + |
| 231 | + <!-- Set the color of title, cancel button text, and non editable texts. --> |
| 232 | + <item name="android:textColor">@color/colorPrimary</item> |
| 233 | + <!-- Set the color of editable texts. --> |
| 234 | + <item name="android:editTextColor">@color/colorPrimaryDark</item> |
| 235 | + <!-- Set the color of the hint of editable texts. --> |
| 236 | + <item name="android:textColorHint">@color/colorPrimaryDark</item> |
| 237 | + <!-- Set the color of the send button text. --> |
| 238 | + <item name="android:textColorPrimaryInverse">@android:color/white</item> |
| 239 | + |
| 240 | + <!-- Set the background color of the send button. --> |
| 241 | + <item name="android:colorPrimary">@color/colorPrimary</item> |
| 242 | + <!-- Set the background color of the cancel button. --> |
| 243 | + <item name="android:colorBackground">@android:color/black</item> |
| 244 | + <!-- Set the color tint of the image logo. --> |
| 245 | + <item name="android:colorForeground">@color/colorPrimary</item> |
| 246 | +</style> |
| 247 | + |
| 248 | +<style name="FeedbackFormTitleStyle"> |
| 249 | + <!-- Customize your theme here. --> |
| 250 | + <item name="android:textAppearance">@style/TextAppearance.AppCompat.Title</item> |
| 251 | +</style> |
| 252 | +``` |
| 253 | + |
| 254 | +### Bring Your Own Widget |
| 255 | + |
| 256 | +You can also use your own UI components to gather feedback and pass the feedback data object to the `Sentry.captureFeedback(Feedback)` function: |
| 257 | + |
| 258 | +```java |
| 259 | +import io.sentry.Sentry; |
| 260 | +import io.sentry.protocol.Feedback; |
| 261 | + |
| 262 | +Feedback feedback = new Feedback("I encountered a bug while using the app."); |
| 263 | +feedback.setName("John Doe"); |
| 264 | +feedback.setContactEmail("john.doe@example.com"); |
| 265 | +// Optionally associate the feedback with an event |
| 266 | +SentryId sentryId = Sentry.captureMessage("My message"); |
| 267 | +feedback.setAssociatedEventId(sentryId); |
| 268 | +Sentry.captureFeedback(feedback); |
| 269 | +``` |
| 270 | +```kotlin |
| 271 | +import io.sentry.Sentry |
| 272 | +import io.sentry.protocol.Feedback |
| 273 | + |
| 274 | +val feedback = Feedback("I encountered a bug while using the app.") |
| 275 | +feedback.name = "John Doe" |
| 276 | +feedback.contactEmail = "john.doe@example.com" |
| 277 | +// Optionally associate the feedback with an event |
| 278 | +val sentryId = Sentry.captureMessage("My message") |
| 279 | +feedback.associatedEventId = sentryId |
| 280 | +Sentry.captureFeedback(feedback) |
| 281 | +``` |
0 commit comments