Guides
FlutterFlow + Appy deep links
Open a FlutterFlow page from an Appy link when the app is installed, and send everyone else to their store. On Pro this needs no changes to native files.
This guide is for FlutterFlow projects that ship iOS and Android apps. FlutterFlow gives every project a URL scheme and every page a route, and that is all an Appy deep link needs on Pro and Business: Appy’s page opens the deep link and sends phones without the app to their store. On Enterprise, the Flutter SDK adds Universal Links, App Links and deferred deep links through FlutterFlow’s custom code.
What works on each plan
| Plan | What the link does | What you set up |
|---|---|---|
| Free | Sends iPhones and iPads to the App Store, Android phones to Google Play, AppGallery, Galaxy Store or GetApps, and computers to your website. It does not open the app. | Store URLs on the link. |
| Pro | Phones first try the link’s Deeplink URL, such as acmeshop://acmeshop.com/product/42. A phone without the app continues to its store. | The URL scheme in App Details and a route on each page you link to. |
| Business | The same, on your own domain such as go.acme.com. With parameter forwarding, query parameters on the link are added to the deep link, the store URLs and the website. | One DNS record. See Custom domains. |
| Enterprise | The link itself is a Universal Link and App Link on acme.appy.to or on your domain, so iOS and Android open the app without loading a page. After an install, the first launch receives the link, and you see which link brought each install. | The appy_sdk plugin, added through custom code and configuration files. |
What happens when someone taps the link
| Where the link opens | App installed | App not installed |
|---|---|---|
| Safari, Chrome or another phone browser | Appy’s page opens acmeshop://acmeshop.com/product/42 and the app shows the product page. | The scheme opens nothing. After about five seconds the page continues to the store for that device; Continue now skips the wait. |
| The in-app browser of Instagram, Facebook, Messenger, TikTok, Snapchat, LinkedIn, X, Telegram, LINE or WeChat | Appy shows an Open the app page and waits for a tap. On Android the button is an intent with your package name, read from the Google Play URL. The page also explains how to open the link in Safari or Chrome. | The same page. Its second button opens the store for that device, or your website. |
| A computer | The default destination URL, for example your FlutterFlow web app. | The same. |
Set up the deep link
- 1
Check the URL scheme
In Settings and Integrations > General > App Details, under Routing & Deep Linking, FlutterFlow fills in a scheme and a host from your project name. Change them if you want, for example to scheme
acmeshopand hostacmeshop.com. - 2
Give the page a route
Select the page, open Route Settings in the properties panel and set the route, for example
product/:productId. The colon marks a page parameter, so the page needs a parameter namedproductId. - 3
Build the deep link
Scheme, host, then the route with real values:
acmeshop://acmeshop.com/product/42. Without a page path,acmeshop://acmeshop.com/opens the app’s landing page. - 4
Create the Appy link
In the dashboard, paste the App Store URL and the Google Play URL in the
https://play.google.com/store/apps/details?id=com.acme.shopform under Mobile app store overrides. Turn on Enable deeplink redirect and enter the deep link as Deeplink URL. The Default destination URL is for computers.
Appy reads your package name from the id in the Google Play URL for in-app browsers on Android. The Deep Link Generator builds the scheme link and the Android intent URL from your scheme and path, if you want to check them first.
Pages that require sign-in
If Requires Authentication is on for the page, a person who isn’t signed in sees your login page first and reaches the linked page after signing in.
An https link on your own domain
The Deeplink URL can also be a Universal Link and App Link on your own domain, such as https://links.acme.com/product/42. App Details doesn’t set this up. Add the domain in Custom Code > Configuration Files as snippets:
<key>com.apple.developer.associated-domains</key>
<array>
<string>applinks:links.acme.com</string>
</array><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="links.acme.com" />
</intent-filter>- Host
apple-app-site-associationandassetlinks.jsonunder/.well-known/on that domain. The AASA and assetlinks generator writes both, and the Universal Link Validator checks them. - For an app on Google Play, use the SHA-256 fingerprint of the app signing key from Play Console, not your upload key.
- Turn on Associated Domains for your App ID under Certificates, Identifiers & Profiles in the Apple Developer portal if your deployment doesn’t do it for you.
- If you also use FlutterFlow Dynamic Links, FlutterFlow adds its domain to your
com.apple.developer.associated-domainsarray and keeps your entries. The value has to stay an array of strings. - Before you put the link on a campaign, check on a device that
https://links.acme.com/product/42opens the product page.
People without the app still reach the store
On Android, Appy opens an https deep link as an intent for your package, read from the Google Play URL, and an intent that finds no app continues to the store for that device. Safari doesn’t open Universal Links from a script, so on iPhone, iPad and Huawei phones Appy’s page shows an Open the app button and continues to the store after about five seconds. Only a tap on that button without the app installed shows your website. Analytics count those clicks as website visits, not as opened apps.
Your own domain and parameters (Business)
- Add
go.acme.comas a custom domain. Every link then also works on that domain, with the same deep link behaviour. - Parameter forwarding adds the link’s query parameters, such as
?utm_source=newsletter, to the deep link, the store URLs and the website. A key the deep link already sets keeps its value. FlutterFlow passes page parameters through the route, so keep the values a page needs in the deep link’s path. - On Business, the custom domain carries your links. Universal Links and App Links on it, which open the app without a page, are part of Enterprise.
Universal Links, App Links and deferred deep links (Enterprise)
On Enterprise, Appy serves the association files for your app on acme.appy.to or on your custom domain, and the appy_sdk plugin receives the links, including the link tapped before an install. Follow the Flutter SDK guide and make its changes in FlutterFlow:
| Step in the Flutter guide | Where in FlutterFlow |
|---|---|
Add appy_sdk | Settings and Integrations > Pubspec Dependencies. |
Call Appy.configure at startup | A custom action in the Final Actions of main.dart. |
Associated Domains applinks:acme.appy.to | A Runner.entitlements snippet, as above. |
App Link intent filter for acme.appy.to | An Activity Tags snippet in AndroidManifest.xml, as above. FlutterFlow already registers your URL scheme. |
| Turn off Flutter’s built-in deep linking | FlutterDeepLinkingEnabled in Info.plist and the flutter_deeplinking_enabled meta-data in AndroidManifest.xml, both in Configuration Files. |
Route links from Appy.onDeepLink | A custom action that listens to the stream and navigates to the page. |
Check your existing deep links
After these changes, open an Appy link and one of your URL-scheme deep links on a device; both should land on the right page. Also compare the Flutter and Dart versions your FlutterFlow project builds with against the plugin’s requirements. Keep the URL-scheme deep link on your Appy links: in-app browsers that ignore Universal Links open the app through Appy’s page with it.
Test on a simulator and a device
Run Mode can’t open deep links. Use a build on a simulator, an emulator or a phone, and test the deep link on its own first:
xcrun simctl openurl booted "acmeshop://acmeshop.com/product/42"
adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "acmeshop://acmeshop.com/product/42"Then open the Appy link, which goes through Appy’s page like a real tap:
xcrun simctl openurl booted "https://appy.to/acme-spring"
adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://appy.to/acme-spring"- App installed: the app opens on the product page.
- App removed: after about five seconds the page continues to the App Store or Google Play.
- On a phone, send yourself the link in Notes or Messages and tap it, as your users would. Typing a URL into the address bar doesn’t always open an app.
- Inside Instagram or TikTok, Appy shows the Open the app page. Tap Open the app.
- With an https deep link on Android,
adb shell pm get-app-links com.acme.shoplists your domain asverifiedonce Android has checked it.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| The store opens although the app is installed | The Deeplink URL’s scheme differs from the one in App Details, or the installed build is older than your change. | Copy the scheme exactly from App Details and install a new build. The adb or simctl command above must open the page. |
| The app opens on its landing page instead of the linked page | The deep link has no page path, the path differs from Route Settings, or a :parameter in the route has no matching page parameter. | Compare the path with the route, for example product/:productId and acmeshop://acmeshop.com/product/42. |
| A login page appears first | Requires Authentication is on for the page. | Expected for private pages: the person reaches the page after signing in. Turn it off only for pages meant to be public. |
| Nothing happens inside Instagram, TikTok or Facebook | In-app browsers don’t always let a page open another app. | The person taps Open the app on Appy’s page, or opens the page in Safari or Chrome as it explains. Check that the Google Play URL contains ?id=. |
| An https deep link opens the browser instead of the app | Associated Domains or the App Link filter is missing, or the Android fingerprint is from the upload key instead of the app signing key. | Check the domain with the Universal Link Validator, use the app signing key’s SHA-256 and run adb shell pm get-app-links with your package name. Or use the URL scheme as the Deeplink URL. |
Compared with FlutterFlow Dynamic Links
FlutterFlow has its own link service, FlutterFlow Dynamic Links, which replaces Firebase Dynamic Links in FlutterFlow projects. Its documentation (October 2026) describes a paid add-on: one unit per project at $10 a month or $96 a year, on a paid FlutterFlow plan. Each project gets a fixed domain, your-project-id.fflink.app, that can’t be changed or replaced with a custom domain. FlutterFlow adds the native settings for that domain itself. People without the app go to the App Store, Google Play or your web app, and an app can create up to 60 links a minute and 1,000 a day.
Appy links work the same for FlutterFlow and other apps, run on your own domain from Business, and also route Android phones to AppGallery, Galaxy Store and GetApps. Scheme deep links on Pro need no native changes. You can use both services: FlutterFlow’s documentation says URL-scheme deep links keep working when FlutterFlow Dynamic Links is on.