iOS and Android Integration¶
Open the Canviq feedback board natively in your app using SFSafariViewController (iOS) or Chrome Custom Tabs (Android). Users get the full Canviq experience — including magic link auth — without leaving your app's navigation.
Why In-App Browser?¶
Unlike a plain WKWebView, SFSafariViewController and Chrome Custom Tabs:
- Share the Safari/Chrome cookie jar, so Canviq sessions persist between app launches
- Are trusted by iOS/Android for magic link email flows (unlike WebView)
- Require zero additional backend code for basic use
Basic Setup¶
iOS (Swift)¶
import SafariServices
func openFeedbackBoard() {
let url = URL(string: "https://\(orgSlug).canviq.app/en")!
let safari = SFSafariViewController(url: url)
safari.preferredBarTintColor = UIColor(named: "AppBackground")
safari.preferredControlTintColor = UIColor(named: "AccentColor")
present(safari, animated: true)
}
Android (Kotlin)¶
import androidx.browser.customtabs.CustomTabsIntent
fun openFeedbackBoard() {
val url = Uri.parse("https://$orgSlug.canviq.app/en")
val intent = CustomTabsIntent.Builder()
.setShowTitle(true)
.setDefaultColorSchemeParams(
CustomTabColorSchemeParams.Builder()
.setToolbarColor(ContextCompat.getColor(this, R.color.app_background))
.build()
)
.build()
intent.launchUrl(this, url)
}
Post-Auth Deep Link (Universal Links / App Links)¶
After a user authenticates via magic link, Canviq can redirect them back into your native app. This requires two things:
- Your app handles Universal Links (iOS) or App Links (Android)
- Canviq has your domain registered as a trusted redirect origin
Step 1 — Register Your Trusted Redirect Origin¶
Go to Settings → General → Trusted Redirect Origins and add your app's domain:
!!! info "Currently manual" The Settings UI for trusted redirect origins is coming soon. Until it ships, contact [email protected] to register your domain.
You can also register via API once you have an org API key with org:write scope:
curl -X PATCH https://canviq.app/api/organizations/{org_id} \
-H "Authorization: Bearer $CANVIQ_API_KEY" \
-d '{
"trusted_redirect_origins": ["https://yourapp.com"]
}'
Step 2 — Configure Universal Links (iOS)¶
In your apple-app-site-association file (served at https://yourapp.com/.well-known/apple-app-site-association):
{
"applinks": {
"details": [
{
"appIDs": ["TEAMID.com.yourcompany.yourapp"],
"components": [
{ "/": "/feedback*", "comment": "Canviq post-auth redirect" }
]
}
]
}
}
Enable Associated Domains in your Xcode project:
Step 3 — Configure App Links (Android)¶
In your assetlinks.json file (served at https://yourapp.com/.well-known/assetlinks.json):
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "com.yourcompany.yourapp",
"sha256_cert_fingerprints": ["AB:CD:EF:..."]
}
}
]
Enable in your AndroidManifest.xml:
<intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="yourapp.com" android:pathPrefix="/feedback" />
</intent-filter>
Step 4 — Pass the Redirect Target When Opening¶
When you open Canviq in the in-app browser, include the destination your app should receive:
func openFeedbackBoard(destination: String = "/feedback") {
// URL-encode the destination
let encoded = destination.addingPercentEncoding(
withAllowedCharacters: .urlQueryAllowed
) ?? ""
let url = URL(string: "https://\(orgSlug).canviq.app/en?redirect=\(encoded)")!
let safari = SFSafariViewController(url: url)
present(safari, animated: true)
}
// Usage: open board, after auth redirect to /feedback?screen=submit
openFeedbackBoard(destination: "https://yourapp.com/feedback?screen=submit")
After the user authenticates, Canviq redirects to https://yourapp.com/feedback?screen=submit. iOS/Android intercepts it, opens your app, and you can re-open the Canviq board in SFSafariViewController — the user is already authenticated.
Handling the Incoming URL in Your App¶
iOS¶
// In SceneDelegate or AppDelegate
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url,
url.host == "yourapp.com",
url.path.hasPrefix("/feedback") else { return }
// Parse the screen parameter and re-open Canviq
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
let screen = components?.queryItems?.first(where: { $0.name == "screen" })?.value
openFeedbackBoard(destination: screen == "submit"
? "https://yourapp.com/feedback?screen=submit"
: "https://yourapp.com/feedback"
)
}
Android¶
// In the Activity that handles the intent
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
val uri = intent?.data ?: return
if (uri.host == "yourapp.com" && uri.path?.startsWith("/feedback") == true) {
val screen = uri.getQueryParameter("screen")
openFeedbackBoard(
destination = if (screen == "submit") "https://yourapp.com/feedback?screen=submit"
else "https://yourapp.com/feedback"
)
}
}
Troubleshooting¶
| Symptom | Likely cause | Fix |
|---|---|---|
| Universal Link not opening app | apple-app-site-association not served correctly | Verify file is served at /.well-known/apple-app-site-association with Content-Type: application/json |
| Redirect loop after auth | Your domain not in trusted redirect origins | Register it in Settings → General or contact support |
| User not authenticated in SFSafariViewController | WebView used instead of SFSafariViewController | Cookies are not shared with WebView — use SFSafariViewController only |
| Magic link not arriving | Email client opens link in default browser, not SFSafariViewController | This is expected — user will be authenticated in Safari, not in-app. See note below |
!!! note "Email clients and in-app browsers" Magic links opened in a default email app open in the system browser (Safari/Chrome), not in your in-app SFSafariViewController. If the user then opens your app, the in-app browser starts a new session. The Universal Link redirect pattern above mitigates this — Canviq sends the user back to your app after auth regardless of which browser they used.