Embed the Quackback feedback widget in your iOS app with a single floating launcher button or programmatic open/close.
- iOS 15+
- Swift 5.9+
Add the package in Xcode: File > Add Package Dependencies, then enter the repository URL:
https://github.com/quackback/quackback-ios
Or add it directly to your Package.swift:
dependencies: [
.package(url: "https://github.com/quackback/quackback-ios", from: "1.0.0"),
],
targets: [
.target(name: "YourApp", dependencies: ["Quackback"]),
]import Quackback
// 1. Configure once at app startup
Quackback.configure(QuackbackConfig(
instanceUrl: URL(string: "https://feedback.yourapp.com")!
))
// 2. Identify the current user
Quackback.identify(userId: "user_123", email: "user@example.com", name: "Jane Smith")
// or, with a server-signed token (recommended for production):
Quackback.identify(ssoToken: fetchedSsoToken)
// or, for unauthenticated visitors:
Quackback.identify()
// 3. Show the floating launcher button
Quackback.showLauncher()
// 4. On logout
Quackback.logout()Turn on Verified identity only in Admin → Settings → Widget to require ssoToken for every identified user. See the Identify users guide for JWT claims and server examples.
| Method | Description |
|---|---|
Quackback.configure(_ config: QuackbackConfig, identity: Identity? = nil) |
Set up the SDK. Pass an optional Identity to bundle identification into the same call. |
Quackback.identify() |
Start an anonymous session. The widget prompts for an email inline the first time the user posts. |
Quackback.identify(userId:email:name:avatarURL:) |
Identify the current user with their details. Simplest option, works out of the box. |
Quackback.identify(ssoToken:) |
Identify the current user with a server-signed JWT. Blocks impersonation. |
Quackback.logout() |
Clear the current user identity. |
Quackback.metadata(_:) |
Attach session metadata ([String: String?]) to feedback. Pass nil values to remove keys. |
Pass an Identity value to configure(_:identity:) to bundle identification at setup time:
Quackback.configure(config, identity: .user(id: "u_123", email: "a@b.com", name: "Ada"))
Quackback.configure(config, identity: .ssoToken("jwt..."))
// Omit the `identity` parameter for anonymous sessions — it's the default.| Quackback.open(view:title:board:) | Open the feedback panel. All parameters optional — see Open options. |
| Quackback.close() | Dismiss the feedback panel. |
| Quackback.showLauncher() | Add the floating launcher button to the key window. |
| Quackback.hideLauncher() | Remove the floating launcher button. |
| Quackback.on(_:handler:) -> EventToken | Subscribe to a widget event. Returns a token for removal. |
| Quackback.off(_ token: EventToken) | Unsubscribe a previously registered listener. |
| Quackback.destroy() | Tear down the SDK entirely (removes WebView, launcher, and all listeners). |
QuackbackConfig(
instanceUrl: URL, // required — your Quackback instance URL
theme: QuackbackTheme = .system, // .light | .dark | .system
placement: QuackbackPosition = .bottomRight, // .bottomRight | .bottomLeft
locale: String? = nil // BCP-47 locale e.g. "fr", "de"
)Attach key-value context to the widget session. Stored on posts created through the widget.
Quackback.metadata(["page": "/settings", "app_version": "2.4.1"])
// Pass nil to remove a key:
Quackback.metadata(["page": nil])Quackback.open(view:title:board:) pre-fills the widget panel:
Quackback.open() // home
Quackback.open(board: "feature-requests") // board filter
Quackback.open(view: .newPost, title: "Bug: crash on save", board: "bugs") // new-post form
Quackback.open(view: .changelog) // changelog feedSubscribe to events emitted by the widget:
let token = Quackback.on(.vote) { data in
print("User voted on post:", data["postId"] ?? "")
}
// Remove the listener when no longer needed
Quackback.off(token)| Event | Payload keys | Description |
|---|---|---|
.ready |
— | Widget has loaded and initialised. |
.vote |
postId, direction |
User voted on a post. |
.submit |
postId, title |
User submitted new feedback. |
.close |
— | User closed the panel (panel dismisses automatically). |
.navigate |
board, postId |
User navigated within the widget. |
MIT