Guides / Building Search UI / Going further

Send Insights Events

The InstantSearch Insights iOS library allows developers to send click, conversion, and view events. For search-related events, it correlates the event with the queryIDs generated when you’ve set the clickAnalytics parameter to true.

Algolia uses valid search-related events for Click and Conversion Analytics. Click and Conversion Analytics form the foundation for more advanced features like A/B Testing and Dynamic Re-Ranking. Algolia uses all valid events for Personalization. Even if you aren’t planning on implementing Personalization right away, it’s helpful to consider sending events as if you were. This lets you implement Personalization later on with a robust corpus of well-formatted user data.

To learn more about why you would want to send events and which events Algolia uses for which features, please read the guide on capturing user behaviors as events. To make sure you’re following InstantSearch best practices, please read the Getting Started guide before sending events.

Supported platforms

  • InstantSearch Insights iOS is supported on iOS, macOS, tvOS and watchOS.

Install the InstantSearch Insights library

Add a dependency on InstantSearch Insights using Swift Package Manager, CocoaPods, or Carthage, and add import InstantSearchInsights to your source files.

Swift Package Manager

To use Swift Package Manager, you should use Xcode 11 to open your project. Click File -> Swift Packages -> Add Package Dependency, and enter the URL of the InstantSearch repository (https://github.com/algolia/instantsearch-ios). Select InstantSearchInsights in the list of products that show up.

If you’re a framework author and use InstantSearch Insights as a dependency, update your Package.swift file:

1
2
3
4
5
6
7
let package = Package(
    // 7.7.0 ..< 8.0.0
    dependencies: [
        .package(name: "InstantSearch", url: "https://github.com/algolia/instantsearch-ios", from: "7.7.0")
    ],
    // ...
)

Add .product(name: "InstantSearchInsights", package: "InstantSearch") to your target dependencies list.

CocoaPods

CocoaPods is a dependency manager for Cocoa projects.

  • If you don’t have CocoaPods installed on your machine, open your terminal and run sudo gem install cocoapods.
  • If you don’t have a Podfile in your project, enter pod init. This creates a Podfile for you.

To install InstantSearch Insights, add the following line to your Podfile:

1
pod 'InstantSearch/Insights', '~> 7.7'
  • On your terminal, run pod update.

Carthage

Carthage is a simple, decentralized dependency manager for Cocoa.

To install InstantSearch, add the following line to your Cartfile:

1
github "algolia/instantsearch-ios" ~> 7.7

Launch the following commands from the project directory:

1
2
3
carthage update
./Carthage/Checkouts/instant-search-ios/carthage-prebuild
carthage build

At this time, Carthage doesn’t provide a way to build only specific subcomponents (or equivalent CocoaPods subspecs ) of a repository. It builds all components and their dependencies with the preceding commands. However, you don’t need to copy frameworks you aren’t using into your project. For instance, if you don’t use the entire set of InstantSearch components, you can delete all InstantSearch frameworks except InstantSearchInsights from the Carthage Build directory.

Initialize the Insights client

First, you need to initialize the Insights client. For that you need your application ID, API key, and the index name. You can find them in the API Keys section of the dashboard. Every event you send should have a userToken field to specify the user it relates to.

1
Insights.register(appId: "testApp", apiKey: "testKey", userToken: "testToken")

Sending events

Once that you registered your index with the application ID and the API key, you can start sending events. For examples of the different kinds of events and what user behaviors translate into them, please refer to the guide on capturing user behaviors as events.

Insights events (view, click, and conversion) don’t take immediate effect. The delay can range from a few minutes to an hour, depending on whether they are sent after a search or not, and how long after a search they are sent. For precise timeframes, see our page on when Insights events take effect.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Insights.shared?.clickedAfterSearch(eventName: "click event",
                                    indexName: "index name",
                                    objectID: "object id",
                                    position: 1,
                                    queryID: "query id")

Insights.shared?.convertedAfterSearch(eventName: "conversion event",
                                      indexName: "index name",
                                      objectIDs: ["obj1", "obj2"],
                                      queryID: "query id")

Insights.shared?.viewed(eventName: "view event",
                        indexName: "index name",
                        filters: ["brand:apple"])

Conversion events don’t always happen on a search results page. For example, a user could buy an item from a product detail page. That means you need to pass the queryID to the detail page. The keeping track of queryID guide shows how to use query parameters to track the queryID.

Embedding click events in the hits and mult-hits widgets

InstantSearch Insights iOS comes pre-packaged inside InstantSearch iOS. This simplifies the tracking of click events that occur on search results generated using the InstantSearch iOS Hits or Hits widgets. You still need to send click events from other sources, and view and conversion events as described before.

If you’re using multiple Hits widgets, you must enable sending click events on each one separately. This gives you the flexibility to decide which click events to track and which to ignore.

Sending click events from the hits widget

1
2
3
4
5
6
7
8
9
let searcher = SingleIndexSearcher(appID: "appID", apiKey: "apiKey", indexName: "indexname")
let hitsInteractor = HitsInteractor<Hit<JSON>>()
// Establish a connection between the searcher and hits interactor
hitsInteractor.connectSearcher(searcher)
// Declare a HitsTracker which takes care of activating clickAnalytics in the Query and extracts queryID from a received result for the index in the question
let hitsTracker = HitsTracker(eventName: "didClickItem", searcher: searcher)
// Did click the 10th item in the list
let hit = hitsInteractor.hit(atIndex: 10)!
hitsTracker.trackClick(for: hit, position: 10)

Sending click events from the multi-hits widget

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
let searcher = MultiIndexSearcher(appID: "appID",
                                    apiKey: "apiKey",
                                    indexNames: ["firstIndex",
                                                 "secondIndex"])
// Declare a separate hits interactor for each of the indices
let firstIndexHitsInteractor = HitsInteractor<Hit<JSON>>()
let secondIndexHitsInteractor = HitsInteractor<Hit<JSON>>()
// Declare a multi-index hits interactor, aggregating previously declared interactors
let hitsInteractor = MultiIndexHitsInteractor(hitsInteractors: [firstIndexHitsInteractor,
                                                                secondIndexHitsInteractor])
// Establish a connection between the searcher and multi-index hits interactor
hitsInteractor.connectSearcher(searcher)
// Declare a HitsTracker which takes care of activating clickAnalytics in the Query and extracts queryID from a received result for the index in the question
// Pointer defines the order of index in the MultiIndexSearcher (so 0 for firstIndex, 1 for secondIndex)
let productsHitsTracker = HitsTracker(eventName: "didClickItem", searcher: searcher, pointer: 0)
// Did click the 10th item in the list
let item1 = firstIndexHitsInteractor.hit(atIndex: 10)!
productsHitsTracker.trackClick(for: item1, position: 10)
// Same for the articles
let articesHitsTracker = HitsTracker(eventName: "didClickArticle", searcher: searcher, pointer: 1)
// Did click the 15th item in the list
let item2 = secondIndexHitsInteractor.hit(atIndex: 15)!
articesHitsTracker.trackClick(for: item2, position: 15)

Logging and debugging

In case you want to check if you’ve correctly sent an event, you need to enable the logging first.

1
Insights.shared(appId: "appId")?.isLoggingEnabled = true

After you enabled it, you can check the output for success messages or errors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// Success
[Algolia Insights - appName] Sync succeded for EventsPackage(id: "37E9A093-8F86-4049-9937-23E99E4E4B33", events: [{
    eventName = "search result click";
    eventType = click;
    index = "my index";
    objectIDs =     (
        1234567
    );
    positions =     (
        3
    );
    queryID = 08a76asda34fl30b7d06b7aa19a9e0;
    timestamp = 1545069313405;
    userToken = "C1D1322E-8CBF-432F-9875-BE3B5AFDA498";
}], region: nil)

//Error
[Algolia Insights - appName] The objectID field is missing (Code: 422)

Customizing the events flush delay

By default, the client transmits tracked events every 30 minutes. You can customize this delay by changing the flushDelay value (in seconds) as follows:

1
Insights.flushDelay = 60

Setting API region

By default, each time you send an event, Algolia geo-routes the API call so that the call targets the closest servers. Today the analytics API supports two regions: United States and Germany. You can specify the region your prefer to use as follows.

1
Insights.region = .de

Did you find this page helpful?