A Guide to Apple Search APIs

Neel Bakshi
7 min readAug 23, 2020

I’m sure all of us would have felt the need to re-engage our users with the app that we’ve built with all that love. All we need is a way to remind our users that your app can help them with the problems that they are facing! Now how do we do that??

Recently I was figuring out ways to solve this problem of re-engagement when I came across iOS Search APIs. All I knew was that you could index your content on Spotlight but I never took it so seriously, but the more I started reading about it, the more I realized that this had a lot of potential to get users onboard. I could use this to educate my user base about the features in my app as well as re-engage them if they ever tried to search for something my app did, from Spotlight or Safari.

In this article I’m going to talk about the different ways you can index your content on Spotlight and I shall also mention those tiny nitty-gritty details which usually get lost in Apple’s documentation but might be essential for you to achieve what you want.

The Search APIs

There are three ways you can index your content on Spotlight or Safari

  • CoreSpotlight
  • NSUserActivity
  • Web Markup

I will not talk about Web Markup a lot, but I will give you some pointers on how you can integrate it if you have web pages related to the content you’re indexing.

Another thing that you need to keep in mind is that there are two indexes

  • Private index which is the on device index, never shared with anyone or any device, even if you have multiple devices.
  • Public index which is shared across devices

This is the information on which we shall build upon in order to make sure you give your users the best experience to re-engage with them.

CoreSpotlight

CoreSpotlight is the way you manage the private on device index for your user.

Apple tells us that you use CoreSpotlight to index content that is specific to the user, for example, the documentation suggests that for an e-commerce app you could index wish-listed items, current orders of a user etc.

In order to index items using CoreSpotlight you need to learn about two classes CSSearchableItem and CSSearchableItemAttributeSet.

CSSearchableItem is the object which will get indexed whereas CSSearchableItemAttributeSet is what is going to describe this item.

A basic index operation looks something like the following and it’s as simple as that:

Make sure that you assign a proper uniqueIdentifier and domainIdentifier to your CSSearchableItem so that you can access them easily later on. The reason this is important is because of the following task, which is de-indexing items.

There will be times when you will have to de-index items, in order to keep the items that you serve on spotlight clean and updated. For example, if a particular item is no longer available, or if that item has been removed from your inventory etc. you will want to remove them.

You can de-index items individually or items under a collective domain or you can start from a clean slate again and CoreSpotlight provides the following methods for you to do it.

Keep in mind that there is no theoretical limit to what you can index, therefore you can go ahead and index whatever you like, although I will strongly suggest that you do not index everything.

Index things which upon discovery are beneficial to the user and will ensure that they do re-engage with your app.

Why do you need to keep the items that you serve on Spotlight clean and updated?

The reason for doing so is that if all your indexed items spam the Spotlight search with results that do not make sense to the user , you might have a very irritated user which can ultimately lead to an uninstall or a bad review for that matter.

In addition to that you need to make sure that you keep your index updated whenever possible so that items that are probably no longer available or do not make sense to the user need to be removed as the ranking of the items that you index depends on how the users interact with them. If you’ve heavily indexed items that are no longer available or items which the user will not want to interact with, they will never appear in your Spotlight search.

NSUserActivity

NSUserActivity helps you manage both the private and public index

Now the above statement might make you question that if you can manage the both the indexes using NSUserActivity why would you ever use CoreSpotlight. There are a few trade-offs involved which I’ll speak about later but first let’s see what NSUserActivity can provide us with.

According to Apple, you use NSUserActivity to index navigation points in your app. The benefit that you get from using NSUserActivity to index is that they you can make them available for Handoff, Siri Smart Reminders and Apple’s Public Indexing.

To index items using NSUserActivity the procedure is as follows

There is one more step you need to integrate in order to start seeing your items on Spotlight. Go to your Info.plist and then add a new key NSUserActivityType as an Array type. Then add your domains as items to this array.

Adding supported domains to Info.plist

An important point to remember while indexing using NSUserActivity is that your application needs to hold a strong reference to the activity object while it is being indexed otherwise it won’t be indexed.

If your activity has a webpageURL associated with it, it can be beneficial to fill that property in your activity object too. That way, your website’s content can also be scraped, and if lots of users end up interacting with it and your indexed item gets highly ranked, users who might not have the app installed might start seeing this result as well if they search for a similar thing. That way you can have organic traffic directed to your content.

De-Indexing — Similar to CoreSpotlight, de-indexing items is possible with NSUserActivity as well

isEligibleForPublicIndexing

The variable isEligibleForPublicIndexing deserves a special mention here because this is the switch that makes your item publicly searchable to your iOS user-base.

The ranking of your item will depend on quite a lot of factors which include:

  • The content associated with it. For example the title, description, ratings, reviews, content-type (remember the kUTTypeText keyword while initializing a CSSearchableItemAttributeSet) etc. Provide thumbnail images if possible too, make your item more engaging.
  • The more engagement the users show with that particular item. If lots of your users are indexing a particular item and/or interacting with that item in spotlight, it’s ranking will go up.
  • The ranking of your webPageURL (if any) that is associated with this particular activity.

Handling Spotlight Items

When a user taps on any of your indexed items in Spotlight you will receive the callback in your AppDelegate in the following function

The above gist summarizes how you can handle them. Pretty simple right!

Using CoreSpotlight and NSUserActivity together

In this section I’m going to talk about two things

  • The trade-offs with using NSUserActivity and CoreSpotlight for indexing items in the on-device index.
  • The things you need to do to make sure that you can use both for their specific use-cases in tandem with each other.

The Trade-offs

In the last section I mentioned that there were certain trade-offs involved with using both these means to manage your on-device index(Not going to mention differences related to the public index).

  • In order to index items using NSUserActivity, you need a strong reference, because of which you usually do it when the user has actually visited that page whereas this limitation does not exist with CoreSpotlight.
  • Apple suggests that you do not create multiple NSUserActivity objects at one time, since if you need them indexed you will need a strong reference to each of them, whereas in CoreSpotlight you could index an array of items.
  • CoreSpotlight does not provide you with the ability to make your indexed item available for Hand-Off or Siri Smart Reminders.

The point of telling you these trade-offs is not to say that one is better than the other. Rather each of these methods have their own use cases and you should use them in accordance with what they solve.

Using them together

In case you’re using both CoreSpotlight and NSUserActivity to index the same item (maybe in different scenarios), you need to make sure that you set the userActivity.uniqueIdentifier is the same as the searchableItem.relatedUniqueIdentifier

If you’re using web markup as well make sure along with the above two properties even the userActivity.webpageURL is the same as them.

Make sure that you do not set the relatedUniqueIdentifier if you’re not using both to index a particular item otherwise it won’t show up in Spotlight.

Conclusion

The reason for this article was that when I was implementing Spotlight Indexing for my app, I had lots of questions which were all answered from different sources. I had to scrape through the Apple Documentation, some things were hidden in plain sight, and some were difficult to figure out while for some questions I just had to implement the code and figure them out. I’ve tried to answer all these questions while framing this article.

This is not to say that the documentation is bad. There are lots of other important information present in those pages especially related to WebMarkup which I shall link below. You should also go through it once to make sure you have everything you need before you can go ahead and do it.

— Neel Bakshi, Mobile Engineer Headout

Passionate about Swift and iOS development? Join us!! We’re hiring!

--

--

Neel Bakshi

Guy who handles everything mobile @headout among other things! Ex @practo