{"id":26103364,"url":"https://github.com/constructor-io/constructorio-client-android","last_synced_at":"2025-04-12T17:23:53.324Z","repository":{"id":37057879,"uuid":"132483938","full_name":"Constructor-io/constructorio-client-android","owner":"Constructor-io","description":"Constructor.io Client for Android Applications","archived":false,"fork":false,"pushed_at":"2024-12-31T00:07:00.000Z","size":2739,"stargazers_count":4,"open_issues_count":2,"forks_count":1,"subscribers_count":33,"default_branch":"master","last_synced_at":"2025-04-12T17:23:34.383Z","etag":null,"topics":["android","android-sdk","constructorio-integrations","kotlin","kotlin-android","search"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Constructor-io.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-05-07T15:55:52.000Z","updated_at":"2024-12-31T00:07:04.000Z","dependencies_parsed_at":"2023-09-27T20:44:24.328Z","dependency_job_id":"4da90f12-8c98-4340-b366-6b9a603b6f08","html_url":"https://github.com/Constructor-io/constructorio-client-android","commit_stats":null,"previous_names":[],"tags_count":81,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Constructor-io%2Fconstructorio-client-android","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Constructor-io%2Fconstructorio-client-android/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Constructor-io%2Fconstructorio-client-android/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Constructor-io%2Fconstructorio-client-android/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Constructor-io","download_url":"https://codeload.github.com/Constructor-io/constructorio-client-android/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248602902,"owners_count":21131710,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","android-sdk","constructorio-integrations","kotlin","kotlin-android","search"],"created_at":"2025-03-09T20:06:39.205Z","updated_at":"2025-04-12T17:23:53.302Z","avatar_url":"https://github.com/Constructor-io.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Release](https://jitpack.io/v/Constructor-io/constructorio-client-android.svg)](https://jitpack.io/#Constructor-io/constructorio-client-android) ![Android min](https://img.shields.io/badge/Android-4.4%2B-green.svg) [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/Constructor-io/constructorio-client-android/blob/master/LICENSE)\n\n# Constructor.io Android Client\n\nAn Android Client for [Constructor.io](http://constructor.io/).  [Constructor.io](http://constructor.io/) provides search as a service that optimizes results using artificial intelligence (including natural language processing, re-ranking to optimize for conversions, and user personalization).\n\n## Documentation\nFull API documentation is available on [Github Pages](https://constructor-io.github.io/constructorio-client-android/)\n\n## 1. Install\n\nPlease follow the directions at [Jitpack.io](https://jitpack.io/#Constructor-io/constructorio-client-android/v2.35.0) to add the client to your project.\n\n## 2. Retrieve an API key\n\nYou can find this in your [Constructor.io dashboard](https://constructor.io/dashboard).  Contact sales if you'd like to sign up, or support if you believe your company already has an account.\n\n## 3. Create a Client Instance\n\n```kotlin\nimport io.constructor.core.ConstructorIo\nimport io.constructor.core.ConstructorIoConfig\n\n// Create the client config\nval config = ConstructorIoConfig(\n  apiKey = \"YOUR API KEY\",\n  serviceUrl = \"ac.cnstrc.com\" // default\n)\n\n// Create the client instance\nConstructorIo.init(this, config)\n\n// Set the user ID (for a logged in user) used for cross device personalization\nConstructorIo.userId = \"uid\"\n```\n## 4. Retrieving the client_id and session_id\nIf you are retrieving results from your backend servers instead of directly using our SDK, there are certain personalization parameters that are needed to be passed along with your requests. And those parameters can be accessed from the Constructor instance.\n\n1. **Client Id**\nThis Can be retrieved by calling **getClientId** function on the client sdk instance.\n```kotlin\nvar constructorClientId = ConstructorIo.getClientId()\n```\n2. **Session Id**\nThis Can be retrieved by calling **getSessionId** function on the client sdk instance.\n```kotlin\nvar constructorSessionId = ConstructorIo.getSessionId()\n```\n\nIn most cases, you will want to store those parameters as cookies preferably as **ConstructorioID_client_id** and **ConstructorioID_session_id** to be sent with your requests to your backend servers.\n\n## 5. Setting test cell information for A/B tests\nWhen A/B testing, it is important to specify which cell the user is being assigned to. Information about the test cell can be set through the `ConstructorIoConfig` object.\n\n```kotlin\nvar ConstructorIoConfig(\n  apiKey = \"YOUR API KEY\",\n  serviceUrl = \"ac.cnstrc.com\", // default\n  testCells = listOf(\"constructorio_test\" to \"control_1\")\n)\n\n// Create the client instance\nConstructorIo.init(this, config)\n\n// The test cells can be edited after creating the client instance\nconstructorIo.testCells = listOf(\"constructorio_test\" to \"control_1\")\n```\n\n## 6. Request Autocomplete Results\n\n```kotlin\n// To specify the number of results you want to have returned from each section, you will need to\n// ... configure this within the ConstructorIoConfig object before instantiating the client\nvar config = ConstructorIoConfig(apiKey = \"YOUR_API_KEY\", autocompleteResultCount = mapOf(\"Products\" to 6, \"Search Suggestions\" to 10))\nConstructorIo.init(this, config)\n\nvar query = \"Dav\"\nvar selectedFacet: HashMap\u003cString, MutableList\u003cString\u003e\u003e? = null\nvar variationsMap: VariationsMap = VariationsMap(\n  groupBy = listOf(mapOf(\"name\" to \"Color\", \"field\" to \"data.color\")),\n  values = mapOf(\n    \"min_price\" to mapOf(\"aggregation\" to \"min\", \"field\" to \"data.price\"),\n    \"max_price\" to mapOf(\"aggregation\" to \"max\", \"field\" to \"data.price\"),\n  ),\n  dtype = \"array\",\n  filterBy = \"\"\"{\"and\":[{\"field\":\"data.brand\",\"value\":\"Best Brand\"}]}\"\"\",\n)\n\n// Using RxJava\nConstructorIo.getAutocompleteResults(query, selectedFacet?.map { it.key to it.value }, variationsMap = variationsMap)\n.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())\n.subscribe {\n  it.onValue {\n    it?.let {\n      view.renderData(it)\n    }\n  }\n}\n\n// Using Coroutines\nrunBlocking {\n  launch {\n    try {\n      val autocompleteResults = ConstructorIo.getAutocompleteResultsCRT(query, selectedFacet?.map { it.key to it.value })\n      // Do something with autocompleteResults\n    } catch (e: Exception) {\n      println(e)\n    }\n  }\n}\n```\n\n### Alternative using Request Builder or DSL\n```kotlin\n// Creating a request using Request Builder\nval autocompleteRequest = AutocompleteRequest.Builder(\"potato\")\n  .setNumResultsPerSection(mapOf(\n    \"Products\" to 6,\n    \"Search Suggestions\" to 8\n  ))\n  .setFilters(mapOf(\n    \"group_id\" to listOf(\"G123\"),\n    \"availability\" to listOf(\"US\", \"CA\")\n  ))\n  .setVariationsMap(variationsMap)\n  .build()\n\n// Creating a request using DSL\nval autocompleteRequest = AutocompleteRequest.build(\"potato\") {\n  numResultsPerSection = mapOf(\n    \"Products\" to 6,\n    \"Search Suggestions\" to 8\n  )\n  filters = mapOf(\n    \"group_id\" to listOf(\"G123\"),\n    \"availability\" to listOf(\"US\", \"CA\")\n  )\n}\n\nConstructorIo.getAutocompleteResults(autocompleteRequest)\n```\n\n## 7. Request Search Results\n\n```kotlin\nvar page = 1\nvar perPage = 10\nvar query = \"Dave's bread\"\nvar selectedFacets: HashMap\u003cString, MutableList\u003cString\u003e\u003e? = null\nvar selectedSortOption: SortOption? = null\nvar variationsMap: VariationsMap = VariationsMap(\n  groupBy = listOf(mapOf(\"name\" to \"Color\", \"field\" to \"data.color\")),\n  values = mapOf(\n    \"min_price\" to mapOf(\"aggregation\" to \"min\", \"field\" to \"data.price\"),\n    \"max_price\" to mapOf(\"aggregation\" to \"max\", \"field\" to \"data.price\"),\n  ),\n  dtype = \"array\",\n  \"\"\"{\"and\":[{\"field\":\"data.brand\",\"value\":\"Best Brand\"}]}\"\"\",\n)\nvar preFilterExpression = \"\"\"{ \"and\": [ { \"name\": \"Color\", \"value\": \"green\" } ] }\"\"\"\n\n\n// Using RxJava\nConstructorIo.getSearchResults(query, selectedFacets?.map { it.key to it.value }, page = page, perPage = perPage, sortBy = selectedSortOption?.sortBy, sortOrder = selectedSortOption?.sortOrder, variationsMap = variationsMap, preFilterExpression = preFilterExpression)\n.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())\n.subscribe {\n  it.onValue {\n    it.response?.let {\n      view.renderData(it)\n    }\n  }\n}\n\n// Using Coroutines\nrunBlocking {\n  launch {\n    try {\n      val searchResults = ConstructorIo.getSearchResultsCRT(query)\n      // Do something with searchResults\n    } catch (e: Exception) {\n      println(e)\n    }\n  }\n}\n```\n\n### Alternative using Request Builder or DSL\n```kotlin\n// Creating a request using Request Builder\nval searchRequest = SearchRequest.Builder(\"potato\")\n  .setFilters(mapOf(\n    \"group_id\" to listOf(\"G123\"),\n    \"Brand\" to listOf(\"Kings\")\n  ))\n  .setHiddenFields(listOf(\"hidden_field_1\", \"hidden_field_2\"))\n  .setVariationsMap(variationsMap)\n  .setPreFilterExpression(preFilterExpression)\n  .build()\n\n// Creating a request using DSL\nval searchRequest = SearchRequest.build(\"potato\") {\n  filters = mapOf(\n    \"group_id\" to listOf(\"G123\"),\n    \"Brand\" to listOf(\"Kings\")\n  )\n  hiddenFields = listOf(\"hidden_field_1\", \"hidden_field_2\")\n}\n\nConstructorIo.getSearchResults(searchRequest)\n```\n\n## 8. Request Browse Results\n\n```kotlin\nvar page = 1\nvar perPage = 10\nvar filterName = \"group_id\"\nvar filterValue = \"Beverages\"\nvar selectedFacets: HashMap\u003cString, MutableList\u003cString\u003e\u003e? = null\nvar selectedSortOption: SortOption? = null\nvar variationsMap: VariationsMap = VariationsMap(\n  groupBy = listOf(mapOf(\"name\" to \"Color\", \"field\" to \"data.color\")),\n  values = mapOf(\n    \"min_price\" to mapOf(\"aggregation\" to \"min\", \"field\" to \"data.price\"),\n    \"max_price\" to mapOf(\"aggregation\" to \"max\", \"field\" to \"data.price\"),\n  ),\n  dtype = \"array\",\n  \"\"\"{\"and\":[{\"field\":\"data.brand\",\"value\":\"Best Brand\"}]}\"\"\"\n)\nvar preFilterExpression = \"\"\"{ \"and\": [ { \"name\": \"Color\", \"value\": \"green\" } ] }\"\"\"\n\n\n// Using RxJava\nConstructorIo.getBrowseResults(filterName, filterValue, selectedFacets?.map { it.key to it.value }, page = page, perPage = perPage, sortBy = selectedSortOption?.sortBy, sortOrder = selectedSortOption?.sortOrder, variationsMap = variationsMap, preFilterExpression = preFilterExpression)\n.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())\n.subscribe {\n  it.onValue {\n    it.response?.let {\n      view.renderData(it)\n    }\n  }\n}\n\n// Using Coroutines\nrunBlocking {\n  launch {\n    try {\n      val browseResults = ConstructorIo.getBrowseResultsCRT(filterName, filterValue)\n      // Do something with browseResults\n    } catch (e: Exception) {\n      println(e)\n    }\n  }\n}\n```\n\n## 8.1 Request Browse Items Results\n\n```kotlin\nvar itemIds = listOf(\"item1\", \"item2\")\nvar selectedFilters: List\u003cPair\u003cString, List\u003cString\u003e\u003e\u003e? = null\nvar browseItemsRequest = BrowseItemsRequest.Builder(itemIds)\n    .setFilters(selectedFilters)\n    .build()\n\n// Using RxJava\nConstructorIo.getBrowseItemsResults(browseItemsRequest)\n.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())\n.subscribe {\n  it.onValue {\n    it.response?.let {\n      view.renderData(it)\n    }\n  }\n}\n\n// Using Coroutines\nrunBlocking {\n  launch {\n    try {\n      val browseResults = constructorIo.getBrowseItemsResultsCRT(filterName, filterValue)\n      // Do something with browseResults\n    } catch (e: Exception) {\n      println(e)\n    }\n  }\n}\n```\n\n### Alternative using Request Builder or DSL\n```kotlin\n// Creating a request using Request Builder\nval browseRequest = BrowseRequest.Builder(\"group_id\", \"123\")\n  .setFilters(mapOf(\n    \"group_id\" to listOf(\"G1234\"),\n    \"Brand\" to listOf(\"Cnstrc\"),\n    \"Color\" to listOf(\"Red\", \"Blue\")\n  ))\n  .setHiddenFacets(listOf(\"hidden_facet_1\", \"hidden_facet_2\"))\n  .setVariationsMap(variationsMap)\n  .setPreFilterExpression(preFilterExpression)\n  .build()\n\n// Creating a request using DSL\nval browseRequest = BrowseRequest.build(\"group_id\", \"123\") {\n  filters = mapOf(\n    \"group_id\" to listOf(\"G1234\"),\n    \"Brand\" to listOf(\"Cnstrc\"),\n    \"Color\" to listOf(\"Red\", \"Blue\")\n  )\n  hiddenFacets = listOf(\"hidden_facet_1\", \"hidden_facet_2\")\n}\n\nConstructorIo.getBrowseResults(browseRequest)\n```\n\n## 9. Request Recommendation Results\n\n```kotlin\nvar numResults = 6\nvar perPage = 10\nvar podId = \"best_sellers\"\nvar selectedFacets: HashMap\u003cString, MutableList\u003cString\u003e\u003e? = null\nvar variationsMap: VariationsMap = VariationsMap(\n  groupBy = listOf(mapOf(\"name\" to \"Color\", \"field\" to \"data.color\")),\n  values = mapOf(\n    \"min_price\" to mapOf(\"aggregation\" to \"min\", \"field\" to \"data.price\"),\n    \"max_price\" to mapOf(\"aggregation\" to \"max\", \"field\" to \"data.price\"),\n  ),\n  dtype = \"array\",\n  \"\"\"{\"and\":[{\"field\":\"data.brand\",\"value\":\"Best Brand\"}]}\"\"\",\n)\nvar preFilterExpression = \"\"\"{ \"and\": [ { \"name\": \"Color\", \"value\": \"green\" } ] }\"\"\"\n\n\n// Using RxJava\nConstructorIo.getRecommendationResults(podId, selectedFacets?.map { it.key to it.value }, numResults, variationsMap = variationsMap, preFilterExpression = preFilterExpression)\n.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())\n.subscribe {\n  it.onValue {\n    it.response?.let {\n      view.renderData(it)\n    }\n  }\n}\n\n// Using Coroutines\nrunBlocking {\n  launch {\n    try {\n      val recommendationResults = ConstructorIo.getRecommendationResultsCRT(podId)\n      // Do something with recommendationResults\n    } catch (e: Exception) {\n      println(e)\n    }\n  }\n}\n```\n\n### Alternative using Request Builder or DSL\n```kotlin\n// Creating a request using Request Builder\nval recommendationsRequest = RecommendationsRequest.Builder(\"product_detail_page\")\n  .setItemIds(listOf(\"item_id_123\"))\n  .setVariationsMap(variationsMap)\n  .build()\n\n// Creating a request using DSL\nval recommendationsRequest = RecommendationsRequest.build(\"product_detail_page\") {\n  itemIds = listOf(\"item_id_123\")\n}\n\nConstructorIo.getRecommendationResults(recommendationsRequest)\n```\n\n## 10. Request Quiz Next Question\n\n```kotlin\nval quizId = \"quiz-id-1\"\nval answers = listOf(\n    listOf(\"1\"), \n    listOf(\"1, 2\"), \n    listOf(\"true\"), \n)\nval versionId = \"version-1\"\nval sectionName = \"Products\"\n\n// Using RxJava\nConstructorIo.getQuizNextQuestion(quizId, answers, versionId, sectionName)\n    .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())\n    .subscribe {\n        it.onValue {\n            it.response?.let {\n                view.renderData(it)\n            }\n        }\n    }\n\n// Using Coroutines\nrunBlocking {\n    launch {\n        try {\n            val quizNextQuestion = ConstructorIo.getQuizNextQuestionCRT(quizId, answers, versionId, sectionName)\n            // Do something with quizNextQuestion\n        } catch (e: Exception) {\n            // Handle error\n            println(e)\n        }\n    }\n}\n```\n\n### Alternative using Request Builder or DSL\n```kotlin\n// Creating a request using Request Builder\nval quizRequest = QuizRequest.Builder(\"quiz-id-1\")\n    .setAnswers(listOf(\n        listOf(\"1\"),\n        listOf(\"1, 2\"),\n        listOf(\"true\"),\n    ))\n    .setVersionId(\"version-1\")\n    .setSection(\"Products\")\n    .build()\n\n// Creating a request using DSL\nval quizRequest = QuizRequest.build(\"quiz-id-1\") {\n    answers = listOf(\n        listOf(\"1\"),\n        listOf(\"1, 2\"),\n        listOf(\"true\"),\n    )\n    versionId = \"version-1\"\n    section = \"Products\"\n}\n\nConstructorIo.getQuizNextQuestion(quizRequest)\n```\n\n## 11. Request Quiz Results\n\n```kotlin\nval quizId = \"quiz-id-1\"\nval answers = listOf(\n    listOf(\"1\"), \n    listOf(\"1, 2\"), \n    listOf(\"true\"), \n)\nval versionId = \"version-1\"\nval sectionName = \"Products\"\n\n// Using RxJava\nConstructorIo.getQuizResults(quizId, answers, versionId, sectionName)\n    .subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())\n    .subscribe {\n        it.onValue {\n            it.response?.let {\n                view.renderData(it)\n            }\n        }\n    }\n\n// Using Coroutines\nrunBlocking {\n    launch {\n        try {\n            val quizResults = ConstructorIo.getQuizResultCRT(quizId, answers, versionId, sectionName)\n            // Do something with quizResults\n        } catch (e: Exception) {\n            // Handle error\n            println(e)\n        }\n    }\n}\n```\n\n### Alternative using Request Builder or DSL\n```kotlin\n// Creating a request using Request Builder\nval quizRequest = QuizRequest.Builder(\"quiz-id-1\")\n    .setAnswers(listOf(\n        listOf(\"1\"),\n        listOf(\"1, 2\"),\n        listOf(\"true\"),\n    ))\n    .setVersionId(\"version-1\")\n    .setSection(\"Products\")\n    .build()\n\n// Creating a request using DSL\nval quizRequest = QuizRequest.build(\"quiz-id-1\") {\n    answers = listOf(\n        listOf(\"1\"),\n        listOf(\"1, 2\"),\n        listOf(\"true\"),\n    )\n    versionId = \"version-1\"\n    section = \"Products\"\n}\n\nConstructorIo.getQuizResults(quizRequest)\n```\n\n## 12. Instrument Behavioral Events\n\nThe Android Client sends behavioral events to [Constructor.io](http://constructor.io/) in order to continuously learn and improve results for future Autosuggest and Search requests.  The Client only sends events in response to being called by the consuming app or in response to user interaction . For example, if the consuming app never calls the SDK code, no events will be sent.  Besides the explicitly passed in event parameters, all user events contain a GUID based user ID that the client sets to identify the user as well as a session ID.\n\nThree types of these events exist:\n\n1. **General Events** are sent as needed when an instance of the Client is created or initialized\n2. **Autocomplete Events** measure user interaction with autocomplete results\n3. **Search Events** measure user interaction with search results\n4. **Browse Events** measure user interaction with browse results\n4. **Recommendation Events** measure user interaction with recommendation results\n5. **Quiz Events** measure user interaction with quiz results\n6. **Conversion Events** measure user events like `add to cart` or `purchase`\n\n### Autocomplete Events\n\n```kotlin\n// Track when the user focuses into the search bar (searchTerm)\nConstructorIo.trackInputFocus(\"\")\n\n// Track when the user selects an autocomplete suggestion (searchTerm, originalQuery, sectionName)\nConstructorIo.trackAutocompleteSelect(\"toothpicks\", \"tooth\", \"Search Suggestions\")\n\n// Track when the user submits a search  (searchTerm, originalQuery)\nConstructorIo.trackSearchSubmit(\"toothpicks\", \"tooth\")\n```\n\n### Search Events\n\n```kotlin\n// Track when search results are loaded into view (searchTerm, resultCount, customerIds of shown items)\nConstructorIo.trackSearchResultsLoaded(\"tooth\", 789, arrayOf(\"1234567-AB\", \"1234567-AB\"))\n\n// Track when a search result is clicked (itemName, customerId, searchTerm, sectionName, resultId)\nConstructorIo.trackSearchResultClick(\"Fashionable Toothpicks\", \"1234567-AB\", \"tooth\", \"Products\", \"179b8a0e-3799-4a31-be87-127b06871de2\")\n\n// v2.18.4+ only\n// Track when a search result is clicked (itemName, customerId, variationId, searchTerm, sectionName, resultId)\nConstructorIo.trackSearchResultClick(\"Fashionable Toothpicks\", \"1234567-AB\", \"RED\", \"tooth\", \"Products\", \"179b8a0e-3799-4a31-be87-127b06871de2\")\n```\n\n### Browse Events\n\n```kotlin\n// Track when browse results are loaded into view (filterName, filterValue, resultCount)\nConstructorIo.trackBrowseResultsLoaded(\"group_id\", \"Snacks\", 674)\n\n// v2.25.2+ only\n// Track when browse results are loaded into view (filterName, filterValue, itemIds, resultCount)\nConstructorIo.trackBrowseResultsLoaded(\"group_id\", \"Snacks\", arrayOf(\"1234\", \"2345\"), 674)\n\n// Track when a browse result is clicked (filterName, filterValue, customerId, resultPositionOnPage, sectionName, resultId)\nConstructorIo.trackBrowseResultClick(\"group_id\", \"Snacks\", \"7654321-BA\", \"4\", \"Products\", \"179b8a0e-3799-4a31-be87-127b06871de2\")\n\n// v2.18.4+ only\n// Track when a browse result is clicked (filterName, filterValue, customerId, variationId, resultPositionOnPage, sectionName, resultId)\nConstructorIo.trackBrowseResultClick(\"group_id\", \"Snacks\", \"7654321-BA\", \"RED\", \"4\", \"Products\", \"179b8a0e-3799-4a31-be87-127b06871de2\")\n```\n\n### Recommendation Events\n\n```kotlin\n// Track when a recommendation result is clicked (podId, strategyId, customerId, variationId, sectionName, resultId, numResultsPerPage, resultPage, resultCount, resultPositionOnPage)\nConstructorIo.trackRecommendationResultClick(\"Best_Sellers\", \"User Featured\", \"7654321-BA\", null, \"Products\", \"179b8a0e-3799-4a31-be87-127b06871de2\", 4, 1, 4, 2)\n\n// Track when recommendation results are loaded into view (podId, numResultsViewed, resultPage, resultCount, resultId, sectionName)\nConstructorIo.trackRecommendationResultsView(\"Best_Sellers\", 4, 1, 4, \"179b8a0e-3799-4a31-be87-127b06871de2\", \"Products\")\n\n// v2.34.0+ only\n// Track when recommendation results are loaded into view (podId, itemIds, numResultsViewed, resultPage, resultCount, resultId, sectionName)\nConstructorIo.trackRecommendationResultsView(\"Best_Sellers\", arrayOf(\"1234\", \"2345\"), 4, 1, 4, \"179b8a0e-3799-4a31-be87-127b06871de2\", \"Products\")\n```\n\n### Quiz Events\n\n```kotlin\n// Track when a quiz result is clicked (quizId, quizVersionId, quizSessionId, customerId, variationId, itemName, sectionName, resultId, numResultsPerPage, resultPage, resultCount) \nConstructorIo.trackQuizResultClick(\"coffee-quiz\", \"23AECMA-1EFKCI\", \"34NCUIEI-214CDN\", \"shirt-a\", \"shirt-a--reg\", \"White shirt\", null, null, 10, 1, 10);\n\n// Track when quiz results are loaded into view (quizId, quizVersionId, quizSessionId, sectionName, resultId, resultPage, resultCount)\nConstructorIo.trackQuizResultLoad(\"coffee-quiz\", \"23AECMA-1EFKCI\", \"34NCUIEI-214CDN\", null, null, 1, 10)\n\n// Track when a quiz result is converted on (quizId, quizVersionId, quizSessionId, displayName, type, isCustomType ,customerId, variationId, itemName, sectionName, revenue)\nConstructorIo.trackQuizConversion(\"coffee-quiz\", \"23AECMA-1EFKCI\", \"34NCUIEI-214CDN\", null, null, null, \"shirt-a\", \"shirt-a--reg\", \"White shirt\", null, \"129.99\")\n```\n\n### Conversion Events\n\n```kotlin\n// Track when an item converts (a.k.a. is added to cart) regardless of the user journey that led to adding to cart (itemName, customerId, revenue, searchTerm, section, conversionType, isCustomType, displayName)\nConstructorIo.trackConversion(\"Fashionable Toothpicks\", \"1234567-AB\", 12.99, \"tooth\", \"Products\", \"add_to_cart\")\n\n// v2.18.4+ only\n// Track when an item converts (a.k.a. is added to cart) regardless of the user journey that led to adding to cart (itemName, customerId, variationId, revenue, searchTerm, section, conversionType, isCustomType, displayName)\nConstructorIo.trackConversion(\"Fashionable Toothpicks\", \"1234567-AB\", \"RED\", 12.99, \"tooth\", \"Products\", \"add_to_cart\")\n\n// Track when items are purchased (customerIds, revenue, orderId)\nConstructorIo.trackPurchase(arrayOf(\"1234567-AB\", \"1234567-AB\"), 25.98, \"ORD-1312343\")\n\n// v2.18.4+ only\n// Track when items are purchased (PurchaseItems(itemId, variationId?, quantity?), revenue, orderId)\nConstructorIo.trackPurchase(arrayOf(PurchaseItem(\"TIT-REP-1997\", \"RED\", 2), PurchaseItem(\"QE2-REP-1969\")), 25.98, \"ORD-1312343\")\n```\n\n### Miscellaneous Events\n\n```kotlin\n// Track when a product detail page is loaded a.k.a after a user clicks on an item. (itemName, customerId, variationId?, sectionName?, url?)\nConstructorIo.trackItemDetailLoaded(\"Pencil\", \"123\", \"234\")\n\n// Track when a product is clicked. Should be used when a clicked product is not part of search/browse/recommendation experiences. (itemName, customerId, variationId?, sectionName?)\nConstructorIo.trackGenericResultClick(\"Pencil\", \"123\", \"234\")\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconstructor-io%2Fconstructorio-client-android","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconstructor-io%2Fconstructorio-client-android","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconstructor-io%2Fconstructorio-client-android/lists"}