Skip to content
Tolinku
Tolinku
Sign In Start Free
Marketing · · 18 min read

App Indexing and SEO for Mobile Apps

By Tolinku Staff
|
Tolinku smart banners dashboard screenshot for marketing blog posts

Every day, billions of searches happen on Google, Bing, and Apple's Spotlight. Most mobile apps are invisible to all of them. Users search for "best Italian restaurants near me" and see web pages, not the restaurant app sitting on their phone. They search for "how to track a package" and get a FedEx web link, not the FedEx app screen that would show them real-time tracking.

This is a missed opportunity. App indexing fixes it by making the content inside your app discoverable through search engines and on-device search. When done correctly, your app screens show up in Google search results with an "Open in App" button, appear in iOS Spotlight suggestions, and surface in Android's launcher search. Users who already have your app get taken directly to the right screen. Users who don't get shown a path to install it.

App indexing SEO is not a separate discipline from web SEO. It is an extension of it. The same principles apply: you need crawlable content, structured data, proper metadata, and a technical foundation that search engines can understand. The difference is that instead of linking to web pages, you are linking to screens inside a native app.

This guide covers how to get your app content indexed by Google and Apple, the technical requirements on both platforms, and the SEO strategies that actually move the needle for organic app traffic.

What Is App Indexing?

App indexing is the process of making content inside your native mobile app discoverable through search. When a user searches for something that matches content in your app, the search engine can display a result that opens the app directly to that content.

There are two main flavors:

Search engine indexing connects your app content to web search results. Google is the primary player here. When Google indexes your app, it can show app-specific results in mobile search, complete with buttons to open the content in your app or install it from the Play Store or App Store.

On-device indexing makes your app content searchable through the operating system's built-in search. On iOS, this is Spotlight Search. On Android, it is the Google app's on-device search. These results appear without any network request; the content is indexed locally on the user's device.

Both types rely on the same foundation: deep links that can route users to specific content within your app. Without working deep links, there is nothing for search engines to point to.

Google App Indexing

Google has supported app indexing since 2013, and it has evolved significantly since then. The current system works through App Links on Android and Universal Links on iOS, combined with structured data on your website.

How It Works

Google's crawler (Googlebot) indexes your website normally. When it finds structured data or HTML markup that associates a web page with an app screen, it creates a connection between the two. On mobile search results, Google can then show an "Open in app" button or even replace the web result entirely with an app result.

The process has three components:

  1. A web page with the same content as the app screen. Google needs something to crawl. If your app shows a product page for "Blue Running Shoes," you need a corresponding web page at a URL like https://example.com/products/blue-running-shoes.

    Deep links that map the web URL to the app screen. On Android, this means Android App Links verified through Digital Asset Links. On iOS, this means Apple Universal Links verified through the apple-app-site-association file.

    Structured data or meta tags that tell Google about the app association. This can be JSON-LD, <meta> tags, or entries in your sitemap.

    Setting Up Google App Indexing

    For a detailed walkthrough of the Google-specific setup process, see our Google App Indexing setup guide. The summary below covers the key steps.

    First, verify your app in Google Search Console. Go to Settings, then Associate your Android app. For iOS apps, the association happens through Universal Links and structured data rather than Search Console directly.

    Next, ensure your Digital Asset Links file is in place for Android:

    // https://example.com/.well-known/assetlinks.json
    [{
      "relation": ["delegate_permission/common.handle_all_urls"],
      "target": {
        "namespace": "android_app",
        "package_name": "com.example.myapp",
        "sha256_cert_fingerprints": [
          "AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90:AB:CD:EF:12:34:56:78:90"
        ]
      }
    }]
    

    For iOS, your apple-app-site-association file should already be configured if you are using Universal Links:

    {
      "applinks": {
        "details": [{
          "appIDs": ["TEAMID.com.example.myapp"],
          "components": [
            { "/": "/products/*" },
            { "/": "/articles/*" },
            { "/": "/users/*" }
          ]
        }]
      }
    }
    

    Google will crawl these files and use them to understand the relationship between your web content and your app.

    Monitoring in Search Console

    Once your app is associated, Search Console shows app-specific data under the Performance report. You can filter by "App (URI)" to see which app screens are appearing in search results, how many impressions they get, and what click-through rates look like.

    Pay attention to the "App Install" versus "App Open" breakdown. Install clicks happen when users do not have your app; Open clicks happen when they do. If your install rate is high relative to opens, your app content is reaching new users through search, which is exactly what you want.

    Apple Spotlight and App Indexing

    Apple's approach to app indexing works differently from Google's. Instead of a single web crawler, Apple uses three mechanisms to index app content.

    NSUserActivity

    When a user views content in your app, you can register that activity with Spotlight. If the same user (or, in some cases, any user) searches for related terms, your app content appears in Spotlight results.

    import CoreSpotlight
    import MobileCoreServices
    
    func indexProductForSpotlight(product: Product) {
        let activity = NSUserActivity(activityType: "com.example.myapp.viewProduct")
        activity.title = product.name
        activity.userInfo = ["productId": product.id]
        activity.isEligibleForSearch = true
        activity.isEligibleForPublicIndexing = true
        activity.webpageURL = URL(string: "https://example.com/products/\(product.slug)")
    
        let attributes = CSSearchableItemAttributeSet(contentType: .content)
        attributes.contentDescription = product.description
        attributes.thumbnailData = product.thumbnailData
        attributes.keywords = product.tags
    
        activity.contentAttributeSet = attributes
        self.userActivity = activity
        activity.becomeCurrent()
    }
    

    Setting isEligibleForPublicIndexing to true tells Apple this content is suitable for all users, not just the current device. For a full guide to Spotlight integration, see Apple Spotlight indexing for iOS apps. Apple aggregates engagement data across users and may surface popular content in Spotlight results even for users who have never visited that screen. See Apple's NSUserActivity documentation for the full API reference.

    CoreSpotlight

    For content that exists in your app but the user has not viewed yet (like a catalog of products or articles), use CoreSpotlight to index items directly:

    import CoreSpotlight
    
    func indexCatalogForSpotlight(products: [Product]) {
        var searchableItems: [CSSearchableItem] = []
    
        for product in products {
            let attributes = CSSearchableItemAttributeSet(contentType: .content)
            attributes.title = product.name
            attributes.contentDescription = product.shortDescription
            attributes.thumbnailData = product.thumbnailData
            attributes.keywords = product.tags
            attributes.contentURL = URL(string: "https://example.com/products/\(product.slug)")
    
            let item = CSSearchableItem(
                uniqueIdentifier: "product-\(product.id)",
                domainIdentifier: "com.example.products",
                attributeSet: attributes
            )
            item.expirationDate = Calendar.current.date(byAdding: .month, value: 1, to: Date())
            searchableItems.append(item)
        }
    
        CSSearchableIndex.default().indexSearchableItems(searchableItems) { error in
            if let error = error {
                print("Indexing failed: \(error.localizedDescription)")
            }
        }
    }
    

    Refer to Apple's CoreSpotlight documentation for details on batch indexing, expiration policies, and handling updates.

    Web Markup

    Apple also crawls your website looking for Smart App Banners and apple-app-site-association files. When it finds them, it can connect web content to app screens for Spotlight results. This is the same infrastructure used by Universal Links, so if you already have Universal Links configured, you are halfway there.

    <meta name="apple-itunes-app" content="app-id=123456789, app-argument=https://example.com/products/blue-shoes">
    

    None of this works without functioning deep links. App indexing is, at its core, a way for search engines to create pointers to locations inside your app. If those pointers do not resolve correctly, the entire system falls apart.

    You need:

    • Android App Links that open your app when a user taps a verified HTTPS URL on Android. These require the Digital Asset Links file and intent filters in your AndroidManifest.xml. See the App Links Developer Guide for setup instructions.
    • iOS Universal Links that open your app from HTTPS URLs on iOS. These require the AASA file and the Associated Domains entitlement in Xcode. See the Universal Links Developer Guide for the full walkthrough.
    • A fallback web page for every app screen you want indexed. Search engines crawl web pages. If there is no web equivalent of your app screen, Google cannot index it.

    The web fallback is the part most teams skip, and it is also the most important part for SEO. Google indexes web pages. It associates those web pages with app screens through structured data and deep link verification. If you only have app content with no web presence, Google has nothing to crawl and nothing to show in search results.

    For teams building out their deep link infrastructure, Tolinku's route configuration handles the mapping between web URLs and app destinations, including the AASA and Digital Asset Links files that both platforms require.

    Structured Data for App Content

    Structured data tells search engines explicitly what your content is and how it connects to your app. The most effective format is JSON-LD, which Google recommends over Microdata or RDFa.

    Basic JSON-LD for App-Linked Pages

    Every web page that has a corresponding app screen should include structured data. At minimum, include the standard properties for your content type, plus the potentialAction property to declare the app link:

    <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "Product",
      "name": "Blue Running Shoes",
      "description": "Lightweight running shoes with cushioned sole.",
      "image": "https://example.com/images/blue-shoes.jpg",
      "url": "https://example.com/products/blue-running-shoes",
      "potentialAction": {
        "@type": "ViewAction",
        "target": [
          "https://example.com/products/blue-running-shoes",
          {
            "@type": "EntryPoint",
            "urlTemplate": "android-app://com.example.myapp/https/example.com/products/blue-running-shoes",
            "actionPlatform": "https://schema.org/AndroidPlatform"
          },
          {
            "@type": "EntryPoint",
            "urlTemplate": "https://example.com/products/blue-running-shoes",
            "actionPlatform": "https://schema.org/IOSPlatform"
          }
        ]
      }
    }
    </script>
    

    The potentialAction with ViewAction and platform-specific EntryPoint tells Google exactly how to open this content on each platform. For Android, the android-app:// URI format is a Google convention that maps to your app's intent filters. For iOS, the standard HTTPS URL works because Universal Links handle the routing.

    See Google's structured data guidelines and the schema.org Action documentation for the full specification.

    Content Type Matters

    Use the most specific schema.org type that fits your content. A recipe app should use Recipe, not generic WebPage. An e-commerce app should use Product with Offer. A news app should use NewsArticle. Google gives richer search result treatments to well-typed content: recipe cards, product carousels, article snippets, and more. For a deeper dive into schema markup for app-linked pages, see our guide on structured data for app content.

    Open Graph and Social SEO

    Search engines are not the only discovery channel. Social platforms (Facebook, Twitter/X, LinkedIn, iMessage, WhatsApp, Slack) all generate link previews when someone shares a URL. These previews drive clicks, and they are controlled by Open Graph meta tags and Twitter Card markup.

    Every web page that represents app content should include:

    <meta property="og:title" content="Blue Running Shoes">
    <meta property="og:description" content="Lightweight running shoes with cushioned sole. Free shipping on orders over $50.">
    <meta property="og:image" content="https://example.com/images/blue-shoes-og.jpg">
    <meta property="og:url" content="https://example.com/products/blue-running-shoes">
    <meta property="og:type" content="product">
    <meta property="og:site_name" content="Example Store">
    
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:title" content="Blue Running Shoes">
    <meta name="twitter:description" content="Lightweight running shoes with cushioned sole.">
    <meta name="twitter:image" content="https://example.com/images/blue-shoes-og.jpg">
    
    <meta property="al:ios:url" content="https://example.com/products/blue-running-shoes">
    <meta property="al:ios:app_store_id" content="123456789">
    <meta property="al:ios:app_name" content="Example Store">
    <meta property="al:android:url" content="https://example.com/products/blue-running-shoes">
    <meta property="al:android:package" content="com.example.myapp">
    <meta property="al:android:app_name" content="Example Store">
    

    The al: (App Links protocol) meta tags are an open standard that social platforms use to detect associated apps. Facebook, in particular, reads these to offer "Open in App" options when users click shared links.

    OG images should be 1200×630 pixels with key information visible even at small sizes. Avoid text-heavy images; they become unreadable in preview thumbnails. See Facebook's Open Graph documentation for the complete list of properties and validation tools.

    If you are using Tolinku, you can configure OG and social preview tags directly on each route, so every deep link generates proper previews when shared.

    App Store Optimization and app indexing SEO are related but distinct. ASO focuses on your app's listing in the App Store or Google Play. App indexing focuses on your app's content appearing in web search results. They reinforce each other.

    When your app content ranks in Google search results and users click through to install your app, that install signal feeds into the App Store's ranking algorithm. Apps with higher install velocity from organic sources tend to rank better in App Store search results as well. Indexed app content can also appear in app packs within search engine results pages, giving your app additional visibility alongside web results.

    Deep links also improve retention metrics, which both app stores use as ranking signals. A user who installs your app from a search result and lands on exactly the content they wanted is more likely to stay engaged than a user who installs from a generic ad and lands on a home screen.

    Keywords Bridge Both Channels

    The keywords you target for web SEO should inform your ASO keyword strategy, and vice versa. If "vegan meal prep recipes" drives traffic to your website, use that phrase in your app's App Store keywords, subtitle, and description. If your app ranks well in the App Store for "quick dinner ideas," make sure you have web content targeting that phrase, with proper structured data linking to the app.

    Research keywords using Google Search Console (for web search performance) and App Store Connect analytics (for App Store search terms). Cross-reference the two to find keyword opportunities that work across both channels.

    Measuring Organic App Traffic

    You cannot improve what you do not measure. Tracking organic traffic to your app requires connecting data from several sources.

    Google Search Console

    Search Console's Performance report shows impressions and clicks for your app content in Google search. Filter by device type (mobile) and appearance (app install, app content) to isolate app-specific search traffic.

    Key metrics to watch:

    • App content impressions: how often your app screens appear in search results
    • Click-through rate (CTR): what percentage of impressions result in clicks
    • App install clicks: clicks that lead to the App Store or Play Store
    • Query distribution: which search terms trigger your app content

    In-App Attribution

    When a user opens your app from a search result, you need to capture that context. On iOS, check the NSUserActivity object passed to your app delegate:

    func application(_ application: UIApplication,
                     continue userActivity: NSUserActivity,
                     restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
        if userActivity.activityType == NSUserActivityTypeBrowsingWeb,
           let url = userActivity.webpageURL {
            // Log the source URL for attribution
            Analytics.log(event: "app_open_from_search", parameters: [
                "url": url.absoluteString,
                "source": "organic_search"
            ])
            // Route to the correct screen
            DeepLinkRouter.handle(url: url)
            return true
        }
        return false
    }
    

    On Android, capture the intent data in your Activity:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val appLinkIntent = intent
        val appLinkAction = appLinkIntent.action
        val appLinkData = appLinkIntent.data
    
        if (Intent.ACTION_VIEW == appLinkAction && appLinkData != null) {
            // Log for attribution
            Analytics.log("app_open_from_search", mapOf(
                "url" to appLinkData.toString(),
                "source" to "organic_search",
                "referrer" to (appLinkIntent.getStringExtra("referrer") ?: "unknown")
            ))
            // Route to the correct screen
            DeepLinkRouter.handle(appLinkData)
        }
    }
    

    Connecting the Dots

    Combine Search Console data with in-app analytics to build a complete picture. Search Console tells you which queries and pages generate clicks. In-app analytics tells you what users do after they arrive. Together, they reveal which search terms bring engaged users versus drive-by visitors.

    Technical Implementation

    Here is a practical walkthrough for implementing app indexing on both platforms.

    Android: Indexing with Google's APIs

    Add the App Indexing library to your Android project:

    // build.gradle (app module)
    dependencies {
        implementation("com.google.firebase:firebase-appindexing:20.5.0")
    }
    

    Then log indexable content when users view screens:

    import com.google.firebase.appindexing.FirebaseAppIndex
    import com.google.firebase.appindexing.Indexable
    import com.google.firebase.appindexing.builders.Indexables
    
    class ProductActivity : AppCompatActivity() {
    
        override fun onStart() {
            super.onStart()
    
            val product = getProductFromIntent()
    
            val indexable = Indexables.digitalDocumentBuilder()
                .setName(product.name)
                .setDescription(product.description)
                .setUrl("https://example.com/products/${product.slug}")
                .setImage("https://example.com/images/${product.imageUrl}")
                .build()
    
            FirebaseAppIndex.getInstance(this).update(indexable)
        }
    }
    

    This registers the content with Google's on-device index. For server-side indexing (making your content appear in Google web search results), the web page with structured data is what matters, not the client-side API.

    iOS: Combining NSUserActivity and CoreSpotlight

    For the best coverage on iOS, use both NSUserActivity (for publicly indexable content) and CoreSpotlight (for private or pre-loaded content). The NSUserActivity approach was shown in the Apple Spotlight section above. Here is how to handle the callback when a user taps a Spotlight result:

    // In your AppDelegate or SceneDelegate
    func application(_ application: UIApplication,
                     continue userActivity: NSUserActivity,
                     restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    
        if userActivity.activityType == CSSearchableItemActionType {
            // Opened from CoreSpotlight
            if let identifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String {
                navigateToContent(identifier: identifier)
                return true
            }
        }
    
        if userActivity.activityType == NSUserActivityTypeBrowsingWeb {
            // Opened from Universal Link (including search results)
            if let url = userActivity.webpageURL {
                DeepLinkRouter.handle(url: url)
                return true
            }
        }
    
        return false
    }
    

    Web: Connecting Both Platforms

    Your web pages tie everything together. Here is a full HTML template for a page that supports both Google App Indexing and Apple's app association:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Blue Running Shoes - Example Store</title>
    
        <!-- Standard SEO -->
        <meta name="description" content="Lightweight running shoes with cushioned sole.">
        <link rel="canonical" href="https://example.com/products/blue-running-shoes">
    
        <!-- Open Graph -->
        <meta property="og:title" content="Blue Running Shoes">
        <meta property="og:description" content="Lightweight running shoes with cushioned sole.">
        <meta property="og:image" content="https://example.com/images/blue-shoes-og.jpg">
        <meta property="og:url" content="https://example.com/products/blue-running-shoes">
    
        <!-- App Links Protocol -->
        <meta property="al:ios:url" content="https://example.com/products/blue-running-shoes">
        <meta property="al:ios:app_store_id" content="123456789">
        <meta property="al:android:url" content="https://example.com/products/blue-running-shoes">
        <meta property="al:android:package" content="com.example.myapp">
    
        <!-- Apple Smart Banner -->
        <meta name="apple-itunes-app"
              content="app-id=123456789, app-argument=https://example.com/products/blue-running-shoes">
    
        <!-- Structured Data -->
        <script type="application/ld+json">
        {
          "@context": "https://schema.org",
          "@type": "Product",
          "name": "Blue Running Shoes",
          "url": "https://example.com/products/blue-running-shoes",
          "potentialAction": {
            "@type": "ViewAction",
            "target": [
              "https://example.com/products/blue-running-shoes",
              {
                "@type": "EntryPoint",
                "urlTemplate": "android-app://com.example.myapp/https/example.com/products/blue-running-shoes",
                "actionPlatform": "https://schema.org/AndroidPlatform"
              }
            ]
          }
        }
        </script>
    </head>
    <body>
        <!-- Page content -->
    </body>
    </html>
    

    App Indexing with Tolinku

    If you are using Tolinku for deep linking, several pieces of the app indexing puzzle are handled for you.

    Each route you create in Tolinku generates a web-accessible URL that serves as the fallback page for your deep link. These pages include configurable OG tags, Twitter Card metadata, and Apple Smart App Banner markup. When Google crawls these URLs, it finds the structured metadata it needs to associate the web page with your app.

    Tolinku's route configuration also generates and hosts the apple-app-site-association and assetlinks.json files automatically. This means the verification layer that both Apple and Google require is always in sync with your route definitions. You do not need to manually edit JSON files every time you add a new deep link path.

    For social sharing and link preview optimization, configure your OG and social preview settings per route. This ensures that every shared link, whether from search results, social media, or messaging apps, displays the correct title, description, and image.

    Best Practices

    Start with your most valuable content. Do not try to index every screen in your app at once. Identify the 10-20 screens that drive the most value (product pages, articles, profiles, listings) and index those first. Expand from there.

    Maintain URL parity. Every app screen you want indexed needs a corresponding web page at a predictable URL. The URL structure should match: if your app shows a product at /products/123, your web page should live at https://example.com/products/123. Keep the paths identical.

    Keep structured data accurate. Stale or incorrect structured data hurts your search presence. If a product goes out of stock or an article gets updated, the structured data on the web page should reflect the change. Use Google's Rich Results Test to validate your markup.

    Set expiration dates on indexed items. For time-sensitive content (events, deals, limited listings), set an expirationDate on your CoreSpotlight items and include expiry signals in your structured data. Stale results in Spotlight or search erode user trust.

    Test on real devices. Spotlight indexing, Universal Link verification, and App Link verification all behave differently in simulators versus real hardware. Test your indexing flow on physical iOS and Android devices before shipping.

    Monitor Search Console weekly. Watch for coverage errors, dropped pages, and changes in app content impressions. Google's indexing is not instant, and issues can take days to surface. Catching problems early prevents traffic loss.

    Use rel="alternate" for app URIs. In addition to JSON-LD, you can add link elements in your HTML head to declare app alternatives:

    <link rel="alternate" href="android-app://com.example.myapp/https/example.com/products/blue-shoes">
    <link rel="alternate" href="ios-app://123456789/https/example.com/products/blue-shoes">
    

    These are an older mechanism, but Google still recognizes them, and they serve as a useful fallback if your JSON-LD has issues.

    Combine ASO and web SEO keyword research. Run your target keywords through both web search tools and app store keyword tools. Phrases that have high volume in both channels are the best targets for app indexing because they give you visibility in two places at once.

    Conclusion

    App indexing SEO is not a one-time setup. It is an ongoing practice that connects your app content to the search queries your users are already making. The technical requirements, deep links, structured data, web fallback pages, platform-specific APIs, are all well-documented and straightforward to implement.

    The payoff is significant. Apps with properly indexed content see organic installs from search queries they would never reach through the App Store alone. Users who arrive through search results with deep links engage more deeply because they land on exactly the content they were looking for.

    Start with your highest-value content. Get your deep links working. Add structured data to your web pages. Register with Google Search Console. Index your content with CoreSpotlight and NSUserActivity. Then monitor, iterate, and expand.

    The search results are already showing app content for your competitors' apps. Make sure your app is there too.

Get deep linking tips in your inbox

One email per week. No spam.

Ready to add deep linking to your app?

Set up Universal Links, App Links, deferred deep linking, and analytics in minutes. Free to start.