Getting Started
The first thing you need is to set up a database at Recombee. Sign up for a free instant account at recombee.com if you haven't already.
We provide client libraries (SDKs) for languages such as JavaScript, Java, Ruby, Python, .NET, PHP and more, which makes the integration very easy.
If you don't use any of the supported languages, you also have the ability to use the REST API directly. See the authentication page for more details.
How to integrate
Integration consists of four main parts:
Each of these parts can be achieved in multiple ways.
The recommendations are usually shown to a user on a website, in a mobile app or within an email campaign.
Sending Interactions
Interactions are the most valuable information for the algorithms in the recommender engine.
There are multiple ways of sending interactions:
Using the SDK
There are multiple kinds of interactions that are supported, but we will use just the following two for now:
- Detail View - sent every time a user views a detail of an item,
- Purchase - sent every time a user completes the main desired goal (a conversion).
Please note that while Recombee uses the term Purchase for conversions, they can have various forms depending on your specific business case.
This means that a Purchase can be sent when a user replies to an advertisement in the case of a job agency, views the whole video in the case of an IPTV platform, or buys a product from an online store.
Detail View
A Detail View of Item xyz
by User 2c169e
can be sent to the recommender as follows:
// Import the library using npm or using the script tag:
// <script src="https://cdn.jsdelivr.net/gh/recombee/js-api-client/dist/recombee-api-client.min.js"></script>
const client = new recombee.ApiClient('myDb', publicToken, {region: 'us-west'});
client.send(new recombee.AddDetailView('2c169e', 'xyz'))
.then(function(res) {
...
})
.catch(function(error) {
...
});
import com.recombee.apiclientkotlin.RecombeeClient
import com.recombee.apiclientkotlin.util.Region
import com.recombee.apiclientkotlin.requests.*
import com.recombee.apiclientkotlin.exceptions.ApiException
val client = RecombeeClient(
databaseId = "your-db-id",
publicToken = "your-public-token",
region = Region.UsWest
)
val request = AddDetailView(userId = "2c169e", itemId = "xyz")
client.send(request,
{ response ->
...
},
{ exception ->
...
}
)
// Alternatively, you can use sendAsync for coroutines instead of callbacks
let client = RecombeeClient(
databaseId: "your-db-id",
publicToken: "your-public-token",
region: .usWest
)
let request = AddDetailView(userId: "2c169e", itemId: "xyz")
do {
let response = try await client.send(request)
// Handle the successful response
print("Success: \(response)")
} catch {
// Handle the error (e.g. ClientError or any other error)
print("Error: \(error)")
}
from recombee_api_client.api_client import RecombeeClient, Region
from recombee_api_client.api_requests import *
client = RecombeeClient('myDb', private_token, region=Region.US_WEST)
client.send(AddDetailView("2c169e", "xyz", timestamp="2014-07-20T02:49:45+02:00", cascade_create=True))
require 'recombee_api_client'
include RecombeeApiClient
client = RecombeeClient.new('myDb', private_token, {:region => 'us-west'})
client.send(AddDetailView.new('2c169e', 'xyz', {'timestamp' => '2014-07-20T02:49:45+02:00', 'cascadeCreate' => true}))
RecombeeClient client = new RecombeeClient("myDb", privateToken).setRegion(Region.US_WEST);
client.send(new AddDetailView("2c169e", "xyz")
.setTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-12-09 13:05:06") )
.setCascadeCreate(true));
<?php
use Recombee\RecommApi\Client;
use Recombee\RecommApi\Requests as Reqs;
$client = new Client("myDb", private_token, ['region' => 'us-west']);
$client -> send(new Reqs\AddDetailView("2c169e", "xyz", ['timestamp' => "2014-07-20T02:49:45+02:00", 'cascadeCreate' => true]));
?>
using Recombee.ApiClient;
using Recombee.ApiClient.ApiRequests;
using Recombee.ApiClient.Bindings;
using Recombee.ApiClient.Util;
var client = new RecombeeClient("myDb", privateToken, region: Region.UsWest);
var datetime = DateTime.Parse("2014-07-20T02:49:45+02:00", null, System.Globalization.DateTimeStyles.RoundtripKind);
client.Send(new AddDetailView("2c169e", "xyz", timestamp: datetime, cascadeCreate: true));
var recombee = require('recombee-api-client');
var rqs = recombee.requests;
var client = new recombee.ApiClient('myDb', privateToken, {region: 'us-west'});
client.send(new rqs.AddDetailView('2c169e', 'xyz', {timestamp: '2014-07-20T02:49:45+02:00', cascadeCreate: true}),
(err, response) => {
//...
}
);
import (
"github.com/recombee/go-api-client/v4/recombee"
"time"
)
client, err := recombee.NewRecombeeClient("myDb", privateToken, "us-west")
if err != nil {
panic(err)
}
_, err = client.NewAddDetailView("2c169e", "xyz").SetCascadeCreate(true).SetTimestamp(time.Unix(1712042581, 0)).Send()
POST /myDb/detailviews/ HTTP/1.0
Host: Based on the region of your DB, see https://docs.recombee.com/regions.html
Content-type: application/json
Body:
{
"itemId": "xyz",
"userId": "2c169e",
"timestamp": "2014-07-20T02:49:45+02:00",
"cascadeCreate": true
}
myDb
is the name of the database you are sending data to (required),publicToken
orprivateToken
is the access token for the given database (required),region
is the region where your DB is located (recommended),itemId
is a unique identifier of the item (required),userId
is a unique identifier of the user (required). For anonymous users, you can use a session ID.
Optional parameters:
timestamp
is a UNIX timestamp or ISO 8601 date-time of the view. If not specified, the current time is used.cascadeCreate
tells the system that it should create the item or the user if it doesn't exist yet.
If not specified, it is set totrue
in client-side SDKs andfalse
in server-side SDKs.
We recommend that you use this parameter to prevent errors in case the item or user doesn't exist yet.
Purchase
Sending a purchase is very similar:
client.send(new recombee.AddPurchase('2c169e', 'xyz', {'recommId': 'db021f23-9e18-4af4-bb71-8ecaf27b615d'}))
.then(function(res) {
...
})
.catch(function(error) {
...
});
val request = AddPurchase(
userId = "2c169e",
itemId = "xyz",
recommId = "db021f23-9e18-4af4-bb71-8ecaf27b615d"
)
client.send(request,
{ response ->
...
},
{ exception ->
...
}
)
let request = AddPurchase(
userId: "2c169e",
itemId: "xyz",
recommId: "db021f23-9e18-4af4-bb71-8ecaf27b615d"
)
try await client.send(request)
client.send(AddPurchase("2c169e", "xyz", recomm_id="db021f23-9e18-4af4-bb71-8ecaf27b615d", cascade_create=True))
client.send(AddPurchase.new('2c169e', 'xyz', {:recomm_id => 'db021f23-9e18-4af4-bb71-8ecaf27b615d', :cascade_create => true}))
client.send(new AddPurchase("2c169e", "xyz")
.setRecommId("db021f23-9e18-4af4-bb71-8ecaf27b615d")
.setCascadeCreate(true));
<?php
$client -> send(new Reqs\AddPurchase("2c169e", "xyz", ['recommId' => 'db021f23-9e18-4af4-bb71-8ecaf27b615d', 'cascadeCreate' => true]));
?>
client.Send(new AddPurchase("2c169e", "xyz", recommId: "db021f23-9e18-4af4-bb71-8ecaf27b615d", cascadeCreate: true));
client.send(new rqs.AddPurchase('2c169e', 'xyz', {recommId: 'db021f23-9e18-4af4-bb71-8ecaf27b615d', cascadeCreate: true}),
(err, response) => {
//...
}
);
_, err = client.NewAddPurchase("2c169e", "xyz").SetRecommId("db021f23-9e18-4af4-bb71-8ecaf27b615d").Send()
POST /myDb/purchases/ HTTP/1.0
Host: rapi.recombee.com
Content-type: application/json
Body:
{
"itemId": "xyz",
"userId": "2c169e",
"recommId": "db021f23-9e18-4af4-bb71-8ecaf27b615d",
"cascadeCreate": true
}
In this example, we are also sending the optional recommId
parameter.
Once you integrate the recommendations, it is very important to set this parameter for all interactions that are based on a previous recommendation (read more about Recommendations).
As a result of sending the recommId
with your interactions, you will get precise success metrics in the Admin UI and the models will also be able to return better recommendations.
There need to be enough interactions in the system for it to produce quality recommendations, so it may take some time before the best recommendations are produced.
If you're looking to improve the performance of the models beforehand, we recommend that you submit a historical log of past interactions. To achieve this, you can use the Batch API endpoint to send multiple interactions in a single request.
Handling Anonymous Users
A user may come to the site as an anonymous user and log into a regular account later. This is especially the case in e-commerce.
However, ideally, you want to track the interactions of the anonymous user before they log in and then use that data to provide better recommendations after they log in.
To achieve this, you can use the userId
parameter of the interactions.
If the user is anonymous, you can use a session ID (or another ID that is unique to the given user or session) as the userId
.
When the user logs in, you can send a Merge Users request to merge the anonymous user with the regular account. This way, all interactions of the anonymous user will be transferred to their account.
Updating the Item Catalog
The second most important kind of data for the recommender system is information about the items (e.g, names, descriptions, categories).
The data that you send about the items is used in multiple ways:
- It can be used for filtering and boosting recommendation results with ReQL, allowing you to influence the recommender engine.
- It can be returned when getting recommendations to show to the users, so that you don't have to make additional requests to your database to get the item details.
- It is also used to compute the recommendations, especially when the items have very few interactions (e.g., newly added items).
There are two possible methods of updating the item catalog:
Using the SDK
For security reasons, it is possible to change the item catalog only from server-side SDKs or using the API with a private token.
Defining Item Properties
Before sending the data, you first have to define the properties of the items that you want to submit to the system.
Creating an Item Property is in a way similar to adding a column to the table of items, while submitting an item is like adding a row to the table.
The following Item Property types are available:
string
int
- integer numberdouble
- floating point numberboolean
- true / falsetimestamp
- UTC timestampset
- a set of stringsimage
- URL of an imageimageList
- array of image URLs
The default value for all created properties is null
.
To create or remove Item Properties, you can use the appropriate API calls, or do it manually in the Admin UI.
For examples of properties that can be useful for the recommender engine, see Integration Tips.
Sending Item Values
Let's say we've added some item properties to our database, and now want to set their values for a particular item xyz
.
This can be done by using the Set Item Values request:
client.send(SetItemValues('xyz',
{
"title": "Television TV2305",
"description": "HD resolution LED TV",
"price": 200,
"categories": ["Electronics", "Televisions"],
"image": "http://examplesite.com/products/xyz.jpg",
"deleted": False
},
cascade_create=True
))
client.send(SetItemValues.new('xyz',
# values
{
'title' => 'Television TV2305',
'description' => 'HD resolution LED TV',
'price' => 200,
'categories' => ['Electronics', 'Televisions'],
'image' => 'http://examplesite.com/products/xyz.jpg',
'deleted' => false
},
# optional parameters
{
'cascadeCreate' => true
}
))
client.send(new SetItemValues("xyz",
new HashMap<String, Object>() {{
put("title", "Television TV2305");
put("description","HD resolution LED TV");
put("price", 200);
put("categories", new String[]{"Electronics", "Televisions"});
put("image", "http://examplesite.com/products/xyz.jpg");
put("deleted", false);
}}
).setCascadeCreate(true));
<?php
$client -> send(new Reqs\SetItemValues("xyz",
// values
[
"title" => "Television TV2305",
"description" => "HD resolution LED TV",
"price" => 200,
"categories" => ["Electronics", "Televisions"],
"image" => "http://examplesite.com/products/xyz.jpg",
"deleted" => false
],
//optional parameters
[
"cascadeCreate" => true
]
));
?>
client.Send(new SetItemValues("xyz",
new Dictionary<string, object>() {
{"title", "Television TV2305"},
{"description","HD resolution LED TV"},
{"price", 200},
{"categories", new string[] {"Electronics", "Televisions"}},
{"image", "http://examplesite.com/products/xyz.jpg"},
{"deleted", false}
},
cascadeCreate: true
));
client.send(new rqs.SetItemValues('xyz',
// values
{
title: 'Television TV2305',
description: 'HD resolution LED TV',
price: 200,
categories: ['Electronics', 'Televisions'],
image: 'http://examplesite.com/products/xyz.jpg',
deleted: false
},
// optional parameters
{
cascadeCreate: true
}
),
(err, response) => {
//...
}
);
_, err = client.NewSetItemValues("xyz", map[string]interface{}{
"title": "Television TV2305",
"description": "HD resolution LED TV",
"price": 200,
"categories": []string{"Electronics", "Televisions"},
"deleted": false,
"image": "http://examplesite.com/products/xyz.jpg",
}).SetCascadeCreate(true).Send()
POST /myDb/items/xyz HTTP/1.0
Host: rapi.recombee.com
Content-type: application/json
Body:
{
"title": "Television TV2305",
"description": "HD resolution LED TV",
"price": 200,
"categories": ["Electronics", "Televisions"],
"deleted": false,
"image": "http://examplesite.com/products/xyz.jpg",
"!cascadeCreate": true
}
The cascadeCreate
parameter indicates that the item of the given itemId
should be created if it does not exist in the database.
After sending the above request, you can check that the values have been successfully set in the Admin UI.
If you wish to send an entire catalog, sending a request for each item separately may be quite slow. To speed up the process, we recommend using Batch requests.
In addition to Item Properties, the system also supports User Properties. These work in a similar way, but are used to describe the users instead of the items. Learn more in the User Properties API section.
Still not sure on how to implement sending of the Item Catalog? See the Tutorial for more details.
Getting Recommendations
Now it's time to get some recommendations!
There are two possible ways to get recommendations onto your site:
Using the SDK
We will use two endpoints:
- Recommend Items to User - The system recommends items to a given user depending on the user's personal taste. This case can be used for example on your homepage.
- Recommend Items to Item - The system recommends items that are related to a given item. The system can also take into account the target user, which can be useful on the page of a product or article, since the endpoint will give the user a list of related items that they might also be interested in.
Recommend Items to User
Getting 5 recommendations for user 2c169e
is very easy:
client.send(new recombee.RecommendItemsToUser('2c169e', 5))
.then(function(res) {
...
})
.catch(function(error) {
...
});
val result = client.sendAsync(RecommendItemsToUser("2c169e", 5))
result.onSuccess { response: RecommendationResponse ->
for (recommendedItem in response.recomms) {
println("ID: ${recommendedItem.id}")
}
}.onFailure { exception -> // ApiException
println("Exception: $exception")
// use fallback ...
}
let request = RecommendItemsToUser(
userId: "2c169e",
count: 5
)
do {
let response = try await client.send(request)
for recommendedItem in response.recomms {
print("ID: \(recommendedItem.id)")
}
} catch {
print("Exception: \(error)")
// use fallback ...
}
recommended = client.send(RecommendItemsToUser('2c169e', 5))
recommended = client.send(RecommendItemsToUser.new('2c169e', 5))
RecommendationResponse recommended = client.send(new RecommendItemsToUser("2c169e", 5));
//There are two easy ways for getting individual recommendations:
// 1. using getIds() method
String[] recomms = recommended.getIds();
// 2. iterating over recommendations
for(Recommendation r: recommended)
{
r.getId();
}
<?php
$recommended = $client -> send(new Reqs\RecommendItemsToUser("2c169e", 5));
?>
RecommendationResponse recommended = client.Send(new RecommendItemsToUser("2c169e", 5));
// Iterating over recommendations:
foreach(Recommendation r in recommended.Recomms)
{
Console.WriteLine(r.Id);
}
client.send(new rqs.RecommendItemsToUser('2c169e', 5),
(err, response) => {
//...
}
);
recommendReq := client.NewRecommendItemsToUser("2c169e", 5)
recommendRes, err := recommendReq.Send()
if err != nil {
panic(err)
}
for _, rec := range recommendRes.Recomms {
fmt.Println(rec.Id)
}
GET /myDb/recomms/users/2c169e/items/?count=5
An object with recommended items in field recomms
is returned. It can look like this:
{
"recommId": "968d7864-1d52-4525-a37f-d5b7dd86fe13",
"recomms": [
{
"id": "item-146"
},
{
"id": "item-462"
},
{
"id": "item-463"
},
{
"id": "item-1555"
},
{
"id": "item-683"
}
]
}
Besides the IDs of the recommended items, a unique recommId
is returned.
If the user interacts with a recommended item (e.g. views, purchases, etc.), it is very important to set this recommId
for that interaction.
As a result, you will get precise success metrics in the Admin UI metrics and the models will also be able to return better recommendations.
Recommend Items to Item
Getting recommendations based on item xyz
which is viewed by user 2c169e
is also easy:
client.send(new recombee.RecommendItemsToItem('xyz', '2c169e', 10,
{
'scenario': 'product_detail',
'returnProperties': true,
'cascadeCreate': true
}
))
.then(function(res) {
...
})
.catch(function(error) {
...
});
val request = RecommendItemsToItem(
itemId = "xyz",
targetUserId = "2c169e",
count = 10,
scenario = "product_detail",
returnProperties = true,
cascadeCreate = true
)
val result = sendAsync(request)
result.onSuccess { response: RecommendationResponse ->
for (recommendedItem in response.recomms) {
println("ID: ${recommendedItem.id}")
}
}.onFailure { exception -> // ApiException
println("Exception: $exception")
// use fallback ...
}
let request = RecommendItemsToItem(
itemId: "xyz",
targetUserId: "2c169e",
count: 10,
scenario: "product_detail",
cascadeCreate: true,
returnProperties: true
)
do {
let response = try await client.send(request)
for recommendedItem in response.recomms {
print("ID: \(recommendedItem.id)")
}
} catch {
print("Exception: \(error)")
// use fallback ...
}
recommended = client.send(RecommendItemsToItem('xyz', '2c169e', 10,
scenario='product_detail',
return_properties=True,
cascade_create=True))
recommended = client.send(RecommendItemsToItem.new('xyz', '2c169e', 10,
{
'scenario' => 'product_detail',
'returnProperties' => true,
'cascadeCreate' => true
})
)
RecommendationResponse recommended = client.send(new RecommendItemsToItem("xyz", "2c169e", 10))
.setScenario("product_detail")
.setReturnProperties(true)
.setCascadeCreate(true);
<?php
$recommended = $client -> send(new Reqs\RecommendItemsToItem('xyz', '2c169e', 10,
[
'scenario' => 'product_detail',
'returnProperties' => true,
'cascadeCreate' => true
])
);
?>
RecommendationResponse recommended = client.Send(new RecommendItemsToItem("xyz", "2c169e", 10,
scenario: "product_detail",
returnProperties: true,
cascadeCreate: true));
client.send(new rqs.RecommendItemsToItem('xyz', '2c169e', 10,
{
'scenario': 'product_detail',
'returnProperties': true,
'cascadeCreate': true
}
),
(err, response) => {
//...
}
);
recommendReq := client.NewRecommendItemsToItem("xyz", "2c169e", 10).
SetScenario("product_detail").
SetReturnProperties(true).
SetCascadeCreate(true)
recommendRes, err := recommendReq.Send()
GET /myDb/recomms/items/xyz/items/?count=10&targetUserId=2c169e&scenario=product_detail&returnProperties=true&cascadeCreate=true
In this case, three optional parameters were also set: scenario
, returnProperties
, and cascadeCreate
.
A Scenario defines a particular application of recommendations on your website, your mobile app or emailing campaign. Some examples can be homepage, watch-next, product-detail, cart, or emailing-after-purchase.
For each of the Scenarios, various parameters can be set in the Recombee Admin UI:
- Logic, which specifies the desired behavior of the recommendation model.
- Filters & Boosters, by which you specify your business rules (which items can be recommended and which items should be preferred).
- Constraints, by which you can specify the number of allowed items in the recommendation response per category, brand, or other criteria.
See Integration Tips for examples of typical scenarios in a particular domain (media, e-commerce, real estate, etc.) and their suggested settings.
You can also customize the above parameters via the API. For more details see the Recommendations API section.
Recommend Item Segments
Recombee can also recommend Item Segments such as categories, genres, or brands. See Segmentations for more information, including how to set them up and use them for recommendations.
Tips and Tricks
Still not sure on how to implement sending interactions & getting recommendations? See the Tutorial for more details.
Personalized Search
Our personalized full-text search enhances the search experience on your site.
Besides recommendations, Recombee can also provide personalized search results. This means that the search results take into account the user's preferences and behavior, not just the search query.
There are two possible ways to implement search on your site:
Using the SDK
Search can be implemented using the Search Items and Search Item Segments API endpoints.
client.send(new recombee.SearchItems('user-13434', 'search query', 5,
{
'scenario': 'search_top',
'returnProperties': true,
'cascadeCreate': true
}
))
.then(function(res) {
...
})
.catch(function(error) {
...
});
val request = SearchItems(
userId = "user-13434",
searchQuery = "search query",
count = 5,
scenario = "search_top",
returnProperties = true,
cascadeCreate = true
)
client.send(request,
{ response: SearchResponse ->
// Handle successful response here...
},
{ exception: ApiException ->
// Handle exception here...
}
)
let request = SearchItems(
userId: "user-13434",
searchQuery: "search query",
count: 5,
scenario: "search_top",
cascadeCreate: true,
returnProperties: true
)
do {
let response: SearchResponse = try await client.send(request)
// Handle successful response here...
print("Search response: \(response)")
} catch {
// Handle error here...
}
matches = client.send(SearchItems('user-13434', 'search query', 5,
scenario='search_top',
return_properties=True,
cascade_create=True))
matches = client.send(SearchItems.new('user-13434', 'search query', 5,
{
'scenario' => 'search_top',
'returnProperties' => true,
'cascadeCreate' => true
})
)
SearchResponse matches = client.send(new SearchItems("user-13434", "search query", 5))
.setScenario("search_top")
.setReturnProperties(true)
.setCascadeCreate(true);
<?php
$matches = $client -> send(new Reqs\SearchItems('user-13434', 'search query', 5,
[
'scenario' => 'search_top',
'returnProperties' => true,
'cascadeCreate' => true
])
);
?>
SearchResponse matches = client.Send(new SearchItems("user-13434", "search query", 5,
scenario: "search_top",
returnProperties: true,
cascadeCreate: true));
client.send(new rqs.SearchItems('user-13434', 'search query', 5,
{
'scenario': 'search_top',
'returnProperties': true,
'cascadeCreate': true
}
),
(err, matches) => {
//...
}
);
searchReq := client.NewSearchItems("user-13434", "search query", 5).
SetScenario("search_top").
SetReturnProperties(true).
SetCascadeCreate(true)
searchRes, err := searchReq.Send()
GET /myDb/search/users/user-13434/items/?searchQuery=query&scenario=search_top&returnProperties=true&cascadeCreate=true