Recommender API v1.0
This document describes the version 1.0 of the Sannsyn Recommender REST API.
If you like, you can try the new 1.1-beta version.
If you like, you can try the new 1.1-beta version.
Getting Started
Communication with the recommender system mostly consists of two very basic interactions:- updates − when you send information about users and products to the system
- recommendation requests − when you ask the system for products to promote
- Send an UpdateHere's a tip
If you want curl to be more expressive, use the -v option.curl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/update' --data '{ "service": "serviceid", "updates": [ { "customer": "customerid", "entityIDs": [ "product ID" ], "what": "PURCHASE", "where": "app" } ] }' - Get Recommendationscurl --user username:password --request POST 'https://recommender.sannsyn.com/recapi/1.0/recommend' --data '{ "service": "serviceid", "externalIds": [ "someothercustomerid" ], "recommender": "ProductForCustomerRecommender" }'
- Send an Update<script type="text/javascript"> var xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; var data = '{ "service": "serviceid", "updates": [ { "customer": "customerid", "entityIDs": [ "productid" ], "what": "PURCHASE", "where": "web" } ] }'; xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/update'); xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid); xmlhttp.send(data); </script>
- Get Recommendations<script type="text/javascript"> var xmlhttp = new XMLHttpRequest(); xmlhttp.withCredentials = true; var data = '{ "service": "serviceid", "recommender": "ProductForCustomerRecommender", "externalIds": [ "someothercustomerid" ], "num": numberofrecs }'; xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/recommend'); xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState == XMLHttpRequest.DONE) { if (xmlhttp.status == 200 || xmlhttp.status == 304) { // do whatever you want with xmlhttp.responseText here. You could for instance send it off to a callback method: callback(xmlhttp.responseText); } } } xmlhttp.send(data); </script>
Implementing the Sannsyn Recommender
In the Browser
Websites can have the client browser fetch recommendations directly. There are only three types of requests to implement: a customer recognition script to be included in all web pages, and two others, sending updates and/or fetching recommendations, anywhere needed.Customer Recognition
The javascript that permits the Sannsyn Recommender System to recognize the client, assures that the subsequent updates and recommendation requests work. The script is included like this:<html>
<head>
<script type="application/javascript" async="true" src="https://recommender.sannsyn.com/ajaxrecapi/1.0/crec?service=serviceid&euid=customerid"></script>
...
</head>
...
The customer ID is here given in the euid parameter. If the customer's ID is unknown when the crec script
URL is constructed, it may be omitted (although this will leave the customer recognition to the crec script
exclusively, and may lead to less accurate recommendations if the user has disabled cookies in the browser).
Adding and Updating Information
Visits to web shops' product pages is to be logged by the recommender. When users enter a product page, an update must be sent. It looks like this:<script type="text/javascript">
var xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;
var data = '{
"service": "serviceid",
"updates": [ { "customer": "customerid", "entityIDs": [ "productid" ], "what": "BROWSE" } ]
}';
xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/update');
xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid);
xmlhttp.send(data);
</script>
Refer to the update requests json fields table if necessary.
The update URLs do not return any information. If you need a confirmation that the request is OK, inspect the status code by using an XMLHttpRequest object and supply an onreadystatechange callback. As an example, if a user's visit to an online newspaper should be marked with both a page ID and a category ID, the update could look something like this (we call the newspaper «The Daily Overseas» and use the shortened form «thedo» as a name for the service):
<script type="text/javascript">
var xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;
xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/update');
xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid);
var data = '{
"service": "thedo",
"updates": [ { "customer": "subscriber472", "entityIDs": [ "article78", "international" ], "what": "BROWSE" } ]
}';
xmlhttp.onreadystatechange = function() {
console.log("HTTP status returned for the category call is " + xmlhttp.readyState);
}
xmlhttp.send(data);
</script>
The returned HTTP code will then be printed to the javascript console.
Retrieving Recommendations
When a browser is to fetch recommendations, a POST request should be issued like this:<script type="text/javascript">
var xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;
xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/recommend');
var data = '{
"service": "serviceid",
"recommender": "recommendername",
"externalIds": [ "customerid" ],
"num": numberofrecs
}';
xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid);
xmlhttp.onreadystatechange = function() {
// do whatever you want with xmlhttp.responseText here.
}
xmlhttp.send(data);
</script>
Our overseas newspaper could have this call on a page to retrieve recommendations for a reader:
<!-- Retrieve 5 recommended articles -->
<script type="text/javascript">
var xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;
xmlhttp.open("POST", 'https://recommender.sannsyn.com/ajaxrecapi/1.0/recommend');
xmlhttp.setRequestHeader("x-ssasid", localStorage.ssasid);
var data = '{
"service": "thedo",
"recommender": "ArticleForSubscriberRecommender",
"externalIds": [ "subscriber36" ],
"num": 5
}';
xmlhttp.onreadystatechange = function() {
// send the results off to the javascript method
// in charge of filling in the correct slot on the page:
fillInRecommendations(xmlhttp.responseText);
}
xmlhttp.send(data);
</script>
In response to this request, the Sannsyn Recommender could send a JSON object with three articles about politics, one
about sports, and a fifth from the literature section, like this:
{
"result": [
"Politics-45",
"Politics-392",
"Politics-460",
"Sports-78",
"Books-177"
],
"origin":"ArticleForSubscriberRecommender"
}
Tracking Exposure and Interaction
For statistics and for enhancement of recommendations and algorithms, exposure of recommendations and clicks thereon must be reported back to the Recommender System. The customer recognition script is constructed to handle this for you, but it needs two data attributes to be placed in the recommendations' DOM-tree elements:data-sannsyn-recommendation− with the recommendation itself (the ID of the product being recommended)data-sannsyn-recommender-ID− with the ID (the name) of the recommender having produced the recommendation in question (given in the recommendation'soriginfield)
Using the result example above to embed recommendations in our HTML, we could construct something like this:
<html>
<head>
<script type="application/javascript" async="true" src="https://recommender.sannsyn.com/ajaxrecapi/1.0/crec?service=thedo&euid=subscriber36">
</head>
<body>
<h1>Recommended for you</h1>
<ul>
<li data-sannsyn-recommendation="Politics-45" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender">
<a href="clickOnPolitics45">Politics-45</a>
</li>
<li data-sannsyn-recommendation="Politics-392" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender">
<a href="clickOnPolitics392">Politics-392</a>
</li>
<li data-sannsyn-recommendation="Politics-460" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender">
<a href="clickOnPolitics460">Politics-460</a>
</li>
<li data-sannsyn-recommendation="Sports-78" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender">
<a href="clickOnSports78">Sports-78</a>
</li>
<li data-sannsyn-recommendation="Books-177" data-sannsyn-recommender-ID="ArticleForSubscriberRecommender">
<a href="clickOnBooks177">Books-177</a>
</li>
</ul>
...
The customer recognition script will detect the recommendations becoming visible on screen. If any
of them is being clicked on, that too is registered. Both of these events are automatically reported back to the
recommender as the user leaves the webpage.
Serverside
The serverside API is for use in cases where it is impossible to fetch recommendations from the browser. Good examples of this is when recommendations are embedded in telephone apps or inside custom applications on desktop computers. Using the serverside API for recommendations that are to be exposed in an ordinary browser, is strongly discouraged.Authentication
Authentication is handled with basic HTTP authentication. Using curl, it looks like this:curl --user username:password 'https://recommender.sannsyn.com/recapi/1.0/ ... '
Failing to authenticate will
give a 401 Unauthorized response.
Adding and Updating Information
(For initial uploads of a complete dataset, look at the Loading a Complete
Dataset section below.
Sending updates from the server is just like sending them from the browser. Here's an example of reporting that a user
has bought a pair of shoes:
curl --user username:password
--request POST 'https://recommender.sannsyn.com/recapi/1.0/update'
--data '{
"service": "shoeshop",
"updates": [ { "customer": "12345", "entityIDs": [ "DrMartens-90"], "what": "PURCHASE" } ]
}'
The parameters should be filled in like specified in the update requests json fields table.
The above example payload gives this information to the recommender system:
Do not expect a lengthy response. The server will reply very concisely: {"text":"Message transmitted","statusOK":true}.
- The update is targeted for a service named shoeshop
- Customer 12345 has purchased an item («entity») with ID DrMartens-90
New Customers and New Products
Suppose we want to submit information about a new customer or a new product to the recommender system. Neither the customer nor the prouct need to be explicitly created in the system; they will be added as part of the update process. So to submit information about a customer that is new to the system, simply follow the process for customers that are already registered:curl --user username:password
--request POST 'https://recommender.sannsyn.com/recapi/1.0/update'
--data '{
"service": "serviceid",
"updates": [ { "customer": "newcustomerid", "entityIDs": [ "newproductid" ], "what": "PURCHASE" } ]
}'
Granted that newcustomerid does not already exist, your new customer is registered; otherwise, the existing one
is updated, and the same goes for newproductid. All IDs in the system are treated as unique identifier strings.
Submitting an ID that is already in use, will tie the given information to this already-in-use ID.
Retrieving Recommendations
We saw in the Getting Started section how easy it is to fetch recommendations. Here is a more elaborate example:curl --user username:password
--request POST 'https://recommender.sannsyn.com/recapi/1.0/recommend'
--data '{
"service": "shoeshop",
"recommender": "ItemToItemRecommender",
"externalIds": [ "Adidas-102" ],
"tags": [ "userid:someothercustomerid" ],
"num": 4
}'
The parameters are specified in the recommendation request json fields table. This
example payload transports the following information to the recommender system:
The recommendation response will have the same structure as in the client side example above.
- The request is for the shoeshop service
- Four recommendations should be generetad from a recommender named ItemToItemRecommender
- Basis for the recommendations is Adidas-102
- The tag gives information about the customer in this case, since the recommender is an item-to-item recommender. The intended consumer of these recommendations is the user someothercustomerid
Some recommendations rely on more than one ID. They could e.g be calculated from the user's ID and at the same time be made to be similar to some other product (ID). How multiple IDs are handled is defined individually in each recommender, but submitting them is uniformly done with the
externalIds array. Here is an example of
retrieving recommendations to fit the contents of a shopping basket with six items in it:
curl --user username:password
--request POST 'https://recommender.sannsyn.com/recapi/1.0/recommend'
--data '{
"service": "service",
"recommender": "ShoppingBasketRecommender",
"externalIds": [
"item-1",
"item-2",
"item-3",
"item-4",
"item-5",
"item-6"
],
"num": number
}'
Tracking Exposure and Interaction
For statistics and for enhancement of recommendations and algorithms, exposure of recommendations and clicks thereon must be reported back to the Recommender System. On a web page, this is automated by the provided javascript, and therefore fairly simple, but when using the recommender system from a server or in telephone or tablet apps, you need to send the reports yourself.These reports really are just another sort of updates, however, so you can use your
update implementation if you pay special attention to the what and the
origin fields in your payload. The what field is to describe the event: it should be
RECCLICK or RECEXPOSURE. The origin field is to contain the id (name) of the
recommender instance that produced the recommendation in question. This is not always the same as the id (name) of the
recommender that you requested, so copy into the origin field of your payload the value received in the
recommendation JSON (in a field equally named origin, see the result example above
if you need an example).Here is what you could send e.g. from a telephone app:
curl --user username:password
--request POST 'https://recommender.sannsyn.com/recapi/1.0/update'
--data '{ "service": "serviceid",
"updates": [ { "customer": "customerid",
"entityIDs": [ "product-1" ],
"what": "RECEXPOSURE",
"where": "app",
"origin": "ItemForCustomerRecommender"
},
{ "customer": "customerid",
"entityIDs": [ "product-3" ],
"what": "RECEXPOSURE",
"where": "app",
"origin": "ItemForCustomerRecommender"
},
{ "customer": "customerid",
"entityIDs": [ "product-3" ],
"what": "RECCLICK",
"where": "app",
"origin": "ItemForCustomerRecommender"
},
]
}'
This tells the recommender system that product-1 and product-3 have been recommended to customerid,
and that customerid has clicked on the recommendation of product-3. It also says that the recommendations
were produced by a recommender named ItemForCustomerRecommender, and that the exposure took place in an app.
Loading a Complete Dataset
A newly started service has no data and will therefore not produce good recommendations. Initially, one should load a set of historical data into the service to avoid this. These data are not sent as individual updates through the REST interface, but as separate files. Dataset files must obey the xml format described in our xsd schema description.Resources
- Payloads expected and returned by the server are described in a spearate document: payload specifications.
- For use with the Episerver Commerce system, there is a Sannsyn Connector for Episerver Commerce available for free download and use.
