iOS SDK
Rage-shake feedback
Let customers shake their phone to report an issue with a screenshot they can review before sending.
Enable rage-shake feedback
Let customers report a pairing failure, stalled sync, or confusing device screen while it is happening. A deliberate shake opens a feedback prompt, followed by a composer where they can describe the issue and review a screenshot before sending it.
Shake and screenshot triggers are disabled by default. Opt in during configuration when they fit your product.
Image markup and resilient background delivery require BTXClientKit 3.1.0 or later. Mosaic and cropping require BTXClientKit 3.4.0 or later, with no additional host configuration.
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.
- Opening an attached image provides markup, mosaic, and cropping with shared undo and redo.
- Done flattens the edits into the attachment and removes original EXIF/GPS metadata. Cancel preserves the original draft.
- Selected photos and videos remain local until the customer sends.
- Send saves the report on the device, closes the composer, and retries delivery while the app is active or on a later activation.
- Successful delivery 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.
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 thread purpose so operator surfaces can distinguish it without separating the customer history.
The compact composer uses a bounded, customer-scoped device outbox. This means
customers can submit without a connection and do not wait for the network in
the composer. Pending reports stay associated with the project and identified
customer that created them. The direct non-UI submitFeedback(...) API still
awaits the server response and returns its delivery result.
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.
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
After a firmware update, ask how the experience went. Use one stable update-session ID so later rating changes and comments stay in the same feedback thread. The sample device and update IDs below come from your app.
These contextual feedback APIs require BTXClientKit 2.2.0 or later.
let updateFeedback = BTXLaunchContext(
conversationPurpose: .feedback,
entryPoint: "firmware_update_complete",
sourceType: "firmware_update",
sourceID: "update_456",
threadTitle: "Firmware update feedback",
threadAttributes: [
"device": [
"id": .string("ring_123"),
"firmwareVersion": .string("2.3.7")
]
]
)
let prompt = BTXFeedbackPrompt(
subject: "Firmware update",
question: "What went wrong during the update?",
choices: ["Update stalled", "Device disconnected", "Unclear instructions"]
)
await BTX.messenger.submitFeedback(
rating: .positive,
subject: "Firmware update",
launchContext: updateFeedback
)
BTX.messenger.presentFeedbackReport(
rating: .negative,
previousRating: .positive,
prompt: prompt,
launchContext: updateFeedback
)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 when the presented composer has safely saved the report on the device. Its thread ID is nil until background delivery finishes.