This setup covers a basic deep link requirement:
A user shares a link like:
https://exampleapp.com/profile?id=123ABCWhen someone clicks the link:
If the app is installed → open the profile in the app
If not → show manual buttons for App Store / Play Store (no auto redirect)
This is done without using Firebase Dynamic Links or Branch.io — just HTML + JavaScript.
🌐 Web Handler (HTML + JS)
You must have a domain (e.g. exampleapp.com) and create a folder named profile and a index.html file inside it.
ex. exampleapp.com/profile/index.html
Paste the following code into index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>ExampleApp Profile Link</title>
<style>
body {
font-family: sans-serif;
background: #f5f5f5;
text-align: center;
padding: 50px 20px;
}
.container {
background: white;
max-width: 400px;
margin: 0 auto;
padding: 30px;
border-radius: 10px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
h1 {
font-size: 22px;
margin-bottom: 10px;
}
p {
color: #666;
margin-bottom: 30px;
}
button {
background-color: #007bff;
color: white;
border: none;
padding: 12px 24px;
font-size: 16px;
border-radius: 5px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="container">
<h1>Opening Profile...</h1>
<p>If the app doesn't open, click below to download it.</p>
<button id="store-button">Download the App</button>
</div>
<script>
window.onload = function () {
const urlParams = new URLSearchParams(window.location.search);
const profileId = urlParams.get('id');
if (profileId) {
const appUrl = `myapp://myapp.com/home?id=${profileId}`;
const isAndroid = /Android/i.test(navigator.userAgent);
const isIOS = /iPhone|iPad|iPod/i.test(navigator.userAgent);
const storeUrlAndroid = 'https://play.google.com/store/apps/details?id=com.example.app';
const storeUrlIOS = 'https://apps.apple.com/app/example-app/id1234567890';
// Attempt to open the app
if (isIOS) {
window.location.href = appUrl;
} else {
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = appUrl;
document.body.appendChild(iframe);
}
// Manual store redirection on button click
document.getElementById('store-button').onclick = () => {
const storeUrl = isAndroid ? storeUrlAndroid : isIOS ? storeUrlIOS : storeUrlAndroid;
window.location.href = storeUrl;
};
} else {
window.location.href = 'https://exampleapp.com';
}
};
</script>
</body>
</html>Reads the
idparameter from the URL (e.g.,?id=123ABC)Attempts to open the app using a custom URL scheme like
exampleapp://home?id=123ABC
(To construct this, use your app’s deep link prefix from FlutterFlow → Settings → App Details → Routing & Deep Linking → URL Scheme. Hover over the little info (i) icon and copy the base URL. Replace the appUrl base with the coppied URL)If the app is not installed, it displays a "Download the App" button
You should replace the Play Store and App Store URLs in the script with your actual app links
🔧 FlutterFlow Integration
By default, FlutterFlow loads the Logged In Page (You Setup In FF Settings) even if a deep link is meant for a different screen. So, if you try to deep link directly to a screen like ProfileView, it may:
Briefly flash and then
Automatically redirect to the Logged In Page.
If you’re seeing this issue, you’re not alone:
👉 Community Post Explaining the Problem
✅ My Solution
Instead of trying to open a specific page directly, I used the Logged In Page to handle the routing logic.
🧩 Steps:
Keep the route as just the page name, e.g.:
/homeDon’t add parameters in the route itself like below.
/home/:idOn your Logged In Page (e.g.,
home):Go to Page Parameters
Add a custom parameter, e.g.,
id
On Page Load → Add Conditional Navigation Logic:
Check if the
idis not empty.If it has a value, navigate to the relevant page (like
ProfilePage) and pass the ID.
✅ Result:
The link like
https://exampleapp.com/profile?id=123ABCopens the appFlutterFlow loads the Logged In Page
The Logged In Page checks the ID and redirects to the target page using FlutterFlow logic
You can save the following base URL in AppState and append the profile ID whenever a user wants to share their profile:
https://exampleapp.com/profile?id=<PROFILE_ID>
⚠️ Cons of This MethodNo post-install redirect – The app won’t remember the link if it's installed after clicking.
Browser issues – Some browsers (like Safari) may block or delay opening the app.
Manual fallback – Users must tap the store button; it doesn’t open automatically.
No tracking – You can’t measure clicks, installs, or app opens unless you build it yourself.
Limited flexibility – Only works for simple use cases like opening a profile.
This approach keeps everything smooth and native inside FlutterFlow — no need for external link services like Branch.io (which may charge after exceeding MAU limits) or Firebase, and no additional costs involved. For simple deep linking needs like opening a profile from a shared URL, this method is more than enough.
If you’ve used a similar method or have improvements in mind, feel free to share your thoughts.