# InstantSearch Insights for Android **InstantSearch Insights Android** library allows developers to report click and conversion metrics related to search queries. It does so by correlating events with queryIDs generated by the search API when a query parameter `clickAnalytics=true` is set. *⚠️ Important: this library is not compatible with the older [insights](instantsearch-android-insights) library.* ## Getting started **InstantSearch Insights** is supported on Android devices starting from SDK 21 and it is built on top of Algolia's [Kotlin API Client](https://github.com/algolia/algoliasearch-client-kotlin). ### Install You can add **InstantSearch Insights** to your Android application by adding the following line to your `build.gradle`'s dependencies. ```groovy implementation "com.algolia:instantsearch-insights-android:$instantsearch_version" ``` ## Quick Start ### Initialize the Insights client You first need to initialize the **Insights client**. For that you need your **Application ID**, **API Key** and the ** index name**. You can find them on [your Algolia account](https://www.algolia.com/api-keys). ```kotlin val appID = ApplicationID("applicationID") val apiKey = APIKey("apiKey") val indexName = IndexName("indexName") val configuration = Insights.Configuration( connectTimeoutInMilliseconds = 5000, readTimeoutInMilliseconds = 5000 ) registerInsights(context, appID, apiKey, indexName, configuration) ``` ### Sending metrics Once that you registered your **index** with the **Application ID** and the **API Key** you can easily start sending metrics * Create a `HitsTracker` to track hits events: ```kotlin val hitsTracker = HitsTracker( eventName = EventName("hits"), searcher = searcher, insights = sharedInsights(indexName) ) ``` * Create a `FilterTracker` for filter events: ```kotlin val filterTracker = FilterTracker( eventName = EventName("demo"), searcher = searcher, insights = sharedInsights(IndexName) ) ``` #### View events | Tracker | Command | | --- | --- | | Hits | `hitsTracker.trackView(hit)` | | Filters | `filterTracker.trackView(facet)` | #### Click events | Tracker | Command | | --- | --- | | Hits | `hitsTracker.trackClick(hit, position)` | | Filters | `filterTracker.trackClick(facet)` | #### Conversion events | Tracker | Command | | --- | --- | | Hits | `hitsTracker.trackConvert(hit)` | | Filters | `filterTracker.trackConversion(facet)` | ### Event Batching By default, events are only sent by batches of 10. You can customize this setting with `minBatchSize`: ```kotlin // At insights registration registerInsights(context, appID, apiKey, indexName, configuration).apply { minBatchSize = 1 } // Or, by getting shared insights sharedInsights(indexName).apply { minBatchSize = 1 } ``` ### User tracking Any event should have an `userToken` field to specify the user it relates to. You can set it in three ways: - Globally for all events - Per application, for every event tracked by this app - Individually on an event ```kotlin // Global userToken default value val configuration = Insights.Configuration( connectTimeoutInMilliseconds = 5000, readTimeoutInMilliseconds = 5000, defaultUserToken = UserToken("userToken") ) registerInsights(context, appID, apiKey, indexName, configuration) // Application userToken, overrides global default sharedInsights(indexName).apply { userToken = UserToken("userToken") } // Event userToken, overrides previous defaults sharedInsights?.clicked( InsightsEvent.Click( eventName = EventName("eventName"), indexName = IndexName("indexName"), userToken = UserToken("userToken"), timestamp = System.currentTimeMillis(), queryID = QueryID("queryId"), resources = InsightsEvent.Resources.ObjectIDs( listOf(ObjectID("objectID1")) ) ) ) ``` ### User opt-out You should allow users to opt-out of tracking anytime they want to. When they request opt-out, you can honor it using: ```kotlin sharedInsights(indexName)?.enabled = false // Or, by getting latest registered Insights instance sharedInsights?.enabled = false ``` ### Logging and debuging In case you want to check if the metric was sent correctly, you need to enable the logging first ```kotlin // At insights registration registerInsights(context, appID, apiKey, indexName, configuration).apply { loggingEnabled = true } // Or, by getting shared insights sharedInsights(indexName).apply { loggingEnabled = true } ``` After you enabled it, you can check the output for success messages or errors ``` // Success D/Algolia Insights: Index=bestbuy: Sync succeeded for View(eventName=EventName(raw=demo), indexName=bestbuy, userToken=UserToken(raw=userToken), timestamp=1634315597574, queryID=null, resources=ObjectIDs(objectIDs=[1762527]))." // Error D/Algolia Insights - indexName The objectID field is missing (Code: 422) ``` To get a more meaningful search experience, please follow our [Getting Started Guide](https://www.algolia.com/doc/guides/building-search-ui/getting-started/android/). ## Upload mechanism Events are stored in a `SharedPreference` database. Each time an event is successfully uploaded, it is removed from the database. An event can be updated using two distinct mechanisms: ### Single upload attempt Every time a new event is stored in the database, the following check is performed: If the number of events is superior or equal to `minBatchSize`, an attempt at uploading all events is performed. If the attempt fails, because of a network issue for example, it will not be retried, and events remain stored in the database. If you set `minBatchSize` to `1`, an upload attempt will be performed each time a new event is generated. ### Periodic upload The Insights library relies on a third party library [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager/). Every 15 minutes, a job will run in the background, whether the application is launched in the foreground or not. Each time a job runs, it will attempt to upload all events stored in the database. If it fails, because of a network issue for example, it will be retried later. The 15 minutes delay between each attempt is enforced by the Android system. It does not allow for a shorter delay, for battery saving reason. You can however configure a longer delay, by setting an higher value than `15` to the variable `debouncingIntervalInMinutes`. Any value below 15 will be ignored, and the 15 minutes delay will remain. ## License InstantSearch Android is [licensed under Apache V2](/LICENSE).