Getting started

First thing you need is your database at Recombee and the corresponding secret key. Create the free instant account at recombee.com, if you don’t have one yet.

We provide client libraries (SDKs) for javascript, Java, Ruby, Node.js, Python,.NET and PHP, which makes the integration very easy. If you don’t use any of these languages, then you can use directly the REST API, but you need to implement authentication – the procedure is explained in the Authentication (HMAC) section along with examples in multiple programming languages.

How to integrate

Integration consist of three principal components:

It can be done in multiple ways:

  1. Server side integration
Server side integration
  1. Frontend (JavaScript) & server side integration
Frontend (JavaScript) & server side integration
  1. Frontend (JavaScript) side integration & Product feed
Frontend (JavaScript) side integration and Product feed

It is also possible to use Recombee for example in the email campaigns.

Send interactions

Interactions are the most valuable information for the algorithms in recommender engine. There are multiple kinds of interactions in the system, but we will use just the following two for now:

  • detail-view - it will be sent to the system every time a user views a detail of an item
  • purchase - it will be sent every time a user purchases an item. Note that this interaction is used also in cases which are not literally purchases as a purchase is for example viewing a video in case of an IPTV platform or replying to an advertisement in case of a job agency.

A detail view of item xyz by user 2c169e575644d840838e is sent to the recommender with the following query:

// Import the library using npm or bower or using the script tag:
// <script src="https://cdn.jsdelivr.net/gh/recombee/js-api-client/dist/recombee-api-client.min.js"></script>

var client = new recombee.ApiClient('myDb', publicToken);
client.send(new recombee.AddDetailView('2c169e575644d840838e', 'xyz'),
    (err, response) => {
    //...
    }
);
from recombee_api_client.api_client import RecombeeClient
from recombee_api_client.api_requests import *

client = RecombeeClient('myDb', private_token)
client.send(AddDetailView("2c169e575644d840838e", "xyz", timestamp="2014-07-20T02:49:45+02:00", cascade_create=True))
require 'recombee_api_client'
include RecombeeApiClient

client = RecombeeClient.new('myDb', private_token)
client.send(AddDetailView.new('2c169e575644d840838e', 'xyz', {'timestamp' => '2014-07-20T02:49:45+02:00', 'cascadeCreate' => true}))
RecombeeClient client = new RecombeeClient("myDb", privateToken);
client.send(new AddDetailView("2c169e575644d840838e", "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);
$client -> send(new Reqs\AddDetailView("2c169e575644d840838e", "xyz", ['timestamp' => "2014-07-20T02:49:45+02:00", 'cascadeCreate' => true]));
?>
using Recombee.ApiClient;
using Recombee.ApiClient.ApiRequests;
using Recombee.ApiClient.Bindings;

var client = new RecombeeClient("myDb", privateToken);
var datetime = DateTime.Parse("2014-07-20T02:49:45+02:00", null, System.Globalization.DateTimeStyles.RoundtripKind);
client.Send(new AddDetailView("2c169e575644d840838e", "xyz", timestamp: datetime, cascadeCreate: true));
var recombee = require('recombee-api-client');
var rqs = recombee.requests;

var client = new recombee.ApiClient('myDb', privateToken);
client.send(new rqs.AddDetailView('2c169e575644d840838e', 'xyz', {timestamp: '2014-07-20T02:49:45+02:00', cascadeCreate: true}),
    (err, response) => {
    //...
    }
);
POST /myDb/detailviews/ HTTP/1.0
Host: rapi.recombee.com
Content-type: application/json

Body:
{
  "itemId": "xyz",
  "userId": "2c169e575644d840838e",
  "timestamp": "2014-07-20T02:49:45+02:00",
  "cascadeCreate": true
}

Where

  • myDb is name of your database :)
  • itemId is an unique identifier of the item.
  • userId is an unique identifier of the user. It might be for example a session ID for anonymous users.

Optional parameters:

  • timestamp is a UNIX timestamp or ISO 8601 date time of the view. If not specified, current time is used.
  • cascadeCreate tells the system that it should create the item or the user if it doesn’t exist in the system yet. We don’t have to explicitly manage the user and item database in the system for now thanks to this parameter. It is set to true by default in the JavaScript client.

Sending a purchase is very similar:

client.send(new recombee.AddPurchase('2c169e575644d840838e', 'xyz'),
    (err, response) => {
    //...
    }
);
client.send(AddPurchase("2c169e575644d840838e", "xyz", timestamp="2015-09-10T04:29:55+02:00", cascade_create=True))
client.send(AddPurchase.new('2c169e575644d840838e', 'xyz', {'timestamp' => '2015-09-10T04:29:55+02:00', 'cascadeCreate' => true}))
client.send(new AddPurchase("2c169e575644d840838e", "xyz")
    .setTimestamp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2016-12-09 14:15:17"))
    .setCascadeCreate(true));
<?php
$client -> send(new Reqs\AddPurchase("2c169e575644d840838e", "xyz", ['timestamp' => "2015-09-10T04:29:55+02:00", 'cascadeCreate' => true]));
?>
datetime = DateTime.Parse("2015-09-10T04:29:55+02:00", null, System.Globalization.DateTimeStyles.RoundtripKind);
client.Send(new AddPurchase("2c169e575644d840838e", "xyz", timestamp: datetime, cascadeCreate: true));
client.send(new rqs.AddPurchase('2c169e575644d840838e', 'xyz', {timestamp: '2015-09-10T04:29:55+02:00', cascadeCreate: true}),
    (err, response) => {
    //...
    }
);
POST /myDb/purchases/ HTTP/1.0
Host: rapi.recombee.com
Content-type: application/json

Body:
{
  "itemId": "xyz",
  "userId": "2c169e575644d840838e",
  "timestamp": 1348162550,
  "cascadeCreate": true
}

The quality of the recommendations heavily depends on the amount of the sent interactions so it may take some time before interactions are gathered and the best quality recommendations are produced. Submitting historical interactions should reduce the time.

Especially in the e-shops is very common that a user comes to the site as an anonymous user (identfied by a session id) and logs into regular account later. Then it’s useful to merge the anonymous user with the regular account, in order to enrich the regular account with interactions made before logging in. Use merge users request for this.

Get recommendations

Now we can get some recommendations for the users. We will use two endpoints:

  • recommend items to user - System recommends items to a given user depending on his/her personal taste. This case can be used for example on your homepage.
  • recommend items to item - System recommends items that are somehow related to a given item. System can take into account also a target user, so this case is useful for example in a detail page of a product, because item-based will give the user a list of related items that he/she might be also interested in.

Getting 5 recommendations for user 2c169e575644d840838e is very easy:

client.send(new recombee.RecommendItemsToUser('2c169e575644d840838e', 5),
    (err, recommended) => {
    //...
    }
);
recommended = client.send(RecommendItemsToUser('2c169e575644d840838e', 5))
recommended = client.send(RecommendItemsToUser.new('2c169e575644d840838e', 5))
RecommendationResponse recommended = client.send(new RecommendItemsToUser("2c169e575644d840838e", 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("2c169e575644d840838e", 5));
?>
RecommendationResponse recommended = client.Send(new RecommendItemsToUser("2c169e575644d840838e", 5));
// Iterating over recommendations:
foreach(Recommendation r in recommended.Recomms)
{
    Console.WriteLine(r.Id);
}
client.send(new rqs.RecommendItemsToUser('2c169e575644d840838e', 5),
    (err, recommended) => {
    //...
    }
);
GET /myDb/recomms/users/2c169e575644d840838e/items/?count=5

An object with recommended items in field recomms is returned. For example:

{
  "recommId": "968d7864-1d52-4525-a37f-d5b7dd86fe13",
  "recomms": [
    {
      "id": "item-146"
    },
    {
      "id": "item-462"
    },
    {
      "id": "item-463"
    },
    {
      "id": "item-1555"
    },
    {
      "id": "item-683"
    }
  ]
}

Getting recommendations based on item xyz which is viewed by user 2c169e575644d840838e is also easy:

client.send(new recombee.RecommendItemsToItem('xyz', '2c169e575644d840838e', 10),
    (err, recommended) => {
    //...
    }
);
recommended = client.send(RecommendItemsToItem('xyz', '2c169e575644d840838e', 10))
recommended = client.send(RecommendItemsToItem.new('xyz', '2c169e575644d840838e', 10))
RecommendationResponse recommended = client.send(new RecommendItemsToItem("xyz", "2c169e575644d840838e", 10));
<?php
$recommended = $client -> send(new Reqs\RecommendItemsToItem("xyz", "2c169e575644d840838e", 10));
?>
RecommendationResponse recommended = client.Send(new RecommendItemsToItem("xyz", "2c169e575644d840838e", 10));
client.send(new rqs.RecommendItemsToItem('xyz', '2c169e575644d840838e', 10),
    (err, recommended) => {
    //...
    }
);
GET /myDb/recomms/items/xyz/items/?count=10&targetUserId=2c169e575644d840838e

The recommendation requests have several parameters – more details here. Most notable are filter and booster parameters which can be used for modeling business rules using our simple language ReQL. Very useful is also returnProperties - with this parameter set, Recombee will also return properties (titles, links, image urls etc.) for the recommended items, which you can use for showing the items to the users.

If the given user or item does not exists in the system yet (for example because the item catalog is updated periodically only once a day) the default behavior is to return an error (HTTP 404). If you rather want to always get some recommendations use cascadeCreate=true - if the given item does not exist, recommender will create the item and for example return some bestsellers. Other useful settings include for example parameters for rotating the given recommendations (important especially when generating periodical email recommendations). It is set to true by default in the JavaScript client.

Recombee can also recommend users instead of items - check recommend users to item and recommend users to user requests.

Manage item catalog

So far we have learned how to send interactions and get recommendations, that are based on those interactions. It should work pretty well, especially if there is a lot of traffic and therefore a lot of interactions. But it still can be improved! Very helpful is sending information about the items (e.g., names, descriptions, categories) to the system.

For security reasons, it is possible to change the item catalog only from server-side using the private token. An alternative to using SDK for catalog synchronization is setting a product feed in the web admin.

After setting catalog, the quality of recommendations should rise mainly for items with few interactions (for example newly added items). Sent data about items can be also used for filtering and boosting recommendation results with the Introduction to ReQL.

Adding item properties

Firstly you have to define properties of items that you want to submit to the system. Setting an item property is somehow equivalent to adding a column to the table of items, so you can later assign a concrete value of the property to each item. The properties may be of various types:

  • string
  • int - integer number
  • double - floating point number
  • boolean
  • timestamp - UTC timestamp
  • set - a set of strings
  • image - url of an image
  • imageList - array with urls of images

For example setting an item property that will hold description of an item is done by the following request:

client.send(AddItemProperty('description', 'string'))
client.send(AddItemProperty.new('description', 'string'))
client.send(new AddItemProperty("description", "string"));
<?php
$client -> send(new Reqs\AddItemProperty("description", "string"));
?>
client.Send(new AddItemProperty("description", "string"));
client.send(new rqs.AddItemProperty('description', 'string'),
    (err, response) => {
    //...
    }
);
PUT /myDb/items/properties/description?type=string

And here is few more examples of creating item properties:

client.send(AddItemProperty('title', 'string'))
client.send(AddItemProperty('price', 'double'))
client.send(AddItemProperty('categories', 'set'))
client.send(AddItemProperty('image', 'image'))
client.send(AddItemProperty('deleted', 'boolean'))
client.send(AddItemProperty.new('title', 'string'))
client.send(AddItemProperty.new('price', 'double'))
client.send(AddItemProperty.new('categories', 'set'))
client.send(AddItemProperty.new('image', 'image'))
client.send(AddItemProperty.new('deleted', 'boolean'))
client.send(new AddItemProperty("title", "string"));
client.send(new AddItemProperty("price", "double"));
client.send(new AddItemProperty("categories", "set"));
client.send(new AddItemProperty("image", "image"));
client.send(new AddItemProperty("deleted", "boolean"));
<?php
$client -> send(new Reqs\AddItemProperty("title", "string"));
$client -> send(new Reqs\AddItemProperty("price", "double"));
$client -> send(new Reqs\AddItemProperty("categories", "set"));
$client -> send(new Reqs\AddItemProperty("image", "image"));
$client -> send(new Reqs\AddItemProperty("deleted", "boolean"));
?>
client.Send(new AddItemProperty("title", "string"));
client.Send(new AddItemProperty("price", "double"));
client.Send(new AddItemProperty("categories", "set"));
client.Send(new AddItemProperty("image", "image"));
client.Send(new AddItemProperty("deleted", "boolean"));
client.send(new rqs.AddItemProperty('title', 'string'))
.then((response) => {
    return client.send(new rqs.AddItemProperty('price', 'double'));
})
.then((response) => {
    return client.send(new rqs.AddItemProperty('categories', 'set'));
})
.then((response) => {
    return client.send(new rqs.AddItemProperty('image', 'image'));
})
.then((response) => {
    return client.send(new rqs.AddItemProperty('deleted', 'boolean'));
})
.catch((error) => {
    // ...
});
PUT /myDb/items/properties/title?type=string
PUT /myDb/items/properties/price?type=double
PUT /myDb/items/properties/categories?type=set
PUT /myDb/items/properties/image?type=image
PUT /myDb/items/properties/deleted?type=boolean

The default value of the created properties is null.

Send item values

Suppose we have created all the properties from preceding example. Now we can set the values of these properties for a particular item xyz. It is done by following 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) => {
        //...
    }
);
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 indicates that the item of the given itemId should be created if it does not exist in the database.

You can check that the values have been successfully set in the graphical user interface.

Sending a whole large catalog via single requests may be quite slow – batch requests should be used for much faster execution.

Similar to item properties are user properties.