Skip to content

Commit 511490c

Browse files
authored
Updated documentation, configuration (#24)
* Ch2950/documentation (#19) * added sections number of results config parameters (#20) * rename api_key (#22) * added config object (#21) * ch3426 add uid parameter (#23)
1 parent b7e5e32 commit 511490c

File tree

15 files changed

+212
-301
lines changed

15 files changed

+212
-301
lines changed

README.md

Lines changed: 113 additions & 233 deletions
Original file line numberDiff line numberDiff line change
@@ -1,273 +1,153 @@
1-
# Constructor.io Android Client Library
1+
[![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)
22

3+
# Constructor.io Android Client
34

4-
An android client library for constructor.io suggestions engine
5+
An 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).
56

6-
# Usage
7+
## 1. Install
78

8-
## 1a. Install using gradle
9-
Add following to main gradle file:
9+
Please follow the directions at [Jitpack.io](https://jitpack.io/#Constructor-io/constructorio-client-android/v1.0.0) to add the client to your project.
1010

11-
```
12-
allprojects {
13-
repositories {
14-
...
15-
maven { url 'https://jitpack.io' }
16-
}
17-
}
18-
```
11+
## 2. Retrieve an API key
12+
You 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.
1913

20-
and then in your app gradle file include Constructor.IO dependency:
14+
## 3. Implement the Autocomplete UI
2115

22-
```
23-
dependencies {
24-
implementation 'com.github.Constructor-io:constructorio-client-android:v0.1'
16+
In your Application class add the following code with your key:
17+
18+
```kotlin
19+
override fun onCreate() {
20+
super.onCreate()
21+
ConstructorIo.init(this, "YOUR API KEY")
22+
23+
val fragment = supportFragmentManager.findFragmentById(R.id.fragment_suggestions) as SuggestionsFragment
24+
fragment.setConstructorListener(object : ConstructorListener {
25+
override fun onSuggestionSelected(term: String, group: Group?, autocompleteSection: String?) {
26+
Log.d(TAG, "onSuggestionSelected")
27+
}
28+
29+
override fun onQuerySentToServer(query: String) {
30+
Log.d(TAG, "onQuerySentToServer")
31+
}
32+
33+
override fun onSuggestionsRetrieved(suggestions: List<Suggestion>) {
34+
Log.d(TAG, "onSuggestionsRetrieved")
35+
}
36+
37+
override fun onErrorGettingSuggestions(error: Throwable) {
38+
Log.d(TAG, "handle network error getting suggestion")
39+
}
40+
})
2541
}
2642
```
2743

28-
## 1b. Manual import
29-
30-
* Clone the android client repository from github ```git clone https://github.com/Constructor-io/constructorio-client-android.git```
31-
* Open and build the project in your IDE
32-
33-
## 2. Retrieve an autocomplete key
34-
35-
You can find this in your [Constructor.io dashboard](https://constructor.io/dashboard).
36-
37-
Contact sales if you'd like to sign up, or support if you believe your company already has an account.
44+
### Selecting Results
45+
To respond to a user selecting an autocomplete result, use the `onSuggestionSelected` method. If the autocomplete result has both a suggested term to search for and a group to search within (as in Apples in Juice Drinks), the group will be passed into the method.
3846

39-
## 3. Init the Constructor.io Library
47+
### Performing Searches
48+
To respond to a user performing a search (instead of selecting an autocomplete result), use the `onQuerySentToServer` method.
4049

41-
In your Application class add the following code with your key:
50+
## 4. Customize the Autocomplete UI
4251

43-
```
44-
override fun onCreate() {
45-
super.onCreate()
46-
ConstructorIo.init(this, "your-key")
47-
}
48-
```
49-
## 4a. Use default out-of-the-box UI
52+
### Using the Default UI
5053

5154
To use the default, out-of-the-box UI, add the Sample Suggestions Fragment to your layout:
5255

5356
```xml
54-
<fragment
55-
android:id="@+id/fragment_suggestions"
56-
android:name="io.constructor.sample.SuggestionsFragment"
57-
android:layout_width="match_parent"
58-
android:layout_height="match_parent" />
59-
```
60-
61-
Skip to #5 if not customizing UI
62-
63-
## 4b. Customize UI
64-
65-
### Extend the suggestion screen fragment `BaseSuggestionFragment`.
66-
67-
Implement the following:
68-
69-
|Element name|Returned Type|Description|
70-
|--|--|--|
71-
|`layoutId`|`Int`|Returns your custom layout resource id for the fragment.|
72-
|`getSuggestionsInputId`|`EditText`|Returns the id of the suggestion input field.|
73-
|`getSuggestionListId`|`RecyclerView`|Returns your suggestion list id.|
74-
|`getSuggestionAdapter`|Class that extends from `BaseSuggestionAdapter`|Returns your custom adapter.|
75-
|`getProgressId`|Int`|Returns progress indicator id, used when request is being in progress. Return 0 for no progress|
76-
77-
To see an example of usage, you can look at `SampleActivityCustom`.
78-
79-
### Extend the suggestion items adapter `BaseSuggestionsAdapter`.
80-
81-
Implement the following :
82-
83-
|Element name|Returned Type|Description|
84-
|--|--|--|
85-
|`getItemLayoutId()`|`Int`|Returns your custom adapter item layout id for suggestion.|
86-
|`getSuggestionNameId()`|`Int`|Return your text view id - the text will be the suggestion. |
87-
|`getSuggestionGroupNameId()`|`Int`|Return your text view id - the text will be the suggestion group name, if found. |
88-
|`onViewTypeSuggestion`|`String` text| Triggered when inflating an item which is a suggestion. Read below for more info.|
89-
|`styleHighlightedSpans(spannable: Spannable, spanStart: Int, spanEnd: Int)`|`Unit`| Override to apply custom styling to highlighted part of suggestions search result. `spannable` is highlighted part of suggestion name, start and end mark position of the `spannable` within whole text.|
90-
91-
abstract val styleHighlightedSpans: ((spannable: Spannable, spanStart: Int, spanEnd: Int) -> Unit)?
92-
93-
In case you need to modify something in the ViewHolder (e.g make the group name bold) you can get a reference to it using `getHolder()`
94-
95-
To see an example of usage, you can look at `SampleActivityCustom`.
96-
97-
## 5. Get a reference to the `SuggestionsFragment` and add `ConstructorListener`:
98-
99-
```
100-
val fragment = supportFragmentManager.findFragmentById(R.id.fragment_suggestions) as SuggestionsFragment
101-
fragment.setConstructorListener(object : ConstructorListener {
102-
override fun onSuggestionsRetrieved(suggestions: List<Suggestion>) {
103-
//got suggestions for a query
104-
}
105-
106-
override fun onQuerySentToServer(query: String) {
107-
//request being made to server
108-
}
109-
110-
override fun onSuggestionSelected(term: String, group: Group?, autocompleteSection: String?) {
111-
//called when user taps on suggestion
112-
}
113-
114-
override fun onErrorGettingSuggestions(error: Throwable) {
115-
//called when there is error getting suggestions
116-
}
117-
})
118-
```
119-
# Additional references
120-
121-
## Searching in Groups
122-
Any data value can belong to a group. We will show the group name right below the item itself, if available.
123-
124-
Let's remember the selection event.
125-
126-
```
127-
fun onSuggestionSelected(term: String, group: Group?, autocompleteSection: String?)
57+
<fragment
58+
android:id="@+id/fragment_suggestions"
59+
android:name="io.constructor.sample.SuggestionsFragment"
60+
android:layout_width="match_parent"
61+
android:layout_height="match_parent"/>
12862
```
12963

130-
Note `group` of type Group. It represents the group for an item and includes the following parameters:
64+
### Using a Custom UI
13165

132-
|Type|Name|Description|
133-
|--|--|--|
134-
|String|groupId|The group's id.|
135-
|String|displayName|The group's display name.|
136-
|String|path|The path to get more data for the group.|
66+
To fully customize the UI, extend the `BaseSuggestionFragment` and the `BaseSuggestionsAdapter`
13767

138-
Let's say you search for 'apple' and the results are:
68+
```kotlin
69+
class CustomSearchFragment : BaseSuggestionFragment() {
13970

140-
141-
```
142-
"suggestions": [
143-
{
144-
"data": {
145-
"groups": [
146-
{
147-
"display_name": "food",
148-
"group_id": "12",
149-
"path": "/0/222/344"
150-
},
151-
{
152-
"display_name": "gadgets",
153-
"group_id": "34",
154-
"path": "/0/252/346/350"
155-
}
156-
]
157-
},
158-
"value": "apple"
159-
}
160-
]
161-
```
162-
163-
We received two groups (food and gadgets) for our suggestion (apple). This means we'll have two suggestions in total:
164-
1. 'apple' in group 'food'
165-
2. 'apple' in group 'gadgets'
166-
167-
When the user taps on (1), term will be `apple` and group name will be `food`.
168-
169-
When the user taps on (2), term will be `apple` and group name will be `gadgets`.
170-
171-
In other words, you can simply check whether the group property is null to find out if the user tapped on a search-in-group result:
172-
173-
```
174-
fun onSuggestionSelected(term: String, group: Group?, autocompleteSection: String) {
175-
if (group == null) {
176-
// user tapped on an item
177-
178-
} else {
179-
// user tapped on a group
71+
override fun onActivityCreated(savedInstanceState: Bundle?) {
72+
super.onActivityCreated(savedInstanceState)
73+
view?.backButton?.setOnClickListener {
74+
view?.input?.text?.clear()
75+
clearSuggestions()
18076
}
77+
view?.searchButton?.setOnClickListener { triggerSearch() }
18178
}
182-
```
183-
184-
## ConstructorListener Interface
185-
186-
### onQuerySentToServer
187-
188-
`onQuerySentToServer(query: String)`
189-
190-
Triggered when the query is sent to the server.
191-
192-
Parameter|Type|Description
193-
|--|--|--|
194-
`query`|String|The query made by the user.
195-
196-
### onSuggestionSelected
197-
198-
`onSuggestionSelected(term: String, group: Group?, autocompleteSection: String?)`
199-
200-
Triggered when a suggestion is selected.
20179

202-
|Parameter|Type|Description|
203-
|--|--|--|
204-
|`term`|String|The suggestion selected.|
205-
|`group`|Group|Provides data on the group the selected term belongs to. Otherwise null.|
206-
|`autocompleteSection`|String|The autocomplete section to which the selected term belongs (e.g "Search Suggestions", "Products"...)|
207-
208-
### onSuggestionsRetrieved
209-
`onSuggestionsRetrieved(suggestions: List<Suggestion>)`
210-
211-
Triggered when the results for the query in question is retrieved.
212-
213-
`suggestions` is a list of `Suggestion`s with the following parameters:
214-
215-
|Parameter|Type|Description|
216-
|--|--|--|
217-
|`text`|String|The name of the suggestion.|
218-
|`groups`|List<Group>|The top groups containing items that match for the query.|
219-
|`matchedTerms`|List<String>|matched terms within the query|
220-
|`sectionName`|String|name of the section eg. "Search Suggestions", "Products"|
221-
222-
### onErrorGettingSuggestions
223-
`override fun onErrorGettingSuggestions(error: Throwable)`
224-
225-
Triggered when error occured while requesting suggestions.
226-
227-
|Parameter|Type|Description|
228-
|--|--|--|
229-
|`error`|Throwable|Exception thrown.|
230-
231-
## BaseSuggestionFragment Abstract Class
232-
233-
Default fragment expose two additional methods for easier implementing custom UI:
80+
// Return your custom adapter
81+
override fun getSuggestionAdapter(): BaseSuggestionsAdapter {
82+
return CustomSuggestionsAdapter()
83+
}
23484

235-
### trackSearch()
85+
// Return your id of the suggestion input field
86+
override fun getSuggestionsInputId(): Int {
87+
return R.id.input
88+
}
23689

237-
Manually track search using text in the input box.
90+
// Return your id of the suggestion list
91+
override fun getSuggestionListId(): Int {
92+
return R.id.suggestions
93+
}
23894

239-
### clearSuggestions()
95+
// Return your progress indicator id, used when request is being in progress. Return 0 for no progress
96+
override fun getProgressId(): Int {
97+
return 0
98+
}
99+
100+
// Return your custom layout resource id for the fragment
101+
override fun layoutId(): Int {
102+
return R.layout.fragment_custom_suggestions
103+
}
240104

241-
Clear input box and suggestion list.
105+
}
242106

243-
## ConstructorIO public API
107+
class CustomSuggestionsAdapter() : BaseSuggestionsAdapter() {
108+
109+
// Triggered when inflating an item which is a suggestion.
110+
override fun onViewTypeSuggestion(holder: ViewHolder, suggestion: String, highlightedSuggestion: Spannable, groupName: String?) {
111+
holder.suggestionName.text = highlightedSuggestion
112+
val spans = highlightedSuggestion.getSpans(0, highlightedSuggestion.length, StyleSpan::class.java)
113+
spans.forEach { highlightedSuggestion.setSpan(ForegroundColorSpan(Color.parseColor("#222222")), highlightedSuggestion.getSpanStart(it), highlightedSuggestion.getSpanEnd(it), 0) }
114+
groupName?.let { holder.suggestionGroupName.text = holder.suggestionGroupName.context.getString(R.string.suggestion_group, it) }
115+
}
244116

245-
### trackConversion(term: String, itemId: String, revenue: String?)
117+
// Return your custom adapter item layout id for suggestion
118+
override val itemLayoutId: Int
119+
get() = R.layout.item_suggestion
120+
121+
// Return your text view id - the text will be the suggestion.
122+
override val suggestionNameId: Int
123+
get() = R.id.suggestionName
124+
125+
// Return your text view id - the text will be the suggestion group name, if present
126+
override val suggestionGroupNameId: Int
127+
get() = R.id.suggestionGroupName
246128

247-
Track conversion event
129+
}
130+
```
248131

249-
|Parameter|Type|Description|
250-
|--|--|--|
251-
|`term`|String|Optional term for which tracking event is reported.|
252-
|`itemId`|String|Id of item for which we want to trigger an event.|
253-
|`revenue`|String|Optional revenue indicator.|
132+
## 5. Instrument Behavioral Events
254133

255-
### trackSearchResultClickThrough(term: String, itemId: String, position: String?)
134+
The 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.
256135

257-
Track search result click event
136+
Three types of these events exist:
258137

259-
|Parameter|Type|Description|
260-
|--|--|--|
261-
|`term`|String|Term used for search.|
262-
|`itemId`|String|Id of item for which we want to track an event.|
263-
|`position`|String|Optional position of clicked item on the list.|
138+
1. **General Events** are sent as needed when an instance of the Client is created or initialized
139+
1. **Autocomplete Events** measure user interaction with autocomplete results and the `CIOAutocompleteViewController` sends them automatically.
140+
1. **Search Events** measure user interaction with search results and the consuming app has to explicitly instrument them itself
264141

265-
### triggerSearchResultLoadedEvent(term: String, resultCount: Int)
142+
```kotlin
143+
import io.constructor.core.ConstructorIo
266144

267-
Track search results loaded event
145+
// Track search results loaded (term, resultCount)
146+
ConstructorIo.trackSearchResultLoaded("a search term", 123)
268147

269-
|Parameter|Type|Description|
270-
|--|--|--|
271-
|`term`|String|Term used for search.|
272-
|`resultCount`|Int|Number of items found.|
148+
// Track search result click (term, itemId, position)
149+
ConstructorIo.trackSearchResultClickThrough("a search term", "an item id", "1")
273150

151+
// Track conversion (item id, term, revenue)
152+
constructorIO.trackConversion("an item id", "a search term", "45.00")
153+
```

0 commit comments

Comments
 (0)