Skip to main content

Submitting User Feedback

Beta release

Getting feedback from users and testers is crucial in the app development process. It provides valuable insights and helps improve the overall user experience. Sauce Labs Mobile App Distribution offers an effortless way to collect feedback through its In-App Feedback feature. By integrating the Sauce Mobile Beta SDK into your app, you can enable users to report bugs, suggest improvements, and share their thoughts directly in the app.

Using In-App Feedback​

If you added the Sauce Mobile Beta SDK to your app, testers can report feedback by shaking the device. Shake to report is controlled by the In-app bug reporting setting of your app, which is on by default. To check or change it:

  1. Open the app in the Sauce Labs Mobile App Distribution dashboard and click SDK Settings.
  2. Turn In-app bug reporting on or off.
  3. Click Save SDK Settings.

The setting applies to sessions that start after you save. Account Owners and Org Admins can change SDK settings.

When a tester shakes the device, the SDK asks "Would you like to provide feedback?" If the tester agrees, the feedback form opens, and the tester can report a bug or share a suggestion.

The feedback is added to the session the tester is running. It appears on the Feedback page of the dashboard and on the session's Feedback tab, where Seek Video jumps the session replay to the moment the tester submitted it. See Viewing Feedback.

Feedback Contents​

When users provide feedback using the In-App Feedback feature, the following information is included:

  • Text - The comment the tester writes to describe the issue or suggestion.
  • Email - The email address the tester enters, if the form shows the email field.
  • Screenshot - A screenshot of the app at the moment the feedback form opened. On iOS, the tester can edit or remove the screenshot before sending.
  • Device and app information - The device model, the OS version, and the app version.
  • Session - The session the tester is running, and how far into the session the tester submitted the feedback.
  • Custom fields - The values of any custom fields you add to the form. See Customizing the Feedback Form.

Customizing In-App Feedback​

Sauce Labs Mobile App Distribution allows you to customize the way In-App Feedback is collected. If you prefer not to use the shake gesture for feedback collection, you can programmatically invoke the feedback form using a button click or any other gesture in your app. This way, users can access the feedback form from a designated area in the app, like the help menu or after encountering unexpected errors.

If you choose to invoke the feedback form programmatically, it is shown even if In-app bug reporting is turned off in your app's SDK settings.

TestFairy.showFeedbackForm();
Example
// Be sure to import the SDK
import com.testfairy.TestFairy;

// Can be invoked on a button press
// or after your app passes a given page
TestFairy.showFeedbackForm();
note

showFeedbackForm() requires a running session. To collect feedback without a session, call TestFairy.showFeedbackForm(context, "<sauce-mobile-beta-token>", true). For custom fields, validation and callbacks, see Customizing the Feedback Form.

Customizing the Feedback Form​

The built-in form has an email field, a message field and, depending on the platform, buttons to attach a screenshot or a screen recording. You customize it by building a feedback options object and handing it to the SDK before the form is shown. Doing so before beginWithoutCrashHandler is fine. The feedback classes are in the TestFairy module on iOS and the com.testfairy package on Android.

The form can be shown in two ways. showFeedbackForm() with no arguments requires a running session and attaches the feedback to it. The overload that takes the app token (showFeedbackForm(context, appToken, takeScreenshot) on Android, showFeedbackForm(appToken, takeScreenshot:) on iOS and showFeedbackForm(appToken, takeScreenshot) on React Native) works without a session and optionally captures a screenshot first. The feedback appears on the Feedback page of the dashboard, without a session.

Rules that apply on Android and iOS:

  • Setting a list of form fields replaces the default fields. To keep the email and message fields, add them yourself with the reserved attribute names :userId (email or user identifier) and :text (message). Always include a :text field.
  • Every other field is sent with the feedback as a feedback attribute named after the field's attribute key, so pick short, stable names.
  • Three field types are built in: single-line text (String), multi-line text (TextArea) and a dropdown list (Select, a map of label to value). You can add up to 32 fields. Attribute names must be non-empty and unique (duplicates are dropped). For any other control, implement the FeedbackFormField interface (onCreateView, getAttribute, getValue) yourself.
  • The reserved fields are pre-filled by the SDK (last used email, unsent draft). The defaultText option only applies to the built-in form and is ignored after you set custom fields.
  • Email is mandatory by default. Hiding the email field lifts the requirement, and so does a custom field list without a :userId field.
  • A custom verifier replaces the SDK's default validation (email present and valid when mandatory, non-empty message), so re-implement the checks you still want.
import com.testfairy.FeedbackContent;
import com.testfairy.FeedbackFormField;
import com.testfairy.FeedbackOptions;
import com.testfairy.FeedbackVerifier;
import com.testfairy.SelectFeedbackFormField;
import com.testfairy.StringFeedbackFormField;
import com.testfairy.TestFairy;
import com.testfairy.TextAreaFeedbackFormField;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

Map<String, String> types = new LinkedHashMap<>(); // label -> value
types.put("Bug", "bug");
types.put("Feature request", "feature");

List<FeedbackFormField> fields = new ArrayList<>();
// Reserved names keep the built-in fields (attribute, placeholder, default value):
fields.add(new StringFeedbackFormField(":userId", "Your email", ""));
fields.add(new TextAreaFeedbackFormField(":text", "Describe the problem", ""));
// Your own fields (any attribute name):
fields.add(new StringFeedbackFormField("phone", "Phone number", ""));
fields.add(new SelectFeedbackFormField("type", "Is this a bug or a feature request?", types, "Bug")); // the default is a label

FeedbackOptions options = new FeedbackOptions.Builder()
.setFeedbackFormFields(fields)
.setEmailMandatory(false) // default true; only enforced when a :userId field exists
.setTakeScreenshotButtonVisible(true)
.setRecordVideoButtonVisible(false)
.setFeedbackInterceptor(content -> content) // optional: inspect or modify before sending; never return null
.setCallback(new FeedbackOptions.Callback() { // optional
@Override public void onFeedbackSent(FeedbackContent content) {}
@Override public void onFeedbackCancelled() {}
@Override public void onFeedbackFailed(int reason, FeedbackContent content) {}
})
.build();
TestFairy.setFeedbackOptions(options);

// Optional: custom validation (returning false blocks sending and shows your message)
TestFairy.setFeedbackVerifier(new FeedbackVerifier() {
@Override public boolean verifyFeedback(FeedbackContent content) {
return content.getEmail().endsWith("@yourcompany.com") && !content.getText().isEmpty();
}
@Override public String getVerificationFailedMessage() {
return "Please use your company email and describe the issue.";
}
});

// Show the form from a button after beginWithoutCrashHandler ...
TestFairy.showFeedbackForm();
// ... or without a running session, optionally taking a screenshot first:
TestFairy.showFeedbackForm(context, "<sauce-mobile-beta-token>", true);
Other FeedbackOptions.Builder options:
  • setEmailFieldVisible(boolean) hides the email field (and lifts the mandatory requirement).
  • setDefaultText(String) pre-fills the message of the built-in form.
  • setBrowserUrl(String) opens your own web form in the browser instead of the native form. The SDK appends sessionUrl, timestamp, user (your setUserId value), platform, packageName, versionName, versionCode and screenName as query parameters. The other options do not apply in this mode.
Shake trigger: call TestFairy.enableFeedbackForm("shake") (Android accepts only "shake") or TestFairy.disableFeedbackForm() before beginWithoutCrashHandler.