Set up deep links with Flutter

Deep links are a powerful tool to enhance your Google Ads App and Web to App campaigns. It helps drive users directly to specific content within your Flutter application. This can help improve user experience, boost engagement, and significantly increase conversion rates for ads. Learn more About integrating deep links with Flutter.

This article guides you on how to implement and validate deep links for your Flutter app, leveraging tools like the Flutter Deeplinking Validator.

On this page


Prepare for success: Use recommended deep link mechanisms

To make deep links work, you typically need to configure both your app and an associated website. The 2 primary, secure, and recommended deep link mechanisms are:

  1. App Links (Android): HTTP/HTTPS URLs that are verified to belong to your website, allowing your Android app to open them directly without user disambiguation.
  2. Universal Links (iOS): HTTP/HTTPS URLs that securely link to content within your iOS app. Similar to App Links, they require verification with your website to ensure that only your app can handle links from your domain.

It’s highly recommended to use these primary mechanisms instead of older custom schemes such as myapp://. They are more secure and unique, and provide a better fallback experience, like directing to your website if the app isn't installed.

How to implement and test deep links in your Flutter app

Implementing deep links in Flutter involves configuring your Flutter app to handle link-based navigation and setting up platform-specific configurations for Android and iOS, as well as web server configurations for domain association. Follow the steps below to successfully implement deep links in your Flutter app.

Step 1 of 4: App setup (Flutter and native configuration)

This step involves configuring your Flutter app to recognize and handle incoming deep link URLs.

A. Handle incoming URLs and navigation (Flutter-side)

Your Flutter application needs to be able to receive and analyze incoming deep link URIs and then navigate to the appropriate screen.

  1. Choose a routing solution.
    • go_router: A popular, declarative routing package for Flutter that simplifies navigation, including deep link handling. It's often recommended for more complex apps. (go_router on pub.dev)
    • Navigator 2.0 (Declarative Navigation): Flutter's core declarative navigation API. While powerful, it can be more complex to set up directly. Packages like go_router are built on top of this.
    • uni_links / app_links packages: These packages help you get the initial link that opened the app and listen to subsequent incoming links. They are useful if you prefer to manage routing logic more manually or with a different routing solution.
  2. Retrieve and analyze the link.
    • Initial link: When your app is opened by a deep link, you need to retrieve this initial URI. Packages like uni_links provide getInitialUri() for this.
    • Subsequent links: If your app is already running and receives a new deep link, you'll need to listen to a stream of incoming URIs. uni_links offers uriLinkStream.
    • When you have the URI, analyze its path and any query parameters to determine the destination screen and data to display such as product ID.
  3. Navigate to the correct screen.
    • Based on the analyzed link, use your chosen routing solution like GoRouter.go(), Navigator.pushNamed() to navigate the user to the relevant screen in your app.

Example (Conceptual - using a routing package like go_router):

// In your main.dart or routing configuration

final GoRouter _router = GoRouter(

  routes: <RouteBase>[

    GoRoute(

      path: '/',

      builder: (BuildContext context, GoRouterState state) {

        return const HomeScreen();

      },

      routes: <RouteBase>[

 биологии        GoRoute(

          path: 'product/:id', // Example: myapp.com/product/123

          builder: (BuildContext context, GoRouterState state) {

            final String productId = state.pathParameters['id']!;

            return ProductScreen(id: productId);

          },

        ),

        // Add other deep linkable routes

        // Example: myapp.com/category/electronics

        GoRoute(

          path: 'category/:categoryName',

          builder: (BuildContext context, GoRouterState state) {

            final String category = state.pathParameters['categoryName']!;

            return CategoryScreen(category: category);

          },

        ),

      ],

    ),

  ],

  // Error handling for unknown routes

  errorBuilder: (context, state) => ErrorScreen(error: state.error),

);

 

// In your MaterialApp

MaterialApp.router(

  routerConfig: _router,

  // ... other MaterialApp properties

)

B. Set up native Android configuration (AndroidManifest.xml)

To enable Android App Links, you need to add intent filters to your android/app/src/main/AndroidManifest.xml file within the main <activity> tag that has android.intent.action.MAIN.

  1. Enable Flutter deep linking. Add this meta-data tag inside your main <activity>:
    <meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
  2. Add intent filters for HTTP/HTTPS links.

    <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" />

        <!-- Accepts URIs that begin with https://yourdomain.com -->

        <data android:scheme="https" android:host="yourdomain.com" />

        <!-- You can add multiple data tags for different hosts or pathPrefixes -->

        <!-- Example for a specific path: -->

        <!-- <data android:scheme="https" android:host="yourdomain.com" android:pathPrefix="/product"/> -->

    </intent-filter>

    <intent-filter> <!-- Also add for http if needed, though https is strongly recommended -->

        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />

        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="http" android:host="yourdomain.com" />

    </intent-filter>

    • Replace yourdomain.com with your actual domain.
    • The android:autoVerify="true" attribute enables your app to be the default handler for links matching the data tags, provided your website association (see Web Setup below) is correctly configured.

C. Set up native iOS configuration

For iOS Universal Links, enable Associated domains in Xcode:

  1. Open your Flutter project's ios folder in Xcode.
  2. Select the Runner target in the Project navigator.
  3. Go to the "Signing & Capabilities" tab.
  4. Click the + Capability button and add "Associated Domains."
  5. Under the "Associated Domains" section, add an entry in the format: applinks:yourdomain.com (replace yourdomain.com with your domain).

Step 2 of 4: Web setup (Domain association)

This step associates your website domains with your app, verifying that your app is authorized to open links for those domains. These files must be served over HTTPS.

A. For Android (App Links)

  1. Create a file named assetlinks.json.
  2. The content should be structured as follows:

    [{

      "relation": ["delegate_permission/common.handle_all_urls"],

      "target": {

        "namespace": "android_app",

        "package_name": "com.yourcompany.yourappname", // Replace with your app's package name

        "sha256_cert_fingerprints": [

          "YOUR_SHA256_CERT_FINGERPRINT_1", // Replace with your release key fingerprint

          "YOUR_SHA256_CERT_FINGERPRINT_2"  // Add debug key fingerprint for testing if needed

        ]

      }

    }]

    ```    *   Replace `com.yourcompany.yourappname` with your app's actual package name (applicationId in your `build.gradle`).

    *   Replace `YOUR_SHA256_CERT_FINGERPRINT_...` with the SHA-256 fingerprints of your app's signing certificate(s). You can get this from the Google Play Console (App integrity > App signing) or using the `keytool` command.
  3. Host this file on your website at the following exact path: https://yourdomain.com/.well-known/assetlinks.json (replace yourdomain.com with your domain).
  4. Ensure the file is served with Content-Type: application/json.

B. For iOS (Universal Links) 

  1. Create a file named apple-app-site-association (no extension).
  2. The content should be structured as follows:
    • Replace YOUR_TEAM_ID.com.yourcompany.yourappbundleid with your Apple Team ID and your app's Bundle Identifier.
    • The paths array specifies which URL paths your app is authorized to open. Use * as a wildcard to match multiple subpaths (e.g., /product/* matches all product detail pages). Use NOT /path/to/exclude/* to exclude specific paths. Using ["*"] or ["/"] generally allows your app to handle all links from the domain.
  3. Host this file on your website at either https://yourdomain.com/.well-known/apple-app-site-association or https://yourdomain.com/apple-app-site-association (at the root). The .well-known path is generally preferred.
  4. Ensure the file is served with Content-Type: application/json and is not gzipped.
Important for iOS: Apple's CDN caches this file. Changes might take some time (up to 48 hours, though often much faster) to propagate. You can use Apple's App Search API Validation Tool to check its status.

Step 3 of 4: Validate your deep links with the Flutter Deeplinking Validator

After you've started implementing deep links, it's crucial to validate your setup. Google provides the Flutter Deeplinking Validator, a tool integrated directly into Flutter DevTools, to help you with this process.

How to access the Flutter Deep Linking Validator

  1. Open your Flutter project in your preferred IDE (like VS Code or Android Studio).
  2. Launch Flutter DevTools.
  3. Navigate to the "Deeplinking Validator" tab, usually found under the list of available tools.
  4. Follow the on-screen instructions to select your project and initiate validation.

Best Practice: Use the validator iteratively during your development process to catch and fix deep linking issues early, ensuring a smoother integration with your App Engagement Ads.


Step 4 of 4: Test your deep links

  1. Use adb to test intent filters:

    adb shell am start -a android.intent.action.VIEW \

        -c android.intent.category.BROWSABLE \

        -d "https://yourdomain.com/product/123" com.yourcompany.yourappname

    • Replace yourdomain.com and com.yourcompany.yourappname accordingly.
  2. Click links from notes, emails, or other apps that match your intent filters.

For iOS

  1. Click links from Safari, Notes, or other apps that match your Associated Domains configuration.
  2. You can also test by pasting the Universal Link into Safari. If configured correctly, a banner should appear at the top of the page offering to open the link in your app.

Best practices for Flutter deep linking

  • Prioritize security and reliability: Use Android App Links and iOS Universal Links. They offer a secure way to link to your app content and provide a graceful fallback to your website if the app isn't installed.
  • Consistent URL structure: Maintain a consistent URL structure between your website and app deep links for easier management and tracking.
  • Thorough testing:
    • Use the Flutter Deeplinking Validator regularly (especially for Android).
    • Test your deep links from various sources, including directly from a browser, from simulated ad clicks, and on different devices and OS versions.
  • Website accessibility and configuration:
    • Ensure your assetlinks.json (Android) and apple-app-site-association (iOS) files are correctly hosted, publicly accessible via HTTPS, and have the correct Content-Type header (e.g., application/json).
    • For iOS, remember the AASA file should not be gzipped by your server and allow for propagation time via Apple's CDN.
  • Prepare for App Not Installed: Always have a relevant fallback experience on your mobile website for users who click a deep link but don't have your app installed.
  • Coordinate with marketing: Ensure your development team and marketing team are aligned on the deep link URLs being used in ad campaigns.

Related links

Was this helpful?

How can we improve it?
Search
Clear search
Close search
Google apps
Main menu
17677934809874241631
true
Search Help Center
true
true
true
true
true
true
73067
false
false
true
true
false