Click here to see your recently viewed pages and most viewed pages.
Hide

Add deep linking to your app

In order for Google to index the content of your app (and for users to enter your app from Google search results), you must specify intent filters in your app manifest that define how to reach specific content inside your app.

Here is how to specify a deep link to your app content:

  1. In your Android manifest file, add one or more <intent-filter> elements for the activities that should be launchable from Google Search results.
  2. Add an <action> tag that specifies the ACTION_VIEW intent action.
  3. Add a <data> tag for each data URI format the activity accepts. This is the primary mechanism to declare the format for your deep links.
  4. Add a <category> for both BROWSABLE and DEFAULT intent categories.
    • BROWSABLE is required in order for the intent to be executable from a web browser. Without it, clicking a link in a browser cannot resolve to your app and only the current web browser will respond to the URL.
    • DEFAULT is not required if your only interest is providing deep links to your app from Google Search results. However, the DEFAULT category is required if you want your Android app to respond when users click links from any other web page that points to your web site. The distinction is that the intent used from Google search results includes the identity of your app, so the intent explicitly points to your app as the recipient — other links to your site do not know your app identity, so the DEFAULT category declares your app can accept an implicit intent.

For example, the following activity allows users to enter the app using an intent to view information about gizmos. The intent filter declares that the activity responds to VIEW action intents containing URIs that begin with http://example.com/gizmos:

<activity android:name="com.example.android.GizmosActivity"
           android:label="@string/title_gizmos" >
     <intent-filter android:label="@string/filter_title_viewgizmos">
         <action android:name="android.intent.action.VIEW" />
         <!-- Accepts URIs that begin with "http://example.com/gizmos" -->
         <data android:scheme="http"
               android:host="example.com"
               android:pathPrefix="/gizmos" />
         <category android:name="android.intent.category.DEFAULT" />
         <category android:name="android.intent.category.BROWSABLE" />
     </intent-filter>
 </activity>

In this example, your app would respond to deep links such as http://example.com/gizmos?1234, http://example.com/gizmos/1234, http://example.com/gizmos/toys/1234, etc.

The intent filter's <data> element must provide the android:scheme attribute, at a minimum. You can then add additional attributes to further refine the type of URI that the activity accepts. For example, you might have multiple activities that accept similar URIs, but which differ simply based on the path name, in which case you should add the path, pathPattern, or pathPrefix attribute to differentiate which activity the system should open for different URI paths.

The above example demonstrates a URI format that's intended to match web page URLs such that the user can open your native app instead of the web page when clicking such links. If you want a simplified format for the Android URIs, you can create alternative data URI formats such as example://gizmos. For example, here's the same intent filter from above that includes support for both the http://example.com/gizmos and example://gizmos format:

<activity
     android:name="com.example.android.GizmosActivity"
     android:label="@string/title_gizmos" >
     <intent-filter android:label="@string/filter_title_viewgizmos">
         <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 "example://gizmos" -->
         <data android:scheme="example"
               android:host="gizmos" />
     </intent-filter>
     <intent-filter android:label="@string/filter_title_viewgizmos">
         <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 "http://example.com/gizmos" -->
         <data android:scheme="http"
               android:host="example.com"
               android:pathPrefix="/gizmos" />
     </intent-filter>
</activity>

This will allow your app to respond to the same http://example.com/gizmos URLs as the example above, as well as deep links such as example://gizmos?1234, example://gizmos/1234, example://gizmos/toys/1234, etc.

Once intent filters are added to your AndroidManifest.xml, your app should handle the data that is passed to your activity. For more information, please see Enabling Deep Links for App Content.

Testing your deep links

You can test your deep links using the Android Debug Bridge:

adb shell am start -a android.intent.action.VIEW -d "http://example.com/gizmos" com.example.android
adb shell am start -a android.intent.action.VIEW -d "example://gizmos" com.example.android

Make sure to test this on a fresh install of your app as well.

Use our deep link test tool to test your app behavior with deep links on your phone. Alternatively, you can test your app's behavior in a browser by creating an HTML page with an intent:// link in it:

<a href="intent://example.com/gizmos#Intent;scheme=http;package=com.example.android;end;">
  http://example.com/gizmos</a>
<a href="intent://gizmos#Intent;scheme=example;package=com.example.android;end;">example://gizmos</a>

You can learn more about using the intent:// URL here.

Restricting access to parts of your app content

In some cases, you may not want Google to index parts of your app. To let Google know this, you can include a noindex.xml file in your Android app to indicate which deep links should not be indexed. You can specify a list of URIs to exclude, or a list of URI prefixes. This is similar to how the robots noindex meta tag works for websites.

First, in your app's XML resources directory, create a new XML file, res/xml/noindex.xml, which looks like the following:

<?xml version="1.0" encoding="utf-8"?>
<search-engine xmlns:android="http://schemas.android.com/apk/res/android">
  <noindex uri="http://example.com/gizmos/hidden_uri"/>
  <noindex uriPrefix="http://example.com/gizmos/hidden_prefix"/>
  <noindex uri="gizmos://hidden_path"/>
  <noindex uriPrefix="gizmos://hidden_prefix"/>
</search-engine>

Deep links that match the uri attribute exactly, or deep links that start with the string matching uriPrefix attribute will not be indexed.

After the noindex.xml file is added, it must be referenced in the application section of the app’s AndroidManifest.xml file. For example;

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.Gizmos">
  <application>
    <activity android:name="com.example.android.GizmosActivity"
        android:label="@string/title_gizmos" >
      <intent-filter android:label="@string/filter_title_viewgizmos">
      <action android:name="android.intent.action.VIEW"/>
      ...
    </activity>
    <meta-data android:name="search-engine" android:resource="@xml/noindex"/>
  </application>
  <uses-permission android:name="android.permission.INTERNET"/>
</manifest>

<meta-data android:name="search-engine" android:resource="@xml/noindex"/> specifies where the noindex.xml file can be found in the app. In order to make sure that your app is indexed consistently, the same noindex.xml file should be included in all versions of your app published in the Google Play Store.

Next, you need to connect your app to your website to let Google know that your app is the official app for your website.