Docs

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:

  1. The app is installed on the device you're testing. If it isn't, that's deferred deep linking — a different flow.
  2. 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.
  3. The build matches the link's environment. A build configured with useTestEnvironment = true handles test-environment links; a production build handles production links. See SDK configuration issues.

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.

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.

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.

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:

  1. Add your SHA-256 fingerprint to the Grovs dashboard — both the debug and release fingerprints. Follow How to Get the SHA-256 Fingerprint.
  2. Confirm the package name in the dashboard matches your applicationId exactly. See How to Get the Package Name.
  3. Check that your https intent filters have android:autoVerify="true" and list both the production and test hosts from the dashboard, as shown in the Android Quick Start.
  4. Verify the file is reachable: open https://<your-grovs-domain>/.well-known/assetlinks.json in a browser and check that it contains your package name and fingerprint.
  5. 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:

Bash
# 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.name

Domains should show verified. Then fire a link directly at the device:

Bash
# 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.plist keys, 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 scheme and associatedDomains in your app.json match the dashboard values, re-run npx 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.

Edit this page on GitHubLast updated 2026-07-29