Embed the widget in mobile apps

Add the Quackback widget to native iOS and Android apps (open source preview): install from GitHub, configure, identify signed-in users with a server-signed ssoToken, open views, and listen to events.

JM
James Morton
Written By James MortonLast updated 8 days ago

The iOS and Android SDKs embed the Quackback widget in your native app, with a floating launcher, signed-in user identification, and event callbacks. This article covers installing, configuring, and identifying users on each platform.

The mobile SDKs wrap the web widget, so the tabs, settings, and identification rules are the same as on the web. See Widget overview.

The SDKs are open source and in preview. They have no tagged releases yet, so install them from GitHub, and expect the APIs below to change before 1.0: quackback-ios and quackback-android.

iOS

Requirements

  • iOS 15 or later
  • Swift 5.9 or later

Install with Swift Package Manager

In Xcode, go to File > Add Package Dependencies, enter the URL below, and set the dependency rule to Branch: main:

https://github.com/QuackbackIO/quackback-ios

Or add it to your Package.swift:

dependencies: [
    .package(url: "https://github.com/QuackbackIO/quackback-ios", branch: "main"),
],
targets: [
    .target(name: "YourApp", dependencies: ["Quackback"]),
]

Configure and identify

import Quackback

// 1. Configure once at app startup
Quackback.configure(QuackbackConfig(
    instanceUrl: URL(string: "https://feedback.yourapp.com")!,
    locale: "fr"  // optional; omit to auto-detect
))

// 2. Identify the signed-in user with a token signed by your server
Quackback.identify(ssoToken: fetchedSsoToken)
// Skip identify for anonymous visitors

// 3. Show the floating launcher
Quackback.showLauncher()

The ssoToken is the same short-lived JWT the web widget uses. Have your backend sign it and send it to the app. See Identify users.

If you already know the user at startup, pass the identity to configure:

Quackback.configure(
    QuackbackConfig(instanceUrl: URL(string: "https://feedback.yourapp.com")!),
    identity: .ssoToken(fetchedSsoToken)
)
// Omit `identity` for anonymous sessions.

Configuration options

QuackbackConfig(
    instanceUrl: URL,                           // required: your Quackback URL
    theme: QuackbackTheme = .system,            // .light | .dark | .system
    placement: QuackbackPosition = .bottomRight, // .bottomRight | .bottomLeft
    locale: String? = nil                       // e.g. "en", "fr", "de"
)

Open programmatically

Quackback.open()                          // default view
Quackback.open(board: "feature-requests") // a specific board

Listen to events

let token = Quackback.on(.vote) { data in
    print("Voted on post:", data["postId"] ?? "")
}

// Stop listening
Quackback.off(token)

Event

Payload keys

Description

.ready

-

Widget loaded

.vote

postId, direction

User voted

.submit

postId, title

User submitted feedback

.close

-

Panel dismissed

Clean up

Quackback.logout()   // clear the identity
Quackback.destroy()  // tear down the SDK

Android

Requirements

  • Android API 24 or later
  • AndroidX

Install from source

The Android SDK is not on Maven Central yet. Build it from the quackback-android repository and publish it to your local Maven repository:

git clone https://github.com/QuackbackIO/quackback-android
cd quackback-android && ./gradlew :quackback:publishToMavenLocal

Then add mavenLocal() to your project's repositories and the dependency to your module's build.gradle.kts:

dependencies {
    implementation("com.quackback:sdk:0.1.0")
}

Configure and identify

// In your Application class
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        Quackback.configure(
            context = this,
            config = QuackbackConfig(
                instanceUrl = "https://feedback.yourapp.com"
            )
        )
    }
}

// After the user signs in; skip identify for anonymous visitors
Quackback.identify(ssoToken = fetchedSsoToken)

// Or, if you know the user at startup, pass the identity to configure:
Quackback.configure(
    context = this,
    config = QuackbackConfig(instanceUrl = "https://feedback.yourapp.com"),
    identity = Identity.SsoToken(fetchedSsoToken)
)
// Omit `identity` for anonymous sessions.

// Show the launcher in your Activity
Quackback.showLauncher()

Configuration options

Property

Type

Default

Description

instanceUrl

String

required

Your Quackback URL

theme

QuackbackTheme

SYSTEM

LIGHT, DARK, or SYSTEM

placement

QuackbackPosition

BOTTOM_RIGHT

BOTTOM_RIGHT or BOTTOM_LEFT

locale

String?

null

Force a language, for example "en" or "fr"

Open programmatically

Quackback.open()
Quackback.open(board = "feature-requests")

Listen to events

val token = Quackback.on(QuackbackEvent.VOTE) { data ->
    Log.d("Quackback", "Voted on: ${data["postId"]}")
}

Quackback.off(token)

Clean up

Quackback.logout()   // clear the identity
Quackback.destroy()  // tear down the SDK

Language

Both SDKs pass locale to the widget so it renders in the right language from the first frame. If you omit locale, the widget uses the device language. Unsupported languages fall back to English. See Internationalize your widget for the supported languages.

Was this helpful?

Your feedback shapes what we write next.