Deep Link Doesn't Open the App
Diagnose links that open the browser instead of your app — Universal Links on iOS, App Links on Android, and native config for Flutter and React Native.
The most common Grovs issue: you tap a link and it opens the browser (or the store) instead of your installed app. Almost every case comes down to platform link-verification config — the associated domain on iOS or the signing fingerprint on Android — not the SDK itself.
Quick checks first
Before digging into a platform section:
- The app is installed on the device you're testing. If it isn't, that's deferred deep linking — a different flow.
- You added both values from the dashboard. Grovs gives you two domains and two URL schemes — one for the test environment, one for production. Configuring only one is the single most common mistake.
- The build matches the link's environment. A build configured with
useTestEnvironment = truehandles test-environment links; a production build handles production links. See SDK configuration issues.
iOS: Universal Links
Link opens Safari instead of the app
Cause: The Associated Domains capability is missing or doesn't list your Grovs domains, so iOS never associates the link's domain with your app.
Fix: Add the Associated Domains capability in Xcode and add applinks: entries for both domains shown in your Grovs dashboard. Follow How to Add an Associated Domain. Also confirm the dashboard has your correct Apple App Prefix (Team ID) and Bundle Identifier — the apple-app-site-association file identifies your app as TEAMID.bundle.identifier, so a typo in either breaks the association.
Config looks right but links still open Safari
Cause: iOS fetches the apple-app-site-association (AASA) file for each associated domain at app install time, via Apple's CDN — not on every launch. If you fixed your Team ID or bundle ID after installing, the device is still using the old association. Apple's CDN can also take a while to pick up changes.
Fix: Delete the app from the device and reinstall it to force a fresh AASA fetch. Verify the file is reachable by opening https://<your-grovs-domain>/.well-known/apple-app-site-association in a browser and checking that it lists your TEAMID.bundle.identifier. If it was recently corrected, allow time for Apple's CDN to refresh before retesting.
Works from Messages but not when pasted into Safari
Cause: This is standard iOS behavior, not a bug. Universal Links do not trigger when the URL is typed or pasted into the Safari address bar, and they won't trigger if the user has previously chosen "Open in Safari" from the Universal Link banner.
Fix: Test by tapping the link from another app — Notes, Messages, or Mail. If the user opted out earlier, long-press the link and choose Open in "YourApp" to restore the association.
Testing in the iOS Simulator
Cause: Universal Links do not work in the Simulator.
Fix: Test Universal Links on a physical device. On the Simulator you can still exercise the custom URL scheme path instead.
Universal Links blocked, and the URL scheme fallback doesn't work either
Cause: The custom URL scheme isn't registered in your app's URL Types, or only one of the two schemes from the dashboard was added.
Fix: Follow How to Add a New URL Scheme and add both scheme values from the dashboard. Verify by typing yoururlscheme:// into Safari's address bar — your app should open.
App opens but the Grovs delegate never fires
Cause: The app opens (so the OS-level config is fine) but the link never reaches the SDK because the SceneDelegate/AppDelegate calls aren't forwarded to Grovs.
Fix: Forward openURLContexts, continue userActivity, and willConnectTo (or their AppDelegate equivalents) to the SDK exactly as shown in Delegate setup, and make sure Grovs.delegate is set — see Deep Linking.
Android: App Links
Link opens the browser (or shows an app chooser) instead of the app
Cause: App Links verification failed. Android verifies https intent filters against the assetlinks.json file served on the link's domain; if the file doesn't list your exact package name and signing certificate's SHA-256 fingerprint, the system falls back to the browser or a disambiguation dialog.
Fix: Work through these in order:
- Add your SHA-256 fingerprint to the Grovs dashboard — both the debug and release fingerprints. Follow How to Get the SHA-256 Fingerprint.
- Confirm the package name in the dashboard matches your
applicationIdexactly. See How to Get the Package Name. - Check that your
httpsintent filters haveandroid:autoVerify="true"and list both the production and test hosts from the dashboard, as shown in the Android Quick Start. - Verify the file is reachable: open
https://<your-grovs-domain>/.well-known/assetlinks.jsonin a browser and check that it contains your package name and fingerprint. - Reinstall the app — verification runs at install time.
Works in debug builds but not in the Play Store release
Cause: The Play App Signing gotcha. When Google Play App Signing is enabled, Google re-signs your app with its own app signing key before distributing it. The fingerprint of your local upload/release keystore is not the fingerprint of the APK users actually install, so verification fails only for store installs.
Fix: In the Google Play Console, go to Setup → App integrity and copy the SHA-256 from App signing key certificate (not the upload key certificate) into the Grovs dashboard. The SHA-256 fingerprint guide covers this under the Google Play App Signing tab.
Checking verification status and testing with adb
Inspect what Android actually verified for your app:
# Show the verification state of each domain (Android 12+)
adb shell pm get-app-links your.package.name
# Force re-verification after fixing the config
adb shell pm verify-app-links --re-verify your.package.nameDomains should show verified. Then fire a link directly at the device:
# Test an App Link
adb shell am start -W -a android.intent.action.VIEW -d "https://your_app_host/path"
# Test the custom URL scheme fallback
adb shell am start -W -a android.intent.action.VIEW -d "myapp://example.com/path"If the scheme test fails too, your intent filter is missing or incomplete — see How to Add a New Intent Filter.
App opens but the listener never fires
Cause: The link reached your activity, but the SDK never saw it because the lifecycle events aren't forwarded.
Fix: Call Grovs.onStart(this) in your launcher activity's onStart() and Grovs.onNewIntent(intent, this) in onNewIntent(), as shown in the Android Quick Start, then register a listener with Grovs.setOnDeeplinkReceivedListener — see Deep Linking.
Flutter and React Native
On Flutter and React Native, link opening is handled entirely by the native layer — the Dart/JS side only receives the payload after the OS has already opened the app. If links don't open the app, the problem is in the native config, and everything in the iOS and Android sections above applies unchanged.
- Flutter: verify the
Info.plistkeys, Associated Domains, URL schemes, and Android intent filters from the Flutter Quick Start. - React Native: verify the native setup in the React Native Quick Start. If you use Expo, the config plugin writes this native config for you — check that
schemeandassociatedDomainsin yourapp.jsonmatch the dashboard values, re-runnpx expo prebuild, and remember it requires a development build, not Expo Go.
A useful tell: if links work on one platform but not the other, the SDK integration is fine and the broken platform's native link-verification config is the culprit.
Still stuck? Email [email protected] with your platform, the link you're testing, and the output of the checks above.