iOS SDK
Collect product feedback
Open a compact feedback composer from a button, shake gesture, or screenshot prompt.
Present feedback from your interface
Connect your own Feedback or Report a problem button to the compact feedback composer.
BTX.messenger.presentFeedbackReport(
includeScreenshot: true
)includeScreenshot controls this presentation only. The captured app window remains a removable local draft and uploads only if the customer sends the report.
Collect feedback about app content
Use contextual feedback when the customer is rating a host-owned item such as a card, report, recommendation, or completed session. Use one stable source identity for that item so later rating changes and comments stay in the same replyable feedback thread.
These contextual feedback APIs require BTXClientKit 2.2.0 or later.
let feedbackContext = BTXConversationStarterSource.topic(
id: "card-feedback-(card.id)",
title: "Card feedback",
topicType: "card",
topicID: card.id,
topicTitle: card.title,
rows: [
BTXThreadIntroRow(label: "Card type", value: card.type),
BTXThreadIntroRow(label: "Card text", value: card.text)
],
threadTitle: "Card feedback"
).launchContext(
baseLaunchContext: BTXLaunchContext(
entryPoint: .feedback(
appName: "Your App",
threadTitle: "Card feedback"
)
)
)
let prompt = BTXFeedbackPrompt(
subject: "Card",
question: "What could be better?",
choices: [
"Not relevant to me",
"Incorrect",
"Repetitive",
"Not useful"
],
textPlaceholder: "Tell us more (optional)"
)
// Positive feedback can submit without interrupting the customer.
let result = await BTX.messenger.submitFeedback(
rating: .positive,
subject: "Card",
launchContext: feedbackContext
)
// Negative feedback can collect reasons and an optional comment.
BTX.messenger.presentFeedbackReport(
rating: .negative,
previousRating: .positive,
prompt: prompt,
launchContext: feedbackContext,
includeScreenshot: false
) { result in
// Reflect success or failure in your host UI.
}submitFeedback(...)sends feedback without presenting SDK UI.presentFeedbackReport(...)shows selectable reasons and optional text.previousRatingrecords an explicit change instead of silently replacing the earlier rating.onSubmittedreports whether BTX accepted the feedback and returns the thread ID when available.
Enable automatic triggers
Shake and screenshot triggers are disabled by default. Opt in during configuration when they fit your product.
BTX.configure(
BTXConfiguration(
publishableClientKey: "cfk_...",
features: [.messenger],
messengerOptions: BTXMessengerOptions(
feedback: BTXFeedbackOptions(
onShake: .enabled(includeScreenCapture: true),
onScreenshot: .enabled
)
)
)
)- A deliberate shake opens a confirmation sheet before the composer, with one “Share feedback or bug” action and a shake toggle.
- A user screenshot can show a dismissible feedback prompt.
- Selected photos and videos remain local until the customer sends.
- Submitting creates a replyable customer-message thread.
BTX uses repeated back-and-forth motion, a startup settling period, and a cooldown to reduce accidental prompts. Motion sampling pauses while the app is inactive or feedback capture is suspended. These are SDK tuning choices, not an iOS sensitivity standard.
Offer a shake preference in Settings
In BTXClientKit 2.3.0 or later, bind your Settings toggle to the same observable preference used by the shake confirmation sheet.
struct FeedbackSettings: View {
@ObservedObject private var preferences = BTX.feedbackPreferences
var body: some View {
Toggle("Shake to send feedback", isOn: $preferences.isShakeEnabled)
}
}BTX.feedbackPreferences.isShakeEnabled defaults to true and persists on the device across sign-out and relaunch. It does not enable the feature by itself: the host must opt in with onShake, and an identified customer is still required. Turning it off leaves manual and screenshot feedback available.
Understand the feedback flow
Feedback reports use the same customer identity and message transport as customer support. BTX marks the new thread with the feedback conversation purpose so operator surfaces can distinguish it without separating the customer history.