Introduction
If you are not using InstantSearch, you’ll have to send the events using one of our API Clients.
All API Clients have methods to make sending events as simple as possible, requiring only one line of code.
We recommend sending click and conversion events using InstantSearch if you have an InstantSearch implementation.
We’re going to take an online bookshop as an example.
We’ll send click and conversion events for our user, which we identify with a userToken
.
The scenario will be as followed: our user, John, has an account with our online bookshop, with a unique user ID of user-123456
.
John starts to look for the latest Harry Potter book.
When he starts typing, each keystroke executes a query on Algolia’s servers, which returns the relevant search results.
Luckily, John will only need two keystrokes for all Harry Potter books to show up.
Implementation Overview
Insights events (click, conversion, view) used for analytics and/or personalization do not take immediate effect. The delay can range from 10 to 60 minutes depending on how long after the search they are sent. For precise times, see our page on when Insights events take effect.
Capturing conversion events
If your UI enables the user to go directly to a conversion point, make sure that you are capturing all relevant events that precede the conversion. For example, if you’ve set up one-click buy as a conversion, you need to process both the click and conversion events before proceeding with the actual sale.
Install the Search-Insights Library
Some of our InstantSearch libraries require you to install our search-insights
library in order to make use of the analytics feature.
For installation instructions, please see their respective pages:
Retrieving the queryID
Every set of search results contains a unique queryID
. When sending click and conversion events, we always use the latest queryID
.
- The first keystroke (for the character ‘H’) has
aef12442b87e97ac
as queryID
.
- The second key stroke (for the characters ‘Ha’) has
cba8245617aeace44
as queryID
.
You need to set clickAnalytics=true
in your search parameters for the queryID
to be included in the search results.
1
2
3
| $res = $index->search('query', [
'clickAnalytics' => true
]);
|
1
2
3
| results = index.search('query', {
clickAnalytics: true
})
|
1
2
3
4
5
6
| index.search({
query: 'query',
clickAnalytics: true
}).then(res => {
// console.log(res);
});
|
1
2
3
4
| res = index.search(
'query',
{'clickAnalytics': True}
)
|
1
2
3
4
5
6
| let query = Query(query: "query")
query.clickAnalytics = true
index.search(query, completionHandler: { (res, error) in
print(res)
})
|
1
2
3
4
| index.search(
new Query("query")
.setClickAnalytics(true)
);
|
1
2
3
4
5
| index.Search(
new Query("query") {
ClickAnalytics = true
}
);
|
1
2
3
4
| index.search(
new Query("query")
.setClickAnalytics(true)
);
|
1
2
3
4
| index.Search(
"query",
opt.ClickAnalytics(false),
)
|
The queryID
, position
, objectID
, and userToken
in this example are all fake. Don’t copy-paste these examples, but change them according to your needs!
Sending Click Events
In his search, John has received all of the Harry Potter books, in chronological order (book 1 to book 7). Since he wants the last one in the series (number 7), he clicks this item with objectID
9780545139700
(this is the ISBN-13 code of the book) at position
number seven of his results.
At this point, we have to send an event using the ClickedObjectIdsAfterSearch method of our API Client.
We named our click event book_click_on_search_page
.
The name of an event is used for your convenience to keep events manageable, even when you send a lot of different events. Make it descriptive so you can instantly identify it.
1
2
3
4
5
6
7
8
9
10
11
12
| $insights = Algolia\AlgoliaSearch\InsightsClient::create(
'YourApplicationID',
'YourSearchOnlyAPIKey'
);
$insights->user("user-123456")->clickedObjectIDsAfterSearch(
'book_click_on_search_page',
'my_online_bookshop_index',
['9780545139700'],
[7],
'cba8245617aeace44'
);
|
1
2
3
4
5
6
7
8
9
10
11
12
| insights = Algolia::Insights.new(
'YourApplicationID',
'YourSearchOnlyAPIKey'
)
insights.user('user-123456').clicked_object_ids_after_search(
'book_click_on_search_page',
'my_online_bookshop_index',
['9780545139700'],
[7],
'cba8245617aeace44'
)
|
1
2
3
4
5
6
7
8
9
10
11
12
| // This requires installing the search-insights separate library:
// https://github.com/algolia/search-insights.js
// https://www.npmjs.com/package/search-insights
aa('clickedObjectIDsAfterSearch', {
userToken: 'user-123456',
eventName: "book_click_on_search_page',
index: 'my_online_bookshop_index'
queryID: 'cba8245617aeace44',
objectIDs: ['9780545139700'],
positions: [7],
});
|
1
2
3
4
5
6
7
8
9
| insights = client.init_insights_client().user('user-123456')
insights.clicked_object_ids_after_search(
'book_click_on_search_page',
'my_online_bookshop_index',
['9780545139700'],
['7l'],
'cba8245617aeace44'
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| Insights.register(
appId: "YourApplicationID",
apiKey: "YourSearchOnlyAPIKey",
userToken: "user-123456"
)
Insights.shared?.clickedAfterSearch(
eventName: "book_click_on_search_page",
indexName: "my_online_bookshop_index",
objectIDs: ["9780545139700"],
positions: [7],
queryID: "cba8245617aeace44"
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| Insights.register(
context,
"YourApplicationID",
"YourSearchOnlyAPIKey",
"user-123456"
)
Insights.shared?.clickedAfterSearch(
"book_click_on_search_page",
"my_online_bookshop_index",
"cba8245617aeace44",
EventObjects.IDs("9780545139700"),
listOf(7)
)
|
1
2
3
4
5
6
7
8
9
10
11
12
| var insights = new InsightsClient(
"YourApplicationID",
"YourSearchOnlyAPIKey"
).User("user-123456");
insights.ClickedObjectIDsAfterSearch(
"book_click_on_search_page",
"my_online_bookshop_index",
new List<string> { "9780545139700" },
new List<uint> { 7 },
"cba8245617aeace44"
);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| AsyncUserInsightsClient insights = new AsyncInsightsClient(
"YourApplicationID",
"YourSearchOnlyAPIKey",
client
).user("user-123456");
insights.clickedObjectIDsAfterSearch(
"book_click_on_search_page",
"my_online_bookshop_index",
Arrays.asList("9780545139700"),
new ArrayList<>(Arrays.asList(7l)),
"cba8245617aeace44"
);
|
1
2
3
4
5
6
7
8
9
10
11
12
| client := insights.NewClient(
"YourApplicationID",
"YourSearchOnlyAPIKey",
).User("user-123456")
res, err := client.ClickedObjectIDsAfterSearch(
"book_click_on_search_page",
"my_only_bookshop_index",
[]string{"9780545139700"},
[]int{7},
"cba8245617aeace44",
)
|
1
2
3
4
5
6
7
8
9
10
| client.execute {
send event ClickedObjectIDsAfterSearch(
"user-123456",
"book_click_on_search_page",
"my_online_bookshop_index",
Seq("9780545139700"),
Seq(7),
"cba8245617aeace44"
)
}
|
Sending Conversion Events
Within the context of search
When John sees the Harry Potter books in his search results, he decides to add the last two books of the series to his favorites. Book number six has an objectID of 9780439785969
in our system and book seven has an objectID of 9780545139700
(both are the ISBN-13 codes of the books). For our bookshop, adding a product to the favorites is the action we designated as our system’s conversion event.
So we add to the results page a conversion event. When sending a conversion event, we don’t need to send the position of the converted object with it. Other than that, we have to send the exact same data as we sent with the click event we just sent.
In this example, we called our conversion event book_favorite_on_search_page
.
1
2
3
4
5
6
7
8
9
10
11
| $insights = Algolia\AlgoliaSearch\InsightsClient::create(
'YourApplicationID',
'YourSearchOnlyAPIKey'
);
$insights->user("user-123456")->convertedObjectIDsAfterSearch(
'book_favorite_on_search_page',
'my_online_bookshop_index',
['9780545139700', '9780439785969'],
'cba8245617aeace44'
);
|
1
2
3
4
5
6
7
8
9
10
11
| insights = Algolia::Insights.new(
'YourApplicationID',
'YourSearchOnlyAPIKey'
)
insights.user('user-123456').converted_object_ids_after_search(
'book_favorite_on_search_page',
'my_online_bookshop_index',
['9780545139700', '9780439785969'],
'cba8245617aeace44'
)
|
1
2
3
4
5
6
7
8
9
10
11
| // This requires installing the search-insights separate library
// https://github.com/algolia/search-insights.js
// https://www.npmjs.com/package/search-insights
aa('convertedObjectIDsAfterSearch', {
userToken: 'user-123456',
index: 'my_online_bookshop_index',
eventName: 'book_click_on_search_page',
queryID: 'cba8245617aeace44',
objectIDs: ['9780545139700', '9780439785969']
});
|
1
2
3
4
5
6
7
8
| insights = client.init_insights_client().user('user-123456')
insights.converted_object_ids_after_search(
'book_favorite_on_search_page',
'my_online_bookshop_index',
['9780545139700', '9780439785969'],
'cba8245617aeace44'
)
|
1
2
3
4
5
6
7
8
9
10
11
12
| Insights.register(
appId: "YourApplicationID",
apiKey: "YourSearchOnlyAPIKey",
userToken: "user-123456"
)
Insights.shared?.convertedAfterSearch(
eventName: "book_favorite_on_search_page",
indexName: "my_online_bookshop_index",
objectIDs: ["9780545139700", "9780439785969"],
queryID: "cba8245617aeace44"
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| Insights.register(
context,
"YourApplicationID",
"YourSearchOnlyAPIKey",
"user-123456"
)
Insights.shared?.convertedAfterSearch(
"book_favorite_on_search_page",
"my_online_bookshop_index",
"cba8245617aeace44",
EventObjects.IDs("9780545139700", "9780439785969")
)
|
1
2
3
4
5
6
7
8
9
10
11
| var insights = new InsightsClient(
"YourApplicationID",
"YourSearchOnlyAPIKey"
).User("user-123456");
insights.ConvertedObjectIDsAfterSearch(
"book_favorite_on_search_page",
"my_online_bookshop_index",
new List<string> { "9780545139700", "9780439785969" },
"cba8245617aeace44"
);
|
1
2
3
4
5
6
7
8
9
10
11
12
| AsyncUserInsightsClient insights = new AsyncInsightsClient(
"YourApplicationID",
"YourSearchOnlyAPIKey",
client
).user("user-123456");
insights.convertedObjectIDsAfterSearch(
"book_favorite_on_search_page",
"my_online_bookshop_index",
Arrays.asList("9780545139700", "9780439785969"),
"cba8245617aeace44"
);
|
1
2
3
4
5
6
7
8
9
10
11
| client := insights.NewClient(
"YourApplicationID",
"YourSearchOnlyAPIKey",
).User("user-123456")
res, err := client.ConvertedObjectIDsAfterSearch(
"book_favorite_on_search_page",
"my_only_bookshop_index",
[]string{"9780545139700", "9780439785969"},
"cba8245617aeace44",
)
|
1
2
3
4
5
6
7
8
9
| client.execute {
send event ConvertedObjectIDsAfterSearch(
"user-123456",
"book_favorite_on_search_page",
"my_online_bookshop_index",
Seq("9780545139700", "9780439785969"),
"cba8245617aeace44"
)
}
|
Outside the context of search
The above code works well if you are sending a conversion event directly from the search page. It works because the search page contains the queryID
, the index
name and the objectID
. However, when sending a conversion event, you’re often not on the search page.
For example, if we consider a conversion to be whenever a user adds a product to the cart, this may happen anywhere, such as the detail page of a product. If this is the case, we need to pass the queryID
from the search page to the detail page.
There are several solutions to this problem. For web applications, this could be localStorage, cookies, query string, or any other available method.
We wrote a guide on using localStorage
.