# Introduction > Source: https://docs.recombee.com > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [How It Works](#how-it-works) * [Where to Use](#where-to-use) * [Let’s Start with Integration](#lets-start-with-integration) # Introduction Recombee is a Recommender as a Service with easy integration and powerful Admin UI. The Recombee recommendation engine can be applied to any domain that has a catalog of items and is interacted by a large number of users. Applicable to web and mobile apps, Recombee improves user experience by showing the most relevant content for individual users. ## How It Works **Item Properties** describe the items that you want to recommend. Example of properties * Categories * Text description * Images * Labels * Genres * Expiration date * Destination * Geo location * Age restriction * and more **User Properties (optional)** describe your users. Example of properties * Gender * Language * Age * and more **Interactions** between Users and Items are the most important data for the recommender system. Supported Interactions * Views * Purchases * Cart Additions * Bookmark * Ratings (Likes) * View Portions Recommendation Type The type can be for example recommendation for a particular user, recommendation of related items or personalized full text. Recommendation Logic Desired behavior of the recommendation models. Business Rules (Filters & Boosters) Influence the outcome of the recommendations by applying custom Filters and Boosters. Scenarios Each Scenario defines a particular application of the recommendations at your website, mobile app or in emailing. ![Recombee Schema - How it works](/img/schema/schema-how-it-works.svg) **Item properties** describe the products or content that you want to recommend to the users. You can define various types of properties that are analyzed by the content-based recommendation models. In addition to that, you can also use the data in your [Filter or Booster rules](/reql). Data can be delivered using a [Catalog Feed](/catalog_feeds) or the [Recombee API](/api). **User properties** (optional) contain data about your users. Data can be delivered using the [Recombee API](/api#users). **Interactions** between Users and Items are the most important data for the recommender system, as the collaborative filtering models learn various relations from them. You can send them using the [No-Code Widget](/no-code-widgets), [Client-Side API](/api_clients), [Server-Side API](/api_clients), or [Segment Integration](/segment). **Scenarios** define a particular application of a recommendation at your website, mobile app, or email. They may be _homepage-featured_, _watch-next_, _read-next_, _similar-products_, _emailing-after-purchase_, or others. Each Scenario is of a particular **recommendation type**. The type can be for example: a recommendation for a particular user, recommendation of related items, or a personalized full-text search. You can also apply various settings to each Scenario. [**Recommendation Logic**](/recommendation_logics) specifies the desired behavior of the recommendation model. We have prepared different [Logics for various use-cases](/recommendation_logics) that you can choose from. [**Business Rules**](/reql#business-rules) are used to filter or boost items based on their properties. We provide a library with frequently used Rules that you can apply out-of-the-box - and start using immediately. You can also specify your own Rules using our intuitive [Recombee Query Language (ReQL)](/reql). [**Constraints**](/scenarios#constraints) allow you to configure how items with shared conditions may repeat within the recommendation results. You can integrate recommendations using our [No-Code widget](/no-code-widgets), our [Widget SDKs](/widget-sdks), or [API SDKs](/api_clients) in the programming language of your choice. ## Where to Use Recombee can be **utilized in various domains:** * Video * Articles, News, Media * E-commerce * Music, Podcasts * Marketplaces * Real estate * Job boards, HR, Networking * Travel, Trips * and many more Thanks to our simple integration process, you will be able to provide **content, product, or specialized personalization** on your **website, web app, mobile app, or emailing** in a short time. **Personalized Search, Homepage, Product/Content detail page, Push notifications,** recommended content in **Read next or Watch next** \- those are only a few examples of how you can apply Recombee personalization to improve UX and loyalty of your users. * Personalized search * Featured on homepage * Newsletter * Read next * Watch next * Similar products * Similar content * Other also bought * Push notifications * etc. ## Let’s Start with Integration [![Getting Started Guide](/img/cards/getting-started-guide.png)Getting Started GuideStep-by-step integration](/getting_started)[![HTML Integration](/img/cards/html-integration.png)HTML IntegrationUsing our No-Code widget](/no-code-widgets)[![Integration Tips](/img/cards/integration-tips.png)Integration TipsAchieve better performance](/integration_tips) --- # Getting Started > Source: https://docs.recombee.com/getting_started > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [How to Integrate](#how-to-integrate) * [Sending Interactions](#getting-started-interactions) * [Using the API SDK](#getting-started-interactions-sdk) * [Handling Anonymous Users](#handling-anonymous-users) * [Reporting Successful Recommendations](#reporting-successful-recommendations) * [Updating the Item Catalog](#getting-started-catalog) * [Using the API SDK](#getting-started-catalog-sdk) * [Defining Item Properties](#defining-item-properties) * [Sending Item Values](#sending-item-values) * [Getting Recommendations](#getting-started-recomms) * [Using the API SDK](#getting-started-recomms-sdk) * [Recommend Items to User](#recommend-items-to-user) * [Recommend Items to Item](#recommend-items-to-item) * [Recommend Item Segments](#recommend-item-segments) * [Tips and Tricks](#tips-and-tricks) * [Personalized Search](#getting-started-search) * [Using the API SDK](#getting-started-search-sdk) # 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](https://www.recombee.com) if you haven't already. ![Getting Started Schema](/img/schema/getting-started-schema.svg) We provide [client libraries (SDKs)](/api_clients) 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](/authentication) for more details. ## How to Integrate Integration consists of four main parts: [Sending Interactions](#getting-started-interactions)[Synchronizing the Item Catalog](#getting-started-catalog)[Showing Recommendations](#getting-started-recomms)[Personalized Search](#getting-started-search) Each of these parts can be achieved in multiple ways. ![](/img/schema/integration.svg) The recommendations are usually shown to a user on a website, in a mobile app or within an email campaign. If you're using an **AI agent or assistant** to integrate Recombee into your application, the documentation includes [an integration guide](/ai_assistant_guide) written specifically for AI assistants. You can use the prompt below as a starting point: Initial Prompt Use this prompt with AI agents to integrate Recombee into your application. ``` Integrate Recombee (a recommendation engine) into my application. Before writing any code, fetch and read the integration guide at https://docs.recombee.com/ai_assistant_guide.md. It's written specifically for AI assistants and covers authentication, catalog sync, interactions, recommendations, and common pitfalls. Use it as your primary reference. First, explore the codebase to understand the stack, data models, and integration points. Then propose a plan before implementing anything. Do not decide on your own where recommendations should appear. Ask me which use cases to implement — homepage recommendations, related items on a product page, personalized search, email suggestions, and so on. The right surfaces depend on my product and priorities, so treat that as a shared decision even when you're otherwise working autonomously. After we agree on the use cases, implement them end to end, and flag any assumptions you have to make along the way. ``` ## Sending Interactions Interactions are the most valuable information for the algorithms in the recommender engine. The interactions that you send are used by the recommender engine in finding out which items are popular, as well as which recommendations perform the best. There are [multiple kinds](/api#user-item-interactions) of interactions that are supported. For example, a [Detail View](/api#add-detail-view) is sent every time a user views the detail of an item, while a [Purchase](/api#add-purchase) is sent every time a user completes the main desired goal (a conversion). In most cases, you will want to send multiple kinds of interactions as part of your integration. Keep in mind that the names of interaction types may not have the same meaning in your business compared to how they are used in Recombee. For example, an event that is called a [Purchase](/api#add-purchase) in Recombee may not necessarily mean that the user has bought something, but could also mean that the user replied to an advertisement or watched a video until the end. You can send interactions using one of the following methods: [API IntegrationCall the API and use your own code to send the interactions.](#getting-started-interactions-sdk)[Segment IntegrationUse the Recombee Destination within the Segment CDP to send interactions in a unified way.](/segment) ### Using the API SDK Sending interactions using the API SDK is very easy. Let's say we want to send a [Detail View](/api#add-detail-view) interaction for item `xyz` by user `2c169e`: ```js // Import the library using npm or using the script tag: // const client = new recombee.ApiClient('myDb', publicToken, {region: 'us-west'}); await client.send(new recombee.AddDetailView('2c169e', 'xyz')); ``` ```kotlin 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 ``` ```swift 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)") } ``` ```python 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)) ``` ```ruby 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})) ``` ```java 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])); ``` ```csharp 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)); ``` ```js var recombee = require('recombee-api-client'); var rqs = recombee.requests; var client = new recombee.ApiClient('myDb', privateToken, { region: 'us-west' }); await client.send( new rqs.AddDetailView('2c169e', 'xyz', { timestamp: '2014-07-20T02:49:45+02:00', cascadeCreate: true, }), ); ``` ```go import ( "github.com/recombee/go-api-client/v6/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() ``` ```http POST /myDb/detailviews/ HTTP/1.0 Host: Based on the region of your DB, see https://docs.recombee.com/regions Content-type: application/json Body: { "itemId": "xyz", "userId": "2c169e", "timestamp": "2014-07-20T02:49:45+02:00", "cascadeCreate": true } ``` There are a few important parameters in the above code: * `myDb` is the name of the database you are sending data to **(required)**, * `publicToken` or `privateToken` is the [access token](https://admin.recombee.com/go-to-database/settings) for the given database **(required)**, * `region` is the [region](/regions) 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 to `true` in client-side SDKs and `false` in server-side SDKs. We recommend that you use this parameter to prevent errors in case the item or user doesn't exist yet. Interactions also have optional parameters unique to each type, such as `duration` for [Detail View](/api#add-detail-view) or `profit` for [Purchase](/api#add-purchase). You can find the full list of parameters in the [API documentation](/api#user-item-interactions). ### Handling Anonymous Users You may encounter a situation where a user comes to the site as an anonymous user and logs 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 handle this situation, you can use the following approach: * For anonymous users, use a session ID or another unique identifier (e.g. a randomly generated ID consistent across the session) as the `userId` parameter when sending interactions. * For logged-in users, use their user ID as the `userId` parameter. * When a user logs in, send a [Merge Users request](/api#request-merge-users) to merge the anonymous user with the regular account. This way, all interactions of the anonymous user will be transferred to their account and the anonymous user ID will be deleted. ### Reporting Successful Recommendations Once you have integrated recommendations into your site or application, it is **very important** to report the success of these recommendations, as without it, the system will not be able to get precise feedback and improve the quality of future recommendations. You should report a successful recommendation by adding a parameter called `recommId` to all interactions which are based on that recommendation. For example, if a user views an item that was recommended to them, you should send the `recommId` of that recommendation with the [Detail View](/api#add-detail-view). If they then purchase the item, you should also send the `recommId` with the [Purchase](/api#add-purchase). You can find the `recommId` in the Recommendation object that you receive from the API: ``` { "recommId": "968d7864-1d52-4525-a37f-d5b7dd86fe13", "recomms": [ { "id": "item-146" }, { "id": "item-462" } ], "numberNextRecommsCalls": 0 } ``` You can then use this value in an optional parameter in all interaction requests in all Recombee API SDKs, as well as in the Segment integration. For the API SDK, you can find a code example in the [API Reference](/api#add-detail-view). As a result of sending the `recommId` with your interactions, the models will be able to return better recommendations and you will also get [precise success metrics in the Admin UI](/admin_ui#reported-metrics). 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](/api#batch) to send multiple interactions in a single request. ## 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](/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: [API IntegrationCall the API and use your own code to send the item catalog.](#getting-started-catalog-sdk)[Catalog FeedSet up a feed that will automatically synchronize your item catalog with Recombee.](/catalog_feeds) ### Using the API 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** * **Integer** \- integer number * **Double** \- floating point number * **Boolean** \- true / false * **Timestamp** \- UTC timestamp * **Set** \- a set of strings * **Image** \- URL of an image * **Image List** \- 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](/api#item-properties), or do it manually in the [Admin UI](/admin_ui). For examples of properties that can be useful for the recommender engine, see [Integration Tips](/integration_tips). You can also assign semantic roles and metadata to your properties - see [Property Roles & Metadata](/api/property_roles_metadata) for the full reference. [![Creating an Item Property](/img/gui/add_property.png)](/img/gui/add_property.png) #### 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](/api#set-item-values) request: ```python 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 )) ``` ```ruby 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 } )) ``` ```java client.send(new SetItemValues("xyz", new HashMap() {{ 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 ] )); ``` ```csharp client.Send(new SetItemValues("xyz", new Dictionary() { {"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 )); ``` ```js await 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, }, ), ); ``` ```go _, 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() ``` ```http 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](/api#request-batch). 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](/api#user-properties). Tip Still not sure on how to implement sending of the Item Catalog? See the[Tutorial](/tutorial#tutorial-catalog) for more details. ## Getting Recommendations Now it's time to get some recommendations! There are three possible ways to get recommendations onto your site: [API IntegrationCall the API and use your own code to show the resulting recommendations to your users.](#getting-started-recomms-sdk)[No-Code WidgetUse the visual editor in the Admin UI and paste the provided embed code into your site.](/no-code-widgets)[Widget SDKsUse a suite of customizable components to quickly embed recommendations into your site.](/widget-sdks) ### Using the API SDK We will use two endpoints: * [Recommend Items to User](/api#request-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](/api#request-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: ```js const recommended = await client.send(new recombee.RecommendItemsToUser('2c169e', 5)); ``` ```kotlin 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 ... } ``` ```swift 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 ... } ``` ```python recommended = client.send(RecommendItemsToUser('2c169e', 5)) ``` ```ruby recommended = client.send(RecommendItemsToUser.new('2c169e', 5)) ``` ```java 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)); ``` ```csharp RecommendationResponse recommended = client.Send(new RecommendItemsToUser("2c169e", 5)); // Iterating over recommendations: foreach(Recommendation r in recommended.Recomms) { Console.WriteLine(r.Id); } ``` ```js const recommended = await client.send(new rqs.RecommendItemsToUser('2c169e', 5)); ``` ```go recommendReq := client.NewRecommendItemsToUser("2c169e", 5) recommendRes, err := recommendReq.Send() if err != nil { panic(err) } for _, rec := range recommendRes.Recomms { fmt.Println(rec.Id) } ``` ```http GET /myDb/recomms/users/2c169e/items/?count=5 ``` An object with recommended items in the `recomms` field is returned. It can look like this: JSON ``` { "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. It can be used for several purposes: * It allows you to [report the success of recommendations](#reporting-successful-recommendations), which gives you metrics in the Admin UI, while also allowing the recommender engine to improve its quality. * It enables you to fetch another set of recommendations for the same user without repeating the ones you have already displayed, which is useful for implementing [Infinite Scroll & Pagination](#infinite-scroll-pagination). #### Recommend Items to Item Getting recommendations based on item `xyz` which is viewed by user `2c169e` is also easy: ```js const recommended = await client.send( new recombee.RecommendItemsToItem( 'xyz', '2c169e', 10, { 'scenario': 'product_detail', 'returnProperties': true, 'cascadeCreate': true } ) ); ``` ```kotlin 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 ... } ``` ```swift 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 ... } ``` ```python recommended = client.send(RecommendItemsToItem('xyz', '2c169e', 10, scenario='product_detail', return_properties=True, cascade_create=True)) ``` ```ruby recommended = client.send(RecommendItemsToItem.new('xyz', '2c169e', 10, { 'scenario' => 'product_detail', 'returnProperties' => true, 'cascadeCreate' => true }) ) ``` ```java 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 ]) ); ``` ```csharp RecommendationResponse recommended = client.Send(new RecommendItemsToItem("xyz", "2c169e", 10, scenario: "product_detail", returnProperties: true, cascadeCreate: true)); ``` ```js const recommended = await client.send( new rqs.RecommendItemsToItem('xyz', '2c169e', 10, { scenario: 'product_detail', returnProperties: true, cascadeCreate: true, }), ); ``` ```go recommendReq := client.NewRecommendItemsToItem("xyz", "2c169e", 10). SetScenario("product_detail"). SetReturnProperties(true). SetCascadeCreate(true) recommendRes, err := recommendReq.Send() ``` ```http 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](/scenarios) 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](/scenarios), various parameters can be set in the [Recombee Admin UI](https://admin.recombee.com/go-to-database/scenarios): * **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](/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](/api#recommendations). [![Setting Logic & Filter in Admin UI](/img/gui/setting_scenario.webp)](/img/gui/setting_scenario.webp) Setting Logic & Filter in the Admin UI #### Recommend Item Segments Recombee can also recommend Item Segments such as categories, genres, or brands. See [Segmentations](/segmentations) for more information, including how to set them up and use them for recommendations. #### Tips and Tricks Getting Properties of Recommended Items from the API The API can also return the properties of the recommended items, which you can then use to display these items to your users. To enable this, set `returnProperties = true` when requesting recommendations. We also recommend that you use the `includedProperties` parameter to specify which properties you want to receive in the response. [Learn more](/api#recommend-items-to-user-param-returnProperties) Handling non-existent Users or Items If the given user or item does not exist 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). Setting `cascadeCreate = true` tells the recommender to rather create the missing item/user instead. Some bestsellers/trending content will be recommended to these completely new (cold start) items/users without interactions and properties. `cascadeCreate` is set to `true` by default in client-side SDKs. [Learn more](/api#recommend-items-to-user-param-cascadeCreate) Infinite Scroll & Pagination If you are implementing features like infinite scroll or pagination, you can use the [Recommend Next Items](/api#recommend-next-items) endpoint to load recommendations based on the previous pages. This means you can fetch the next set of recommended items without repeating the ones you have already displayed. To use this functionality, you must provide the `recommId` from the initial recommendation request. [Learn more](/api#recommend-next-items) Recommending Users instead of Items Recombee can also recommend Users instead of Items. For this purpose, we provide [Recommend Users to Item](/api#recommend-users-to-item) and [Recommend Users to User](/api#recommend-users-to-user) endpoints. [Learn more](/api#recommending-users) Tip Still not sure on how to implement sending interactions & getting recommendations? See the[Tutorial](/tutorial#tutorial-interactions-recommendations) 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 three possible ways to implement search on your site: [API IntegrationCall the search API and use your own code to show the returned items to your users.](#getting-started-search-sdk)[No-Code WidgetUse the visual editor in the Admin UI and paste the produced embed code into your site.](/no-code-widgets#html-widget-full-text-search)[Widget SDKsUse a suite of customizable components to quickly embed search into your site.](/widget-sdks#quick-search) ### Using the API SDK Search can be implemented using the [Search Items](/api#search-items) and [Search Item Segments](/api#search-item-segments) API endpoints. ```js const matches = await client.send( new recombee.SearchItems( 'user-13434', 'search query', 5, { 'scenario': 'search_top', 'returnProperties': true, 'cascadeCreate': true } ) ); ``` ```kotlin 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... } ) ``` ```swift 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... } ``` ```python matches = client.send(SearchItems('user-13434', 'search query', 5, scenario='search_top', return_properties=True, cascade_create=True)) ``` ```ruby matches = client.send(SearchItems.new('user-13434', 'search query', 5, { 'scenario' => 'search_top', 'returnProperties' => true, 'cascadeCreate' => true }) ) ``` ```java 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 ]) ); ``` ```csharp SearchResponse matches = client.Send(new SearchItems("user-13434", "search query", 5, scenario: "search_top", returnProperties: true, cascadeCreate: true)); ``` ```js const matches = await client.send( new rqs.SearchItems('user-13434', 'search query', 5, { scenario: 'search_top', returnProperties: true, cascadeCreate: true, }), ); ``` ```go searchReq := client.NewSearchItems("user-13434", "search query", 5). SetScenario("search_top"). SetReturnProperties(true). SetCascadeCreate(true) searchRes, err := searchReq.Send() ``` ```http GET /myDb/search/users/user-13434/items/?searchQuery=query&scenario=search_top&returnProperties=true&cascadeCreate=true ``` --- # Recommendation Logics > Source: https://docs.recombee.com/recommendation_logics > For the complete documentation index, see [llms.txt](/llms.txt). # Recommendation Logics Logic allows you to specify the desired behavior of the recommendation model. While Recombee is generally a domain-independent recommendation engine and the default model is optimized to work well in most cases, we have used our experience in some frequent domains to setup some tuned models, and you can now easily pick the logic that is tailored for the particular case. ## Setting Logic in the Admin UI You can assign a particular logic to a [Scenario](/scenarios) in the [Admin UI](/admin_ui). [![Setting Logic in the Admin UI](/img/gui/set_logic.png)](/img/gui/set_logic.png) Alternatively you can [use API parameters to set the logic](#recommendation-logics-set-via-api). ## List of Logics Below is a list of logics available for most databases. Some databases tweaked by the Recombee support team may have custom logics not specified here. Tip See [Integration Tips](/integration_tips) if you are not sure which logic should be used in your use case. ### Universal Models Universal Recombee models for the most common use-cases. #### recombee:default Default model ensemble aiming to work well in most common use cases. It is an ensemble of collaborative filtering and content-based recommendation, backed by popularity-based models when there's not enough data in the given context. The ensemble is being continuously optimized by AI so it automatically adapts to incoming data. --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Users to Item](/api#request-recommend-users-to-item)· [Recommend Users to User](/api#request-recommend-users-to-user)· [Recommend Item Segments to Item](/api#request-recommend-item-segments-to-item)· [Recommend Item Segments to User](/api#request-recommend-item-segments-to-user)· [Recommend Item Segments to Item Segment](/api#request-recommend-item-segments-to-item-segment) #### recombee:homepage Universal model ensemble suitable for putting recommendations on the homepage / welcome-screen scenarios. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) #### recombee:personal Universal model ensemble suitable for user-based recommendations reflecting the personal tastes of the current user. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- Requirements There must be interaction data for the user. #### recombee:similar Universal model ensemble suitable for either recommending items which are similar to the given item (in case of Items-to-Item recommendation), or recommending users who are similar to the given user (in case of Users-to-User recommendation). --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Users to User](/api#request-recommend-users-to-user) #### recombee:popular Universal model suitable for recommending globally popular items, taking into account all interaction types. More important actions (purchases, cart-additions) have higher weight for computing the popularity than less important actions (detail-views). --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Items to User](/api#request-recommend-items-to-user) --- Requirements Interaction data (Detail Views/Purchases/Cart Additions) must be present. --- ##### Parameters timePeriod Duration Default: **14d** The time period in which the popularity is measured. --- userSegmentFilter String Default: **true** [ReQL filter](https://docs.recombee.com/reql_filtering_and_boosting#reql-filtering) on top of user properties defining the segment of users among whom the popularity is calculated. For example, when user properties like `profession` and `country` are provided for some users, you may only ask for items popular among software developers in US and Canada: `'profession'=="software developer" and 'country' in {"US", "CA"}`. --- interactionTypes Enum Set Default: **\[bookmarks, cartAdditions, detailViews, purchases, ratings, viewPortions\]** Allowed Values: **bookmarks |** **cartAdditions |** **detailViews |** **purchases |** **ratings |** **viewPortions** Interaction types to be taken into account when computing the popularity. By default, all the interactions are taken into account. But for example by providing only `["purchases"]`, you will retrieve items which are most frequently purchased, no matter how frequently are they (or the other items) viewed, bookmarked, etc. #### recombee:popular-segments Universal model ensemble suitable for recommending globally popular segments. --- Applicable to endpoints [Recommend Item Segments to User](/api#request-recommend-item-segments-to-user) --- ##### Parameters timePeriod Duration Default: **14d** The time period in which the popularity is measured. --- userSegmentFilter String Default: **true** [ReQL filter](https://docs.recombee.com/reql_filtering_and_boosting.html#reql-filtering) on top of user properties defining the segment of users among whom the popularity is calculated. For example, when user properties like `profession` and `country` are provided for some users, you may only ask for items popular among software developers in US and Canada: `'profession'=="software developer" and 'country' in {"US", "CA"}`. --- interactionTypes Enum Set Default: **\[bookmarks, cartAdditions, detailViews, purchases, ratings, viewPortions\]** Allowed Values: **bookmarks |** **cartAdditions |** **detailViews |** **purchases |** **ratings |** **viewPortions** Interaction types to be taken into account when computing the popularity. #### recombee:recently-viewed Model returning the list of recently viewed items for a particular user. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- Requirements Detail Views must exist for the user. --- ##### Parameters maxAge Duration Default: **14d** Maximal age of the DetailView since the current timestamp. --- recencyOrdering Enum Default: **descending** Allowed Values: **ascending |** **descending** Order in which the items are returned with regard to the time when they were interacted. When the order is descending, the last interacted item is at the beginning of the list of recommendations. When it is ascending, the first interacted item matching the `maxAge` condition is at the beginning of the list. #### recombee:visually-similar Model recommending similar items based on visual similarity (using deep-learning neural networks to process the images provided through the image properties). While the image similarity can take part in other Logics as well, in `recombee:visually-similar`, it is explicitly used as the primary model. Image processing may take some time. Therefore, changes in image item properties do not take effect in real-time. The functionality is still in beta mode. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item) --- Requirements Some image properties must be defined for items, with valid image links provided for the majority of the items in the catalog. --- ##### Parameters useFallbackModels Boolean Default: **false** Enable fallback models to make the recommendations if the model based on visual similarity cannot be used (e.g. due to a missing image for the given source item). #### recombee:similar-properties Model recommending similar items based on item properties (numerical values, sets, and texts). While property values can take part in other Logics, in `recombee:similar-properties`, they are explicitly used as the primary data source for recommending similar items or uses. Various machine-learning methods, including NLP deep-learning networks that process unstructured text descriptions, are used to compute the similarities. --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Users to User](/api#request-recommend-users-to-user) --- Requirements Some properties must exist for the items/users, depending on the used API endpoint. --- ##### Parameters useFallbackModels Boolean Default: **false** Enable fallback models to make recommendations if the model based on item properties cannot be used (e.g. due to missing property values for the given source item). #### recombee:emailing Model ensemble suitable for recommending items in periodic e-mailing campaigns. It contains fine-tuned rotation settings so that the set of recommended items for a particular user changes with each e-mail sent. By default, rotation only takes into account recommendations (e-mails) at most 14 days old. Should a longer time period be needed for your use case, kindly contact support@recombee.com. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- ##### Parameters rotationPolicy Enum Default: **smart** Allowed Values: **smart |** **total** A policy determining how strictly should already recommended items be rotated. The default option "smart" contains fine-tuned rotation settings, which take into account the position of recommended items and enable some of the items to re-appear in further e-mails. Option "total" never recommends items that have already appeared in previous e-mails. #### recombee:custom-sort Model suitable for recommending items ordered by a ReQL expression given as a booster --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Items to User](/api#request-recommend-items-to-user) #### recombee:related-to-segment Recommends items that are contextually related to the [Item Segment](https://docs.recombee.com/segmentations) and should be of interest to the user. Items may belong to the Segment or be outside it if they are strongly relevant. Consider using [recombee:personal-from-segment](https://docs.recombee.com/recommendation_logics#recombee-personal-from-segment) if you want recommendations strictly limited to items within the Segment. **Examples:** * _News:_ For the "Climate Change" Segment, recommend articles about renewable energy (inside the Segment) or related topics like electric vehicles (outside the Segment). * _Music:_ For the "Jazz" Segment, recommend jazz-related songs, including classic tracks (inside the Segment) or modern experimental pieces (outside the Segment). * _E-commerce:_ For the "Digital Cameras" Segment, recommend products like digital cameras (inside the Segment) or accessories like tripods, lenses, or lighting kits (outside the Segment). * _Video Streaming:_ For the "Science Fiction" Segment, recommend sci-fi movies (inside the Segment) or related dystopian thrillers (outside the Segment). --- Applicable to endpoints [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) #### recombee:personal-from-segment Recommends items from the [Item Segment](https://docs.recombee.com/segmentations), tailored to the user's preferences. Consider using [recombee:related-to-segment](https://docs.recombee.com/recommendation_logics#recombee-related-to-segment) if you don't need all the recommended items to belong to the Segment. **Examples:** * _News:_ For the "Environmental News" Segment, recommend articles on climate policy or renewable energy that align with the user’s reading history. * _Music:_ For the "Jazz" Segment, recommend jazz songs matching the user’s listening habits. * _E-commerce:_ For the "Digital Cameras" Segment, recommend digital cameras the user is most likely to be interested in, based on their browsing and purchase history. * _Video Streaming:_ For the "Science Fiction" Segment, recommend sci-fi movies that match the user’s preferences. --- Applicable to endpoints [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) #### recombee:popular-from-segment Recommends the most popular items within the [Item Segment](https://docs.recombee.com/segmentations), based on overall engagement. Use this Logic to highlight trending or widely appealing items. **Examples:** * _News:_ Most-read articles from the "World Politics" Segment. * _Music:_ Most-streamed tracks from the "Rock" Segment. * _E-commerce:_ Best-selling smartphones in the "Smartphones" Segment. * _Video Streaming:_ Most-watched action movies in the "Action Movies" Segment. --- Applicable to endpoints [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) --- Requirements Interaction data (Detail Views/Purchases/Cart Additions) must be present. --- ##### Parameters timePeriod Duration Default: **14d** The time period in which the popularity is measured. --- interactionTypes Enum Set Default: **\[bookmarks, cartAdditions, detailViews, purchases, ratings, viewPortions\]** Allowed Values: **bookmarks |** **cartAdditions |** **detailViews |** **purchases |** **ratings |** **viewPortions** Interaction types to be taken into account when computing the popularity. By default, all the interactions are taken into account. But for example by providing only `["purchases"]`, you will retrieve items which are most frequently purchased, no matter how frequently are they (or the other items) viewed, bookmarked, etc. #### recombee:items-from-top-segment-for-you This Composite Logic provides a comprehensive recommendation in a single response consisting of: * **Top Segment for the User**: It identifies and returns the most relevant Item Segment (e.g., the top category) for the user from the specified Segmentation. * **Top Items from the Segment**: Along with the Segment, it also returns a list of the top items within that Segment. This Logic is ideal for recommending a section and its content together, making it particularly useful for personalized homepage sections. If you want to display multiple distinct sections in a personalized order on your homepage, you can achieve this by making multiple Composite Recommendation requests within a single Batch call. For more specific use cases, such as "Videos From The Top Genre For You" or "Products from the Top Category For You," there are specialized Logics available. --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Segment Items Source Endpoint: **Item Segments to User** The Logic returns the most relevant Item Segment (e.g., the top category) for the user from the specified Segmentation. --- Result Endpoint: **Items to Item Segment** The Logic returns the list of the top items within the top Segment. #### recombee:because-you-interacted This Composite Logic delivers two results within a single response consisting of: * _Item the User Interacted With_: The Logic selects and returns an item that the user has interacted with, based on the interaction types specified by the interactionTypes parameter (e.g., Watched, Purchased, Liked). * _Top Related Items_: Simultaneously, it returns a list of top items related to that specific interacted item. This Logic is ideal for general "Because You..." scenarios, where recommendations are tailored based on the user's previous interactions. For more specific use cases, such as "Because You Bought" or "Because You Watched", there are specialized Logics available. --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Items Source Endpoint: **Items to User** The Logic selects and returns an item that the user has recently interacted with. ##### Parameters interactionTypes Enum Set Default: **\[bookmarks, cartAdditions, detailViews, purchases, ratings, viewPortions\]** Allowed Values: **bookmarks |** **cartAdditions |** **detailViews |** **purchases |** **ratings |** **viewPortions** Defines which interactions are considered when selecting the item the user has interacted with --- maxDaysAgo Integer Default: **30** Defines the maximum number of days since the user interacted the item for it to be considered for the "Because" selection. For example, setting maxDaysAgo to 7 will only consider items interacted within the last 7 days. --- Result Endpoint: **Items to Item** The Logic returns a list of top items related to a specific item, offering content the user is likely to be interested in. #### recombee:swiping-feed This Logic is designed for infinite swiping feed experiences (such as reels or short-form video feeds), where users continuously browse content and can express feedback through likes or dislikes. It optimizes recommendations in real time based on a configurable combination of user engagement (likes, number of viewed items, purchases), and time spent consuming content. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item](/api#request-recommend-items-to-item) --- Requirements [View Portions](https://docs.recombee.com/api#set-view-portion) shall be sent for consumed content, with the [autoPresented parameter](https://docs.recombee.com/api#set-view-portion-param-autoPresented) set to `true` and [timeSpent](https://docs.recombee.com/api#set-view-portion-param-timeSpent) specified Likes and dislikes shall be sent as +1 / -1 [Ratings](https://docs.recombee.com/api#add-rating) After a few items have been presented, call [Recommend Next Items](https://docs.recombee.com/api#recommend-next-items) to retrieve the next batch of content --- ##### Parameters creationTimestamp Property Default: **None** Property representing the creation time of an item, enabling the Logic to evaluate and prioritize newer content in recommendations. --- timeSpentWeight Double Default: **0** Weight (0–1) controlling the importance of [time spent](https://docs.recombee.com/api#set-view-portion-param-timeSpent) on content in the optimization. --- likeWeight Double Default: **0** Weight (0–1) controlling the importance of user likes (positive [Ratings](https://docs.recombee.com/api#add-rating)) in the optimization. --- itemsShownWeight Double Default: **0** Weight (0–1) controlling the importance of maximizing the number of items consumed by the user. --- purchaseWeight Double Default: **0** Weight (0–1) controlling the importance of [Purchases](https://docs.recombee.com/api#purchases) in the optimization. ### Search Models for both personalized and non-personalized fulltext search. #### search:personalized Smart personalized fulltext search which takes into account both the search query and the personal preferences of the user. --- Applicable to endpoints [Search Items](/api#request-search-items)· [Search Item Segments](/api#request-search-item-segments) --- ##### Parameters personalizationImpact Enum Default: **medium** Allowed Values: **low |** **medium |** **high** Determines whether personalization or full-text should have a higher priority in the ranking of the items. --- allowEmptyQueryFallback Boolean Default: **true** Controls the behavior of the Logic when the `searchQuery` is empty. If set to _true_, the Logic returns personalized recommendations in case of an empty search query. If set to _false_, an empty result list is returned instead. #### search:non-personalized Non-personalized fulltext search, based purely on how well the search query is matched. --- Applicable to endpoints [Search Items](/api#request-search-items)· [Search Item Segments](/api#request-search-item-segments) --- ##### Parameters allowEmptyQueryFallback Boolean Default: **true** Controls the behavior of the Logic when the `searchQuery` is empty. If set to _true_, the Logic returns personalized recommendations in case of an empty search query. If set to _false_, an empty result list is returned instead. #### search:semantic Semantic search utilizes a large language model (LLM) to improve search accuracy by understanding the intent and context behind user queries. Instead of relying solely on keyword matches, the system comprehends the semantic meaning of queries and retrieves results that align with the user's intentions. This advanced Logic delivers more accurate, context-aware search results, even when the query terms differ from the content in the database. This Logic can be enabled upon request for Recombee Premium customers. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Search Items](/api#request-search-items) --- ##### Parameters allowEmptyQueryFallback Boolean Default: **true** Controls the behavior of the Logic when the `searchQuery` is empty. If set to _true_, the Logic returns personalized recommendations in case of an empty search query If set to _false_, an empty result list is returned instead. ### E-commerce Models specifically tuned for E-Commerce use-cases. #### ecommerce:homepage Model ensemble suitable for recommending products on homepage/welcome page in E-Commerce and online retail systems. See the [Scenario Recipe](https://docs.recombee.com/recipes/e-commerce/fully-personalized-homepage/for-you-sections) guide for more information. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) #### ecommerce:similar-products Model ensemble suitable for recommending similar products (alternatives) to a source (currently viewed) product. See the [Scenario Recipe](https://docs.recombee.com/recipes/e-commerce/product-detail/alternative-products-and-upsell) guide for more information. --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item) #### ecommerce:cross-sell Model ensemble suitable for recommending compatible/complementary products. In user-based case, the products are compatible with those that the user has already put to the shopping cart. In item-based case, they are compatible with the source (currently viewed) item. See the Scenario Recipe guides for the [product detail](https://docs.recombee.com/recipes/e-commerce/product-detail/bought-together-and-accessories) and [cart](https://docs.recombee.com/recipes/e-commerce/cart) use cases. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Users to Item](/api#request-recommend-users-to-item) --- Requirements Purchases must be present for the item/user. #### ecommerce:bestseller Model suitable for recommending globally most purchased items. See the [Scenario Recipe](https://docs.recombee.com/recipes/e-commerce/fully-personalized-homepage/bestsellers) guide for more information. --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Items to User](/api#request-recommend-items-to-user) --- Requirements Purchases must be present in the database. #### ecommerce:similarly-purchasing Recommends users with similar purchasing behavior as the source user. --- Applicable to endpoints [Recommend Users to User](/api#request-recommend-users-to-user) --- Requirements Purchases must be present for the user. #### ecommerce:products-from-top-category-for-you This Composite Logic provides personalized product recommendations within a single response, tailored to the user's shopping preferences: * **Top Category for the User**: It identifies and returns the most relevant product category for the user, based on their interaction history such as views, purchases, or cart additions. * **Top Products from the Category**: Along with the top category, it also returns a list of the top products within that category. This logic is ideal for scenarios where you want to recommend both a product category and its associated products, making it particularly useful for personalized sections on e-commerce homepages. If you want to display multiple rows for distinct top categories in a personalized order, you can achieve this by making multiple Composite Recommendation requests within a single Batch call. It is expected that the Item Segmentation selected in the configuration represents the product categories relevant to your e-commerce platform. See the [Scenario Recipe](https://docs.recombee.com/recipes/e-commerce/fully-personalized-homepage/personalized-re-ordering-of-sections-advanced) guide for more information. --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Segment Items Source Endpoint: **Item Segments to User** The Logic returns the most relevant product category for the user. --- Result Endpoint: **Items to Item Segment** The Logic returns the list of the top products in the category. #### ecommerce:products-from-top-segment-for-you This Composite Logic delivers personalized product recommendations in a single response: * **Top Segment for the User**: It identifies and returns the most relevant Segment for the user. Depending on the selected Item Segmentation, this Segment could be a Brand, Tag, or other attributes. * **Top Products from the Segment**: Along with the top Segment, it also returns a list of the top products associated with that Segment. This Logic is ideal for recommending both a Segment, such as a brand, and its associated products. For example, it can be used to recommend "Top Products from Your Favorite Brand …" This makes it particularly useful for personalized sections on e-commerce homepages. If you want to display multiple rows for distinct top Segments (e.g., different brands or tags), you can achieve this by making multiple Composite Recommendation requests within a single Batch call. It is expected that the Item Segmentation selected in the configuration represents Segments like brands, tags, or other key attributes relevant to your e-commerce platform. --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Segment Items Source Endpoint: **Item Segments to User** The Logic returns the most relevant product category for the user. --- Result Endpoint: **Items to Item Segment** The Logic returns the list of the top products in the category. #### ecommerce:because-you-purchased This Composite Logic provides personalized product recommendations based on the user's past purchases, all within a single response: * **Product the User Purchased**: It identifies and returns a product that the user has previously purchased. * **Top Complementary Products**: Along with the purchased product, it returns a list of complementary products, such as accessories or related items that pair well with the original purchase. This Logic is ideal for scenarios like "Because You Purchased …," where recommendations are tailored to the user's purchasing history and focus on products that complement what the user has already bought. --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Items Source Endpoint: **Items to User** The Logic selects and returns a product that the user has recently purchased. ##### Parameters maxDaysAgo Integer Default: **90** Defines the maximum number of days since the user purchased the item for it to be considered for the "Because" selection. For example, setting maxDaysAgo to 14 will only consider items purchased within the last 14 days. --- Result Endpoint: **Items to Item** The Logic returns a list of complementary products to a specific item, offering those the user is likely to be interested in. ### Video Set of fine-tuned Video logics, specifically designed for VOD and similar use cases. #### video:continue-watching Model ensemble suitable for recommending partially watched movies or episodes, or the next episode from a watched series. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/fully-personalized-homepage/continue-watching) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- ##### Parameters watchingStartedPercentage Integer Default: **10** Percentage of an asset length for it to be considered as being watched. --- watchingCompletedPercentage Integer Default: **90** Percentage of an asset length for it to be considered as completely watched. --- assetType Enum Default: **movies+episodes** Allowed Values: **movies |** **episodes |** **movies+episodes** Asset type to be recommended. #### video:personal Model ensemble suitable for recommending personalized rows on the homepage or browse pages. Rows with specific content (e.g. award-winning movies) can be set up by applying filters. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/fully-personalized-homepage/recommended-for-you-rows) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) --- ##### Parameters assetType Enum Default: **movies+episodes** Allowed Values: **movies |** **episodes |** **series |** **movies+episodes |** **movies+series** Asset type to be recommended. --- excludeAlreadyWatched Boolean Default: **true** Exclude already watched assets. #### video:segments-for-you Model ensemble suitable for recommending favorite segments (genres, actors, ...) for a specific user. A particular segmentation must exist beforehand. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/fully-personalized-homepage/actors-for-you) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Item Segments to User](/api#request-recommend-item-segments-to-user) #### video:popular Model ensemble suitable for recommending globally popular items. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/fully-personalized-homepage/popular-and-trending) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) --- ##### Parameters timePeriod Duration Default: **14d** The time period in which the popularity is measured. --- userSegmentFilter String Default: **true** [ReQL filter](https://docs.recombee.com/reql_filtering_and_boosting#reql-filtering) on top of user properties defining the segment of users among whom the popularity is calculated. For example, when user properties like `profession` and `country` are provided for some users, you may only ask for items popular among software developers in US and Canada: `'profession'=="software developer" and 'country' in {"US", "CA"}`. --- assetType Enum Default: **movies+episodes** Allowed Values: **movies |** **episodes |** **series |** **movies+episodes |** **movies+series** Asset type to be recommended. --- excludeAlreadyWatched Boolean Default: **false** Exclude already watched assets. #### video:editors-picks Model ensemble suitable for recommendations of hand-picked editorial content. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/fully-personalized-homepage/editors-picks-for-you) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- ##### Parameters picks Item IDs Array Default: **\[\]** List of items to be recommended. --- excludeAlreadyWatched Boolean Default: **false** Exclude already watched assets. --- personalizedReordering Boolean Default: **true** Reorder picked assets in a personalized way for the user. #### video:more-like-this Model ensemble suitable for recommending similar assets on the asset detail page. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/asset-detail-and-player/more-like-this) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item) --- ##### Parameters assetType Enum Default: **movies+episodes** Allowed Values: **movies |** **episodes |** **series |** **movies+episodes |** **movies+series** Asset type to be recommended. --- excludeAlreadyWatched Boolean Default: **false** Exclude already watched assets. #### video:watch-next Model ensemble suitable for end-of-playback recommendations embedded in a video player. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/asset-detail-and-player/watch-next) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item) --- ##### Parameters assetType Enum Default: **movies+episodes** Allowed Values: **episodes |** **movies |** **series |** **movies+episodes |** **movies+series** Asset type to be recommended. --- excludeAlreadyWatched Boolean Default: **false** Exclude already watched assets. #### video:episodes-list Model ensemble suitable for reverse-chronological listing episodes of a particular series. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item) --- ##### Parameters excludeAlreadyWatched Boolean Default: **false** Exclude already watched assets. #### video:search Smart personalized full-text search suitable for searching movies, series, and episodes. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/search-movies-and-series) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Search Items](/api#request-search-items) --- ##### Parameters assetType Enum Default: **movies+episodes** Allowed Values: **movies |** **episodes |** **series |** **movies+episodes |** **movies+series** Asset type to be recommended. --- personalizationImpact Enum Default: **medium** Allowed Values: **low |** **medium |** **high** Determines whether personalization or full-text should have a higher priority in the ranking of the items. #### video:search-segments Smart personalized full-text search suitable for searching segments (genres, actors, ...). A particular segmentation must exist beforehand. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Search Item Segments](/api#request-search-item-segments) #### video:emailing Model ensemble suitable for sending personalized emails with personalized content for the user. It contains fine-tuned rotation settings so that the set of recommended assets for a particular user changes with each e-mail sent. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/search-movies-and-series) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- ##### Parameters assetType Enum Default: **movies+episodes** Allowed Values: **movies |** **episodes |** **series |** **movies+episodes |** **movies+series** Asset type to be recommended. --- rotationPolicy Enum Default: **smart** Allowed Values: **smart |** **total** A policy determining how strictly should already recommended items be rotated. The default option "smart" contains fine-tuned rotation settings, which take into account the position of recommended items and enable some of the items to re-appear in further e-mails. Option "total" never recommends items that have already appeared in previous e-mails. #### video:videos-from-top-genre-for-you This Composite Logic delivers a comprehensive recommendation in a single response consisting of: * **Top Genre for the User**: It identifies and returns the most relevant genre or category for the user, based on their viewing history and preferences. * **Top Videos from the Genre**: Along with the top genre, it also returns a list of the top videos within that genre or category. This Logic is ideal for recommending both a genre and its associated videos together, making it particularly useful for personalized sections on the homepages of video streaming platforms. If you wish to display multiple rows for distinct top genres in a personalized order, you can achieve this by making multiple Composite Recommendation requests within a single Batch call. It is expected that the Item Segmentation selected in the configuration represents the genres or categories of the videos. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/fully-personalized-homepage/personalized-re-ordering-of-rows-advanced) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Segment Items Source Endpoint: **Item Segments to User** The Logic returns the most relevant genre for the user. --- Result Endpoint: **Items to Item Segment** The Logic returns the list of the top items within the top genre. #### video:videos-from-top-segment-for-you This Composite Logic delivers a comprehensive recommendation in a single response consisting of: * **Top Segment for the User**: It identifies and returns the most relevant Segment for the user. Depending on the selected Item Segmentation, this could be a Director, Theme, Tag, Actor, etc. * **Top Videos from the Segment**: Along with the top Segment, it also returns a list of the top videos associated with that Segment. Based on the selected Item Segmentation, this Logic can be used for rows such as “Your Favorite Director … And Their Movies” or “Videos About Your Favorite Topic …”. If you wish to display multiple rows for distinct top Segments in a personalized order, you can achieve this by making multiple Composite Recommendation requests within a single Batch call. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Segment Items Source Endpoint: **Item Segments to User** The Logic returns the most relevant Item Segment (e.g., the top Director, Theme, Tag, Actor, etc) for the user from the specified Segmentation. --- Result Endpoint: **Items to Item Segment** The Logic returns the list of the top videos within the top Segment. #### video:because-you-watched This Composite Logic delivers personalized recommendations based on a user's previous watching activity, all within a single response consisting of: * **Video the User Watched**: It selects and returns a video that the user has recently watched. * **Top Related Videos**: Along with the watched video, it also returns a list of top videos related to that specific video, offering content the user is likely to be interested in. This Logic is ideal for scenarios like “Because You Watched …,” where recommendations are tailored to the user’s recent watching history. The watched video is determined based on View Portion interactions, and you can refine this by specifying the maxDaysAgo and minWatchedPercentage parameters to define which View Portions are considered. If no such View Portion exists, an empty recommendation is returned. If you want to display multiple sets of related videos based on different watched content, you can achieve this by making multiple Composite Recommendation requests within a single Batch call. See the [Scenario Recipe](https://docs.recombee.com/recipes/video/fully-personalized-homepage/because-you-watched) guide for more information. _This Logic is not available in new databases by default. Please contact [support@recombee.com](mailto:support@recombee.com) if you want to use it._ --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Items Source Endpoint: **Items to User** The Logic selects and returns a video that the user has recently watched. ##### Parameters maxDaysAgo Integer Default: **30** Defines the maximum number of days since the user watched a video for it to be considered for the "Because" selection. For example, setting maxDaysAgo to 7 will only consider videos watched within the last 7 days. --- minWatchedPercentage Integer Default: **75** Defines the minimum portion of a video that must be watched, based on the View Portion interaction, for it to be considered watched by the user (e.g. 75% by default). This ensures that only videos where the user has engaged with at least the specified portion are included in the "Because" selection. --- Result Endpoint: **Items to Item** The Logic returns a list of top videos related to a specific video, offering content the user is likely to be interested in. ### News Set of fine-tuned News Logics, specifically crafted to enhance recommendation experiences for news platforms, ensuring relevance and timeliness. #### news:daily-news Model ensemble optimized for high-visibility placements. It ensures users stay connected to the most significant news stories while maintaining a personalized experience based on their past behavior. It caters to frequent visitors by consistently offering fresh, relevant content. See the [Scenario Recipe](https://docs.recombee.com/recipes/news/homepage/top-stories) guide for more information. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- ##### Parameters editorsPicks Item IDs Array Default: **\[\]** A selection of editorially chosen items that are prepended to the recommended content list, ensuring these highlighted items are seen first by the user. --- publishedTimestamp Property Default: **None** Property indicating the publication date of articles, used to assess content freshness. #### news:personal Model ensemble providing individualized content suggestions, carefully selecting the best choices from the catalog to match each user's specific interests. It is particularly suitable for the _For You_ scenarios, where personalized recommendations are essential. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) #### news:read-next Model ensemble recommending personalized articles most likely to engage users after they finish reading the current article. It considers the content of the current article and analyzes both recent and long-term user behavior to encourage continued reading and extend visit duration. Suitable for _Continue Reading_ or _You Might Also Like_ scenarios. See the [Scenario Recipe](https://docs.recombee.com/recipes/news/article/read-next) guide for more information. --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item) #### news:trending Model ensemble recommending news articles that are currently trending, providing users with content that is gaining widespread interest and should not be missed. Suitable for the _Trending Articles_ scenario. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) --- ##### Parameters excludeAlreadyRead Boolean Default: **true** Excludes articles the user has already read. #### news:popular Model ensemble recommending articles that are highly popular within a specified time period. It is ideal for _Popular Articles_ scenario, allowing users to see what others find interesting. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item](/api#request-recommend-items-to-item)· [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) --- ##### Parameters excludeAlreadyRead Boolean Default: **true** Excludes articles the user has already read. --- timePeriod Duration Default: **14d** The time frame used to measure item popularity. #### news:recent Model ensemble showcasing the most recently published articles, ensuring users stay updated with the latest content. Suitable for the _Latest News_ scenario. See the [Scenario Recipe](https://docs.recombee.com/recipes/news/homepage/latest-news) guide for more information. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user)· [Recommend Items to Item Segment](/api#request-recommend-items-to-item-segment) --- ##### Parameters excludeAlreadyRead Boolean Default: **true** Excludes articles the user has already read. --- publishedTimestamp Property Default: **None** Property indicating the publication date of articles, used to assess content freshness. #### news:related Model ensemble recommending articles that are related to the current article, providing users with a seamless continuation of their reading experience on a given topic. Suitable for the _Related Articles_ scenario. --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item) --- ##### Parameters excludeAlreadyRead Boolean Default: **true** Excludes articles the user has already read. #### news:categories-for-you Model ensemble recommending categories relevant to the user based on their previously read articles. Suitable, for example, for personalized re-ordering of sections on the homepage. Assumes the scenario is configured with an Item Segmentation representing article categories. --- Applicable to endpoints [Recommend Item Segments to User](/api#request-recommend-item-segments-to-user) #### news:editors-picks Model ensemble suitable for recommendations of hand-picked editorial content. See the [Scenario Recipe](https://docs.recombee.com/recipes/news/homepage/personalized-editors-picks) guide for more information. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- ##### Parameters picks Item IDs Array Default: **\[\]** List of items to be recommended. --- excludeAlreadyRead Boolean Default: **false** Exclude already read articles. --- personalizedReordering Boolean Default: **true** Reorder picked articles in a personalized way for the user. #### news:emailing The `news:emailing` Logic is designed to provide a personalized selection of articles for email newsletters. This Logic combines: * Personalized recommendations based on the user's reading history and preferences. * Key unread articles to ensure the user stays informed about the most important news they haven’t seen yet. To maintain content freshness, it is advisable to apply a Filter that limits the selection to recently published articles, depending on the email frequency. For example, for a daily digest, you can filter for articles published within the last 24 hours. See the [Scenario Recipe](https://docs.recombee.com/recipes/news/personalized-emailing) guide for more information. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) --- ##### Parameters editorsPicks Item IDs Array Default: **\[\]** A selection of editorially chosen items that are prepended to the recommended content list, ensuring these highlighted items are seen first by the user. #### news:articles-from-top-category-for-you This Composite Logic provides a comprehensive recommendation in a single response consisting of: * **Top Segment for the User**: It identifies and returns the most relevant Item Segment (e.g., the top category) for the user from the specified Segmentation. * **Top Items from the Segment**: Along with the Segment, it also returns a list of the top items within that Segment. This Logic is ideal for recommending a section and its content together, making it particularly useful for personalized homepage sections. If you want to display multiple distinct sections in a personalized order on your homepage, you can achieve this by making multiple Composite Recommendation requests within a single Batch call. For more specific use cases, such as "Videos From The Top Genre For You" or "Products from the Top Category For You," there are specialized Logics available. See the [Scenario Recipe](https://docs.recombee.com/recipes/news/homepage/personalized-sections-with-reordering) guide for more information. --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Segment Items Source Endpoint: **Item Segments to User** The Logic returns the most relevant Item Segment (e.g., the top category) for the user from the specified Segmentation. --- Result Endpoint: **Items to Item Segment** The Logic returns the list of the top items within the top Segment. #### news:articles-from-top-segment-for-you This Composite Logic delivers personalized news article recommendations in a single response: * **Top Segment for the User**: It identifies and returns the most relevant Segment for the user. Depending on the selected Item Segmentation, this Segment could be based on attributes such as authors or tags. * **Top Articles from the Segment**: Along with the top Segment, it returns a list of the top articles associated with that Segment. This Logic is ideal for recommending both a Segment (e.g., a favorite author or popular tag) and its associated articles. For example, it can be used for scenarios like "Top Articles from Your Favorite Author". If you wish to display multiple distinct Segments in a personalized order, you can achieve this by making multiple Composite Recommendation requests within a single Batch call. --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Segment Items Source Endpoint: **Item Segments to User** The Logic returns the most relevant Item Segment (e.g., the top category) for the user from the specified Segmentation. --- Result Endpoint: **Items to Item Segment** The Logic returns the list of the top items within the top Segment. #### news:because-you-read This Composite Logic delivers personalized news article recommendations based on the user's previous reading activity, all within a single response: * **Article the User Read**: It selects and returns an article that the user has previously read. * **Top Related Articles**: Along with the read article, it returns a list of top related articles focused on the same or similar topics, offering follow-up content or deeper insights into the subject the user has already shown interest in. This Logic is ideal for scenarios like “Because You Read …,” where recommendations are tailored to the user’s reading history. It can recommend follow-up articles, related pieces, or additional articles on similar subjects. --- Applicable to endpoints [Composite Recommendation](/api#composite-recommendation) --- ##### Composite Stages For Recommendation Source Result User Item Items Source Endpoint: **Items to User** The Logic selects and returns an article that the user has previously read. ##### Parameters maxDaysAgo Integer Default: **7** Defines the maximum number of days since the user purchased the item for it to be considered for the "Because" selection. For example, setting maxDaysAgo to 14 will only consider items purchased within the last 14 days. --- Result Endpoint: **Items to Item** The Logic returns a list of top related articles focused on the same or similar topics, offering follow-up content or deeper insights into the subject the user has already shown interest in #### news:search Smart full-text search for news articles, with configurable freshness, trendingness, and personalization sliders. --- Applicable to endpoints [Search Items](/api#request-search-items) --- ##### Parameters allowEmptyQueryFallback Boolean Default: **true** Controls the behavior of the Logic when the `searchQuery` is empty. If set to _true_, the Logic returns personalized recommendations in case of an empty search query. If set to _false_, an empty result list is returned instead. --- freshnessDateProperty Property Default: **None** Name of the item property that stores the article publication date, used for freshness scoring. --- freshnessWeight Double Default: **0.5** Controls how much freshness affects the final ranking. --- trendingnessPeriod Duration Default: **1d** Time window from which interaction data is used to compute trendingness. --- trendingnessWeight Double Default: **0.3** Controls how much trendingness affects the final ranking. --- personalizationWeight Double Default: **0.2** Controls how much personalization affects the final ranking. ### Classified Advertising Models tailored for classified advertising (real estate, automotive, electronics, services, etc.). #### classifieds:homepage Model ensemble suitable for recommending products on homepage/welcome page of a Classified advertising site. --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) #### classifieds:personal Model ensemble suitable for recommending picked ads right for the given user. Can be used on different places, such as in-category recommendation when augmented with appropriate [ReQL filter](https://docs.recombee.com/reql_filtering_and_boosting#reql-filtering). --- Applicable to endpoints [Recommend Items to User](/api#request-recommend-items-to-user) #### classifieds:similar-ads Model ensemble suitable for recommending ads that are similar to the one which is currently viewed. --- Applicable to endpoints [Recommend Items to Item](/api#request-recommend-items-to-item) **Table of contents** * [Setting logic in the Admin UI](#setting-logic-in-the-admin-ui) * [Universal Models](#universal-models) * [recombee:default](#recombee-default) * [recombee:homepage](#recombee-homepage) * [recombee:personal](#recombee-personal) * [recombee:similar](#recombee-similar) * [recombee:popular](#recombee-popular) * [recombee:popular-segments](#recombee-popular-segments) * [recombee:recently-viewed](#recombee-recently-viewed) * [recombee:visually-similar](#recombee-visually-similar) * [recombee:similar-properties](#recombee-similar-properties) * [recombee:emailing](#recombee-emailing) * [recombee:custom-sort](#recombee-custom-sort) * [recombee:related-to-segment](#recombee-related-to-segment) * [recombee:personal-from-segment](#recombee-personal-from-segment) * [recombee:popular-from-segment](#recombee-popular-from-segment) * [recombee:items-from-top-segment-for-you](#recombee-items-from-top-segment-for-you) * [recombee:because-you-interacted](#recombee-because-you-interacted) * [recombee:swiping-feed](#recombee-swiping-feed) * [Search](#search) * [search:personalized](#search-personalized) * [search:non-personalized](#search-non-personalized) * [search:semantic](#search-semantic) * [E-commerce](#e-commerce) * [ecommerce:homepage](#ecommerce-homepage) * [ecommerce:similar-products](#ecommerce-similar-products) * [ecommerce:cross-sell](#ecommerce-cross-sell) * [ecommerce:bestseller](#ecommerce-bestseller) * [ecommerce:similarly-purchasing](#ecommerce-similarly-purchasing) * [ecommerce:products-from-top-category-for-you](#ecommerce-products-from-top-category-for-you) * [ecommerce:products-from-top-segment-for-you](#ecommerce-products-from-top-segment-for-you) * [ecommerce:because-you-purchased](#ecommerce-because-you-purchased) * [Video](#video) * [video:continue-watching](#video-continue-watching) * [video:personal](#video-personal) * [video:segments-for-you](#video-segments-for-you) * [video:popular](#video-popular) * [video:editors-picks](#video-editors-picks) * [video:more-like-this](#video-more-like-this) * [video:watch-next](#video-watch-next) * [video:episodes-list](#video-episodes-list) * [video:search](#video-search) * [video:search-segments](#video-search-segments) * [video:emailing](#video-emailing) * [video:videos-from-top-genre-for-you](#video-videos-from-top-genre-for-you) * [video:videos-from-top-segment-for-you](#video-videos-from-top-segment-for-you) * [video:because-you-watched](#video-because-you-watched) * [News](#news) * [news:daily-news](#news-daily-news) * [news:personal](#news-personal) * [news:read-next](#news-read-next) * [news:trending](#news-trending) * [news:popular](#news-popular) * [news:recent](#news-recent) * [news:related](#news-related) * [news:categories-for-you](#news-categories-for-you) * [news:editors-picks](#news-editors-picks) * [news:emailing](#news-emailing) * [news:articles-from-top-category-for-you](#news-articles-from-top-category-for-you) * [news:articles-from-top-segment-for-you](#news-articles-from-top-segment-for-you) * [news:because-you-read](#news-because-you-read) * [news:search](#news-search) * [Classified Advertising](#classified-advertising) * [classifieds:homepage](#classifieds-homepage) * [classifieds:personal](#classifieds-personal) * [classifieds:similar-ads](#classifieds-similar-ads) * [Setting logic using API parameter](#recommendation-logics-set-via-api) ## Setting Logic Using API Parameter To specify the logic for individual recommendation requests, pass its name (e.g., `ecommerce:homepage`) to the `logic` parameter. ```js const result = await client.send( new recombee.RecommendItemsToUser( 'user-x', 10, { logic: 'ecommerce:homepage' } ) ); ``` ```kotlin val request = RecommendItemsToUser( userId = "user-x", count = 10, logic = Logic(name = "ecommerce:homepage") ) val result = client.sendAsync(request) result.onSuccess { recommendationResponse -> // Handle the successful response } ... ``` ```swift let request = RecommendItemsToUser( userId: "user-x", count: 10, logic: Logic(name: "ecommerce:homepage") ) do { let recommendationResponse = try await client.send(request) // Handle the successful response print("Recommendation response: \(recommendationResponse)") } catch { // Handle error print("Error: \(error)") } ``` ```js const result = await client.send( new rqs.RecommendItemsToUser( 'user-x', 10, { logic: 'ecommerce:homepage' } ) ); ``` ```python result = client.send(RecommendItemsToUser("user-x", 10, logic="ecommerce:homepage")) ``` ```ruby result = client.send(RecommendItemsToUser.new('user-x', 10, {:logic => 'ecommerce:homepage'})) ``` ```java import com.recombee.api_client.bindings.Logic; RecommendationResponse result = client.send(new RecommendItemsToUser("user-x", 10) .setLogic(new Logic("ecommerce:homepage")) ); ``` ```php $result = $client->send(new RecommendItemsToUser('user-x', 10, ['logic' => 'ecommerce:homepage'])); ``` ```csharp using Recombee.ApiClient.Bindings; RecommendationResponse result = client.Send(new RecommendItemsToUser("user-x", 10, logic: new Logic(name: "ecommerce:homepage") ) ); ``` ```go request := client.NewRecommendItemsToUser("user-x", 10).SetLogic(bindings.Logic{Name: "ecommerce:homepage"}) recommended, err := request.Send() ``` ```http GET /my-db-id/recomms/users/user-x/items/?count=10&logic=ecommerce:homepage ``` Most logics include sensible default parameters, but you can customize them to suit your specific needs. The example below uses a placeholder logic named `example:logic-parameters` to demonstrate how to set various types of parameters. Note that this logic is just an example and does not exist in the system. The parameter names and values are also for demonstration purposes only. Please refer to the documentation of the specific logic you intend to use for the correct parameter names and expected values. ```js const result = await client.send(new recombee.RecommendItemsToUser('user-x', 10, { logic: { name: 'example:logic-parameters', settings: { // basic types boolean: true, double: 3.14, int: 42, string: 'example', stringArray: ['value1', 'value2', 'value3'], // available keys: days, hours, minutes, seconds duration: { days: 3, hours: 12 }, // one of possible values: e.g. 'ascending', 'descending' enum: 'ascending', // array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) enumArray: ['cartAdditions', 'cartAdditions', 'purchases'], // set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) enumSet: ['cartAdditions'], // array of item IDs itemIdsArray: ['item1', 'item2', 'item3'], // name of the item segmentation itemSegmentation: 'segmentationName', // name of the item/user property property: 'category', // ReQL filter expression as a string reqlFilter: `'category' == "electronics"`, // 'since' and 'until' should be ISO 8601 format strings or Unix timestamps timeInterval: { since: '2024-01-01T00:00:00Z', until: '2024-12-31T23:59:59Z' }, } } }) ); ``` ```kotlin val request = RecommendItemsToUser( userId = "user-x", count = 10, logic = Logic( name = "example:logic-parameters", settings = mapOf( // basic types "boolean" to true, "double" to 3.14, "int" to 42, "string" to "example", "stringArray" to listOf("value1", "value2", "value3"), // available keys: days, hours, minutes, seconds "duration" to mapOf("days" to 3, "hours" to 12), // one of possible values: e.g. 'ascending', 'descending' "enum" to "ascending", // array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) "enumArray" to listOf("cartAdditions", "cartAdditions", "purchases"), // set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) "enumSet" to listOf("cartAdditions"), // array of item IDs "itemIdsArray" to listOf("item1", "item2", "item3"), // name of the item segmentation "itemSegmentation" to "segmentationName", // name of the item/user property "property" to "category", // ReQL filter expression as a string "reqlFilter" to "'category' == \"electronics\"", // 'since' and 'until' should be ISO 8601 format strings or Unix timestamps "timeInterval" to mapOf("since" to "2024-01-01T00:00:00Z", "until" to "2024-12-31T23:59:59Z") ) ) ) val result = client.sendAsync(request) result.onSuccess { recommendationResponse -> // Handle the successful response } ``` ```swift let request = RecommendItemsToUser( userId: "user-x", count: 10, logic: Logic( name: "example:logic-parameters", settings: [ // basic types "boolean": true, "double": 3.14, "int": 42, "string": "example", "stringArray": ["value1", "value2", "value3"], // available keys: days, hours, minutes, seconds "duration": ["days": 3, "hours": 12], // one of possible values: e.g. 'ascending', 'descending' "enum": "ascending", // array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) "enumArray": ["cartAdditions", "cartAdditions", "purchases"], // set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) "enumSet": ["cartAdditions"], // array of item IDs "itemIdsArray": ["item1", "item2", "item3"], // name of the item segmentation "itemSegmentation": "segmentationName", // name of the item/user property "property": "category", // ReQL filter expression as a string "reqlFilter": "'category' == \"electronics\"", // 'since' and 'until' should be ISO 8601 format strings or Unix timestamps "timeInterval": ["since": "2024-01-01T00:00:00Z", "until": "2024-12-31T23:59:59Z"] ] ) ) do { let recommendationResponse = try await client.send(request) // Handle the successful response print("Recommendation Response: \(recommendationResponse)") } catch { // Handle error print("Error: \(error)") } ``` ```js const result = await client.send( new rqs.RecommendItemsToUser( 'user-x', 10, { logic: { name: 'example:logic-parameters', settings: { // basic types boolean: true, double: 3.14, int: 42, string: 'example', stringArray: ['value1', 'value2', 'value3'], // available keys: days, hours, minutes, seconds duration: { days: 3, hours: 12 }, // one of possible values: e.g. 'ascending', 'descending' enum: 'ascending', // array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) enumArray: ['cartAdditions', 'cartAdditions', 'purchases'], // set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) enumSet: ['cartAdditions'], // array of item IDs itemIdsArray: ['item1', 'item2', 'item3'], // name of the item segmentation itemSegmentation: 'segmentationName', // name of the item/user property property: 'category', // ReQL filter expression as a string reqlFilter: `'category' == "electronics"`, // 'since' and 'until' should be ISO 8601 format strings or Unix timestamps timeInterval: { since: '2024-01-01T00:00:00Z', until: '2024-12-31T23:59:59Z' }, } } } ) ); ``` ```python from recombee_api_client.inputs import Logic result = client.send( RecommendItemsToUser( "user-x", 10, logic=Logic( name="example:logic-parameters", settings={ # basic types "boolean": True, "double": 3.14, "int": 42, "string": "example", "stringArray": ["value1", "value2", "value3"], # available keys: days, hours, minutes, seconds "duration": {"days": 3, "hours": 12}, # one of possible values: e.g. 'ascending', 'descending' "enum": "ascending", # array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) "enumArray": ["cartAdditions", "cartAdditions", "purchases"], # set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) "enumSet": ["cartAdditions"], # array of item IDs "itemIdsArray": ["item1", "item2", "item3"], # name of the item segmentation "itemSegmentation": "segmentationName", # name of the item/user property "property": "category", # ReQL filter expression as a string "reqlFilter": "'category' == \"electronics\"", # 'since' and 'until' should be ISO 8601 format strings or Unix timestamps "timeInterval": {"since": "2024-01-01T00:00:00Z", "until": "2024-12-31T23:59:59Z"}, }, ), ) ) ``` ```ruby result = client.send( RecommendItemsToUser.new( 'user-x', 10, { :logic => Logic.new( :name => 'example:logic-parameters', :settings => { # basic types "boolean" => true, "double" => 3.14, "int" => 42, "string" => "example", "stringArray" => ["value1", "value2", "value3"], # available keys: days, hours, minutes, seconds "duration" => { "days" => 3, "hours" => 12 }, # one of possible values: e.g. 'ascending', 'descending' "enum" => "ascending", # array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) "enumArray" => ["cartAdditions", "cartAdditions", "purchases"], # set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) "enumSet" => ["cartAdditions"], # array of item IDs "itemIdsArray" => ["item1", "item2", "item3"], # name of the item segmentation "itemSegmentation" => "segmentationName", # name of the item/user property "property" => "category", # ReQL filter expression as a string "reqlFilter" => "'category' == \"electronics\"", # 'since' and 'until' should be ISO 8601 format strings or Unix timestamps "timeInterval" => { "since" => "2024-01-01T00:00:00Z", "until" => "2024-12-31T23:59:59Z" } } ) } ) ) ``` ```java import com.recombee.api_client.bindings.Logic; Map settings = new HashMap<>(); // basic types settings.put("boolean", true); settings.put("double", 3.14); settings.put("int", 42); settings.put("string", "example"); settings.put("stringArray", Arrays.asList("value1", "value2", "value3")); // available keys: days, hours, minutes, seconds settings.put("duration", new HashMap() {{ put("days", 3); put("hours", 12); }}); // one of possible values: e.g. 'ascending', 'descending' settings.put("enum", "ascending"); // array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) settings.put("enumArray", Arrays.asList("cartAdditions", "cartAdditions", "purchases")); // set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) settings.put("enumSet", Arrays.asList("cartAdditions")); // array of item IDs settings.put("itemIdsArray", Arrays.asList("item1", "item2", "item3")); // name of the item segmentation settings.put("itemSegmentation", "segmentationName"); // name of the item/user property settings.put("property", "category"); // ReQL filter expression as a string settings.put("reqlFilter", "'category' == \"electronics\""); // 'since' and 'until' should be ISO 8601 format strings or Unix timestamps settings.put("timeInterval", new HashMap() {{ put("since", "2024-01-01T00:00:00Z"); put("until", "2024-12-31T23:59:59Z"); }}); Logic l = new Logic("example:logic-parameters", settings); RecommendationResponse result = client.send(new RecommendItemsToUser("user-x", 10) .setLogic(l)); ``` ```php $result = $client->send( new RecommendItemsToUser("user-x", 10, [ "logic" => [ "name" => "example:logic-parameters", "settings" => [ // basic types "boolean" => true, "double" => 3.14, "int" => 42, "string" => "example", "stringArray" => ["value1", "value2", "value3"], // available keys: days, hours, minutes, seconds "duration" => ["days" => 3, "hours" => 12], // one of possible values: e.g. 'ascending', 'descending' "enum" => "ascending", // array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) "enumArray" => ["cartAdditions", "cartAdditions", "purchases"], // set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) "enumSet" => ["cartAdditions"], // array of item IDs "itemIdsArray" => ["item1", "item2", "item3"], // name of the item segmentation "itemSegmentation" => "segmentationName", // name of the item/user property "property" => "category", // ReQL filter expression as a string "reqlFilter" => '\'category\' == "electronics"', // 'since' and 'until' should be ISO 8601 format strings or Unix timestamps "timeInterval" => [ "since" => "2024-01-01T00:00:00Z", "until" => "2024-12-31T23:59:59Z", ], ], ], ]), ); ``` ```csharp using Recombee.ApiClient.Bindings; var settings = new Dictionary() { // basic types {"boolean", true}, {"double", 3.14}, {"int", 42}, {"string", "example"}, {"stringArray", new[] {"value1", "value2", "value3"}}, // available keys: days, hours, minutes, seconds {"duration", new Dictionary() {{"days", 3}, {"hours", 12}}}, // one of possible values: e.g. 'ascending', 'descending' {"enum", "ascending"}, // array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) {"enumArray", new[] {"cartAdditions", "cartAdditions", "purchases"}}, // set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) {"enumSet", new[] {"cartAdditions"}}, // array of item IDs {"itemIdsArray", new[] {"item1", "item2", "item3"}}, // name of the item segmentation {"itemSegmentation", "segmentationName"}, // name of the item/user property {"property", "category"}, // ReQL filter expression as a string {"reqlFilter", "'category' == \"electronics\""}, // 'since' and 'until' should be ISO 8601 format strings or Unix timestamps {"timeInterval", new Dictionary() {{"since", "2024-01-01T00:00:00Z"}, {"until", "2024-12-31T23:59:59Z"}}} }; Logic l = new Logic("example:logic-parameters", settings); var recommendationResponse = client.Send(new RecommendItemsToUser("user-x", 10, logic: l)); ``` ```go logicSettings := map[string]interface{}{ // basic types "boolean": true, "double": 3.14, "int": 42, "string": "example", "stringArray": []string{"value1", "value2", "value3"}, // available keys: days, hours, minutes, seconds "duration": map[string]interface{}{"days": 3, "hours": 12}, // one of possible values: e.g. 'ascending', 'descending' "enum": "ascending", // array of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates allowed) "enumArray": []string{"cartAdditions", "cartAdditions", "purchases"}, // set of possible values, e.g. 'cartAdditions', 'purchases', 'views' (duplicates not allowed) "enumSet": []string{"cartAdditions"}, // array of item IDs "itemIdsArray": []string{"item1", "item2", "item3"}, // name of the item segmentation "itemSegmentation": "segmentationName", // name of the item/user property "property": "category", // ReQL filter expression as a string "reqlFilter": `'category' == "electronics"`, // 'since' and 'until' should be ISO 8601 format strings or Unix timestamps "timeInterval": map[string]interface{}{"since": "2024-01-01T00:00:00Z", "until": "2024-12-31T23:59:59Z"}, } logic := bindings.Logic{Name: "example:logic-parameters", Settings: &logicSettings} recommended, err := client.NewRecommendItemsToUser("user-x", 10).SetLogic(logic).Send() ``` ```http POST /my-db-id/recomms/users/user-x/items/ Body: { "count": 10, "logic": { "name": "example:logic-parameters", "settings": { "boolean": true, "double": 3.14, "int": 42, "string": "example", "stringArray": ["value1", "value2", "value3"], "duration": { "days": 3, "hours": 12 }, "enum": "ascending", "enumArray": ["cartAdditions", "cartAdditions", "purchases"], "enumSet": ["cartAdditions"], "itemIdsArray": ["item1", "item2", "item3"], "itemSegmentation": "segmentationName", "property": "category", "reqlFilter": "'category' == \"electronics\"", "timeInterval": { "since": "2024-01-01T00:00:00Z", "until": "2024-12-31T23:59:59Z" } } } } ``` --- # Integration Tips > Source: https://docs.recombee.com/integration_tips > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Content Recommendations](#integration-tips-content) * [Videos](#integration-tips-content-videos) * [Items Catalog](#items-catalog) * [Modeling Series](#modeling-series) * [Interactions](#interactions) * [Scenarios](#scenarios) * [News & Articles](#integration-tips-content-articles) * [Items Catalog](#id2) * [Interactions](#id3) * [Scenarios](#id4) * [Music & Podcasts](#integration-tips-content-music-and-podcasts) * [Items Catalog](#id7) * [Interactions](#id8) * [Setting Up Recommendations](#id9) * [Scenarios](#id10) * [Songs / Podcasts for You](#songs-podcasts-for-you) * [New Releases](#new-releases) * [Trending Songs / Podcasts](#trending-songs-podcasts) * [Related Songs or Podcasts](#related-songs-or-podcasts) * [Top Artists / Podcasters for You](#integration-tips-top-artists-for-the-user) * [Related Artists / Podcasters](#related-artists-podcasters) * [Top Albums for You](#top-albums-for-you) * [Product Recommendations](#integration-tips-product) * [Items Catalog](#id11) * [Handling Variants](#handling-variants) * [Interactions](#id12) * [Scenarios](#id14) * [Real Estate Recommendations](#integration-tips-real-estate) * [Items Catalog](#id17) * [Interactions](#id18) * [Setting Up Recommendations](#id19) * [Scenarios](#id20) * [Properties in User-Specified Area](#properties-in-user-specified-area) * [Properties in a Geolocation](#properties-in-a-geolocation) * [Similar Properties](#similar-properties) * [Homepage for Registered Users](#homepage-for-registered-users) * [Email](#id21) * [Search](#id22) * [Paginated Recommendations](#paginated-recommendations) # Integration Tips Thanks to the versatility of our solution and hundreds of algorithms in our stack Recombee can be utilized in a wide variety of areas. You can use Recombee for recommending almost any type of content or product: videos, articles, fashion, real-estate, podcasts, jobs ... you name it :) ![](/img/headings/integration-tips.png) Every domain has its specifics and the following sections present some of the best practices for the correct use of our recommendation service. --- **Choose your domain** [Content Recommendationsvideos, news, articles, music, etc.](#integration-tips-content)[Product Recommendationse-commerce, classified advertising, etc.](#integration-tips-product)[Real Estate Recommendationshouses, apartments, land etc. for sale or rent](#integration-tips-real-estate) --- ## Content Recommendations [Videos](#integration-tips-content-videos)[News & Articles](#integration-tips-content-articles)[Music & Podcasts](#integration-tips-content-music-and-podcasts) ### Videos ![](/img/integration_tips/videos.png) #### Items Catalog * Each video (movie, series, asset) should be an _item_ in Recombee * Typical [item properties](/getting_started#getting-started-catalog) are for example: * title \[`string`\] * categories/genres \[`set`\] * description \[`string`\] * languages \[`set`\] * image \[`image`\] - for example a poster * cast \[`set`\] * tags \[`set`\] * year \[`int`\] * availability \[`boolean`\] * minimal age of viewer \[`int`\] * available since \[`timestamp`\] * date of expiration \[`timestamp`\] * is subscription needed \[`boolean`\] - for determining if the item is available for a particular user * type \[`string`\] - determines if the item is a _movie_, _series_, _episode_, etc. ##### Modeling Series Items in the catalog may be organized into [**Series**](/api#series), expressing an explicit, known ordering of items where applicable. Typical examples of series include consecutive TV show episodes, book titles, or podcast episodes. The hierarchy can be either **one-level** (_series → episodes_) or **multi-level** (_series → seasons → episodes_), depending on the structure of your content. ![](/img/integration_tips/series-schema.png) * **Step 1: Upload episodes and series as Items** Model every **episode**, **season**, and **series** as an _Item_ with the appropriate item properties (e.g., title, director, release date, etc.). * **Step 2: Set hierarchy** Use the [Insert to Series](/api#insert-to-series) endpoint to organize the Items into a series hierarchy. * For a **series → season** link, set [itemType](/api#insert-to-series-param-itemType) \= `series`. * For a **series/season → item** link, set [itemType](/api#insert-to-series-param-itemType) \= `item`. * The [time](/api#insert-to-series-param-time) parameter defines the ordering within the series and should correspond to the season or episode number. **Example:** * _For each season_: ``` InsertToSeries (seriesId = "", itemType = "series", itemId = "", time = "") ``` * _For each episode_: ``` InsertToSeries (seriesId = "", itemType = "item", itemId = "", time = "") ``` The [Video Logics](/recommendation_logics#video) have built-in support for handling Series (e.g., recommending newly published episodes, recommending next episode, etc.). #### Interactions * Send a [detail view](/api#request-add-detail-view) whenever a user clicks a video thumbnail * Set a few important milestones in the video (e.g. 15%, 50%, 75%) and send a [view portion](/api#request-set-view-portion) whenever the user watches the video until a milestone * It is very common to send a [purchase](/api#request-add-purchase) when you consider the movie to be consumed by the user (e.g. the user watched it until 90%) * If users can bookmark or rate the items, send[bookmarks](/api#request-add-bookmark) and[ratings](/api#request-add-rating) * Likes should be modeled as positive[ratings](/api#request-add-rating) (e.g. with rating `1.0`) Don't forget to provide the _recommId_ parameter if the interaction is based on the recommendations. It will[give you very precise insight](/admin_ui#success-metrics-kpi) into the success of the recommendations in the Admin UI. #### Scenarios [Video RecipesDiscover how to personalize various use cases within your video platform.](/recipes/video) ### News & Articles ![](/img/integration_tips/news_articles.png) #### Items Catalog * Each article should be an _item_ in Recombee * Typical[item properties](/getting_started#getting-started-catalog) are for example: * title \[`string`\] * categories \[`set`\] * tags \[`set`\] * published \[`boolean`\] * url \[`string`\] * lead paragraph \[`string`\] * image \[`image`\] * expire date \[`timestamp`\] * is paid content \[`boolean`\] * author \[`string`\] #### Interactions * Send a [detail view](/api#request-add-detail-view) whenever a user opens an article. * If users can rate the items, send[ratings](/api#request-add-rating). Likes should be modeled as positive[ratings](/api#request-add-rating) (e.g. with rating `1.0`). * Don't forget to provide the _recommId_ parameter if the interaction is based on the recommendations. It will[give you very precise insight](/admin_ui#success-metrics-kpi) into the success of the recommendations in the Admin UI. * Optional enhancement: Set a few important milestones in the article (e.g. 30%, 50%, 75%) and send a[view portion](/api#request-set-view-portion) whenever the user reads (scrolls) up to the portion #### Scenarios [News RecipesDiscover how to personalize various use cases within your news platform.](/recipes/news) ### Music & Podcasts ![](/img/integration_tips/songs.png) #### Items Catalog * Each song should be an _item_ in Recombee * Typical[item properties](/getting_started#getting-started-catalog) are for example: * title \[`string`\] * artist \[`string`\] * genre \[`string`\] * featured artists \[`set`\] * labels \[`set`\] * album title \[`string`\] * album cover \[`image`\] * country \[`string`\] * release date \[`timestamp`\] * is explicit \[`boolean`\] * duration \[`int`\] #### Interactions * Set a few important milestones in the song (e.g. 15%, 50%, 75%, 100%) and send a[view portion](/api#request-set-view-portion) whenever the user listens to the song until a milestone * Send us [ratings](/api#request-add-rating)with the _rating_ set to `1.0` for liked songs * Send us [ratings](/api#request-add-rating)with the _rating_ set to `-1.0` for disliked songs #### Setting Up Recommendations * Create a [scenario](/scenarios) for each place you want to show the recommendations. * Set [filters](/reql) to the scenarios: At least a filter for recommending only available items should be set. If the availability is based on the release date, the filter can look like this: ReQL ``` 'release_date' < now() ``` In many cases, you also need to show only appropriate content to minors. If you set a[user property](/api#user-properties) `is_minor` to _true_ for the minors, then the filter can look like this: ReQL ``` if context_user["is_minor"] then not 'is_explicit' else true ``` Such filter rules can be added to the[Global Settings](/scenarios#scenarios-in-admin-ui-global-settings), so they are applied to all your scenarios. #### Scenarios * Create a [scenario](/scenarios) for each place you want to show the recommendations. ##### Songs / Podcasts for You To obtain a personalized list of the top songs or podcasts for a user call the[Recommend Items To User](/api#request-recommend-items-to-user) endpoint with the _recombee:personal_ [Logic](/recommendation_logics). ##### New Releases To obtain a personalized list of the recently added songs or podcasts that shall be interesting for the user, call the[Recommend Items To User](/api#request-recommend-items-to-user) endpoint with the _recombee:personal_ [Logic](/recommendation_logics) and add the_Recent items_ [predefined Filter rule](scenarios#filters). ##### Trending Songs / Podcasts To obtain songs or podcasts that are currently globally popular, use[Recommend Items To User](/api#request-recommend-items-to-user) endpoint with the _recombee:popular_ [Logic](/recommendation_logics). * You can choose what time period will be taken into consideration when evaluating the most popular songs using the_timePeriod_ parameter of the Logic (value is in seconds) * The currently popular content can often vary in different countries. If you upload the user's _country_ as the[user property](/api#user-properties), you can get the content popular among users from the same country by setting _userSegmentFilter_ parameter of the Logic to: ReQL ``` 'country' == context_user["country"] ``` ##### Related Songs or Podcasts In order to obtain songs that are related to a particular song, call the[Recommend Items To User](/api#request-recommend-items-to-user) endpoint with the _recombee:similar_ [Logic](/recommendation_logics). You can use these songs e.g. for the autoplay, so it keeps the mood of the song the user is currently listening to. ##### Top Artists / Podcasters for You Based on the listened songs, Recombee can recommend interesting artists for the user. * First, create an[Item Segmentation](/segmentations) on the [item property](/getting_started#getting-started-catalog) that contains the primary artist * Then go to the [Scenarios](/segmentations) section and create a scenario of the[Recommend Item Segments To User](/api#request-recommend-item-segments-to-user) type based on the created _artists_Segmentation Requesting this scenario will give you the artists that shall be the most interesting for a particular user. ##### Related Artists / Podcasters You can show the related artists on an artist's detail page. * If you don't have an[Item Segmentation](/segmentations)based on the primary artist yet, create one * Then go to the [Scenarios](/segmentations) section and create a scenario of the[Item Segments To Item Segment](/api#request-recommend-item-segments-to-item-segment) with both Context and Result Segmentations set to the_artists_ Segmentation Requesting this scenario with _segmentId_ set to a particular artist will give you the artists related to that artist. ##### Top Albums for You Based on the listened songs, Recombee can recommend albums that shall be interesting for the user. * First, create an[Item Segmentation](/segmentations) on the [item property](/getting_started#getting-started-catalog) that contains the album title or ID * Then go to the [Scenarios](/segmentations) section and create a scenario of the[Recommend Item Segments To User](/api#request-recommend-item-segments-to-user) type based on the created _albums_Segmentation Request this scenario to get the top albums for the user. ## Product Recommendations ![](/img/integration_tips/product.png) ### Items Catalog * Each product that you want to recommend should be an _item_ in Recombee. * Typical[item properties](/getting_started#getting-started-catalog) are for example: * title \[`string`\] * image link \[`image`\] * available \[`boolean`\] * categories \[`set`\] * price \[`double`\] * url \[`string`\] * brand / vendor \[`string`\] * on sale \[`boolean`\] Then there are various segment-specific properties, for example in fashion: > * gender \[`string`\] > * material \[`string`\] > * color \[`string`\] > * available sizes \[`set`\] Tip You can set a [catalog feed](/catalog_feeds) (e.g. Google Merchant Feed) in the Admin UI for products catalog synchronization #### Handling Variants * If your products come in multiple variants (sizes, colors), the preferred representation in most cases is to have the master product as an item in Recombee and send interactions to it from pages of all its variants. * If you want to ensure compatibility of available product sizes and user's preferred sizes, model both as item/user properties and use filter like this one: ReQL ``` context_user["sizes"] == null OR size('available_sizes' & context_user["sizes"]) > 0 ``` * In the case of having each variant as an item in Recombee, the recommendations will also work, but it may take longer to train the models properly at lower traffic sites as the number of interactions is divided between all the variants. ### Interactions * Send a [detail view](/api#request-add-detail-view) whenever a user views a detail page of a product * Send a [cart addition](/api#request-add-cart-addition) whenever a user adds a product into the cart * Send a [purchase](/api#request-add-purchase) whenever a user buys a product. * There will be an[Add Purchase request](/api#request-add-purchase) per each product in the ordered cart. Optionally, these requests can be sent inside a single[Batch request](/api#request-batch). * Set the `price` parameter to see revenue based on recommendations in the [Admin UI](/admin_ui). * If users can bookmark or rate the items, send[bookmarks](/api#request-add-bookmark) and[ratings](/api#request-add-rating) * It is suggested to provide the _recommId_ parameter if the interaction is based on the recommendations. It will [give you very precise insight](/admin_ui#success-metrics-kpi) into the success of the recommendations in the Admin UI. ### Scenarios [E-commerce RecipesDiscover how to personalize various use cases within your e-commerce site.](/recipes/e-commerce) ## Real Estate Recommendations ![](/img/integration_tips/real_estate.png) ### Items Catalog * Each property (building, apartment, ...) that you want to recommend should be an _item_ in Recombee. * Typical[item properties](/getting_started#getting-started-catalog) are for example: * title \[`string`\] * image link \[`image`\] * available \[`boolean`\] * url \[`string`\] * state \[`string`\] * city \[`string`\] * neighborhood \[`string`\] * zip code \[`string`\] * latitude \[`double`\] * longitude \[`double`\] * price \[`double`\] * description \[`string`\] * square feet \[`int`\] * number of bedrooms \[`int`\] * number of bathrooms \[`int`\] * parking spaces \[`int`\] * pets allowed \[`boolean`\] * year built \[`int`\] * type \[`string`\] - _apartment_ / _family house_ / _condo_ / ... * amenities \[`set`\] - e.g. _air condition_, _balcony_, _fire place_, _swimming pool_ ... ### Interactions * Send a [detail view](/api#request-add-detail-view) whenever a user views a detail page of a property * Send a [bookmark](/api#request-add-bookmark) whenever a user bookmarks a property * Send a [purchase](/api#request-add-purchase) when a user expresses a strong interest in the particular property - e.g. makes an offer or books a tour. * Don't forget to provide the _recommId_ parameter if the interaction is based on the recommendations. It will[give you very precise insight](/admin_ui#success-metrics-kpi) into the success of the recommendations in the Admin UI. ### Setting Up Recommendations * Create a [scenario](/scenarios) for each place you want to show the recommendations. * Into the [Global Settings](/scenarios#scenarios-in-admin-ui-global-settings) add a filter to allow only available properties to be recommended. You can pick predefined rule _Available items_ from the _Recombee Business Rules Library_. ### Scenarios #### Properties in User-Specified Area * After a user inserts the area where the user is looking for a property the best deals for the user in the area will be delivered by Recombee * Use[Recommend Items To User](/api#request-recommend-items-to-user) endpoint with _recombee:homepage_ [Logic](/recommendation_logics) in that case * The area inserted by the user should be sent in the `filter`parameter of the[Recommend Items To User request](/api#request-recommend-items-to-user) in order to allow only properties from the particular area. It can look like: ReQL ``` 'state'=="TX" and 'city'=="Austin" ``` * Alternatively, you can store the user's area to Recombee as[user properties](/api#user-properties), and use filter like: ReQL ``` 'state' == context_user["state"] and 'city' == context_user["city"] ``` #### Properties in a Geolocation * If the user browses a map, you can show (or highlight) the most fitting properties for the user (according to the user's past interactions). * Use[Recommend Items To User](/api#request-recommend-items-to-user) endpoint with _recombee:personal_ [Logic](/recommendation_logics) * Set the request's `filter` parameter to allow only properties in the map radius. You can use [earth\_distance](/reql_functions#reql-func-earth-distance) ReQL function to achive this. ReQL ``` earth_distance('latitude', 'longitude', , < centre of the map longitude> ) < ``` #### Similar Properties * Use[Recommend Items To Item](/api#request-recommend-items-to-item) with _recombee:similar_ [Logic](/recommendation_logics) * You may want to apply predefined _Upsell_ rule from the[Recombee Business Rules Library](/scenarios#filters) to prefer items that are a bit more expensive than the one that is currently viewed by the user. #### Homepage for Registered Users * Use[Recommend Items To User](/api#request-recommend-items-to-user) endpoint with _recombee:homepage_ [Logic](/recommendation_logics) * If the user has already interactions, properties in the user's location should be picked by Recombee. You can (especially for new users) ensure it by `filters` or `boosters`. #### Email * Use[Recommend Items To User](/api#request-recommend-items-to-user) endpoint with _recombee:emailing_ [Logic](/recommendation_logics) * If the user has already interactions, properties in the user's location should be picked by Recombee. You can ensure it by setting`filters` or `boosters`. * If the user set some custom conditions, e.g. minimal number of bedrooms or maximal price, you can also express these as a filter: ReQL ``` 'num_bedrooms' >= 2 and 'price' < 10000 ``` #### Search * Use the [Search](/api#search) endpoint and let your users search the properties in a personalized way * You can also apply `filters` or `boosters` \- e.g. search only within an area using[earth\_distance](/reql_functions#reql-func-earth-distance) ReQL function. ## Paginated Recommendations If you want to get subsequent recommendations for the next page of results, call[Recommend next items](/api#request-recommend-next-items) endpoint. --- # Item Segmentations > Source: https://docs.recombee.com/segmentations > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [A Step-by-Step Video Tutorial on Item Segmentations](#a-step-by-step-video-tutorial-on-item-segmentations) * [Creating an Item Segmentation](#creating-segmentation) * [Property-Based Segmentation](#property-based-segmentation) * [Examples](#property-based-examples) * [Example 1](#example-1) * [Example 2](#example-2) * [Creating in the Admin UI](#creating-in-the-admin-ui) * [Creating via the API](#creating-via-the-api) * [Recommending Segments](#recommending-segments) * [Requesting Recommendations](#requesting-recommendations) * [Filtering and Boosting](#filtering-and-boosting) * [Advanced Options for Creating the Segmentations](#advanced-creating-segmentations) * [Manual ReQL Segmentation](#manual-reql-segmentation) * [Example](#example) * [Creating in the Admin UI](#id2) * [Creating via the API](#id3) * [Auto ReQL Segmentation](#auto-reql-segmentation) * [Examples](#id4) * [Example 1](#id5) * [Example 2](#id6) * [Example 3](#example-3) * [Creating in the Admin UI](#id7) * [Creating via the API](#id8) # Item Segmentations _Item Segmentation_ is an abstraction on top of the catalog of Items. It allows you to group the Items into Segments based on their properties. _The Segments_ can be then recommended to your users. ![](/img/headings/segmentations.png) It is common to Segment the Items by: * **category** or **brand** in the case of products * **genre** in the case of movies * **artist** in the case of songs * belonging to particular **homepage rows** \- see[this section](#advanced-creating-segmentations) for other advanced use cases [Recommend Item Segments To User](/api#request-recommend-item-segments-to-user)can be then used to recommend the[top brands](/recipes/e-commerce/fully-personalized-homepage/brands-for-you) /[top artists or actors](/recipes/video/fully-personalized-homepage/actors-for-you) /[top categories or genres](/recipes/video/fully-personalized-homepage/personalized-re-ordering-of-rows-advanced) for a particular user. It is also possible to get[related Segments to a particular item](/api#request-recommend-item-segments-to-item) (e.g. brands related to a product, artists related to a song),[Segments related to another Item Segment](/api#request-recommend-item-segments-to-item-segment) (e.g. artists similar to a particular artist, brands related to a brand), or [search within the Segments](/api#request-search-item-segments) (search brands, artists, etc. with a search query). ## A Step-by-Step Video Tutorial on Item Segmentations ## Creating an Item Segmentation There are multiple ways a Segmentation can be defined. The most frequently used and the easiest to set up is Property-based Segmentation. See this section for info on [more advanced options for creating the Segmentations](/segmentations#advanced-creating-segmentations). ### Property-Based Segmentation Property-based Segmentation groups the Items by the value of a particular property. The property can be of `string` or `set` type. `NULL` values are ignored. #### Examples Consider the following data about the Items: ![](/img/segmentations/segmentations_examples_items.png) ##### Example 1 Segmentation based on the _country_property (of type `string`) will create the following three Segments: ![](/img/segmentations/segmentations_examples_county_property.png) For example, the value of the _country_property for the _it\_crowd_ is `GB`, and therefore the _it\_crowd_ belongs to the`GB` Segment. ##### Example 2 Segmentation based on the _genres_ property (of type `set`) will create the following three Segments: ![](/img/segmentations/segmentations_examples_genres_property.png) Note that an Item can belong to multiple Segments: In that case, _the\_silence\_of\_the\_lambs_ belongs to both`Horror` and `Thriller` Segments. #### Creating in the Admin UI [![You can create the Property-based Segmentation in the Admin UI by picking the name of the property](/img/segmentations/admin_ui_property_based.png)](/img/segmentations/admin_ui_property_based.png) You can create the Property-based Segmentation in the Admin UI by picking the name of the property * Navigate to the _Segmentations_ section * Create a new Segmentation of the _Property-based_ type and select by which Item property the Items shall be segmented. * Check the preview of the resulting Segments and confirm the setup #### Creating via the API * Call the [Create Property Based Segmentation](/api#request-create-property-based-segmentation) endpoint. --- ## Recommending Segments ### Requesting Recommendations The Segments can be recommended or searched using the following endpoints: * [Recommend Item Segments To User](/api#request-recommend-item-segments-to-user) * [Recommend Item Segments To Item](/api#request-recommend-item-segments-to-item) * [Recommend Item Segments To Item Segment](/api#request-recommend-item-segments-to-item-segment) * [Search Item Segments](/api#request-search-item-segments%3E) Before you can use any of that endpoints, you need to[create an Item Segmentation](segmentations#creating-segmentation) and then set up a[Scenario](/scenarios) in the Admin UI which will use that Segmentation. [![Create a Scenario which returns Segments](/img/segmentations/admin_ui_scenario_type.png)](/img/segmentations/admin_ui_scenario_type.png) Create a Scenario which returns Segments [![Choose the Segmentation which shall be used in the Scenario](/img/segmentations/admin_ui_scenario_choose_segmentation.png)](/img/segmentations/admin_ui_scenario_choose_segmentation.png) Choose the Segmentation which shall be used in the Scenario The ID of that Scenario needs to be provided in the `scenario` parameter of the recommendation request: ```js const recommended = await client.send( new recombee.RecommendItemSegmentsToUser('2c169e', 5, { scenario: 'top_categories', cascadeCreate: true, }), ); ``` ```python recommended = client.send(RecommendItemSegmentsToUser('2c169e', 5, scenario='top_categories', cascade_create=True)) ``` ```ruby recommended = client.send(RecommendItemSegmentsToUser.new('2c169e', 5, { 'scenario' => 'top_categories', 'cascadeCreate' => true }) ) ``` ```java RecommendationResponse recommended = client.send(new RecommendItemSegmentsToUser("2c169e", 5)) .setScenario("top_categories") .setCascadeCreate(true); ``` ```php $recommended = $client -> send(new Reqs\RecommendItemSegmentsToUser('2c169e', 5, [ 'scenario' => 'top_categories', 'cascadeCreate' => true ]) ); ``` ```csharp RecommendationResponse recommended = client.Send(new RecommendItemSegmentsToUser("2c169e", 5, scenario: "top_categories", cascadeCreate: true)); ``` ```js const recommended = await client.send( new rqs.RecommendItemSegmentsToUser('2c169e', 5, { scenario: 'top_categories', cascadeCreate: true, }), ); ``` ```http GET /myDb/recomms/users/2c169e/item-segments/?count=10&scenario=top_categories&cascadeCreate=true ``` These are some examples of how recommending Segments can be used on your website or in your app: * [Recommending the top genres/categories for a user, and re-ordering homepage rows accordingly](/recipes/video/fully-personalized-homepage/personalized-re-ordering-of-rows-advanced) * [Recommending the top brands for a user](/recipes/e-commerce/fully-personalized-homepage/brands-for-you) * [Recommending the top artists or actors for a user](/recipes/video/fully-personalized-homepage/actors-for-you) ### Filtering and Boosting Recommended Segments can be [filtered or boosted using ReQL](reql). You can access the ID of a Segment in ReQL using `'segmentId'`. **Examples of filters:** * Do not recommend the _coupons_ category to the users ReQL ``` 'segmentId' != "coupons" ``` * Do not recommend horror movies to kids ReQL ``` if context_user["is_child_profile"] then 'segmentId' != "Horror" else true ``` **Example of a booster:** * Boosting the _Editors Pick_ section ReQL ``` if 'segmentId' == "Editors Pick" then 2 else 1 ``` ## Advanced Options for Creating the Segmentations ### Manual ReQL Segmentation With Manual ReQL Segmentation, you specify individual Segments of the Segmentation. Each Segment is defined by a [ReQL](/reql) filter: Items passing the filter belong to the Segment. #### Example Consider the same data about the Items as in [this section](/segmentations#property-based-examples). You can create an Item Segmentation where each Segment will represent one row on the homepage. With defined Segments as follows: ![](/img/segmentations/definition_manual_segmentation.png) Items get segmented in this way: ![](/img/segmentations/segmentations_examples_manual_segmentation.png) You will get the optimal order of these homepage rows for the particular user by calling the[Recommend Item Segments To User](/api#request-recommend-item-segments-to-user)endpoint. #### Creating in the Admin UI [![You can create individual Segments of the Manual ReQL Segmentation in the Admin UI](/img/segmentations/admin_ui_manual_reql.png)](/img/segmentations/admin_ui_manual_reql.png) You can create individual Segments of the Manual ReQL Segmentation in the Admin UI * Navigate to the _Segmentations_ section * Give the Segmentation a title, which gets translated into the Segmentation ID, and optionally also give a description * Create the first Segment by giving it a name (which gets again translated into the Segment's ID) and providing the [ReQL](/reql) filter * You can check which Items belong to the Segment by clicking on _Preview items_ * Click _Add Segment_ to add another Segment * When satisfied with the setup, click _Create_ to confirm it #### Creating via the API * First, create an empty Segmentation using[Create Manual ReQL Segmentation](/api#request-create-manual-reql-segmentation) * Then, add the individual Segments using[Add Manual ReQL Segment](/api#request-add-manual-reql-segment) ### Auto ReQL Segmentation Auto ReQL Segmentation is specified by a [ReQL](/reql) expression that for each Item returns a **set of Segments** to which the Item belongs. The individual Segments don't need to be predefined in any way. #### Examples ##### Example 1 The following expression returns the set of _genres_: ReQL ``` 'genres' ``` For example, for _johnny\_english_ it returns `{"Comedy"}` and for _the\_silence\_of\_the\_lambs_ it returns`{"Horror", "Thriller"}`. Therefore it behaves the same as the[Property-based Segmentation](/segmentations#property-based-segmentation) using the _genres_ property: ![](/img/segmentations/segmentations_examples_auto_genres.png) ##### Example 2 The following Segmentation put the Items into Segments according to their _genres_ and also adds a`Critically Acclaimed` Segment for items with`'critically_acclaimed' == true`. ReQL ``` 'genres' + (if 'critically_acclaimed' then {"Critically Acclaimed"} else {}) ``` For example, for _johnny\_english_ it returns `{"Comedy"}`, for _friends_ it returns `{"Comedy", "Critically Acclaimed"}`, and for _the\_silence\_of\_the\_lambs_ it returns `{"Horror", "Thriller", "Critically Acclaimed"}`. ![](/img/segmentations/segmentations_examples_auto_genres_acclaimed.png) ##### Example 3 The Segments of the following Segmentation are a combination of the Item's _genres_ and _country_ (British comedies, US thrillers, etc.). ReQL ``` map(lambda 'genre': 'genre' + "-" + 'country', 'genres') ``` For example, for _johnny\_english_ it returns `{"Comedy-GB"}`, for _friends_ it returns `{"Comedy-US"}`, and for _the\_silence\_of\_the\_lambs_ it returns`{"Horror-US", "Thriller-US"}`. ![](/img/segmentations/segmentations_examples_auto_genre_country.png) #### Creating in the Admin UI [![You can specify the ReQL expression for the Auto ReQL Segmentation in the Admin UI](/img/segmentations/admin_ui_auto_reql.png)](/img/segmentations/admin_ui_auto_reql.png) You can specify the ReQL expression for the Auto ReQL Segmentation in the Admin UI * Navigate to the _Segmentations_ section * Create a new Segmentation of the _Auto ReQL_ type * Give the Segmentation a title, which gets translated into the Segmentation ID, and optionally also give a description * Provide the [ReQL](/reql) expression which returns a set of Segments to which an Item belongs * Check the preview of the resulting Segments and confirm the setup #### Creating via the API * Call the[Create Auto ReQL Segmentation](/api#request-create-auto-reql-segmentation)endpoint. --- # Tutorial > Source: https://docs.recombee.com/tutorial > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Server Side - Interactions & Recommendations](#tutorial-interactions-recommendations) * [Video Tutorial](#video-tutorial) * [Source Codes](#source-codes) * [Text Tutorial](#text-tutorial) * [Sending Interactions](#sending-interactions) * [Recommending Items to User](#recommending-items-to-user) * [Recommending Items to Item](#recommending-items-to-item) * [Recommending Users to Item](#recommending-users-to-item) * [Server Side - Uploading Items Catalog](#tutorial-catalog) * [Source Codes](#id2) * [Text Tutorial](#id3) * [Defining Item Properties](#defining-item-properties) * [Setting Item Values](#setting-item-values) * [ReQL Filtering](#tutorial-reql) * [Source Codes](#id4) * [Text Tutorial](#id5) * [JavaScript Integration](#javascript-integration) # Tutorial [Interactions & recommendationsServer side](#tutorial-interactions-recommendations)[Uploading items catalogServer side](#tutorial-catalog)[ReQL filteringRestrictions on the recommended items](#tutorial-reql) ## Server Side - Interactions & Recommendations The first part of the tutorial covers sending interactions to the system and getting recommendations based on them. ### Video Tutorial ### Source Codes [Python](/files/tutorial/1/tutorial1.py)[Java](/files/tutorial/1/tutorial1.java)[Ruby](/files/tutorial/1/tutorial1.rb)[PHP](/files/tutorial/1/tutorial1.php)[C#](/files/tutorial/1/tutorial1.cs)[Node.js](/files/tutorial/1/tutorial1.js) ### Text Tutorial #### Sending Interactions Suppose that I run a website which offers tickets to cultural events and I already have some collected data from the past - namely views of the events and purchases of the tickets by the users. For simplicity, I have the interactions in two .json files with the same structure. JSON ``` purchases.json: [ {"user_id": "user-50", "item_id": "event-276", "timestamp": "2016-04-20T12:50:42+02:00"}, {"user_id": "user-389", "item_id": "event-73", "timestamp": "2014-07-20T02:49:45+02:00"}, {"user_id": "user-204", "item_id": "event-116", "timestamp": "2015-04-22T13:32:32+02:00"}, ... ] detail_views.json: [ {"user_id": "user-7", "item_id": "event-12 ", "timestamp": "2016-04-20T13:25:55+02:00"}, {"user_id": "user-384", "item_id": "event-73", "timestamp": "2016-04-20T13:07:10+02:00"}, {"user_id": "user-12", "item_id": "event-113", "timestamp": "2016-04-20T12:50:42+02:00"}, ... ] ... ``` We will use [SDK](/api_clients) for communication with Recombee, as it greatly simplifies the process of the integration. I need the Recombee client, so we will import it from the already installed package. We will also import all the classes for the requests in order to spare some typing. Then, I create the instance of the client. It is initialized with the ID of my database and the secret token, which I both gained when I [created the instant account](https://admin.recombee.com/sign-up), so we will just copy and paste them from the UI at[admin.recombee.com](https://admin.recombee.com). ```python from recombee_api_client.api_client import RecombeeClient from recombee_api_client.api_requests import * client = RecombeeClient('events-example', 'PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G') ``` ```java RecombeeClient client = new RecombeeClient("events-example", "PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G"); ``` ```ruby require 'recombee_api_client' include RecombeeApiClient client = RecombeeClient.new('events-example', 'PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G') ``` ```php use Recombee\RecommApi\Client; use Recombee\RecommApi\Requests as Reqs; use Recombee\RecommApi\Exceptions as Ex; $client = new Client('events-example', 'PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G'); ``` ```csharp using Recombee.ApiClient; using Recombee.ApiClient.ApiRequests; using Recombee.ApiClient.Bindings; var client = new RecombeeClient("events-example", "PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G"); ``` ```js var recombee = require('recombee-api-client'); var rqs = recombee.requests; var client = new recombee.ApiClient('events-example', 'PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G'); ``` Now, I want to upload some interactions to the recommender system. We will start by reading and the purchases from the json file and creating an [AddPurchase](/api#request-add-purchase)request object for each purchase in the file. It takes two mandatory parameters - the `userId` and the `itemId`. We will set the optional parameter `timestamp` to `time`, because the default value is the current time, but I want a particular time from past. And we will also set `cascadeCreate` to `true` in order to create in the system the yet non existing items and users. ```python from recombee_api_client.api_client import RecombeeClient from recombee_api_client.api_requests import * import json client = RecombeeClient('events-example', 'PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G') requests = [] with open('purchases.json') as f: interactions = json.loads(f.read()) for interaction in interactions: r = AddPurchase(interaction['user_id'], interaction['item_id'], timestamp=interaction['timestamp'], cascade_create=True) ``` ```java RecombeeClient client = new RecombeeClient("events-example", "PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G"); JSONParser parser = new JSONParser(); try { JSONArray a = (JSONArray) parser.parse(new FileReader("purchases.json")); for (Object o : a) { JSONObject interaction = (JSONObject) o; Date time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX").parse((String)interaction.get("timestamp")); Request r = new AddPurchase((String) interaction.get("userId"), (String) interaction.get("itemId")) .setTimestamp(time).setCascadeCreate(true); } } catch (org.json.simple.parser.ParseException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } ``` ```ruby require 'json' client = RecombeeClient.new('events-example', 'PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G') file = File.read('purchases.json') JSON.parse(file).each do |interaction| user_id = interaction['user_id'] item_id = interaction['item_id'] time = interaction['timestamp'] r = AddPurchase.new(user_id, item_id, 'timestamp' => time, 'cascadeCreate' => true) end ``` ```php $client = new Client('events-example', 'PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G'); $str = file_get_contents('purchases.json'); foreach(json_decode($str, true) as $interacion) { $user_id = $interacion['user_id']; $item_id = $interacion['item_id']; $time = $interacion['timestamp']; $r = new Reqs\AddPurchase($user_id, $item_id, ['timestamp' => $time, 'cascadeCreate' => true]); } ``` ```csharp var client = new RecombeeClient("events-example", "PbBaEVxx8ZOj0x3BhGtqfHyi8qQ8rm8rE1JBnSPoCnHwetzO3gjHer96YVAIa14G"); string[] allLines = File.ReadAllLines(@"purchases.csv"); var parsed = from line in allLines let row = line.Split(',') select new { UserId = row[0], ItemId = row[1], Timestamp = DateTime.Parse(row[2], null, System.Globalization.DateTimeStyles.RoundtripKind) }; var purchases = parsed.Select(x => new AddPurchase(x.UserId, x.ItemId, timestamp: x.Timestamp, cascadeCreate: true)); ``` ```js var interactions = require('./purchases.json'); var requests = interactions.map((interaction) => { var userId = interaction['user_id']; var itemId = interaction['item_id']; var time = interaction['timestamp']; return new rqs.AddPurchase(userId, itemId, {timestamp: time, cascadeCreate: true}); }); ``` I could send the purchases one by one, using the send method of the client. ```python client.send(r) ``` ```java client.send(r); ``` ```ruby client.send(r) ``` ```php $client->send($r); ``` ```csharp foreach(AddPurchase purchase in purchases) client.Send(purchase); ``` ```js purchases.forEach((purchase) => client.send(purchase)); ``` Sending individual requests is very beneficial when you have the recommender already deployed in production as the system can immediately modify its recommendations using the just received interaction. But uploading larger data from the past with individual requests would be quite slow, so for sending the list of purchases we will use the [Batch](/api#request-batch) request, which can encapsulate many requests into a single request. ```python requests = [] with open('purchases.json') as f: interactions = json.loads(f.read()) for interaction in interactions: r = AddPurchase(interaction['user_id'], interaction['item_id'], timestamp=interaction['timestamp'], cascade_create=True) requests.append(r) br = Batch(requests) client.send(br) ``` ```java ArrayList interactions = new ArrayList<>(); try { ... Request r = new AddPurchase((String) interaction.get("userId"), (String) interaction.get("itemId")) .setTimestamp(time).setCascadeCreate(true); interactions.add(r); ... } ... client.send(new Batch(interactions)); ``` ```ruby interactions = [] file = File.read('purchases.json') JSON.parse(file).each do |interaction| user_id = interaction['user_id'] item_id = interaction['item_id'] time = interaction['timestamp'] r = AddPurchase.new(user_id, item_id, 'timestamp' => time, 'cascadeCreate' => true) interactions.push(r) end br = Batch.new(interactions) client.send(br) ``` ```php $requests = array(); $str = file_get_contents('purchases.json'); foreach(json_decode($str, true) as $interacion) { $user_id = $interacion['user_id']; $item_id = $interacion['item_id']; $time = $interacion['timestamp']; $r = new Reqs\AddPurchase($user_id, $item_id, ['timestamp' => $time, 'cascadeCreate' => true]); array_push($requests, $r); } $br = new Reqs\Batch($requests); $client->send($br); ``` ```csharp client.Send(new Batch(purchases)); ``` ```js client.send(new rqs.Batch(requests), (err, responses) => { console.log(responses); }); ``` Now let's run the script and see the result in the Admin UI. You should see the uploaded items in the _Catalog listing_. You can also check interactions of an item by clicking its id. [![Items in the catalog listing](/img/tutorial/1/catalog1.png)](/img/tutorial/1/catalog1.png) Now I'll change the code to send the detail views by changing the name of file with interactions (_purchases.csv_ to _detail\_views.csv_ ) and the name of the class from _AddPurchase_ to[AddDetailView](/api#request-add-detail-view). ```python r = AddDetailView(interaction['user_id'], interaction['item_id'], timestamp=interaction['timestamp'], cascade_create=True) ``` ```java Request r = new AddDetailView((String) interaction.get("userId"), (String) interaction.get("itemId")) .setTimestamp(time).setCascadeCreate(true); ``` ```ruby r = AddDetailView.new(user_id, item_id, 'timestamp' => time, 'cascadeCreate' => true) ``` ```php $r = new Reqs\AddDetailView($user_id, $item_id, ['timestamp' => $time, 'cascadeCreate' => true]); ``` ```csharp var detailViews = parsed.Select(x => new AddDetailView(x.UserId, x.ItemId, timestamp: x.Timestamp, cascadeCreate: true)); ``` ```js return new rqs.AddDetailView(userId, itemId, {timestamp: time, cascadeCreate: true}); ``` After running the changed code, detail views should appear in the interface. [![Interactions in the catalog listing](/img/tutorial/1/catalog2.png)](/img/tutorial/1/catalog2.png) You can also see the visualization in the _KPI console_, which is updated up to every few minutes. [![Interactions in the KPI](/img/tutorial/1/kpi1.png)](/img/tutorial/1/kpi1.png) #### Recommending Items to User Now it's time to get some recommendations based on the uploaded interactions. Suppose that _user-27_ just came to my website. I want to immediately show him 5 events that he will most likely favor. I'll use the[RecommendItemsToUser](/api#request-recommend-items-to-user) for this task. ```python recommended = client.send(RecommendItemsToUser('user-27', 5)) print(recommended) ``` ```java RecommendationResponse recommended = client.send(new RecommendItemsToUser("user-27", 5)); for(Recommendation rec: recommended) System.out.println(rec.getId()); ``` ```ruby recommended = client.send(RecommendItemsToUser.new('user-27', 5)) puts(recommended) ``` ```php $recommended = $client->send(new Reqs\RecommendItemsToUser('user-27', 5)); echo 'User based recommendation for "user-27": ' . print_r($recommended, true) . "\n"; ``` ```csharp Console.WriteLine("Recommendations for \"user-27\":"); RecommendationResponse recommended = client.Send(new RecommendItemsToUser("user-27", 5)); foreach(Recommendation rec in recommended.Recomms) Console.WriteLine(rec.Id); ``` ```js client.send(new rqs.RecommendItemsToUser('user-27', 5), (err, recommendations) => { console.log(recommendations); }); ``` An object with recommended items in field `recomms` is returned. For example: JSON ``` { "recommId": "c386301b-8f9d-4841-9b83-9e7f1f6bb463", "recomms": [ { "id": "event-5" }, { "id": "event-17" }, { "id": "event-32" }, { "id": "event-19" }, { "id": "event-92" } ] } ``` Now I can show these recommended events to _user-27_ at my homepage. #### Recommending Items to Item Let's say that the user likes the recommended events, and clicked one of them, namely _event-32_, to see the details. The page of the event contains box with related events, which are obtained by requesting the[RecommendItemsToItem](/api#request-recommend-items-to-item). The id of the user is passed in the request as well, to make the related items personalized for _user-27_. ```python recommended = client.send(RecommendItemsToItem('event-32', 'user-27', 5)) print(recommended) ``` ```java recommended = client.send(new RecommendItemsToItem("event-32", "user-27", 5)); for(Recommendation rec: recommended) System.out.println(rec.getId()); ``` ```ruby recommended = client.send(RecommendItemsToItem.new('event-32', 'user-27', 5)) puts(recommended) ``` ```php $recommended = $client->send(new Reqs\RecommendItemsToItem('event-32', 'user-27', 5)); echo 'Related items to "event-32" for "user-27": ' . print_r($recommended, true) . "\n"; ``` ```csharp Console.WriteLine("Items related to \"event-32\" for \"user-27\":"); recommended = client.Send(new RecommendItemsToItem("event-32", "user-27", 5)); foreach(Recommendation rec in recommended.Recomms) Console.WriteLine(rec.Id); ``` ```js client.send(new rqs.RecommendItemsToItem('event-32', 'user-27', 5), (err, recommendations) => { console.log(recommendations); }); ``` Returning: JSON ``` { "recommId": "a7add465-d29d-4a1b-9e38-4923378ec0b5", "recomms": [ { "id": "event-59" }, { "id": "event-19" }, { "id": "event-17" }, { "id": "event-38" }, { "id": "event-3" } ] } ``` #### Recommending Users to Item Other two supported recommendation endpoints,[RecommendUsersToItem](/api#request-recommend-users-to-item) and[RecommendUsersToUser](/api#request-recommend-users-to-user) return users instead of items. For example if I want to know which users would be most likely interested in attending_event-42_, I'll call the[RecommendUsersToItem](/api#request-recommend-users-to-item). ```python recommended = client.send(RecommendUsersToItem('event-42', 5)) print(recommended) ``` ```java recommended = client.send(new RecommendUsersToItem("event-42", 5)); for(Recommendation rec: recommended) System.out.println(rec.getId()); ``` ```ruby recommended = client.send(RecommendUsersToItem.new('event-42', 5)) puts(recommended) ``` ```php $recommended = $client->send(new Reqs\RecommendUsersToItem('event-42', 5)); echo 'Users who should be interested in "event-42": ' . print_r($recommended, true) . "\n"; ``` ```csharp Console.WriteLine("Users who should be interested in to \"event-42\":"); recommended = client.Send(new RecommendUsersToItem("event-42", 5)); foreach(Recommendation rec in recommended.Recomms) Console.WriteLine(rec.Id); ``` ```js client.send(new rqs.RecommendUsersToItem('event-42', 5), (err, recommendations) => { console.log(recommendations); }); ``` Returning: JSON ``` { "recommId": "a7add465-d29d-4a1b-9e38-4923378ec0b5", "recomms": [ { "id": "user-47" }, { "id": "user-95" }, { "id": "user-10" }, { "id": "user-50" }, { "id": "user-54" } ] } ``` As you can see sending interactions and getting recommendations is very easy, and took just few lines of code. In the next tutorial I'll show you how to send properties of the items to Recombee and how to use these properties in filtering and boosting according to your business rules. ## Server Side - Uploading Items Catalog ### Source Codes [Python](/files/tutorial/2-catalog/catalog.py)[Java](/files/tutorial/2-catalog/catalog.java)[Ruby](/files/tutorial/2-catalog/catalog.rb)[PHP](/files/tutorial/2-catalog/catalog.php)[C#](/files/tutorial/2-catalog/catalog.cs)[Node.js](/files/tutorial/2-catalog/catalog.js) ### Text Tutorial Items in the Recombee system can have many properties such as title, description, categories, price and many other. There are two possibilities how to get your items catalog into Recombee - one is setting a [catalog feed](/catalog_feeds)and the other is uploading the data from your server. This tutorial covers the second option. Let's continue with the sample company that sell tickets to cultural events from previous part of the tutorial. The events have following properties: | id | name String | city String | venue String | genres Set | date Timestamp | price Double | | -------------------- | ----------------------------------- | ----------- | -------------- | ------------------------------------- | ---------------- | ------------ | | nyphilharmonic181210 | New York Philharmonic: Rachmaninoff | New York | Lincoln Center | \["classical music"\] | 2018-12-10 19:00 | 94.0 | | beachboys190321 | Beach Boys | New Jersey | Arts Center | \["rock music", "rock’n’roll music"\] | 2019-03-21 20:00 | 69.0 | | snoopdogg191102 | Snoop Dogg | New York | Terminal 5 | \["hip-hop", "rap"\] | 2019-02-11 19:00 | 42.0 | I have these data in a json object, where the keys are IDs of the items and values contain an object with item properties. JSON ``` { "nyphilharmonic181210": { "title": "New York Philharmonic: Rachmaninoff", "city": "New York", "venue": "Lincoln Center", "date": "2017-12-10", "genres": ["classical music"], "price": 94.0 } "beachboys190321": { ... }, .... } ``` #### Defining Item Properties Now, let's see how we can send these data to Recombee, and how they are used in recommendations. First, I need to define the properties. They can be thought as columns in relational database. In my case the properties are _title_, _city_, _venue_, _date_, _genres_ and _price_. I add them using the [Admin UI](/admin_ui): [![Add item property in Admin UI](/img/gui/add_property2.png)](/img/gui/add_property2.png) Alternatively, I can add them by calling the API: ```python client.send(AddItemProperty('title', 'string')) client.send(AddItemProperty('city', 'string')) client.send(AddItemProperty('venue', 'string')) client.send(AddItemProperty('date', 'timestamp')) client.send(AddItemProperty('genres', 'set')) client.send(AddItemProperty('price', 'double')) ``` ```java client.send(new AddItemProperty("title", "string")); client.send(new AddItemProperty("city", "string")); client.send(new AddItemProperty("venue", "string")); client.send(new AddItemProperty("date", "timestamp")); client.send(new AddItemProperty("genres", "set")); client.send(new AddItemProperty("price", "double")); ``` ```ruby client.send(AddItemProperty.new('title', 'string')) client.send(AddItemProperty.new('city', 'string')) client.send(AddItemProperty.new('venue', 'string')) client.send(AddItemProperty.new('date', 'timestamp')) client.send(AddItemProperty.new('genres', 'set')) client.send(AddItemProperty.new('price', 'double')) ``` ```php $client->send(new Reqs\AddItemProperty('title', 'string')); $client->send(new Reqs\AddItemProperty('city', 'string')); $client->send(new Reqs\AddItemProperty('venue', 'string')); $client->send(new Reqs\AddItemProperty('date', 'timestamp')); $client->send(new Reqs\AddItemProperty('genres', 'set')); $client->send(new Reqs\AddItemProperty('price', 'double')); ``` ```csharp client.Send(new AddItemProperty("title", "string")); client.Send(new AddItemProperty("city", "string")); client.Send(new AddItemProperty("venue", "string")); client.Send(new AddItemProperty("date", "timestamp")); client.Send(new AddItemProperty("genres", "set")); client.Send(new AddItemProperty("price", "double")); ``` ```js client.send( new rqs.Batch([ new rqs.AddItemProperty('title', 'string'), new rqs.AddItemProperty('city', 'string'), new rqs.AddItemProperty('venue', 'string'), new rqs.AddItemProperty('date', 'timestamp'), new rqs.AddItemProperty('genres', 'set'), new rqs.AddItemProperty('price', 'double') ]) ); ``` The properties are now in the place. If there were already some items in the database, they would have all the values set to `NULL`. #### Setting Item Values I start by reading the file, parsing the json and iterating over the item IDs and corresponding property values. I will send them to Recombee with [SetItemValues](/api#request-set-item-values) requests.[SetItemValues](/api#request-set-item-values) takes the `itemId`, the property values of the items, and the optional parameter `cascadeCreate` which I set to `true` in order to create items in the system if they don't exist yet. I use the [Batch](/api#request-batch) to speed up the uploading. ```python requests = [] with open('items.json') as f: data = json.loads(f.read()) for item_id,values in data.items(): r = SetItemValues(item_id, values, cascade_create=True) requests.append(r) res = client.send(Batch(requests)) ``` ```java ArrayList requests = new ArrayList<>(); try { // HashMap> HashMap> items = new ObjectMapper().readValue(new FileReader("items.json"), HashMap.class); for (Map.Entry> entry : items.entrySet()) { String itemId = entry.getKey(); HashMap values = entry.getValue(); requests.add(new SetItemValues(itemId, values).setCascadeCreate(true)); } } catch (IOException e) { e.printStackTrace(); } BatchResponse[] res = client.send(new Batch(requests)); ``` ```ruby file = File.read('items.json') requests = JSON.parse(file).map do |item_id, values| SetItemValues.new(item_id, values, :cascade_create => true) end br = Batch.new(requests) puts client.send(br) ``` ```php $requests = array(); $str = file_get_contents('items.json'); foreach(json_decode($str, true) as $item_id => $values) { $r = new Reqs\SetItemValues($item_id, $values, ['cascadeCreate' => true]); array_push($requests, $r); } $br = new Reqs\Batch($requests); $res = $client->send($br); ``` ```csharp using (StreamReader r = new StreamReader("items.json")) { string json = r.ReadToEnd(); Dictionary> items = JsonConvert.DeserializeObject>>(json); var requests = new List(); foreach(KeyValuePair> entry in items) { var itemId = entry.Key; var values = entry.Value; // Dictionary with names of properties as keys // and values of the properties as values requests.Add(new SetItemValues(itemId, values, cascadeCreate: true)); } client.Send(new Batch(requests)); } ``` ```js var catalog = require('./items.json'); var requests = []; for (var itemId in catalog) { var values = catalog[itemId]; requests.push(new rqs.SetItemValues(itemId, values, {cascadeCreate: true})); } client.send(new rqs.Batch(requests)); ``` I can check the uploaded items in the Admin UI. Other properties that are usually very useful, but were not included in this example are **text descriptions**, which are processed by text mining algorithms, and **links to images** (property types **Image** and**Image List**) that can be used for finding visually similar items using artificial neural networks and other images processing models. ## ReQL Filtering ### Source Codes [Python](/files/tutorial/3-reql/reql.py)[Java](/files/tutorial/3-reql/reql.java)[Ruby](/files/tutorial/3-reql/reql.rb)[PHP](/files/tutorial/3-reql/reql.php)[C#](/files/tutorial/3-reql/reql.cs)[Node.js](/files/tutorial/3-reql/reql.js) ### Text Tutorial [ReQL](/reql) filtering allows you to put some restrictions on the recommended items. Tip You can use ReQL also for specifying the [Business Rules](/reql#business-rules) in the Admin UI Let's assume I have the catalog of cultural events from previous part of the tutorial uploaded in my database. It contains following item properties: _title_, _city_, _venue_, _genres_, _date_ and _price_. I want to get some related items to item_nyphilharmonic181210_, which is concert by the New York Philharmonic. These recommendations will be shown to_user-27_. I use [RecommendItemsToItem](/api#request-recommend-items-to-item) for this purpose: ```python recommended = client.send(RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, cascade_create=True)) print(recommended) ``` ```js var callback = function (err, res) { if(err) { console.log(err); return; } console.log(res.recomms); } client.send( new recombee.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, {cascadeCreate: true}), callback); ``` ```java RecommendationResponse recommended = client.send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3) .setCascadeCreate(true)); for(Recommendation rec: recommended) System.out.println(rec.getId()); ``` ```ruby require 'pp' recommended = client.send(RecommendItemsToItem.new('nyphilharmonic181210', 'user-27', 3, :cascade_create => true)) pp recommended ``` ```php $recommended = $client->send(new Reqs\RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, ['cascadeCreate' => true])); echo print_r($recommended, true) . "\n"; ``` ```csharp RecommendationResponse recommended = client.Send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3, cascadeCreate: true)); foreach(Recommendation rec in recommended.Recomms) Console.WriteLine(rec.Id); ``` ```js var callback = function (err, res) { if(err) { console.log(err); return; } console.log(res.recomms); } client.send( new rqs.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, {cascadeCreate: true}), callback); ``` I got some IDs, but in order to evaluate the quality of the recommendations, I need to set optional parameter `returnProperties` to`true`. ```python recommended = client.send(RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, return_properties=True)) print(json.dumps(recommended, indent=4)) ``` ```js client.send( new recombee.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, {returnProperties: true})), callback); ``` ```java recommended = client.send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3) .setReturnProperties(true)); printRecommendedItems(recommended); // ... private static void printRecommendedItems(RecommendationResponse recommended) { for(Recommendation rec: recommended) { System.out.format("%s:\n", rec.getId()); for (Map.Entry entry : rec.getValues().entrySet()) { String propertyName = entry.getKey(); Object propertyValue = entry.getValue(); System.out.format(" %s: %s\n", propertyName, propertyValue); } } System.out.println("\n"); } ``` ```ruby recommended = client.send(RecommendItemsToItem.new('nyphilharmonic181210', 'user-27', 3, :return_properties => true)) ``` ```php $recommended = $client->send(new Reqs\RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, ['returnProperties' => true])); ``` ```csharp recommended = client.Send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3, returnProperties: true)); WriteRecommendedItemsToConsole(recommended); // .. private static void WriteRecommendedItemsToConsole(RecommendationResponse recommended) { foreach(Recommendation rec in recommended.Recomms) { Console.WriteLine("{0}:", rec.Id); foreach (KeyValuePair entry in rec.Values) { var propertyName = entry.Key; var propertyValue = entry.Value; Console.WriteLine(" {0}: {1}", propertyName, propertyValue); } } Console.WriteLine("\n\n"); } ``` ```js client.send( new rqs.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, {returnProperties: true})), callback); ``` Now I get also the property values of recommended items. As you can see, the recommended items look pretty related to the concert of the philharmonic. JSON ``` { "recomms": [ { "values": { "city": "New York", "price": 56.0, "venue": "Lincoln Center", "title": "Ravel's Daphnis et Chloe and Dvorak", "genres": [ "classical music" ], "date": 1523318400.0 }, "id": "ravelsdaphnis180410" }, { "values": { "city": "Los Angeles", "price": 62.0, "venue": "Walt Disney Concert Hall", "title": "Los Angeles Philharmonic: Rachmaninoff", "genres": [ "classical music" ], "date": 1558742400.0 }, "id": "laphilharmonic190525" }, { "values": { "city": "San Francisco", "price": 58.0, "venue": "Davies Symphony Hall", "title": "Czech Philharmonic: Dvorak", "genres": [ "classical music" ], "date": 1573430400.0 }, "id": "czechphilharmonic191111" } ], "recommId": "295b2aa5-8375-48bc-82dd-e1555ee0b5ec" } ``` But if the user is interested in the _New York Philharmonic_ concert which takes place in _New York City_, there is only slight chance that the user will attend concert of _Los Angeles Philharmonic_ in LA. So I want to put restriction on the recommendations to return only events that take place in _New York_. This can be easily done by setting filter `'city' == "New York"`. ```python recommended = client.send(RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, return_properties=True, filter="'city' == \"New York\" ")) ``` ```js client.send( new recombee.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, { returnProperties: true, filter: "'city' == \"New York\"" }), callback); ``` ```java recommended = client.send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3) .setReturnProperties(true) .setFilter("'city' == \"New York\"")); ``` ```ruby recommended = client.send(RecommendItemsToItem.new('nyphilharmonic181210', 'user-27', 3, :return_properties => true, :filter => "'city' == \"New York\"")) ``` ```php $recommended = $client->send(new Reqs\RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, ['returnProperties' => true, 'filter' => "'city' == \"New York\""])); ``` ```csharp recommended = client.Send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3, returnProperties: true, filter: "'city' == \"New York\"")); ``` ```js client.send( new rqs.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, { returnProperties: true, filter: "'city' == \"New York\"" }), callback); ``` As you can see I use single quotes for accessing values of the properties and double quotes, which I had to escape, for creating the_New York_ string. Now all the events I received take place in New York: JSON ``` { "recomms": [ { "values": { "city": "New York", "genres": [ "classical music" ], "venue": "Lincoln Center", "price": 56.0, "date": 1523318400.0, "title": "Ravel's Daphnis et Chloe and Dvorak" }, "id": "ravelsdaphnis180410" }, { "values": { "city": "New York", "genres": [ "classical music" ], "venue": "Carnegie Hall", "price": 72.0, "date": 1558656000.0, "title": "Staatskapelle Dresden in NY: Schubert" }, "id": "staatskapelle190524" }, { "values": { "city": "New York", "genres": [ "classical music" ], "venue": "Brooklyn Museum", "price": 63.0, "date": 1552780800.0, "title": "Brooklyn Symphony Orchestra: Borodin, Shostakovich" }, "id": "brooklynsymphony190317" } ], "recommId": "8ef292ca-7f4c-4be0-8f63-fdb9f4a9fee0" } ``` The problem is that some events may have already passed, and therefore should not be recommended. To filter these events out I compare the date property with current time, which obtain by calling ReQL function[now()](/reql_functions#reql-func-now). The filter therefore becomes `'city' == "New York" and 'date' >= now()`: ```python recommended = client.send(RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, return_properties=True, filter="'city' == \"New York\" AND 'date' >= now()")) ``` ```js client.send( new recombee.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, { returnProperties: true, filter: "'city' == \"New York\" AND 'date' >= now()" }), callback); ``` ```java recommended = client.send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3) .setReturnProperties(true) .setFilter("'city' == \"New York\" AND 'date' >= now()")); ``` ```ruby recommended = client.send(RecommendItemsToItem.new('nyphilharmonic181210', 'user-27', 3, :return_properties => true, :filter => "'city' == \"New York\" AND 'date' >= now()")) ``` ```php $recommended = $client->send(new Reqs\RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, ['returnProperties' => true, 'filter' => "'city' == \"New York\" AND 'date' >= now()"])); ``` ```csharp recommended = client.Send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3, returnProperties: true, filter: "'city' == \"New York\" AND 'date' >= now()")); ``` ```js client.send( rqs.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, { returnProperties: true, filter: "'city' == \"New York\" AND 'date' >= now()" }), callback); ``` Now all the events are upcoming. Another restriction can be restriction on genres - let's suppose the user chose to view only items that have_ballet_ as one of their _genres_. It is done by appending`"ballet" in 'genres'` to the filter: ```python recommended = client.send(RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, return_properties=True, filter="'city' == \"New York\" AND 'date' >= now() AND \"ballet\" in 'genres'")) ``` ```js client.send( new recombee.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, { returnProperties: true, filter: "'city' == \"New York\" AND 'date' >= now() AND \"ballet\" in 'genres'" }), callback); ``` ```java recommended = client.send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3) .setReturnProperties(true) .setFilter("'city' == \"New York\" AND 'date' >= now() AND \"ballet\" in 'genres'")); ``` ```ruby recommended = client.send(RecommendItemsToItem.new('nyphilharmonic181210', 'user-27', 3, :return_properties => true, :filter => "'city' == \"New York\" AND 'date' >= now() AND \"ballet\" in 'genres'")) ``` ```php $recommended = $client->send(new Reqs\RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, ['returnProperties' => true, 'filter' => "'city' == \"New York\" AND 'date' >= now() AND \"ballet\" in 'genres'"])); ``` ```csharp recommended = client.Send(new RecommendItemsToItem("nyphilharmonic181210", "user-27", 3, returnProperties: true, filter: "'city' == \"New York\" AND 'date' >= now() AND \"ballet\" in 'genres'")); ``` ```js client.send( new rqs.RecommendItemsToItem('nyphilharmonic181210', 'user-27', 3, { returnProperties: true, filter: "'city' == \"New York\" AND 'date' >= now() AND \"ballet\" in 'genres'" }), callback); ``` JSON ``` { "recomms": [ { "values": { "city": "New York", "price": 82.0, "venue": "Metropolitan Opera House", "title": "American Ballet Theatre: Harlequinade", "date": 1564185600.0, "genres": [ "ballet" ] }, "id": "americanballet190727" }, { "values": { "city": "New York", "price": 77.0, "venue": "Joyce Theater", "title": "BalletX & Raphael Xavier", "date": 1555027200.0, "genres": [ "contemporary dance", "ballet" ] }, "id": "balletx190412" }, { "values": { "city": "New York", "price": 92.0, "venue": "David H. Koch Theater", "title": "NYCB: Orpheus", "date": 1561334400.0, "genres": [ "ballet" ] }, "id": "nycb190624" } ], "recommId": "f05b4d84-fec0-4ef8-8875-eac9bd378c6c" } ``` Sometimes the filter may depend on the currently viewed item. For example, we may want to change our filter not to permit only items from_New York_, but recommend events from the same city where the event that is currently viewed by the user takes place. The [context\_item function](/reql_functions#reql-func-context-item), which retrieves properties of current item, makes achieving this behavior easy. We will permit only items that have the same _city_as context item: `'city' == context_item["city"]`. Therefore if we get recommendations related to an event that takes place in _Los Angeles_, we get only events taking place in LA. ```python recommended = client.send(RecommendItemsToItem('laphilharmonic190525', 'user-27', 3, return_properties=True, filter="'city' == context_item[\"city\"] AND 'date' >= now() AND \"ballet\" in 'genres'")) ``` ```js client.send( new recombee.RecommendItemsToItem('laphilharmonic190525', 'user-27', 3, { returnProperties: true, filter: "'city' == context_item[\"city\"] AND 'date' >= now() AND \"ballet\" in 'genres'" }), callback); ``` ```java recommended = client.send(new RecommendItemsToItem("laphilharmonic190525", "user-27", 3) .setReturnProperties(true) .setFilter("'city' == context_item[\"city\"] AND 'date' >= now() AND \"ballet\" in 'genres'")); ``` ```ruby recommended = client.send(RecommendItemsToItem.new('laphilharmonic190525', 'user-27', 3, :return_properties => true, :filter => "'city' == context_item[\"city\"] AND 'date' >= now() AND \"ballet\" in 'genres'")) ``` ```php $recommended = $client->send(new Reqs\RecommendItemsToItem('laphilharmonic190525', 'user-27', 3, ['returnProperties' => true, 'filter' => "'city' == context_item[\"city\"] AND 'date' >= now() AND \"ballet\" in 'genres'"])); ``` ```csharp recommended = client.Send(new RecommendItemsToItem("laphilharmonic190525", "user-27", 3, returnProperties: true, filter: "'city' == context_item[\"city\"] AND 'date' >= now() AND \"ballet\" in 'genres'")); ``` ```js client.send( new rqs.RecommendItemsToItem('laphilharmonic190525', 'user-27', 3, { returnProperties: true, filter: "'city' == context_item[\"city\"] AND 'date' >= now() AND \"ballet\" in 'genres'" }), callback); ``` As you can see, the possibilities of filtering are very broad. Besides filtering, there is also the possibility to[boost some items](/reql_filtering_and_boosting#reql-boosting) or[use properties of users](/api#request-add-user-property). ## JavaScript Integration To see the steps required to integrate Recombee with your website or JavaScript application, please refer to the [example in our JavaScript SDK Documentation](/js_client#integration-example). --- # API Reference > Source: https://docs.recombee.com/api > For the complete documentation index, see [llms.txt](/llms.txt). # API Reference This section lists all the available API endpoints, that allow you to manage item catalog, users, their interactions and get recommendations. * Version: `6.3.0` * Base URL: Based on the [region](/regions) of your database * API consumes: `application/json` * API produces: `application/json` * Authentication: [HMAC](/authentication) (already implemented in the SDKs) * OpenAPI definition: [YAML](/openapi.yaml) | [JSON](/openapi.json) ## Items The following methods allow you to maintain the set of items in the catalog. The items are specified using their ids, which are unique string identifiers matching _^\[a-zA-Z0-9\_-:@.\]+$_, i.e., they may consist of digits, Latin letters, underscores, colons, minus signs, at signs, and dots. Item ID `undefined` is forbidden. put #### Add Item Adds new item of the given `itemId` to the items catalog. All the item properties for the newly created items are set to null. ```js client.send(new requests.AddItem(itemId)); ``` ```python client.send(AddItem(item_id)) ``` ```ruby client.send(AddItem.new(item_id)) ``` ```java client.send(new AddItem(itemId)); ``` ```php $client->send(new Reqs\AddItem($item_id)); ``` ```csharp client.Send(new AddItem(itemId)); ``` ```go request := client.NewAddItem(itemId) _, err := request.Send() ``` ```http PUT /{databaseId}/items/{itemId} ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item to be created. --- ##### Responses 201 Successful operation. --- 400 The `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 409 The `itemId` is already present in the item catalog. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete Item Deletes an item of the given `itemId` from the catalog. If there are any _purchases_, _ratings_, _bookmarks_, _cart additions_, or _detail views_ of the item present in the database, they will be deleted in cascade as well. Also, if the item is present in some _series_, it will be removed from all the _series_ where present. If an item becomes obsolete/no longer available, it is meaningful to keep it in the catalog (along with all the interaction data, which are very useful), and **only exclude the item from recommendations**. In such a case, use [ReQL filter](https://docs.recombee.com/reql) instead of deleting the item completely. ```js client.send(new requests.DeleteItem(itemId)); ``` ```python client.send(DeleteItem(item_id)) ``` ```ruby client.send(DeleteItem.new(item_id)) ``` ```java client.send(new DeleteItem(itemId)); ``` ```php $client->send(new Reqs\DeleteItem($item_id)); ``` ```csharp client.Send(new DeleteItem(itemId)); ``` ```go request := client.NewDeleteItem(itemId) _, err := request.Send() ``` ```http DELETE /{databaseId}/items/{itemId} ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item to be deleted. --- ##### Responses 200 Successful operation. --- 400 The `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 The `itemId` is not present in the item catalog. In many cases, you may consider this code a success – it only tells you that nothing has been deleted from the database since the item was already not present. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Items Gets a list of IDs of items currently present in the catalog. ```js const result = await client.send(new requests.ListItems({ // optional parameters: filter: 'price > 50', // string count: 10, // integer offset: 0, // integer returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array })); ``` ```python result = client.send(ListItems( # optional parameters: filter='price > 50', # string count=10, # integer offset=0, # integer return_properties=True, # boolean included_properties=['title', 'price', 'publishedAt'], # array )) ``` ```ruby result = client.send(ListItems.new({ # optional parameters: filter: 'price > 50', # string count: 10, # integer offset: 0, # integer return_properties: true, # boolean included_properties: ['title', 'price', 'publishedAt'], # array })) ``` ```java Item[] result = client.send(new ListItems() .setFilter("price > 50") // String .setCount(10) // long .setOffset(0) // long .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"title", "price", "publishedAt"}) // String[] ); ``` ```php $result = $client->send(new Reqs\ListItems([ // optional parameters: 'filter' => 'price > 50', // string 'count' => 10, // integer 'offset' => 0, // integer 'returnProperties' => true, // boolean 'includedProperties' => ['title', 'price', 'publishedAt'], // array ])); ``` ```csharp IEnumerable result = client.Send(new ListItems( // optional parameters: filter: "price > 50", // string count: 10, // long offset: 0, // long returnProperties: true, // bool includedProperties: new string[] { "title", "price", "publishedAt" } // string[] )); ``` ```go request := client.NewListItems(). // optional parameters: SetFilter("price > 50"). // string SetCount(10). // int SetOffset(0). // int SetReturnProperties(true). // bool SetIncludedProperties([]string{"title", "price", "publishedAt"}) // []string result, err := request.Send() // result is of the type []bindings.Item ``` ```http GET /{databaseId}/items/list/?filter=price > 50 &count=10 &offset=0 &returnProperties=true &includedProperties=title,price,publishedAt ``` --- Calls Limit Per Minute 100 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- filter String Located in: **query** Required: **No** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to filter items to be listed. Only the items for which the expression is _true_ will be returned. --- count Integer Located in: **query** Required: **No** The number of items to be listed. --- offset Integer Located in: **query** Required: **No** Specifies the number of items to skip (ordered by `itemId`). --- returnProperties Boolean Located in: **query** Required: **No** Since version: **1.4.0** With `returnProperties=true`, property values of the listed items are returned along with their IDs in a JSON dictionary. Example response: ``` [ { "itemId": "tv-178", "description": "4K TV with 3D feature", "categories": ["Electronics", "Televisions"], "price": 342, "url": "myshop.com/tv-178" }, { "itemId": "mixer-42", "description": "Stainless Steel Mixer", "categories": ["Home & Kitchen"], "price": 39, "url": "myshop.com/mixer-42" } ] ``` --- includedProperties Array Located in: **query** Required: **No** Since version: **1.4.0** Allows specifying which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. Example response for `includedProperties=description,price`: ``` [ { "itemId": "tv-178", "description": "4K TV with 3D feature", "price": 342 }, { "itemId": "mixer-42", "description": "Stainless Steel Mixer", "price": 39 } ] ``` --- ##### Responses 200 Successful operation. ``` [ "item-1", "item-2", "item-3" ] ``` --- 404 If present, `filter` contains a non-existing item property. --- delete #### Delete More Items Deletes all the items that pass the filter. If an item becomes obsolete/no longer available, it is meaningful to **keep it in the catalog** (along with all the interaction data, which are very useful) and **only exclude the item from recommendations**. In such a case, use [ReQL filter](https://docs.recombee.com/reql) instead of deleting the item completely. ```js const result = await client.send(new requests.DeleteMoreItems(filter)); ``` ```python result = client.send(DeleteMoreItems(filter)) ``` ```ruby result = client.send(DeleteMoreItems.new(filter)) ``` ```java DeleteMoreItemsResponse result = client.send(new DeleteMoreItems(filter)); ``` ```php $result = $client->send(new Reqs\DeleteMoreItems($filter)); ``` ```csharp DeleteMoreItemsResponse result = client.Send(new DeleteMoreItems(filter)); ``` ```go request := client.NewDeleteMoreItems(filter) result, err := request.Send() // result is of the type bindings.DeleteMoreItemsResponse ``` ```http DELETE /{databaseId}/more-items/ Body (application/json): { "filter": "price > 50" } ``` --- Since version 3.3.0 --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **3.3.0** ID of your database. --- filter String Located in: **body** Required: **Yes** Since version: **3.3.0** A [ReQL](https://docs.recombee.com/reql) expression, which returns `true` for the items that shall be updated. --- ##### Responses 200 Successful operation. ``` { "itemIds": [ "item-42", "item-125", "item-11" ], "count": 3 } ``` --- 400 Invalid filter. --- ## Item Properties ### Item properties definition Item properties are used for modeling your domain. The following methods allow the definition of item properties. The properties may be thought of as columns in a relational database table. put #### Add Item Property Adding an item property is somewhat equivalent to adding a column to the table of items. The items may be characterized by various properties of different types. ```js client.send(new requests.AddItemProperty(propertyName, type, { // optional parameters: role: 'title', // string / Object metadata: [], // array })); ``` ```python client.send(AddItemProperty(property_name, type, # optional parameters: role='title', # string / dict metadata=[], # array )) ``` ```ruby client.send(AddItemProperty.new(property_name, type, { # optional parameters: role: 'title', # string / Hash metadata: [], # array })) ``` ```java client.send(new AddItemProperty(propertyName, type) .setRole(new PropertyRole("title")) // PropertyRole .setMetadata(new PropertyMetadata[]{}) // PropertyMetadata[] ); ``` ```php $client->send(new Reqs\AddItemProperty($property_name, $type, [ // optional parameters: 'role' => 'title', // string / array (map) 'metadata' => [], // array ])); ``` ```csharp client.Send(new AddItemProperty(propertyName, type, // optional parameters: role: new PropertyRole(name: "title"), // PropertyRole metadata: new PropertyMetadata[] {} // PropertyMetadata[] )); ``` ```go request := client.NewAddItemProperty(propertyName, propertyType). // optional parameters: SetRole(bindings.PropertyRole{Name: "title"}). // bindings.PropertyRole SetMetadata([]bindings.PropertyMetadata{}) // []bindings.PropertyMetadata _, err := request.Send() ``` ```http PUT /{databaseId}/items/properties/{propertyName} Body (application/json): { "type": "string", "role": "title", "metadata": [] } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- propertyName String Located in: **path** Required: **Yes** Name of the item property to be created. Currently, the following names are reserved: `id`, `itemid`, case-insensitively. Also, the length of the property name must not exceed 63 characters. --- type String Located in: **body** Required: **Yes** Value type of the item property to be created. One of: `int`, `double`, `string`, `boolean`, `timestamp`, `set`, `image` or `imageList`. * `int` \- Signed integer number. * `double` \- Floating point number. It uses 64-bit base-2 format (IEEE 754 standard). * `string` \- UTF-8 string. * `boolean` \- _true_ / _false_ * `timestamp` \- Value representing date and time. ISO8601-1 pattern (string) or UTC epoch time (number). * `set` \- Set of strings. * `image` \- URL of an image (`jpeg`, `png` or `gif`). * `imageList` \- List of URLs that refer to images. --- role String Object Located in: **body** Required: **No** Since version: **6.3.0** [Role](https://docs.recombee.com/api/property_roles_metadata#roles) to assign to the property. --- metadata Array Located in: **body** Required: **No** Since version: **6.3.0** List of [metadata](https://docs.recombee.com/api/property_roles_metadata#metadata) entries to assign to the property. --- ##### Responses 201 Successful operation. --- 400 Property name does not match ^\[a-zA-Z0-9\_-:\]+$, or it is a reserved keyword (''id'', ''itemid''), or its length exceeds 63 characters. Type information is missing, or the given type is invalid. --- 409 Property of the given name is already present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete Item Property Deleting an item property is roughly equivalent to removing a column from the table of items. ```js client.send(new requests.DeleteItemProperty(propertyName)); ``` ```python client.send(DeleteItemProperty(property_name)) ``` ```ruby client.send(DeleteItemProperty.new(property_name)) ``` ```java client.send(new DeleteItemProperty(propertyName)); ``` ```php $client->send(new Reqs\DeleteItemProperty($property_name)); ``` ```csharp client.Send(new DeleteItemProperty(propertyName)); ``` ```go request := client.NewDeleteItemProperty(propertyName) _, err := request.Send() ``` ```http DELETE /{databaseId}/items/properties/{propertyName} ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- propertyName String Located in: **path** Required: **Yes** Name of the property to be deleted. --- ##### Responses 200 Successful operation. --- 400 Property name does not match ^\[a-zA-Z0-9\_-:\]+$. --- 404 Property of the given name is not present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been deleted from the database since the item property was already not present. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### Get Item Property Info Gets information about specified item property. ```js const result = await client.send(new requests.GetItemPropertyInfo(propertyName)); ``` ```python result = client.send(GetItemPropertyInfo(property_name)) ``` ```ruby result = client.send(GetItemPropertyInfo.new(property_name)) ``` ```java PropertyInfo result = client.send(new GetItemPropertyInfo(propertyName)); ``` ```php $result = $client->send(new Reqs\GetItemPropertyInfo($property_name)); ``` ```csharp PropertyInfo result = client.Send(new GetItemPropertyInfo(propertyName)); ``` ```go request := client.NewGetItemPropertyInfo(propertyName) result, err := request.Send() // result is of the type bindings.PropertyInfo ``` ```http GET /{databaseId}/items/properties/{propertyName} ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- propertyName String Located in: **path** Required: **Yes** Name of the property about which the information is to be retrieved. --- ##### Responses 200 Successful operation. ``` { "name": "num-processors", "type": "int" } ``` --- 400 Property name does not match ^\[a-zA-Z0-9\_-:\]+$. --- 404 Property of the given name is not present in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Item Properties Gets the list of all the item properties in your database. ```js const result = await client.send(new requests.ListItemProperties()); ``` ```python result = client.send(ListItemProperties()) ``` ```ruby result = client.send(ListItemProperties.new()) ``` ```java PropertyInfo[] result = client.send(new ListItemProperties()); ``` ```php $result = $client->send(new Reqs\ListItemProperties()); ``` ```csharp IEnumerable result = client.Send(new ListItemProperties()); ``` ```go request := client.NewListItemProperties() result, err := request.Send() // result is of the type []bindings.PropertyInfo ``` ```http GET /{databaseId}/items/properties/list/ ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- ##### Responses 200 Successful operation. ``` [ { "name": "tags", "type": "set" }, { "name": "release-date", "type": "timestamp" }, { "name": "description", "type": "string" } ] ``` --- 404 Invalid URL. --- ### Values of item properties The following methods allow assigning property values to items in the catalog. Set values are examined by content-based algorithms and used for recommendations, especially in the case of cold-start items that have no interactions yet. Properties are also used in [ReQL](https://docs.recombee.com/reql) for filtering and boosting according to your business rules. post #### Set Item Values Sets/updates (some) property values of the given item. The properties (columns) must be previously created by [Add item property](https://docs.recombee.com/api#add-item-property). ```js client.send(new requests.SetItemValues(itemId, values, { // optional parameters: cascadeCreate: true, // boolean })); ``` ```python client.send(SetItemValues(item_id, values, # optional parameters: cascade_create=True, # boolean )) ``` ```ruby client.send(SetItemValues.new(item_id, values, { # optional parameters: cascade_create: true, # boolean })) ``` ```java client.send(new SetItemValues(itemId, values) .setCascadeCreate(true) // boolean ); ``` ```php $client->send(new Reqs\SetItemValues($item_id, $values, [ // optional parameters: 'cascadeCreate' => true, // boolean ])); ``` ```csharp client.Send(new SetItemValues(itemId, values, // optional parameters: cascadeCreate: true // bool )); ``` ```go request := client.NewSetItemValues(itemId, values). // optional parameters: SetCascadeCreate(true) // bool _, err := request.Send() ``` ```http POST /{databaseId}/items/{itemId} ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item which will be modified. --- Object Located in: **body** Required: **Yes** The values for the individual properties. Example of the body: ``` { "product_description": "4K TV with 3D feature", "categories": ["Electronics", "Televisions"], "price_usd": 342, "in_stock_from": "2016-11-16T08:00Z", "image": "http://myexamplesite.com/products/4ktelevision3d/image.jpg", "other_images": ["http://myexamplesite.com/products/4ktelevision3d/image2.jpg", "http://myexamplesite.com/products/4ktelevision3d/image3.jpg"] } ``` Set item values can also **cascade create** the item if it's not already present in the database. For this functionality: * _When using the client libraries_: Set the optional _cascadeCreate_ parameter to true, just like when creating an interaction. * _When using directly REST API_: Set special "property" `!cascadeCreate`. Example: ``` { "product_description": "4K TV with 3D feature", "!cascadeCreate": true } ``` Note the exclamation mark (!) at the beginning of the parameter's name to distinguish it from item property names. --- ##### Responses 200 Successful operation. --- 400 Property name does not match ''^\[a-zA-Z0-9\_-:\]+$'', value does not match the property type. --- 404 Property of the given name is not present in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### Get Item Values Gets all the current property values of the given item. ```js const result = await client.send(new requests.GetItemValues(itemId)); ``` ```python result = client.send(GetItemValues(item_id)) ``` ```ruby result = client.send(GetItemValues.new(item_id)) ``` ```java Map result = client.send(new GetItemValues(itemId)); ``` ```php $result = $client->send(new Reqs\GetItemValues($item_id)); ``` ```csharp Item result = client.Send(new GetItemValues(itemId)); ``` ```go request := client.NewGetItemValues(itemId) result, err := request.Send() // result is of the type map[string]interface{} ``` ```http GET /{databaseId}/items/{itemId} ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item whose properties are to be obtained. --- ##### Responses 200 Successful operation. ``` { "release-date": null, "tags": [ "electronics", "laptops" ], "num-processors": 12, "description": "Very powerful laptop", "weight": 1.6 } ``` --- 400 The _itemId_ does not match ^\[a-zA-Z0-9\_-:@.\]+$ --- 404 Item of the given _itemId_ is not present in the catalog. If there is no additional info in the JSON response, you probably have an error in your URL. --- post #### Update More Items Updates (some) property values of all the items that pass the filter. Example: _Setting all the items that are older than a week as unavailable_ ``` { "filter": "'releaseDate' < now() - 7*24*3600", "changes": {"available": false} } ``` ```js const result = await client.send(new requests.UpdateMoreItems(filter, changes)); ``` ```python result = client.send(UpdateMoreItems(filter, changes)) ``` ```ruby result = client.send(UpdateMoreItems.new(filter, changes)) ``` ```java UpdateMoreItemsResponse result = client.send(new UpdateMoreItems(filter, changes)); ``` ```php $result = $client->send(new Reqs\UpdateMoreItems($filter, $changes)); ``` ```csharp UpdateMoreItemsResponse result = client.Send(new UpdateMoreItems(filter, changes)); ``` ```go request := client.NewUpdateMoreItems(filter, changes) result, err := request.Send() // result is of the type bindings.UpdateMoreItemsResponse ``` ```http POST /{databaseId}/more-items/ Body (application/json): { "filter": "price > 50", "changes": {} } ``` --- Since version 3.3.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **3.3.0** ID of your database. --- filter String Located in: **body** Required: **Yes** Since version: **3.3.0** A [ReQL](https://docs.recombee.com/reql) expression, which returns `true` for the items that shall be updated. --- changes Object Located in: **body** Required: **Yes** Since version: **3.3.0** A dictionary where the keys are properties that shall be updated. --- ##### Responses 200 Successful operation. Returns IDs of updated items and their count. ``` { "itemIds": [ "item-42", "item-125", "item-11" ], "count": 3 } ``` --- 400 Invalid filter, property name does not match ''^\[a-zA-Z0-9\_-:\]+$'', value does not match the property type. --- 404 Property of the given name is not present in the database. --- ## Users The following methods allow you to manage users in your database. User ID `undefined` is forbidden. put #### Add User Adds a new user to the database. ```js client.send(new requests.AddUser(userId)); ``` ```python client.send(AddUser(user_id)) ``` ```ruby client.send(AddUser.new(user_id)) ``` ```java client.send(new AddUser(userId)); ``` ```php $client->send(new Reqs\AddUser($user_id)); ``` ```csharp client.Send(new AddUser(userId)); ``` ```go request := client.NewAddUser(userId) _, err := request.Send() ``` ```http PUT /{databaseId}/users/{userId} ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **path** Required: **Yes** ID of the user to be added. --- ##### Responses 201 Successful operation. --- 400 The `userId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 409 User of the given userId is already present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete User Deletes a user of the given _userId_ from the database. If there are any purchases, ratings, bookmarks, cart additions or detail views made by the user present in the database, they will be deleted in cascade as well. ```js client.send(new requests.DeleteUser(userId)); ``` ```python client.send(DeleteUser(user_id)) ``` ```ruby client.send(DeleteUser.new(user_id)) ``` ```java client.send(new DeleteUser(userId)); ``` ```php $client->send(new Reqs\DeleteUser($user_id)); ``` ```csharp client.Send(new DeleteUser(userId)); ``` ```go request := client.NewDeleteUser(userId) _, err := request.Send() ``` ```http DELETE /{databaseId}/users/{userId} ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **path** Required: **Yes** ID of the user to be deleted. --- ##### Responses 200 Successful operation. --- 400 The _userId_ does not match ''^\[a-zA-Z0-9\_-:@.\]+$''. --- 404 User of the given `userId` is not present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been deleted from the database since the user was already not present. If there is no additional info in the JSON response, you probably have an error in your URL. --- put #### Merge Users Allowed on Client-Side Merges interactions (purchases, ratings, bookmarks, detail views ...) of two different users under a single user ID. This is especially useful for online e-commerce applications working with anonymous users identified by unique tokens such as the session ID. In such applications, it may often happen that a user owns a persistent account, yet accesses the system anonymously while, e.g., putting items into a shopping cart. At some point in time, such as when the user wishes to confirm the purchase, (s)he logs into the system using his/her username and password. The interactions made under anonymous session ID then become connected with the persistent account, and merging these two becomes desirable. Merging happens between two users referred to as the _target_ and the _source_. After the merge, all the interactions of the source user are attributed to the target user, and the source user is **deleted**. By default, the _Merge Users_ request is only available from server-side integrations for security reasons, to prevent potential abuse. If you need to call this request from a client-side environment (such as a web or mobile app), please contact our support and request access to enable this feature for your database. ```js client.send(new recombee.MergeUsers(targetUserId, sourceUserId, { // optional parameters: cascadeCreate: true, // boolean })); ``` ```kotlin client.send(MergeUsers(targetUserId, sourceUserId, // optional parameters: cascadeCreate = true, // Boolean )) ``` ```swift _ = try await client.send(MergeUsers(targetUserId: targetUserId, sourceUserId: sourceUserId, // optional parameters: cascadeCreate: true // Bool )) ``` ```js client.send(new requests.MergeUsers(targetUserId, sourceUserId, { // optional parameters: cascadeCreate: true, // boolean })); ``` ```python client.send(MergeUsers(target_user_id, source_user_id, # optional parameters: cascade_create=True, # boolean )) ``` ```ruby client.send(MergeUsers.new(target_user_id, source_user_id, { # optional parameters: cascade_create: true, # boolean })) ``` ```java client.send(new MergeUsers(targetUserId, sourceUserId) .setCascadeCreate(true) // boolean ); ``` ```php $client->send(new Reqs\MergeUsers($target_user_id, $source_user_id, [ // optional parameters: 'cascadeCreate' => true, // boolean ])); ``` ```csharp client.Send(new MergeUsers(targetUserId, sourceUserId, // optional parameters: cascadeCreate: true // bool )); ``` ```go request := client.NewMergeUsers(targetUserId, sourceUserId). // optional parameters: SetCascadeCreate(true) // bool _, err := request.Send() ``` ```http PUT /{databaseId}/users/{targetUserId}/merge/{sourceUserId}?cascadeCreate=true ``` --- Calls Limit Per Minute 100 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- targetUserId String Located in: **path** Required: **Yes** ID of the target user. --- sourceUserId String Located in: **path** Required: **Yes** ID of the source user. --- cascadeCreate Boolean Located in: **query** Required: **No** Sets whether the user _targetUserId_ should be created if not present in the database. --- ##### Responses 201 Successful operation. --- 400 The _sourceUserId_ or _targetUserId_ does not match ^\[a-zA-Z0-9\_-:@.\]+$ --- 404 The _sourceUserId_ or _targetUserId_ does not exist in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Users Gets a list of IDs of users currently present in the catalog. ```js const result = await client.send(new requests.ListUsers({ // optional parameters: filter: '\'country\' == "US"', // string count: 10, // integer offset: 0, // integer returnProperties: true, // boolean includedProperties: ['username', 'country'], // array })); ``` ```python result = client.send(ListUsers( # optional parameters: filter='\'country\' == "US"', # string count=10, # integer offset=0, # integer return_properties=True, # boolean included_properties=['username', 'country'], # array )) ``` ```ruby result = client.send(ListUsers.new({ # optional parameters: filter: '\'country\' == "US"', # string count: 10, # integer offset: 0, # integer return_properties: true, # boolean included_properties: ['username', 'country'], # array })) ``` ```java User[] result = client.send(new ListUsers() .setFilter("'country' == \"US\"") // String .setCount(10) // long .setOffset(0) // long .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"username", "country"}) // String[] ); ``` ```php $result = $client->send(new Reqs\ListUsers([ // optional parameters: 'filter' => '\'country\' == "US"', // string 'count' => 10, // integer 'offset' => 0, // integer 'returnProperties' => true, // boolean 'includedProperties' => ['username', 'country'], // array ])); ``` ```csharp IEnumerable result = client.Send(new ListUsers( // optional parameters: filter: "'country' == \"US\"", // string count: 10, // long offset: 0, // long returnProperties: true, // bool includedProperties: new string[] { "username", "country" } // string[] )); ``` ```go request := client.NewListUsers(). // optional parameters: SetFilter("'country' == \"US\""). // string SetCount(10). // int SetOffset(0). // int SetReturnProperties(true). // bool SetIncludedProperties([]string{"username", "country"}) // []string result, err := request.Send() // result is of the type []bindings.User ``` ```http GET /{databaseId}/users/list/?filter='country' == "US" &count=10 &offset=0 &returnProperties=true &includedProperties=username,country ``` --- Calls Limit Per Minute 100 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- filter String Located in: **query** Required: **No** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to filter users to be listed. Only the users for which the expression is _true_ will be returned. --- count Integer Located in: **query** Required: **No** The number of users to be listed. --- offset Integer Located in: **query** Required: **No** Specifies the number of users to skip (ordered by `userId`). --- returnProperties Boolean Located in: **query** Required: **No** Since version: **1.4.0** With `returnProperties=true`, property values of the listed users are returned along with their IDs in a JSON dictionary. Example response: ``` [ { "userId": "user-81", "country": "US", "sex": "M" }, { "userId": "user-314", "country": "CAN", "sex": "F" } ] ``` --- includedProperties Array Located in: **query** Required: **No** Since version: **1.4.0** Allows specifying which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. Example response for `includedProperties=country`: ``` [ { "userId": "user-81", "country": "US" }, { "userId": "user-314", "country": "CAN" } ] ``` --- ##### Responses 200 Successful operation. ``` [ "user-1", "user-2", "user-3" ] ``` --- 404 Invalid URL. --- ## User Properties ### User properties definition User properties are used for modeling users. The following methods allow the definition of user properties. The properties may be thought of as columns in a relational database table. put #### Add User Property Adding a user property is somewhat equivalent to adding a column to the table of users. The users may be characterized by various properties of different types. ```js client.send(new requests.AddUserProperty(propertyName, type, { // optional parameters: role: 'title', // string / Object metadata: [], // array })); ``` ```python client.send(AddUserProperty(property_name, type, # optional parameters: role='title', # string / dict metadata=[], # array )) ``` ```ruby client.send(AddUserProperty.new(property_name, type, { # optional parameters: role: 'title', # string / Hash metadata: [], # array })) ``` ```java client.send(new AddUserProperty(propertyName, type) .setRole(new PropertyRole("title")) // PropertyRole .setMetadata(new PropertyMetadata[]{}) // PropertyMetadata[] ); ``` ```php $client->send(new Reqs\AddUserProperty($property_name, $type, [ // optional parameters: 'role' => 'title', // string / array (map) 'metadata' => [], // array ])); ``` ```csharp client.Send(new AddUserProperty(propertyName, type, // optional parameters: role: new PropertyRole(name: "title"), // PropertyRole metadata: new PropertyMetadata[] {} // PropertyMetadata[] )); ``` ```go request := client.NewAddUserProperty(propertyName, propertyType). // optional parameters: SetRole(bindings.PropertyRole{Name: "title"}). // bindings.PropertyRole SetMetadata([]bindings.PropertyMetadata{}) // []bindings.PropertyMetadata _, err := request.Send() ``` ```http PUT /{databaseId}/users/properties/{propertyName} Body (application/json): { "type": "string", "role": "title", "metadata": [] } ``` --- Since version 1.3.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **1.3.0** ID of your database. --- propertyName String Located in: **path** Required: **Yes** Since version: **1.3.0** Name of the user property to be created. Currently, the following names are reserved: `id`, `userid`, case-insensitively. Also, the length of the property name must not exceed 63 characters. --- type String Located in: **body** Required: **Yes** Value type of the user property to be created. One of: `int`, `double`, `string`, `boolean`, `timestamp`, `set`. * `int` \- Signed integer number. * `double` \- Floating point number. It uses 64-bit base-2 format (IEEE 754 standard). * `string` \- UTF-8 string. * `boolean` \- _true_ / _false_ * `timestamp` \- Value representing date and time. ISO8601-1 pattern (string) or UTC epoch time (number). * `set` \- Set of strings. --- role String Object Located in: **body** Required: **No** [Role](https://docs.recombee.com/api/property_roles_metadata#roles) to assign to the property. --- metadata Array Located in: **body** Required: **No** List of [metadata](https://docs.recombee.com/api/property_roles_metadata#metadata) entries to assign to the property. --- ##### Responses 201 Successful operation. --- 400 Property name does not match ^\[a-zA-Z0-9\_-:\]+$, or it is a reserved keyword (''id'', ''userid''), or its length exceeds 63 characters. Type information is missing, or the given type is invalid. --- 409 Property of the given name is already present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete User Property Deleting a user property is roughly equivalent to removing a column from the table of users. ```js client.send(new requests.DeleteUserProperty(propertyName)); ``` ```python client.send(DeleteUserProperty(property_name)) ``` ```ruby client.send(DeleteUserProperty.new(property_name)) ``` ```java client.send(new DeleteUserProperty(propertyName)); ``` ```php $client->send(new Reqs\DeleteUserProperty($property_name)); ``` ```csharp client.Send(new DeleteUserProperty(propertyName)); ``` ```go request := client.NewDeleteUserProperty(propertyName) _, err := request.Send() ``` ```http DELETE /{databaseId}/users/properties/{propertyName} ``` --- Since version 1.3.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **1.3.0** ID of your database. --- propertyName String Located in: **path** Required: **Yes** Since version: **1.3.0** Name of the property to be deleted. --- ##### Responses 200 Successful operation. --- 400 Property name does not match ^\[a-zA-Z0-9\_-:\]+$. --- 404 Property of the given name is not present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been deleted from the database since the user property was already not present. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### Get User Property Info Gets information about specified user property. ```js const result = await client.send(new requests.GetUserPropertyInfo(propertyName)); ``` ```python result = client.send(GetUserPropertyInfo(property_name)) ``` ```ruby result = client.send(GetUserPropertyInfo.new(property_name)) ``` ```java PropertyInfo result = client.send(new GetUserPropertyInfo(propertyName)); ``` ```php $result = $client->send(new Reqs\GetUserPropertyInfo($property_name)); ``` ```csharp PropertyInfo result = client.Send(new GetUserPropertyInfo(propertyName)); ``` ```go request := client.NewGetUserPropertyInfo(propertyName) result, err := request.Send() // result is of the type bindings.PropertyInfo ``` ```http GET /{databaseId}/users/properties/{propertyName} ``` --- Since version 1.3.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **1.3.0** ID of your database. --- propertyName String Located in: **path** Required: **Yes** Since version: **1.3.0** Name of the property about which the information is to be retrieved. --- ##### Responses 200 Successful operation. ``` { "name": "country", "type": "string" } ``` --- 400 Property name does not match ^\[a-zA-Z0-9\_-:\]+$. --- 404 Property of the given name is not present in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List User Properties Gets the list of all the user properties in your database. ```js const result = await client.send(new requests.ListUserProperties()); ``` ```python result = client.send(ListUserProperties()) ``` ```ruby result = client.send(ListUserProperties.new()) ``` ```java PropertyInfo[] result = client.send(new ListUserProperties()); ``` ```php $result = $client->send(new Reqs\ListUserProperties()); ``` ```csharp IEnumerable result = client.Send(new ListUserProperties()); ``` ```go request := client.NewListUserProperties() result, err := request.Send() // result is of the type []bindings.PropertyInfo ``` ```http GET /{databaseId}/users/properties/list/ ``` --- Since version 1.3.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **1.3.0** ID of your database. --- ##### Responses 200 Successful operation. ``` [ { "name": "country", "type": "string" }, { "name": "sex", "type": "string" } ] ``` --- 404 Invalid URL. --- ### Values of user properties The following methods allow assigning property values to the user. Set values are examined by content-based algorithms and used in building recommendations, especially for users that have only a few interactions (e.g., new users). Useful properties may be, for example, gender or region. The values can be used in filtering using the [context\_user ReQL function](https://docs.recombee.com/reql_functions#context-user-function). post #### Set User Values Sets/updates (some) property values of the given user. The properties (columns) must be previously created by [Add user property](https://docs.recombee.com/api#add-user-property). ```js client.send(new requests.SetUserValues(userId, values, { // optional parameters: cascadeCreate: true, // boolean })); ``` ```python client.send(SetUserValues(user_id, values, # optional parameters: cascade_create=True, # boolean )) ``` ```ruby client.send(SetUserValues.new(user_id, values, { # optional parameters: cascade_create: true, # boolean })) ``` ```java client.send(new SetUserValues(userId, values) .setCascadeCreate(true) // boolean ); ``` ```php $client->send(new Reqs\SetUserValues($user_id, $values, [ // optional parameters: 'cascadeCreate' => true, // boolean ])); ``` ```csharp client.Send(new SetUserValues(userId, values, // optional parameters: cascadeCreate: true // bool )); ``` ```go request := client.NewSetUserValues(userId, values). // optional parameters: SetCascadeCreate(true) // bool _, err := request.Send() ``` ```http POST /{databaseId}/users/{userId} ``` --- Since version 1.3.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **1.3.0** ID of your database. --- userId String Located in: **path** Required: **Yes** Since version: **1.3.0** ID of the user which will be modified. --- Object Located in: **body** Required: **Yes** Since version: **1.3.0** The values for the individual properties. Example of the body: ``` { "country": "US", "sex": "F" } ``` Set user values can also **cascade create** the user if it's not already present in the database. For this functionality: * _When using the client libraries_: Set the optional _cascadeCreate_ parameter to true, just like when creating an interaction. * _When using directly REST API_: Set special "property" `!cascadeCreate`. Example: ``` { "country": "US", "!cascadeCreate": true } ``` Note the exclamation mark (!) at the beginning of the parameter's name to distinguish it from item property names. --- ##### Responses 200 Successful operation. --- 400 Property name does not match ''^\[a-zA-Z0-9\_-:\]+$'', value does not agree to property type. --- 404 Property of the given name is not present in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### Get User Values Gets all the current property values of the given user. ```js const result = await client.send(new requests.GetUserValues(userId)); ``` ```python result = client.send(GetUserValues(user_id)) ``` ```ruby result = client.send(GetUserValues.new(user_id)) ``` ```java Map result = client.send(new GetUserValues(userId)); ``` ```php $result = $client->send(new Reqs\GetUserValues($user_id)); ``` ```csharp User result = client.Send(new GetUserValues(userId)); ``` ```go request := client.NewGetUserValues(userId) result, err := request.Send() // result is of the type map[string]interface{} ``` ```http GET /{databaseId}/users/{userId} ``` --- Since version 1.3.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **1.3.0** ID of your database. --- userId String Located in: **path** Required: **Yes** Since version: **1.3.0** ID of the user whose properties are to be obtained. --- ##### Responses 200 Successful operation. ``` { "country": "US", "sex": "F" } ``` --- 400 The _userId_ does not match ^\[a-zA-Z0-9\_-:@.\]+$ --- 404 User of the given _userId_ is not present in the catalog. If there is no additional info in the JSON response, you probably have an error in your URL. --- ## User-Item Interactions The following methods allow adding, deleting, and listing interactions between the users and the items. ### Detail Views post #### Add Detail View Allowed on Client-Side Adds a detail view of the given item made by the given user. ```js client.send(new recombee.AddDetailView(userId, itemId, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number duration: 35, // integer cascadeCreate: true, // boolean recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object autoPresented: false, // boolean })); ``` ```kotlin client.send(AddDetailView(userId, itemId, // optional parameters: timestamp = Instant.parse("2022-05-13T18:25:43Z"), // Instant duration = 35L, // Long cascadeCreate = true, // Boolean recommId = "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData = emptyMap(), // Map autoPresented = false, // Boolean )) ``` ```swift _ = try await client.send(AddDetailView(userId: userId, itemId: itemId, // optional parameters: timestamp: ISO8601DateFormatter().date(from: "2022-05-13T18:25:43Z")!, // Date duration: 35, // Int cascadeCreate: true, // Bool recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData: [:], // JSONDictionary autoPresented: false // Bool )) ``` ```js client.send(new requests.AddDetailView(userId, itemId, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number duration: 35, // integer cascadeCreate: true, // boolean recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object autoPresented: false, // boolean })); ``` ```python client.send(AddDetailView(user_id, item_id, # optional parameters: timestamp='2022-05-13T18:25:43Z', # string / number duration=35, # integer cascade_create=True, # boolean recomm_id='ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data={}, # dict auto_presented=False, # boolean )) ``` ```ruby client.send(AddDetailView.new(user_id, item_id, { # optional parameters: timestamp: '2022-05-13T18:25:43Z', # string / number duration: 35, # integer cascade_create: true, # boolean recomm_id: 'ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data: {}, # Hash auto_presented: false, # boolean })) ``` ```java client.send(new AddDetailView(userId, itemId) .setTimestamp(Date.from(Instant.parse("2022-05-13T18:25:43Z"))) // Date .setDuration(35) // long .setCascadeCreate(true) // boolean .setRecommId("ce52ada4-e4d9-4885-943c-407db2dee837") // String .setAdditionalData(new HashMap()) // Map .setAutoPresented(false) // boolean ); ``` ```php $client->send(new Reqs\AddDetailView($user_id, $item_id, [ // optional parameters: 'timestamp' => '2022-05-13T18:25:43Z', // string / number 'duration' => 35, // integer 'cascadeCreate' => true, // boolean 'recommId' => 'ce52ada4-e4d9-4885-943c-407db2dee837', // string 'additionalData' => [], // array (map) 'autoPresented' => false, // boolean ])); ``` ```csharp client.Send(new AddDetailView(userId, itemId, // optional parameters: timestamp: DateTime.Parse("2022-05-13T18:25:43Z"), // DateTime duration: 35, // long cascadeCreate: true, // bool recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // string additionalData: new Dictionary(), // Dictionary autoPresented: false // bool )); ``` ```go request := client.NewAddDetailView(userId, itemId). // optional parameters: SetTimestamp(time.Date(2022, time.May, 13, 18, 25, 43, 0, time.UTC)). // time.Time SetDuration(35). // int SetCascadeCreate(true). // bool SetRecommId("ce52ada4-e4d9-4885-943c-407db2dee837"). // string SetAdditionalData(map[string]interface{}{}). // map[string]interface{} SetAutoPresented(false) // bool _, err := request.Send() ``` ```http POST /{databaseId}/detailviews/ Body (application/json): { "userId": "user-1", "itemId": "item-1", "timestamp": "2022-05-13T18:25:43Z", "duration": 35, "cascadeCreate": true, "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "additionalData": {}, "autoPresented": false } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **body** Required: **Yes** User who viewed the item --- itemId String Located in: **body** Required: **Yes** Viewed item --- timestamp String Number Located in: **body** Required: **No** UTC timestamp of the view as ISO8601-1 pattern or UTC epoch time. The default value is the current time. --- duration Integer Located in: **body** Required: **No** Duration of the view --- cascadeCreate Boolean Located in: **body** Required: **No** Sets whether the given user/item should be created if not present in the database. --- recommId String Located in: **body** Required: **No** Since version: **2.2.0** If this detail view is based on a recommendation request, `recommId` is the id of the clicked recommendation. --- additionalData Object Located in: **body** Required: **No** Since version: **2.3.0** Additional data associated with the interaction. The expected structure is defined for specific use cases and will be provided by the Recombee Support team when applicable. --- autoPresented Boolean Located in: **body** Required: **No** Since version: **6.0.0** Indicates whether the item was automatically presented to the user (e.g., in a swiping feed) or explicitly requested by the user (e.g., by clicking on a link). Defaults to `false`. --- ##### Responses 200 Successful operation. --- 400 Given `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. `timestamp` or `duration` is not a real number ≥ 0. --- 404 The `cascadeCreate` is not set true and the `userId` or the `itemId` were found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- 409 A detail view of the exact same `userId`, `itemId`, and `timestamp` is already present in the database. Note that a user may view an item's details multiple times, yet triplets (`userId`, `itemId`, `timestamp`) must be unique. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete Detail View Deletes an existing detail view uniquely specified by (`userId`, `itemId`, and `timestamp`) or all the detail views with the given `userId` and `itemId` if `timestamp` is omitted. ```js client.send(new requests.DeleteDetailView(userId, itemId, { // optional parameters: timestamp: 1652466343, // number })); ``` ```python client.send(DeleteDetailView(user_id, item_id, # optional parameters: timestamp=1652466343, # number )) ``` ```ruby client.send(DeleteDetailView.new(user_id, item_id, { # optional parameters: timestamp: 1652466343, # number })) ``` ```java client.send(new DeleteDetailView(userId, itemId) .setTimestamp(Date.from(Instant.ofEpochSecond(1652466343))) // Date ); ``` ```php $client->send(new Reqs\DeleteDetailView($user_id, $item_id, [ // optional parameters: 'timestamp' => 1652466343, // number ])); ``` ```csharp client.Send(new DeleteDetailView(userId, itemId, // optional parameters: timestamp: DateTimeOffset.FromUnixTimeSeconds(1652466343).UtcDateTime // DateTime )); ``` ```go request := client.NewDeleteDetailView(userId, itemId). // optional parameters: SetTimestamp(time.Unix(1652466343, 0)) // time.Time _, err := request.Send() ``` ```http DELETE /{databaseId}/detailviews/?userId=user-1 &itemId=item-1 ×tamp=1652466343 ``` --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **query** Required: **Yes** ID of the user who made the detail view. --- itemId String Located in: **query** Required: **Yes** ID of the item whose details were viewed. --- timestamp Number Located in: **query** Required: **No** Unix timestamp of the detail view. If the `timestamp` is omitted, then all the detail views with the given `userId` and `itemId` are deleted. --- ##### Responses 200 Successful operation. --- 400 Given `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, or `timestamp` is not a real number ≥ 0. --- 404 The `userId`, `itemId`, or detail view with the given (`userId`, `itemId`, `timestamp`) not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Item Detail Views Lists all the detail views of the given item ever made by different users. ```js const result = await client.send(new requests.ListItemDetailViews(itemId)); ``` ```python result = client.send(ListItemDetailViews(item_id)) ``` ```ruby result = client.send(ListItemDetailViews.new(item_id)) ``` ```java DetailView[] result = client.send(new ListItemDetailViews(itemId)); ``` ```php $result = $client->send(new Reqs\ListItemDetailViews($item_id)); ``` ```csharp IEnumerable result = client.Send(new ListItemDetailViews(itemId)); ``` ```go request := client.NewListItemDetailViews(itemId) result, err := request.Send() // result is of the type []bindings.DetailView ``` ```http GET /{databaseId}/items/{itemId}/detailviews/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item whose detail views are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "userId": "user-a", "duration": 14.23, "autoPresented": true, "timestamp": 1348151906.0 }, { "itemId": "item-x", "userId": "user-b", "duration": null, "autoPresented": false, "timestamp": 1348239363.0 } ] ``` --- 400 The `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `itemId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List User Detail Views Lists all the detail views of different items ever made by the given user. ```js const result = await client.send(new requests.ListUserDetailViews(userId)); ``` ```python result = client.send(ListUserDetailViews(user_id)) ``` ```ruby result = client.send(ListUserDetailViews.new(user_id)) ``` ```java DetailView[] result = client.send(new ListUserDetailViews(userId)); ``` ```php $result = $client->send(new Reqs\ListUserDetailViews($user_id)); ``` ```csharp IEnumerable result = client.Send(new ListUserDetailViews(userId)); ``` ```go request := client.NewListUserDetailViews(userId) result, err := request.Send() // result is of the type []bindings.DetailView ``` ```http GET /{databaseId}/users/{userId}/detailviews/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **path** Required: **Yes** ID of the user whose detail views are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-y", "userId": "user-a", "duration": 134.03, "autoPresented": true, "timestamp": 1348139180.0 }, { "itemId": "item-x", "userId": "user-a", "duration": 14.23, "autoPresented": false, "timestamp": 1348151906.0 } ] ``` --- 400 The `userId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `userId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- ### Purchases post #### Add Purchase Allowed on Client-Side Adds a purchase of the given item made by the given user. ```js client.send(new recombee.AddPurchase(userId, itemId, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean amount: 1, // number price: 25.0, // number profit: 5.0, // number recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object })); ``` ```kotlin client.send(AddPurchase(userId, itemId, // optional parameters: timestamp = Instant.parse("2022-05-13T18:25:43Z"), // Instant cascadeCreate = true, // Boolean amount = 1.0, // Double price = 25.0, // Double profit = 5.0, // Double recommId = "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData = emptyMap(), // Map )) ``` ```swift _ = try await client.send(AddPurchase(userId: userId, itemId: itemId, // optional parameters: timestamp: ISO8601DateFormatter().date(from: "2022-05-13T18:25:43Z")!, // Date cascadeCreate: true, // Bool amount: 1.0, // Double price: 25.0, // Double profit: 5.0, // Double recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData: [:] // JSONDictionary )) ``` ```js client.send(new requests.AddPurchase(userId, itemId, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean amount: 1, // number price: 25.0, // number profit: 5.0, // number recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object })); ``` ```python client.send(AddPurchase(user_id, item_id, # optional parameters: timestamp='2022-05-13T18:25:43Z', # string / number cascade_create=True, # boolean amount=1, # number price=25.0, # number profit=5.0, # number recomm_id='ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data={}, # dict )) ``` ```ruby client.send(AddPurchase.new(user_id, item_id, { # optional parameters: timestamp: '2022-05-13T18:25:43Z', # string / number cascade_create: true, # boolean amount: 1, # number price: 25.0, # number profit: 5.0, # number recomm_id: 'ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data: {}, # Hash })) ``` ```java client.send(new AddPurchase(userId, itemId) .setTimestamp(Date.from(Instant.parse("2022-05-13T18:25:43Z"))) // Date .setCascadeCreate(true) // boolean .setAmount(1.0) // double .setPrice(25.0) // double .setProfit(5.0) // double .setRecommId("ce52ada4-e4d9-4885-943c-407db2dee837") // String .setAdditionalData(new HashMap()) // Map ); ``` ```php $client->send(new Reqs\AddPurchase($user_id, $item_id, [ // optional parameters: 'timestamp' => '2022-05-13T18:25:43Z', // string / number 'cascadeCreate' => true, // boolean 'amount' => 1, // number 'price' => 25.0, // number 'profit' => 5.0, // number 'recommId' => 'ce52ada4-e4d9-4885-943c-407db2dee837', // string 'additionalData' => [], // array (map) ])); ``` ```csharp client.Send(new AddPurchase(userId, itemId, // optional parameters: timestamp: DateTime.Parse("2022-05-13T18:25:43Z"), // DateTime cascadeCreate: true, // bool amount: 1.0, // double price: 25.0, // double profit: 5.0, // double recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // string additionalData: new Dictionary() // Dictionary )); ``` ```go request := client.NewAddPurchase(userId, itemId). // optional parameters: SetTimestamp(time.Date(2022, time.May, 13, 18, 25, 43, 0, time.UTC)). // time.Time SetCascadeCreate(true). // bool SetAmount(1.0). // float64 SetPrice(25.0). // float64 SetProfit(5.0). // float64 SetRecommId("ce52ada4-e4d9-4885-943c-407db2dee837"). // string SetAdditionalData(map[string]interface{}{}) // map[string]interface{} _, err := request.Send() ``` ```http POST /{databaseId}/purchases/ Body (application/json): { "userId": "user-1", "itemId": "item-1", "timestamp": "2022-05-13T18:25:43Z", "cascadeCreate": true, "amount": 1, "price": 25.0, "profit": 5.0, "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "additionalData": {} } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **body** Required: **Yes** User who purchased the item --- itemId String Located in: **body** Required: **Yes** Purchased item --- timestamp String Number Located in: **body** Required: **No** UTC timestamp of the purchase as ISO8601-1 pattern or UTC epoch time. The default value is the current time. --- cascadeCreate Boolean Located in: **body** Required: **No** Sets whether the given user/item should be created if not present in the database. --- amount Number Located in: **body** Required: **No** Since version: **1.6.0** Amount (number) of purchased items. The default is 1\. For example, if `user-x` purchases two `item-y` during a single order (session...), the `amount` should equal 2. --- price Number Located in: **body** Required: **No** Since version: **1.6.0** Price paid by the user for the item. If `amount` is greater than 1, the sum of prices of all the items should be given. --- profit Number Located in: **body** Required: **No** Since version: **1.6.0** Your profit from the purchased item. The profit is natural in the e-commerce domain (for example, if `user-x` purchases `item-y` for $100 and the gross margin is 30 %, then the profit is $30) but is also applicable in other domains (for example, at a news company it may be income from a displayed advertisement on article page). If `amount` is greater than 1, the sum of profit of all the items should be given. --- recommId String Located in: **body** Required: **No** Since version: **2.2.0** If this purchase is based on a recommendation request, `recommId` is the id of the clicked recommendation. --- additionalData Object Located in: **body** Required: **No** Since version: **2.3.0** Additional data associated with the interaction. The expected structure is defined for specific use cases and will be provided by the Recombee Support team when applicable. --- ##### Responses 200 Successful operation. --- 400 The `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. `timestamp` is not a real number ≥ 0. --- 404 The `cascadeCreate` is not set true and the `userId` or the `itemId` were found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- 409 A purchase of the exact same `userId`, `itemId`, and `timestamp` is already present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete Purchase Deletes an existing purchase uniquely specified by `userId`, `itemId`, and `timestamp` or all the purchases with the given `userId` and `itemId` if `timestamp` is omitted. ```js client.send(new requests.DeletePurchase(userId, itemId, { // optional parameters: timestamp: 1652466343, // number })); ``` ```python client.send(DeletePurchase(user_id, item_id, # optional parameters: timestamp=1652466343, # number )) ``` ```ruby client.send(DeletePurchase.new(user_id, item_id, { # optional parameters: timestamp: 1652466343, # number })) ``` ```java client.send(new DeletePurchase(userId, itemId) .setTimestamp(Date.from(Instant.ofEpochSecond(1652466343))) // Date ); ``` ```php $client->send(new Reqs\DeletePurchase($user_id, $item_id, [ // optional parameters: 'timestamp' => 1652466343, // number ])); ``` ```csharp client.Send(new DeletePurchase(userId, itemId, // optional parameters: timestamp: DateTimeOffset.FromUnixTimeSeconds(1652466343).UtcDateTime // DateTime )); ``` ```go request := client.NewDeletePurchase(userId, itemId). // optional parameters: SetTimestamp(time.Unix(1652466343, 0)) // time.Time _, err := request.Send() ``` ```http DELETE /{databaseId}/purchases/?userId=user-1 &itemId=item-1 ×tamp=1652466343 ``` --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **query** Required: **Yes** ID of the user who made the purchase. --- itemId String Located in: **query** Required: **Yes** ID of the item which was purchased. --- timestamp Number Located in: **query** Required: **No** Unix timestamp of the purchase. If the `timestamp` is omitted, then all the purchases with the given `userId` and `itemId` are deleted. --- ##### Responses 200 Successful operation. --- 400 Given `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, or `timestamp` is not a real number ≥ 0. --- 404 The `userId`, `itemId`, or purchase with the given (`userId`, `itemId`, `timestamp`) not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Item Purchases Lists all the ever-made purchases of the given item. ```js const result = await client.send(new requests.ListItemPurchases(itemId)); ``` ```python result = client.send(ListItemPurchases(item_id)) ``` ```ruby result = client.send(ListItemPurchases.new(item_id)) ``` ```java Purchase[] result = client.send(new ListItemPurchases(itemId)); ``` ```php $result = $client->send(new Reqs\ListItemPurchases($item_id)); ``` ```csharp IEnumerable result = client.Send(new ListItemPurchases(itemId)); ``` ```go request := client.NewListItemPurchases(itemId) result, err := request.Send() // result is of the type []bindings.Purchase ``` ```http GET /{databaseId}/items/{itemId}/purchases/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item whose purchases are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "userId": "user-a", "timestamp": 1348151906.0 }, { "itemId": "item-x", "userId": "user-b", "timestamp": 1348327154.0 } ] ``` --- 400 The `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `itemId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List User Purchases Lists all the purchases ever made by the given user. ```js const result = await client.send(new requests.ListUserPurchases(userId)); ``` ```python result = client.send(ListUserPurchases(user_id)) ``` ```ruby result = client.send(ListUserPurchases.new(user_id)) ``` ```java Purchase[] result = client.send(new ListUserPurchases(userId)); ``` ```php $result = $client->send(new Reqs\ListUserPurchases($user_id)); ``` ```csharp IEnumerable result = client.Send(new ListUserPurchases(userId)); ``` ```go request := client.NewListUserPurchases(userId) result, err := request.Send() // result is of the type []bindings.Purchase ``` ```http GET /{databaseId}/users/{userId}/purchases/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **path** Required: **Yes** ID of the user whose purchases are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "timestamp": 1348151906.0, "userId": "user-a" }, { "itemId": "item-z", "timestamp": 1348239363.0, "userId": "user-a" } ] ``` --- 400 The `userId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `userId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- ### Ratings post #### Add Rating Allowed on Client-Side Adds a rating of the given item made by the given user. ```js client.send(new recombee.AddRating(userId, itemId, rating, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object })); ``` ```kotlin client.send(AddRating(userId, itemId, rating, // optional parameters: timestamp = Instant.parse("2022-05-13T18:25:43Z"), // Instant cascadeCreate = true, // Boolean recommId = "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData = emptyMap(), // Map )) ``` ```swift _ = try await client.send(AddRating(userId: userId, itemId: itemId, rating: rating, // optional parameters: timestamp: ISO8601DateFormatter().date(from: "2022-05-13T18:25:43Z")!, // Date cascadeCreate: true, // Bool recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData: [:] // JSONDictionary )) ``` ```js client.send(new requests.AddRating(userId, itemId, rating, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object })); ``` ```python client.send(AddRating(user_id, item_id, rating, # optional parameters: timestamp='2022-05-13T18:25:43Z', # string / number cascade_create=True, # boolean recomm_id='ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data={}, # dict )) ``` ```ruby client.send(AddRating.new(user_id, item_id, rating, { # optional parameters: timestamp: '2022-05-13T18:25:43Z', # string / number cascade_create: true, # boolean recomm_id: 'ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data: {}, # Hash })) ``` ```java client.send(new AddRating(userId, itemId, rating) .setTimestamp(Date.from(Instant.parse("2022-05-13T18:25:43Z"))) // Date .setCascadeCreate(true) // boolean .setRecommId("ce52ada4-e4d9-4885-943c-407db2dee837") // String .setAdditionalData(new HashMap()) // Map ); ``` ```php $client->send(new Reqs\AddRating($user_id, $item_id, $rating, [ // optional parameters: 'timestamp' => '2022-05-13T18:25:43Z', // string / number 'cascadeCreate' => true, // boolean 'recommId' => 'ce52ada4-e4d9-4885-943c-407db2dee837', // string 'additionalData' => [], // array (map) ])); ``` ```csharp client.Send(new AddRating(userId, itemId, rating, // optional parameters: timestamp: DateTime.Parse("2022-05-13T18:25:43Z"), // DateTime cascadeCreate: true, // bool recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // string additionalData: new Dictionary() // Dictionary )); ``` ```go request := client.NewAddRating(userId, itemId, rating). // optional parameters: SetTimestamp(time.Date(2022, time.May, 13, 18, 25, 43, 0, time.UTC)). // time.Time SetCascadeCreate(true). // bool SetRecommId("ce52ada4-e4d9-4885-943c-407db2dee837"). // string SetAdditionalData(map[string]interface{}{}) // map[string]interface{} _, err := request.Send() ``` ```http POST /{databaseId}/ratings/ Body (application/json): { "userId": "user-1", "itemId": "item-1", "timestamp": "2022-05-13T18:25:43Z", "rating": 0.5, "cascadeCreate": true, "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "additionalData": {} } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **body** Required: **Yes** User who submitted the rating --- itemId String Located in: **body** Required: **Yes** Rated item --- timestamp String Number Located in: **body** Required: **No** UTC timestamp of the rating as ISO8601-1 pattern or UTC epoch time. The default value is the current time. --- rating Number Located in: **body** Required: **Yes** Rating rescaled to interval \[-1.0,1.0\], where -1.0 means the worst rating possible, 0.0 means neutral, and 1.0 means absolutely positive rating. For example, in the case of 5-star evaluations, rating = (numStars-3)/2 formula may be used for the conversion. --- cascadeCreate Boolean Located in: **body** Required: **No** Sets whether the given user/item should be created if not present in the database. --- recommId String Located in: **body** Required: **No** Since version: **2.2.0** If this rating is based on a recommendation request, `recommId` is the id of the clicked recommendation. --- additionalData Object Located in: **body** Required: **No** Since version: **2.3.0** Additional data associated with the interaction. The expected structure is defined for specific use cases and will be provided by the Recombee Support team when applicable. --- ##### Responses 200 Successful operation. --- 400 The `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, or rating is not a real number from \[-1.0,1.0\], or timestamp is not a real number ≥ 0. --- 404 The `cascadeCreate` is not set true and the `userId` or the `itemId` were found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- 409 A rating of the exact same `userId`, `itemId`, and `timestamp` is already present in the database. Note that a user may rate an item multiple times, yet triplets (userId, itemId, timestamp) must be unique. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete Rating Deletes an existing rating specified by (`userId`, `itemId`, `timestamp`) from the database or all the ratings with the given `userId` and `itemId` if `timestamp` is omitted. ```js client.send(new requests.DeleteRating(userId, itemId, { // optional parameters: timestamp: 1652466343, // number })); ``` ```python client.send(DeleteRating(user_id, item_id, # optional parameters: timestamp=1652466343, # number )) ``` ```ruby client.send(DeleteRating.new(user_id, item_id, { # optional parameters: timestamp: 1652466343, # number })) ``` ```java client.send(new DeleteRating(userId, itemId) .setTimestamp(Date.from(Instant.ofEpochSecond(1652466343))) // Date ); ``` ```php $client->send(new Reqs\DeleteRating($user_id, $item_id, [ // optional parameters: 'timestamp' => 1652466343, // number ])); ``` ```csharp client.Send(new DeleteRating(userId, itemId, // optional parameters: timestamp: DateTimeOffset.FromUnixTimeSeconds(1652466343).UtcDateTime // DateTime )); ``` ```go request := client.NewDeleteRating(userId, itemId). // optional parameters: SetTimestamp(time.Unix(1652466343, 0)) // time.Time _, err := request.Send() ``` ```http DELETE /{databaseId}/ratings/?userId=user-1 &itemId=item-1 ×tamp=1652466343 ``` --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **query** Required: **Yes** ID of the user who rated the item. --- itemId String Located in: **query** Required: **Yes** ID of the item which was rated. --- timestamp Number Located in: **query** Required: **No** Unix timestamp of the rating. If the `timestamp` is omitted, then all the ratings with the given `userId` and `itemId` are deleted. --- ##### Responses 200 Successful operation. --- 400 Given `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, or `timestamp` is not a real number ≥ 0. --- 404 The `userId`, `itemId` or rating with the given (`userId`, `itemId`, `timestamp`) not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Item Ratings Lists all the ratings of an item ever submitted by different users. ```js const result = await client.send(new requests.ListItemRatings(itemId)); ``` ```python result = client.send(ListItemRatings(item_id)) ``` ```ruby result = client.send(ListItemRatings.new(item_id)) ``` ```java Rating[] result = client.send(new ListItemRatings(itemId)); ``` ```php $result = $client->send(new Reqs\ListItemRatings($item_id)); ``` ```csharp IEnumerable result = client.Send(new ListItemRatings(itemId)); ``` ```go request := client.NewListItemRatings(itemId) result, err := request.Send() // result is of the type []bindings.Rating ``` ```http GET /{databaseId}/items/{itemId}/ratings/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item whose ratings are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "userId": "user-a", "rating": -0.25, "timestamp": 1348151906.0 }, { "itemId": "item-x", "userId": "user-b", "rating": 0.0, "timestamp": 1348239363.0 } ] ``` --- 400 The `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `itemId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List User Ratings Lists all the ratings ever submitted by the given user. ```js const result = await client.send(new requests.ListUserRatings(userId)); ``` ```python result = client.send(ListUserRatings(user_id)) ``` ```ruby result = client.send(ListUserRatings.new(user_id)) ``` ```java Rating[] result = client.send(new ListUserRatings(userId)); ``` ```php $result = $client->send(new Reqs\ListUserRatings($user_id)); ``` ```csharp IEnumerable result = client.Send(new ListUserRatings(userId)); ``` ```go request := client.NewListUserRatings(userId) result, err := request.Send() // result is of the type []bindings.Rating ``` ```http GET /{databaseId}/users/{userId}/ratings/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **path** Required: **Yes** ID of the user whose ratings are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-y", "userId": "user-a", "rating": 0.5, "timestamp": 1348139180.0 }, { "itemId": "item-x", "userId": "user-a", "rating": -0.25, "timestamp": 1348151906.0 } ] ``` --- 400 The `userId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `userId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- ### Cart Additions post #### Add Cart Addition Allowed on Client-Side Adds a cart addition of the given item made by the given user. ```js client.send(new recombee.AddCartAddition(userId, itemId, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean amount: 1, // number price: 25.0, // number recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object })); ``` ```kotlin client.send(AddCartAddition(userId, itemId, // optional parameters: timestamp = Instant.parse("2022-05-13T18:25:43Z"), // Instant cascadeCreate = true, // Boolean amount = 1.0, // Double price = 25.0, // Double recommId = "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData = emptyMap(), // Map )) ``` ```swift _ = try await client.send(AddCartAddition(userId: userId, itemId: itemId, // optional parameters: timestamp: ISO8601DateFormatter().date(from: "2022-05-13T18:25:43Z")!, // Date cascadeCreate: true, // Bool amount: 1.0, // Double price: 25.0, // Double recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData: [:] // JSONDictionary )) ``` ```js client.send(new requests.AddCartAddition(userId, itemId, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean amount: 1, // number price: 25.0, // number recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object })); ``` ```python client.send(AddCartAddition(user_id, item_id, # optional parameters: timestamp='2022-05-13T18:25:43Z', # string / number cascade_create=True, # boolean amount=1, # number price=25.0, # number recomm_id='ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data={}, # dict )) ``` ```ruby client.send(AddCartAddition.new(user_id, item_id, { # optional parameters: timestamp: '2022-05-13T18:25:43Z', # string / number cascade_create: true, # boolean amount: 1, # number price: 25.0, # number recomm_id: 'ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data: {}, # Hash })) ``` ```java client.send(new AddCartAddition(userId, itemId) .setTimestamp(Date.from(Instant.parse("2022-05-13T18:25:43Z"))) // Date .setCascadeCreate(true) // boolean .setAmount(1.0) // double .setPrice(25.0) // double .setRecommId("ce52ada4-e4d9-4885-943c-407db2dee837") // String .setAdditionalData(new HashMap()) // Map ); ``` ```php $client->send(new Reqs\AddCartAddition($user_id, $item_id, [ // optional parameters: 'timestamp' => '2022-05-13T18:25:43Z', // string / number 'cascadeCreate' => true, // boolean 'amount' => 1, // number 'price' => 25.0, // number 'recommId' => 'ce52ada4-e4d9-4885-943c-407db2dee837', // string 'additionalData' => [], // array (map) ])); ``` ```csharp client.Send(new AddCartAddition(userId, itemId, // optional parameters: timestamp: DateTime.Parse("2022-05-13T18:25:43Z"), // DateTime cascadeCreate: true, // bool amount: 1.0, // double price: 25.0, // double recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // string additionalData: new Dictionary() // Dictionary )); ``` ```go request := client.NewAddCartAddition(userId, itemId). // optional parameters: SetTimestamp(time.Date(2022, time.May, 13, 18, 25, 43, 0, time.UTC)). // time.Time SetCascadeCreate(true). // bool SetAmount(1.0). // float64 SetPrice(25.0). // float64 SetRecommId("ce52ada4-e4d9-4885-943c-407db2dee837"). // string SetAdditionalData(map[string]interface{}{}) // map[string]interface{} _, err := request.Send() ``` ```http POST /{databaseId}/cartadditions/ Body (application/json): { "userId": "user-1", "itemId": "item-1", "timestamp": "2022-05-13T18:25:43Z", "cascadeCreate": true, "amount": 1, "price": 25.0, "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "additionalData": {} } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **body** Required: **Yes** User who added the item to the cart --- itemId String Located in: **body** Required: **Yes** Item added to the cart --- timestamp String Number Located in: **body** Required: **No** UTC timestamp of the cart addition as ISO8601-1 pattern or UTC epoch time. The default value is the current time. --- cascadeCreate Boolean Located in: **body** Required: **No** Sets whether the given user/item should be created if not present in the database. --- amount Number Located in: **body** Required: **No** Since version: **1.6.0** Amount (number) added to cart. The default is 1\. For example, if `user-x` adds two `item-y` during a single order (session...), the `amount` should equal 2. --- price Number Located in: **body** Required: **No** Since version: **1.6.0** Price of the added item. If `amount` is greater than 1, the sum of prices of all the items should be given. --- recommId String Located in: **body** Required: **No** Since version: **2.2.0** If this cart addition is based on a recommendation request, `recommId` is the id of the clicked recommendation. --- additionalData Object Located in: **body** Required: **No** Since version: **2.3.0** Additional data associated with the interaction. The expected structure is defined for specific use cases and will be provided by the Recombee Support team when applicable. --- ##### Responses 200 Successful operation. --- 400 The `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, `timestamp` is not a real number ≥ 0. --- 404 The `cascadeCreate` is not set true and the `userId` or the `itemId` were found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- 409 A cart addition of the exact same `userId`, `itemId`, and `timestamp` is already present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete Cart Addition Deletes an existing cart addition uniquely specified by `userId`, `itemId`, and `timestamp` or all the cart additions with the given `userId` and `itemId` if `timestamp` is omitted. ```js client.send(new requests.DeleteCartAddition(userId, itemId, { // optional parameters: timestamp: 1652466343, // number })); ``` ```python client.send(DeleteCartAddition(user_id, item_id, # optional parameters: timestamp=1652466343, # number )) ``` ```ruby client.send(DeleteCartAddition.new(user_id, item_id, { # optional parameters: timestamp: 1652466343, # number })) ``` ```java client.send(new DeleteCartAddition(userId, itemId) .setTimestamp(Date.from(Instant.ofEpochSecond(1652466343))) // Date ); ``` ```php $client->send(new Reqs\DeleteCartAddition($user_id, $item_id, [ // optional parameters: 'timestamp' => 1652466343, // number ])); ``` ```csharp client.Send(new DeleteCartAddition(userId, itemId, // optional parameters: timestamp: DateTimeOffset.FromUnixTimeSeconds(1652466343).UtcDateTime // DateTime )); ``` ```go request := client.NewDeleteCartAddition(userId, itemId). // optional parameters: SetTimestamp(time.Unix(1652466343, 0)) // time.Time _, err := request.Send() ``` ```http DELETE /{databaseId}/cartadditions/?userId=user-1 &itemId=item-1 ×tamp=1652466343 ``` --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **query** Required: **Yes** ID of the user who made the cart addition. --- itemId String Located in: **query** Required: **Yes** ID of the item which was added to the cart. --- timestamp Number Located in: **query** Required: **No** Unix timestamp of the cart addition. If the `timestamp` is omitted, then all the cart additions with the given `userId` and `itemId` are deleted. --- ##### Responses 200 Successful operation. --- 400 Given `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, or `timestamp` is not a real number ≥ 0. --- 404 The `userId`, `itemId`, or cart addition with the given (`userId`, `itemId`, `timestamp`) not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Item Cart Additions Lists all the ever-made cart additions of the given item. ```js const result = await client.send(new requests.ListItemCartAdditions(itemId)); ``` ```python result = client.send(ListItemCartAdditions(item_id)) ``` ```ruby result = client.send(ListItemCartAdditions.new(item_id)) ``` ```java CartAddition[] result = client.send(new ListItemCartAdditions(itemId)); ``` ```php $result = $client->send(new Reqs\ListItemCartAdditions($item_id)); ``` ```csharp IEnumerable result = client.Send(new ListItemCartAdditions(itemId)); ``` ```go request := client.NewListItemCartAdditions(itemId) result, err := request.Send() // result is of the type []bindings.CartAddition ``` ```http GET /{databaseId}/items/{itemId}/cartadditions/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item whose cart additions are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "userId": "user-a", "timestamp": 1348151906.0 }, { "itemId": "item-x", "userId": "user-a", "timestamp": 1348327154.0 } ] ``` --- 400 The `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `itemId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List User Cart Additions Lists all the cart additions ever made by the given user. ```js const result = await client.send(new requests.ListUserCartAdditions(userId)); ``` ```python result = client.send(ListUserCartAdditions(user_id)) ``` ```ruby result = client.send(ListUserCartAdditions.new(user_id)) ``` ```java CartAddition[] result = client.send(new ListUserCartAdditions(userId)); ``` ```php $result = $client->send(new Reqs\ListUserCartAdditions($user_id)); ``` ```csharp IEnumerable result = client.Send(new ListUserCartAdditions(userId)); ``` ```go request := client.NewListUserCartAdditions(userId) result, err := request.Send() // result is of the type []bindings.CartAddition ``` ```http GET /{databaseId}/users/{userId}/cartadditions/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **path** Required: **Yes** ID of the user whose cart additions are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "timestamp": 1348151906.0, "userId": "user-a" }, { "itemId": "item-z", "timestamp": 1348239363.0, "userId": "user-a" } ] ``` --- 400 The `userId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `userId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- ### Bookmarks post #### Add Bookmark Allowed on Client-Side Adds a bookmark of the given item made by the given user. ```js client.send(new recombee.AddBookmark(userId, itemId, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object })); ``` ```kotlin client.send(AddBookmark(userId, itemId, // optional parameters: timestamp = Instant.parse("2022-05-13T18:25:43Z"), // Instant cascadeCreate = true, // Boolean recommId = "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData = emptyMap(), // Map )) ``` ```swift _ = try await client.send(AddBookmark(userId: userId, itemId: itemId, // optional parameters: timestamp: ISO8601DateFormatter().date(from: "2022-05-13T18:25:43Z")!, // Date cascadeCreate: true, // Bool recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData: [:] // JSONDictionary )) ``` ```js client.send(new requests.AddBookmark(userId, itemId, { // optional parameters: timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object })); ``` ```python client.send(AddBookmark(user_id, item_id, # optional parameters: timestamp='2022-05-13T18:25:43Z', # string / number cascade_create=True, # boolean recomm_id='ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data={}, # dict )) ``` ```ruby client.send(AddBookmark.new(user_id, item_id, { # optional parameters: timestamp: '2022-05-13T18:25:43Z', # string / number cascade_create: true, # boolean recomm_id: 'ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data: {}, # Hash })) ``` ```java client.send(new AddBookmark(userId, itemId) .setTimestamp(Date.from(Instant.parse("2022-05-13T18:25:43Z"))) // Date .setCascadeCreate(true) // boolean .setRecommId("ce52ada4-e4d9-4885-943c-407db2dee837") // String .setAdditionalData(new HashMap()) // Map ); ``` ```php $client->send(new Reqs\AddBookmark($user_id, $item_id, [ // optional parameters: 'timestamp' => '2022-05-13T18:25:43Z', // string / number 'cascadeCreate' => true, // boolean 'recommId' => 'ce52ada4-e4d9-4885-943c-407db2dee837', // string 'additionalData' => [], // array (map) ])); ``` ```csharp client.Send(new AddBookmark(userId, itemId, // optional parameters: timestamp: DateTime.Parse("2022-05-13T18:25:43Z"), // DateTime cascadeCreate: true, // bool recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // string additionalData: new Dictionary() // Dictionary )); ``` ```go request := client.NewAddBookmark(userId, itemId). // optional parameters: SetTimestamp(time.Date(2022, time.May, 13, 18, 25, 43, 0, time.UTC)). // time.Time SetCascadeCreate(true). // bool SetRecommId("ce52ada4-e4d9-4885-943c-407db2dee837"). // string SetAdditionalData(map[string]interface{}{}) // map[string]interface{} _, err := request.Send() ``` ```http POST /{databaseId}/bookmarks/ Body (application/json): { "userId": "user-1", "itemId": "item-1", "timestamp": "2022-05-13T18:25:43Z", "cascadeCreate": true, "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "additionalData": {} } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **body** Required: **Yes** User who bookmarked the item --- itemId String Located in: **body** Required: **Yes** Bookmarked item --- timestamp String Number Located in: **body** Required: **No** UTC timestamp of the bookmark as ISO8601-1 pattern or UTC epoch time. The default value is the current time. --- cascadeCreate Boolean Located in: **body** Required: **No** Sets whether the given user/item should be created if not present in the database. --- recommId String Located in: **body** Required: **No** Since version: **2.2.0** If this bookmark is based on a recommendation request, `recommId` is the id of the clicked recommendation. --- additionalData Object Located in: **body** Required: **No** Since version: **2.3.0** Additional data associated with the interaction. The expected structure is defined for specific use cases and will be provided by the Recombee Support team when applicable. --- ##### Responses 200 Successful operation. --- 400 The `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, `timestamp` is not a real number ≥ 0. --- 404 The `cascadeCreate` is not set true and the `userId` or the `itemId` were found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- 409 A bookmark of the exact same `userId`, `itemId`, and `timestamp` is already present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete Bookmark Deletes a bookmark uniquely specified by `userId`, `itemId`, and `timestamp` or all the bookmarks with the given `userId` and `itemId` if `timestamp` is omitted. ```js client.send(new requests.DeleteBookmark(userId, itemId, { // optional parameters: timestamp: 1652466343, // number })); ``` ```python client.send(DeleteBookmark(user_id, item_id, # optional parameters: timestamp=1652466343, # number )) ``` ```ruby client.send(DeleteBookmark.new(user_id, item_id, { # optional parameters: timestamp: 1652466343, # number })) ``` ```java client.send(new DeleteBookmark(userId, itemId) .setTimestamp(Date.from(Instant.ofEpochSecond(1652466343))) // Date ); ``` ```php $client->send(new Reqs\DeleteBookmark($user_id, $item_id, [ // optional parameters: 'timestamp' => 1652466343, // number ])); ``` ```csharp client.Send(new DeleteBookmark(userId, itemId, // optional parameters: timestamp: DateTimeOffset.FromUnixTimeSeconds(1652466343).UtcDateTime // DateTime )); ``` ```go request := client.NewDeleteBookmark(userId, itemId). // optional parameters: SetTimestamp(time.Unix(1652466343, 0)) // time.Time _, err := request.Send() ``` ```http DELETE /{databaseId}/bookmarks/?userId=user-1 &itemId=item-1 ×tamp=1652466343 ``` --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **query** Required: **Yes** ID of the user who made the bookmark. --- itemId String Located in: **query** Required: **Yes** ID of the item which was bookmarked. --- timestamp Number Located in: **query** Required: **No** Unix timestamp of the bookmark. If the `timestamp` is omitted, then all the bookmarks with the given `userId` and `itemId` are deleted. --- ##### Responses 200 Successful operation. --- 400 Given `userId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, or `timestamp` is not a real number ≥ 0. --- 404 The `userId`, `itemId`, or bookmark with the given (`userId`, `itemId`, `timestamp`) not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Item Bookmarks Lists all the ever-made bookmarks of the given item. ```js const result = await client.send(new requests.ListItemBookmarks(itemId)); ``` ```python result = client.send(ListItemBookmarks(item_id)) ``` ```ruby result = client.send(ListItemBookmarks.new(item_id)) ``` ```java Bookmark[] result = client.send(new ListItemBookmarks(itemId)); ``` ```php $result = $client->send(new Reqs\ListItemBookmarks($item_id)); ``` ```csharp IEnumerable result = client.Send(new ListItemBookmarks(itemId)); ``` ```go request := client.NewListItemBookmarks(itemId) result, err := request.Send() // result is of the type []bindings.Bookmark ``` ```http GET /{databaseId}/items/{itemId}/bookmarks/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- itemId String Located in: **path** Required: **Yes** ID of the item whose bookmarks are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "userId": "user-a", "timestamp": 1348151906.0 }, { "itemId": "item-x", "userId": "user-a", "timestamp": 1348327154.0 } ] ``` --- 400 The `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `itemId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List User Bookmarks Lists all the bookmarks ever made by the given user. ```js const result = await client.send(new requests.ListUserBookmarks(userId)); ``` ```python result = client.send(ListUserBookmarks(user_id)) ``` ```ruby result = client.send(ListUserBookmarks.new(user_id)) ``` ```java Bookmark[] result = client.send(new ListUserBookmarks(userId)); ``` ```php $result = $client->send(new Reqs\ListUserBookmarks($user_id)); ``` ```csharp IEnumerable result = client.Send(new ListUserBookmarks(userId)); ``` ```go request := client.NewListUserBookmarks(userId) result, err := request.Send() // result is of the type []bindings.Bookmark ``` ```http GET /{databaseId}/users/{userId}/bookmarks/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- userId String Located in: **path** Required: **Yes** ID of the user whose bookmarks are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "timestamp": 1348151906.0, "userId": "user-a" }, { "itemId": "item-z", "timestamp": 1348239363.0, "userId": "user-a" } ] ``` --- 400 The `userId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `userId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- ### View Portions post #### Set View Portion Allowed on Client-Side Sets viewed portion of an item (for example a video or article) by a user (at a session). If you send a new request with the same (`userId`, `itemId`, `sessionId`), the portion gets updated. ```js client.send(new recombee.SetViewPortion(userId, itemId, portion, { // optional parameters: sessionId: 'ABAD1D', // string timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object autoPresented: false, // boolean timeSpent: 42, // number })); ``` ```kotlin client.send(SetViewPortion(userId, itemId, portion, // optional parameters: sessionId = "ABAD1D", // String timestamp = Instant.parse("2022-05-13T18:25:43Z"), // Instant cascadeCreate = true, // Boolean recommId = "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData = emptyMap(), // Map autoPresented = false, // Boolean timeSpent = 42.0, // Double )) ``` ```swift _ = try await client.send(SetViewPortion(userId: userId, itemId: itemId, portion: portion, // optional parameters: sessionId: "ABAD1D", // String timestamp: ISO8601DateFormatter().date(from: "2022-05-13T18:25:43Z")!, // Date cascadeCreate: true, // Bool recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // String additionalData: [:], // JSONDictionary autoPresented: false, // Bool timeSpent: 42.0 // Double )) ``` ```js client.send(new requests.SetViewPortion(userId, itemId, portion, { // optional parameters: sessionId: 'ABAD1D', // string timestamp: '2022-05-13T18:25:43Z', // string / number cascadeCreate: true, // boolean recommId: 'ce52ada4-e4d9-4885-943c-407db2dee837', // string additionalData: {}, // Object autoPresented: false, // boolean timeSpent: 42, // number })); ``` ```python client.send(SetViewPortion(user_id, item_id, portion, # optional parameters: session_id='ABAD1D', # string timestamp='2022-05-13T18:25:43Z', # string / number cascade_create=True, # boolean recomm_id='ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data={}, # dict auto_presented=False, # boolean time_spent=42, # number )) ``` ```ruby client.send(SetViewPortion.new(user_id, item_id, portion, { # optional parameters: session_id: 'ABAD1D', # string timestamp: '2022-05-13T18:25:43Z', # string / number cascade_create: true, # boolean recomm_id: 'ce52ada4-e4d9-4885-943c-407db2dee837', # string additional_data: {}, # Hash auto_presented: false, # boolean time_spent: 42, # number })) ``` ```java client.send(new SetViewPortion(userId, itemId, portion) .setSessionId("ABAD1D") // String .setTimestamp(Date.from(Instant.parse("2022-05-13T18:25:43Z"))) // Date .setCascadeCreate(true) // boolean .setRecommId("ce52ada4-e4d9-4885-943c-407db2dee837") // String .setAdditionalData(new HashMap()) // Map .setAutoPresented(false) // boolean .setTimeSpent(42.0) // double ); ``` ```php $client->send(new Reqs\SetViewPortion($user_id, $item_id, $portion, [ // optional parameters: 'sessionId' => 'ABAD1D', // string 'timestamp' => '2022-05-13T18:25:43Z', // string / number 'cascadeCreate' => true, // boolean 'recommId' => 'ce52ada4-e4d9-4885-943c-407db2dee837', // string 'additionalData' => [], // array (map) 'autoPresented' => false, // boolean 'timeSpent' => 42, // number ])); ``` ```csharp client.Send(new SetViewPortion(userId, itemId, portion, // optional parameters: sessionId: "ABAD1D", // string timestamp: DateTime.Parse("2022-05-13T18:25:43Z"), // DateTime cascadeCreate: true, // bool recommId: "ce52ada4-e4d9-4885-943c-407db2dee837", // string additionalData: new Dictionary(), // Dictionary autoPresented: false, // bool timeSpent: 42.0 // double )); ``` ```go request := client.NewSetViewPortion(userId, itemId, portion). // optional parameters: SetSessionId("ABAD1D"). // string SetTimestamp(time.Date(2022, time.May, 13, 18, 25, 43, 0, time.UTC)). // time.Time SetCascadeCreate(true). // bool SetRecommId("ce52ada4-e4d9-4885-943c-407db2dee837"). // string SetAdditionalData(map[string]interface{}{}). // map[string]interface{} SetAutoPresented(false). // bool SetTimeSpent(42.0) // float64 _, err := request.Send() ``` ```http POST /{databaseId}/viewportions/ Body (application/json): { "userId": "user-1", "itemId": "item-1", "portion": 0.5, "sessionId": "ABAD1D", "timestamp": "2022-05-13T18:25:43Z", "cascadeCreate": true, "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "additionalData": {}, "autoPresented": false, "timeSpent": 42 } ``` --- Since version 2.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **2.1.0** ID of your database. --- userId String Located in: **body** Required: **Yes** Since version: **2.1.0** User who viewed a portion of the item --- itemId String Located in: **body** Required: **Yes** Since version: **2.1.0** Viewed item --- portion Number Located in: **body** Required: **Yes** Since version: **2.1.0** Viewed portion of the item (number between 0.0 (viewed nothing) and 1.0 (viewed full item) ). It should be the actual viewed part of the item, no matter the seeking. For example, if the user seeked immediately to half of the item and then viewed 10% of the item, the `portion` should still be `0.1`. --- sessionId String Located in: **body** Required: **No** Since version: **2.1.0** ID of the session in which the user viewed the item. Default is `null` (`None`, `nil`, `NULL` etc., depending on the language). --- timestamp String Number Located in: **body** Required: **No** Since version: **2.1.0** UTC timestamp of the view portion as ISO8601-1 pattern or UTC epoch time. The default value is the current time. --- cascadeCreate Boolean Located in: **body** Required: **No** Since version: **2.1.0** Sets whether the given user/item should be created if not present in the database. --- recommId String Located in: **body** Required: **No** Since version: **2.2.0** If this view portion is based on a recommendation request, `recommId` is the id of the clicked recommendation. --- additionalData Object Located in: **body** Required: **No** Since version: **2.3.0** Additional data associated with the interaction. The expected structure is defined for specific use cases and will be provided by the Recombee Support team when applicable. --- autoPresented Boolean Located in: **body** Required: **No** Since version: **6.0.0** Indicates whether the item was automatically presented to the user (e.g., in a swiping feed) or explicitly requested by the user (e.g., by clicking on a link). Defaults to `false`. --- timeSpent Number Located in: **body** Required: **No** Since version: **6.0.0** The duration (in seconds) that the user viewed the item. In update requests, this value may only increase and is required only if it has changed. --- ##### Responses 200 Successful operation. --- 400 The `userId`, `itemId` or `sessionId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, or the `portion` is not a real number from \[0.0,1.0\]. --- 404 The `cascadeCreate` is not set true and the `userId` or the `itemId` were found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- 409 A view portion of the exact same `userId`, `itemId`, and a greater or equal `timestamp` (or a greater `portion`) is already present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete View Portion Deletes an existing view portion specified by (`userId`, `itemId`, `sessionId`) from the database. ```js client.send(new requests.DeleteViewPortion(userId, itemId, { // optional parameters: sessionId: 'ABAD1D', // string })); ``` ```python client.send(DeleteViewPortion(user_id, item_id, # optional parameters: session_id='ABAD1D', # string )) ``` ```ruby client.send(DeleteViewPortion.new(user_id, item_id, { # optional parameters: session_id: 'ABAD1D', # string })) ``` ```java client.send(new DeleteViewPortion(userId, itemId) .setSessionId("ABAD1D") // String ); ``` ```php $client->send(new Reqs\DeleteViewPortion($user_id, $item_id, [ // optional parameters: 'sessionId' => 'ABAD1D', // string ])); ``` ```csharp client.Send(new DeleteViewPortion(userId, itemId, // optional parameters: sessionId: "ABAD1D" // string )); ``` ```go request := client.NewDeleteViewPortion(userId, itemId). // optional parameters: SetSessionId("ABAD1D") // string _, err := request.Send() ``` ```http DELETE /{databaseId}/viewportions/?userId=user-1 &itemId=item-1 &sessionId=ABAD1D ``` --- Since version 2.1.0 --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **2.1.0** ID of your database. --- userId String Located in: **query** Required: **Yes** Since version: **2.1.0** ID of the user who rated the item. --- itemId String Located in: **query** Required: **Yes** Since version: **2.1.0** ID of the item which was rated. --- sessionId String Located in: **query** Required: **No** Since version: **2.1.0** Identifier of a session. --- ##### Responses 200 Successful operation. --- 400 Given `userId`, `itemId` or `sessionId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 The `userId`, `itemId` or view portion with the given (`userId`, `itemId`, `sessionId`) not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Item View Portions Lists all the view portions of an item ever submitted by different users. ```js const result = await client.send(new requests.ListItemViewPortions(itemId)); ``` ```python result = client.send(ListItemViewPortions(item_id)) ``` ```ruby result = client.send(ListItemViewPortions.new(item_id)) ``` ```java ViewPortion[] result = client.send(new ListItemViewPortions(itemId)); ``` ```php $result = $client->send(new Reqs\ListItemViewPortions($item_id)); ``` ```csharp IEnumerable result = client.Send(new ListItemViewPortions(itemId)); ``` ```go request := client.NewListItemViewPortions(itemId) result, err := request.Send() // result is of the type []bindings.ViewPortion ``` ```http GET /{databaseId}/items/{itemId}/viewportions/ ``` --- Since version 2.1.0 --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **2.1.0** ID of your database. --- itemId String Located in: **path** Required: **Yes** Since version: **2.1.0** ID of the item whose view portions are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "userId": "user-a", "sessionId": "ABAD1D", "portion": 0.5, "autoPresented": true, "timeSpent": 40.5, "timestamp": 1348151906.0 }, { "itemId": "item-x", "userId": "user-b", "sessionId": null, "portion": 1, "autoPresented": false, "timeSpent": 0, "timestamp": 1348239363.0 } ] ``` --- 400 The `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `itemId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List User View Portions Lists all the view portions ever submitted by the given user. ```js const result = await client.send(new requests.ListUserViewPortions(userId)); ``` ```python result = client.send(ListUserViewPortions(user_id)) ``` ```ruby result = client.send(ListUserViewPortions.new(user_id)) ``` ```java ViewPortion[] result = client.send(new ListUserViewPortions(userId)); ``` ```php $result = $client->send(new Reqs\ListUserViewPortions($user_id)); ``` ```csharp IEnumerable result = client.Send(new ListUserViewPortions(userId)); ``` ```go request := client.NewListUserViewPortions(userId) result, err := request.Send() // result is of the type []bindings.ViewPortion ``` ```http GET /{databaseId}/users/{userId}/viewportions/ ``` --- Since version 2.1.0 --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **2.1.0** ID of your database. --- userId String Located in: **path** Required: **Yes** Since version: **2.1.0** ID of the user whose view portions are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemId": "item-x", "userId": "user-a", "sessionId": "ABAD1D", "portion": 0.25, "autoPresented": false, "timeSpent": 1.5, "timestamp": 1348151906.0 }, { "itemId": "item-y", "userId": "user-a", "sessionId": "EWQKOL", "portion": 0.1, "autoPresented": true, "timeSpent": 231.25, "timestamp": 1348239363.0 } ] ``` --- 400 The `userId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Given `userId` not found in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- ## Recommendations Recommendation methods are capable of recommending items (Recommend Items to User, Recommend Items to Item) or users (Recommend Users to Item, Recommend Users to User). See Segmentations section for recommendation endpoints that return Segments (e.g. "recommend categories to a user"). ### Recommending Items Recommendation endpoints that return the Items (content, products, etc.). get #### Recommend Items to User Allowed on Client-Side Based on the user's past interactions (purchases, ratings, etc.) with the items, recommends top-N items that are most likely to be of high value for the given user. The most typical use cases are recommendations on the homepage, in some "Picked just for you" section, or in email. The returned items are sorted by relevance (the first item being the most relevant). Besides the recommended items, also a unique `recommId` is returned in the response. It can be used to: * Let Recombee know that this recommendation was successful (e.g., user clicked one of the recommended items). See [Reported metrics](https://docs.recombee.com/admin_ui#reported-metrics). * Get subsequent recommended items when the user scrolls down (_infinite scroll_) or goes to the next page. See [Recommend Next Items](https://docs.recombee.com/api#recommend-next-items). It is also possible to use POST HTTP method (for example in the case of a very long ReQL filter) - query parameters then become body parameters. ```js const result = await client.send(new recombee.RecommendItemsToUser(userId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number })); ``` ```kotlin val result = client.sendAsync(RecommendItemsToUser(userId, count, // optional parameters: scenario = "homepage", // String cascadeCreate = true, // Boolean returnProperties = true, // Boolean includedProperties = listOf("title", "price", "publishedAt"), // List filter = "price > 50", // String booster = "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic = Logic(name = "recombee:default"), // Logic reqlExpressions = mapOf( "isInUsersCity" to "context_user[\"city\"] in 'cities'", ), // Map minRelevance = "low", // String rotationRate = 0.1, // Double rotationTime = 7200.0, // Double )) result.onSuccess { response: RecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: RecommendationResponse = try await client.send(RecommendItemsToUser(userId: userId, count: count, // optional parameters: scenario: "homepage", // String cascadeCreate: true, // Bool returnProperties: true, // Bool includedProperties: ["title", "price", "publishedAt"], // [String] filter: "price > 50", // String booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic: Logic(name: "recombee:default"), // Logic reqlExpressions: [ "isInUsersCity": "context_user[\"city\"] in 'cities'", ], // JSONDictionary minRelevance: "low", // String rotationRate: 0.1, // Double rotationTime: 7200.0 // Double )) ``` ```js const result = await client.send(new requests.RecommendItemsToUser(userId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number })); ``` ```python result = client.send(RecommendItemsToUser(user_id, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean return_properties=True, # boolean included_properties=['title', 'price', 'publishedAt'], # array filter='price > 50', # string booster="if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic='recombee:default', # string / dict reql_expressions={ 'isInUsersCity': 'context_user["city"] in \'cities\'', }, # dict min_relevance='low', # string rotation_rate=0.1, # number rotation_time=7200.0, # number )) ``` ```ruby result = client.send(RecommendItemsToUser.new(user_id, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean return_properties: true, # boolean included_properties: ['title', 'price', 'publishedAt'], # array filter: 'price > 50', # string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic: 'recombee:default', # string / Hash reql_expressions: { 'isInUsersCity' => 'context_user["city"] in \'cities\'', }, # Hash min_relevance: 'low', # string rotation_rate: 0.1, # number rotation_time: 7200.0, # number })) ``` ```java RecommendationResponse result = client.send(new RecommendItemsToUser(userId, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"title", "price", "publishedAt"}) // String[] .setFilter("price > 50") // String .setBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("isInUsersCity", "context_user[\"city\"] in 'cities'"); }}) // Map .setMinRelevance("low") // String .setRotationRate(0.1) // double .setRotationTime(7200.0) // double ); ``` ```php $result = $client->send(new Reqs\RecommendItemsToUser($user_id, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'returnProperties' => true, // boolean 'includedProperties' => ['title', 'price', 'publishedAt'], // array 'filter' => 'price > 50', // string 'booster' => "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'isInUsersCity' => 'context_user["city"] in \'cities\'', ], // array (map) 'minRelevance' => 'low', // string 'rotationRate' => 0.1, // number 'rotationTime' => 7200.0, // number ])); ``` ```csharp RecommendationResponse result = client.Send(new RecommendItemsToUser(userId, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool returnProperties: true, // bool includedProperties: new string[] { "title", "price", "publishedAt" }, // string[] filter: "price > 50", // string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "isInUsersCity", "context_user[\"city\"] in 'cities'" }, }, // Dictionary minRelevance: "low", // string rotationRate: 0.1, // double rotationTime: 7200.0 // double )); ``` ```go logicName := "recombee:default" request := client.NewRecommendItemsToUser(userId, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetReturnProperties(true). // bool SetIncludedProperties([]string{"title", "price", "publishedAt"}). // []string SetFilter("price > 50"). // string SetBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "isInUsersCity": "context_user[\"city\"] in 'cities'", }). // map[string]string SetMinRelevance("low"). // string SetRotationRate(0.1). // float64 SetRotationTime(7200.0) // float64 result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/users/{userId}/items/?count=10 &scenario=homepage &cascadeCreate=true &returnProperties=true &includedProperties=title,price,publishedAt &filter=price > 50 &booster=if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1 &logic=recombee:default &reqlExpressions={"isInUsersCity":"context_user[\"city\"] in 'cities'"} &minRelevance=low &rotationRate=0.1 &rotationTime=7200.0 ``` --- Since version 2.0.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **2.0.0** ID of your database. --- userId String Located in: **path** Required: **Yes** Since version: **2.0.0** ID of the user for whom personalized recommendations are to be generated. --- count Integer Located in: **query** Required: **Yes** Since version: **2.0.0** Number of items to be recommended (N for the top-N recommendation). --- scenario String Located in: **query** Required: **No** Since version: **2.0.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **2.0.0** If the user does not exist in the database, returns a list of non-personalized recommendations and creates the user in the database. This allows, for example, rotations in the following recommendations for that user, as the user will be already known to the system. --- returnProperties Boolean Located in: **query** Required: **No** Since version: **2.0.0** With `returnProperties=true`, property values of the recommended items are returned along with their IDs in a JSON dictionary. The acquired property values can be used to easily display the recommended items to the user. Example response: ``` { "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "recomms": [ { "id": "tv-178", "values": { "description": "4K TV with 3D feature", "categories": ["Electronics", "Televisions"], "price": 342, "url": "myshop.com/tv-178" } }, { "id": "mixer-42", "values": { "description": "Stainless Steel Mixer", "categories": ["Home & Kitchen"], "price": 39, "url": "myshop.com/mixer-42" } } ], "numberNextRecommsCalls": 0 } ``` --- includedProperties Array Located in: **query** Required: **No** Since version: **2.0.0** Allows specifying which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. Example response for `includedProperties=description,price`: ``` { "recommId": "a86ee8d5-cd8e-46d1-886c-8b3771d0520b", "recomms": [ { "id": "tv-178", "values": { "description": "4K TV with 3D feature", "price": 342 } }, { "id": "mixer-42", "values": { "description": "Stainless Steel Mixer", "price": 39 } } ], "numberNextRecommsCalls": 0 } ``` --- filter String Located in: **query** Required: **No** Since version: **2.0.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to filter recommended items based on the values of their attributes. Filters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- booster String Located in: **query** Required: **No** Since version: **2.0.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to boost the recommendation rate of some items based on the values of their attributes. Boosters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- logic String Object Located in: **query** Required: **No** Since version: **2.4.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.0.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended item. This can be used to compute additional properties of the recommended items that are not stored in the database. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "isInUsersCity": "context_user[\"city\"] in 'cities'", "distanceToUser": "earth_distance('location', context_user[\"location\"])" } } ``` Example response: ``` { "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "recomms": [ { "id": "restaurant-178", "reqlEvaluations": { "isInUsersCity": true, "distanceToUser": 5200.2 } }, { "id": "bar-42", "reqlEvaluations": { "isInUsersCity": false, "distanceToUser": 2516.0 } } ], "numberNextRecommsCalls": 0 } ``` --- minRelevance String Located in: **query** Required: **No** Since version: **2.0.0** **Expert option:** Specifies the threshold of how relevant must the recommended items be to the user. Possible values one of: "low", "medium", "high". The default value is "low", meaning that the system attempts to recommend a number of items equal to _count_ at any cost. If there is not enough data (such as interactions or item properties), this may even lead to bestseller-based recommendations to be appended to reach the full _count_. This behavior may be suppressed by using "medium" or "high" values. In such a case, the system only recommends items of at least the requested relevance and may return less than _count_ items when there is not enough data to fulfill it. --- rotationRate Number Located in: **query** Required: **No** Since version: **2.0.0** **Expert option:** If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per request in a backward fashion. You may penalize an item for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example, `rotationRate=0.2` for only slight rotation of recommended items. Default: `0`. --- rotationTime Number Located in: **query** Required: **No** Since version: **2.0.0** **Expert option:** Taking _rotationRate_ into account, specifies how long it takes for an item to recover from the penalization. For example, `rotationTime=7200.0` means that items recommended less than 2 hours ago are penalized. Default: `7200.0`. --- ##### Responses 200 Successful operation. ``` { "recommId": "3f6ad2f2-a3f1-4ba1-a690-f4f01f76d4eb", "recomms": [ { "id": "item-146" }, { "id": "item-462" }, { "id": "item-463" } ], "numberNextRecommsCalls": 0 } ``` --- 400 userId does not match ^\[a-zA-Z0-9\_-:@.\]+$, count is not a positive integer, filter or booster is not valid [ReQL](https://docs.recombee.com/reql) expressions, filter expression does not return boolean, booster does not return double or integer. --- 404 userId not found in the database and cascadeCreate is false. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### Recommend Items to Item Allowed on Client-Side Recommends a set of items that are somehow related to one given item, _X_. A typical scenario is when the user _A_ is viewing _X_. Then you may display items to the user that he might also be interested in. Recommend items to item request gives you Top-N such items, optionally taking the target user _A_ into account. The returned items are sorted by relevance (the first item being the most relevant). Besides the recommended items, also a unique `recommId` is returned in the response. It can be used to: * Let Recombee know that this recommendation was successful (e.g., user clicked one of the recommended items). See [Reported metrics](https://docs.recombee.com/admin_ui#reported-metrics). * Get subsequent recommended items when the user scrolls down (_infinite scroll_) or goes to the next page. See [Recommend Next Items](https://docs.recombee.com/api#recommend-next-items). It is also possible to use POST HTTP method (for example in the case of a very long ReQL filter) - query parameters then become body parameters. ```js const result = await client.send(new recombee.RecommendItemsToItem(itemId, targetUserId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number })); ``` ```kotlin val result = client.sendAsync(RecommendItemsToItem(itemId, targetUserId, count, // optional parameters: scenario = "homepage", // String cascadeCreate = true, // Boolean returnProperties = true, // Boolean includedProperties = listOf("title", "price", "publishedAt"), // List filter = "price > 50", // String booster = "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic = Logic(name = "recombee:default"), // Logic reqlExpressions = mapOf( "isInUsersCity" to "context_user[\"city\"] in 'cities'", ), // Map minRelevance = "low", // String rotationRate = 0.1, // Double rotationTime = 7200.0, // Double )) result.onSuccess { response: RecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: RecommendationResponse = try await client.send(RecommendItemsToItem(itemId: itemId, targetUserId: targetUserId, count: count, // optional parameters: scenario: "homepage", // String cascadeCreate: true, // Bool returnProperties: true, // Bool includedProperties: ["title", "price", "publishedAt"], // [String] filter: "price > 50", // String booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic: Logic(name: "recombee:default"), // Logic reqlExpressions: [ "isInUsersCity": "context_user[\"city\"] in 'cities'", ], // JSONDictionary minRelevance: "low", // String rotationRate: 0.1, // Double rotationTime: 7200.0 // Double )) ``` ```js const result = await client.send(new requests.RecommendItemsToItem(itemId, targetUserId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number })); ``` ```python result = client.send(RecommendItemsToItem(item_id, target_user_id, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean return_properties=True, # boolean included_properties=['title', 'price', 'publishedAt'], # array filter='price > 50', # string booster="if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic='recombee:default', # string / dict reql_expressions={ 'isInUsersCity': 'context_user["city"] in \'cities\'', }, # dict min_relevance='low', # string rotation_rate=0.1, # number rotation_time=7200.0, # number )) ``` ```ruby result = client.send(RecommendItemsToItem.new(item_id, target_user_id, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean return_properties: true, # boolean included_properties: ['title', 'price', 'publishedAt'], # array filter: 'price > 50', # string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic: 'recombee:default', # string / Hash reql_expressions: { 'isInUsersCity' => 'context_user["city"] in \'cities\'', }, # Hash min_relevance: 'low', # string rotation_rate: 0.1, # number rotation_time: 7200.0, # number })) ``` ```java RecommendationResponse result = client.send(new RecommendItemsToItem(itemId, targetUserId, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"title", "price", "publishedAt"}) // String[] .setFilter("price > 50") // String .setBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("isInUsersCity", "context_user[\"city\"] in 'cities'"); }}) // Map .setMinRelevance("low") // String .setRotationRate(0.1) // double .setRotationTime(7200.0) // double ); ``` ```php $result = $client->send(new Reqs\RecommendItemsToItem($item_id, $target_user_id, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'returnProperties' => true, // boolean 'includedProperties' => ['title', 'price', 'publishedAt'], // array 'filter' => 'price > 50', // string 'booster' => "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'isInUsersCity' => 'context_user["city"] in \'cities\'', ], // array (map) 'minRelevance' => 'low', // string 'rotationRate' => 0.1, // number 'rotationTime' => 7200.0, // number ])); ``` ```csharp RecommendationResponse result = client.Send(new RecommendItemsToItem(itemId, targetUserId, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool returnProperties: true, // bool includedProperties: new string[] { "title", "price", "publishedAt" }, // string[] filter: "price > 50", // string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "isInUsersCity", "context_user[\"city\"] in 'cities'" }, }, // Dictionary minRelevance: "low", // string rotationRate: 0.1, // double rotationTime: 7200.0 // double )); ``` ```go logicName := "recombee:default" request := client.NewRecommendItemsToItem(itemId, targetUserId, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetReturnProperties(true). // bool SetIncludedProperties([]string{"title", "price", "publishedAt"}). // []string SetFilter("price > 50"). // string SetBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "isInUsersCity": "context_user[\"city\"] in 'cities'", }). // map[string]string SetMinRelevance("low"). // string SetRotationRate(0.1). // float64 SetRotationTime(7200.0) // float64 result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/items/{itemId}/items/?targetUserId=user-1 &count=10 &scenario=homepage &cascadeCreate=true &returnProperties=true &includedProperties=title,price,publishedAt &filter=price > 50 &booster=if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1 &logic=recombee:default &reqlExpressions={"isInUsersCity":"context_user[\"city\"] in 'cities'"} &minRelevance=low &rotationRate=0.1 &rotationTime=7200.0 ``` --- Since version 2.0.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **2.0.0** ID of your database. --- itemId String Located in: **path** Required: **Yes** Since version: **2.0.0** ID of the item for which the recommendations are to be generated. --- targetUserId String Located in: **query** Required: **Yes** Since version: **2.0.0** ID of the user who will see the recommendations. Specifying the _targetUserId_ is beneficial because: * It makes the recommendations personalized * Allows the calculation of Actions and Conversions in the graphical user interface, as Recombee can pair the user who got recommendations and who afterward viewed/purchased an item. If you insist on not specifying the user, pass `null`(`None`, `nil`, `NULL` etc., depending on the language) to _targetUserId_. Do not create some special dummy user for getting recommendations, as it could mislead the recommendation models, and result in wrong recommendations. For anonymous/unregistered users, it is possible to use, for example, their session ID. --- count Integer Located in: **query** Required: **Yes** Since version: **2.0.0** Number of items to be recommended (N for the top-N recommendation). --- scenario String Located in: **query** Required: **No** Since version: **2.0.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **2.0.0** If an item of the given _itemId_ or user of the given _targetUserId_ doesn't exist in the database, it creates the missing entity/entities and returns some (non-personalized) recommendations. This allows, for example, rotations in the following recommendations for the user of the given _targetUserId_, as the user will be already known to the system. --- returnProperties Boolean Located in: **query** Required: **No** Since version: **2.0.0** With `returnProperties=true`, property values of the recommended items are returned along with their IDs in a JSON dictionary. The acquired property values can be used to easily display the recommended items to the user. Example response: ``` { "recommId": "0c6189e7-dc1a-429a-b613-192696309361", "recomms": [ { "id": "tv-178", "values": { "description": "4K TV with 3D feature", "categories": ["Electronics", "Televisions"], "price": 342, "url": "myshop.com/tv-178" } }, { "id": "mixer-42", "values": { "description": "Stainless Steel Mixer", "categories": ["Home & Kitchen"], "price": 39, "url": "myshop.com/mixer-42" } } ], "numberNextRecommsCalls": 0 } ``` --- includedProperties Array Located in: **query** Required: **No** Since version: **2.0.0** Allows specifying which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. Example response for `includedProperties=description,price`: ``` { "recommId": "6842c725-a79f-4537-a02c-f34d668a3f80", "recomms": [ { "id": "tv-178", "values": { "description": "4K TV with 3D feature", "price": 342 } }, { "id": "mixer-42", "values": { "description": "Stainless Steel Mixer", "price": 39 } } ], "numberNextRecommsCalls": 0 } ``` --- filter String Located in: **query** Required: **No** Since version: **2.0.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to filter recommended items based on the values of their attributes. Filters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- booster String Located in: **query** Required: **No** Since version: **2.0.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to boost the recommendation rate of some items based on the values of their attributes. Boosters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- logic String Object Located in: **query** Required: **No** Since version: **2.4.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.0.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended item. This can be used to compute additional properties of the recommended items that are not stored in the database. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "isInUsersCity": "context_user[\"city\"] in 'cities'", "distanceToUser": "earth_distance('location', context_user[\"location\"])", "isFromSameCompany": "'company' == context_item[\"company\"]" } } ``` Example response: ``` { "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "recomms": [ { "id": "restaurant-178", "reqlEvaluations": { "isInUsersCity": true, "distanceToUser": 5200.2, "isFromSameCompany": false } }, { "id": "bar-42", "reqlEvaluations": { "isInUsersCity": false, "distanceToUser": 2516.0, "isFromSameCompany": true } } ], "numberNextRecommsCalls": 0 } ``` --- minRelevance String Located in: **query** Required: **No** Since version: **2.0.0** **Expert option:** If the _targetUserId_ is provided: Specifies the threshold of how relevant must the recommended items be to the user. Possible values one of: "low", "medium", "high". The default value is "low", meaning that the system attempts to recommend a number of items equal to _count_ at any cost. If there is not enough data (such as interactions or item properties), this may even lead to bestseller-based recommendations being appended to reach the full _count_. This behavior may be suppressed by using "medium" or "high" values. In such case, the system only recommends items of at least the requested relevance and may return less than _count_ items when there is not enough data to fulfill it. --- rotationRate Number Located in: **query** Required: **No** Since version: **2.0.0** **Expert option:** If the _targetUserId_ is provided: If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per request in a backward fashion. You may penalize an item for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example, `rotationRate=0.2` for only slight rotation of recommended items. --- rotationTime Number Located in: **query** Required: **No** Since version: **2.0.0** **Expert option:** If the _targetUserId_ is provided: Taking _rotationRate_ into account, specifies how long it takes for an item to recover from the penalization. For example, `rotationTime=7200.0` means that items recommended less than 2 hours ago are penalized. --- ##### Responses 200 Successful operation. ``` { "recommId": "768448ea-10b3-4028-bb76-4b2f95121d19", "recomms": [ { "id": "item-146" }, { "id": "item-462" }, { "id": "item-463" } ], "numberNextRecommsCalls": 0 } ``` --- 400 itemId does not match ^\[a-zA-Z0-9\_-:@.\]+$, count is not a positive integer, filter or booster is not valid [ReQL](https://docs.recombee.com/reql) expressions, filter expression does not return boolean, booster does not return double or integer. --- 404 itemId not found in the database and cascadeCreate is false. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### Recommend Items to Item Segment Allowed on Client-Side Recommends Items that are the most relevant to a particular Segment from a context [Segmentation](https://docs.recombee.com/segmentations). Based on the used Segmentation, this endpoint can be used for example for: * Recommending articles related to a particular topic * Recommending songs belonging to a particular genre * Recommending products produced by a particular brand You need to set the used context Segmentation in the Admin UI in the [Scenario settings](https://docs.recombee.com/scenarios) prior to using this endpoint. The returned items are sorted by relevance (the first item being the most relevant). It is also possible to use the POST HTTP method (for example, in the case of a very long ReQL filter) — query parameters then become body parameters. ```js const result = await client.send(new recombee.RecommendItemsToItemSegment(contextSegmentId, targetUserId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:personal-from-segment', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number })); ``` ```kotlin val result = client.sendAsync(RecommendItemsToItemSegment(contextSegmentId, targetUserId, count, // optional parameters: scenario = "homepage", // String cascadeCreate = true, // Boolean returnProperties = true, // Boolean includedProperties = listOf("title", "price", "publishedAt"), // List filter = "price > 50", // String booster = "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic = Logic(name = "recombee:personal-from-segment"), // Logic reqlExpressions = mapOf( "isInUsersCity" to "context_user[\"city\"] in 'cities'", ), // Map minRelevance = "low", // String rotationRate = 0.1, // Double rotationTime = 7200.0, // Double )) result.onSuccess { response: RecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: RecommendationResponse = try await client.send(RecommendItemsToItemSegment(contextSegmentId: contextSegmentId, targetUserId: targetUserId, count: count, // optional parameters: scenario: "homepage", // String cascadeCreate: true, // Bool returnProperties: true, // Bool includedProperties: ["title", "price", "publishedAt"], // [String] filter: "price > 50", // String booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic: Logic(name: "recombee:personal-from-segment"), // Logic reqlExpressions: [ "isInUsersCity": "context_user[\"city\"] in 'cities'", ], // JSONDictionary minRelevance: "low", // String rotationRate: 0.1, // Double rotationTime: 7200.0 // Double )) ``` ```js const result = await client.send(new requests.RecommendItemsToItemSegment(contextSegmentId, targetUserId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:personal-from-segment', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number })); ``` ```python result = client.send(RecommendItemsToItemSegment(context_segment_id, target_user_id, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean return_properties=True, # boolean included_properties=['title', 'price', 'publishedAt'], # array filter='price > 50', # string booster="if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic='recombee:personal-from-segment', # string / dict reql_expressions={ 'isInUsersCity': 'context_user["city"] in \'cities\'', }, # dict min_relevance='low', # string rotation_rate=0.1, # number rotation_time=7200.0, # number )) ``` ```ruby result = client.send(RecommendItemsToItemSegment.new(context_segment_id, target_user_id, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean return_properties: true, # boolean included_properties: ['title', 'price', 'publishedAt'], # array filter: 'price > 50', # string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic: 'recombee:personal-from-segment', # string / Hash reql_expressions: { 'isInUsersCity' => 'context_user["city"] in \'cities\'', }, # Hash min_relevance: 'low', # string rotation_rate: 0.1, # number rotation_time: 7200.0, # number })) ``` ```java RecommendationResponse result = client.send(new RecommendItemsToItemSegment(contextSegmentId, targetUserId, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"title", "price", "publishedAt"}) // String[] .setFilter("price > 50") // String .setBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1") // String .setLogic(new Logic("recombee:personal-from-segment")) // Logic .setReqlExpressions(new HashMap() {{ put("isInUsersCity", "context_user[\"city\"] in 'cities'"); }}) // Map .setMinRelevance("low") // String .setRotationRate(0.1) // double .setRotationTime(7200.0) // double ); ``` ```php $result = $client->send(new Reqs\RecommendItemsToItemSegment($context_segment_id, $target_user_id, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'returnProperties' => true, // boolean 'includedProperties' => ['title', 'price', 'publishedAt'], // array 'filter' => 'price > 50', // string 'booster' => "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string 'logic' => 'recombee:personal-from-segment', // string / array (map) 'reqlExpressions' => [ 'isInUsersCity' => 'context_user["city"] in \'cities\'', ], // array (map) 'minRelevance' => 'low', // string 'rotationRate' => 0.1, // number 'rotationTime' => 7200.0, // number ])); ``` ```csharp RecommendationResponse result = client.Send(new RecommendItemsToItemSegment(contextSegmentId, targetUserId, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool returnProperties: true, // bool includedProperties: new string[] { "title", "price", "publishedAt" }, // string[] filter: "price > 50", // string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string logic: new Logic(name: "recombee:personal-from-segment"), // Logic reqlExpressions: new Dictionary { { "isInUsersCity", "context_user[\"city\"] in 'cities'" }, }, // Dictionary minRelevance: "low", // string rotationRate: 0.1, // double rotationTime: 7200.0 // double )); ``` ```go logicName := "recombee:personal-from-segment" request := client.NewRecommendItemsToItemSegment(contextSegmentId, targetUserId, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetReturnProperties(true). // bool SetIncludedProperties([]string{"title", "price", "publishedAt"}). // []string SetFilter("price > 50"). // string SetBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "isInUsersCity": "context_user[\"city\"] in 'cities'", }). // map[string]string SetMinRelevance("low"). // string SetRotationRate(0.1). // float64 SetRotationTime(7200.0) // float64 result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/item-segments/items/?contextSegmentId=segment-1 &targetUserId=user-1 &count=10 &scenario=homepage &cascadeCreate=true &returnProperties=true &includedProperties=title,price,publishedAt &filter=price > 50 &booster=if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1 &logic=recombee:personal-from-segment &reqlExpressions={"isInUsersCity":"context_user[\"city\"] in 'cities'"} &minRelevance=low &rotationRate=0.1 &rotationTime=7200.0 ``` --- Since version 5.0.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **5.0.0** ID of your database. --- contextSegmentId String Located in: **query** Required: **Yes** Since version: **5.0.0** ID of the segment from `contextSegmentationId` for which the recommendations are to be generated. --- targetUserId String Located in: **query** Required: **Yes** Since version: **5.0.0** ID of the user who will see the recommendations. Specifying the _targetUserId_ is beneficial because: * It makes the recommendations personalized * Allows the calculation of Actions and Conversions in the graphical user interface, as Recombee can pair the user who got recommendations and who afterward viewed/purchased an item. If you insist on not specifying the user, pass `null`(`None`, `nil`, `NULL` etc., depending on the language) to _targetUserId_. Do not create some special dummy user for getting recommendations, as it could mislead the recommendation models, and result in wrong recommendations. For anonymous/unregistered users, it is possible to use, for example, their session ID. --- count Integer Located in: **query** Required: **Yes** Since version: **5.0.0** Number of items to be recommended (N for the top-N recommendation). --- scenario String Located in: **query** Required: **No** Since version: **5.0.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **5.0.0** If a user of the given _targetUserId_ doesn't exist in the database, it creates this user and returns some (non-personalized) recommendations. This allows, for example, rotations in the following recommendations for the user of the given _targetUserId_, as the user will be already known to the system. --- returnProperties Boolean Located in: **query** Required: **No** Since version: **5.0.0** With `returnProperties=true`, property values of the recommended items are returned along with their IDs in a JSON dictionary. The acquired property values can be used to easily display the recommended items to the user. Example response: ``` { "recommId": "0c6189e7-dc1a-429a-b613-192696309361", "recomms": [ { "id": "tv-178", "values": { "description": "4K TV with 3D feature", "categories": ["Electronics", "Televisions"], "price": 342, "url": "myshop.com/tv-178" } }, { "id": "mixer-42", "values": { "description": "Stainless Steel Mixer", "categories": ["Home & Kitchen"], "price": 39, "url": "myshop.com/mixer-42" } } ], "numberNextRecommsCalls": 0 } ``` --- includedProperties Array Located in: **query** Required: **No** Since version: **5.0.0** Allows specifying which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. Example response for `includedProperties=description,price`: ``` { "recommId": "6842c725-a79f-4537-a02c-f34d668a3f80", "recomms": [ { "id": "tv-178", "values": { "description": "4K TV with 3D feature", "price": 342 } }, { "id": "mixer-42", "values": { "description": "Stainless Steel Mixer", "price": 39 } } ], "numberNextRecommsCalls": 0 } ``` --- filter String Located in: **query** Required: **No** Since version: **5.0.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to filter recommended items based on the values of their attributes. Filters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- booster String Located in: **query** Required: **No** Since version: **5.0.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to boost the recommendation rate of some items based on the values of their attributes. Boosters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- logic String Object Located in: **query** Required: **No** Since version: **5.0.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.0.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended item. This can be used to compute additional properties of the recommended items that are not stored in the database. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "isInUsersCity": "context_user[\"city\"] in 'cities'", "distanceToUser": "earth_distance('location', context_user[\"location\"])" } } ``` Example response: ``` { "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "recomms": [ { "id": "restaurant-178", "reqlEvaluations": { "isInUsersCity": true, "distanceToUser": 5200.2 } }, { "id": "bar-42", "reqlEvaluations": { "isInUsersCity": false, "distanceToUser": 2516.0 } } ], "numberNextRecommsCalls": 0 } ``` --- minRelevance String Located in: **query** Required: **No** Since version: **5.0.0** **Expert option:** If the _targetUserId_ is provided: Specifies the threshold of how relevant must the recommended items be to the user. Possible values one of: "low", "medium", "high". The default value is "low", meaning that the system attempts to recommend a number of items equal to _count_ at any cost. If there is not enough data (such as interactions or item properties), this may even lead to bestseller-based recommendations being appended to reach the full _count_. This behavior may be suppressed by using "medium" or "high" values. In such case, the system only recommends items of at least the requested relevance and may return less than _count_ items when there is not enough data to fulfill it. --- rotationRate Number Located in: **query** Required: **No** Since version: **5.0.0** **Expert option:** If the _targetUserId_ is provided: If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per request in a backward fashion. You may penalize an item for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example, `rotationRate=0.2` for only slight rotation of recommended items. --- rotationTime Number Located in: **query** Required: **No** Since version: **5.0.0** **Expert option:** If the _targetUserId_ is provided: Taking _rotationRate_ into account, specifies how long it takes for an item to recover from the penalization. For example, `rotationTime=7200.0` means that items recommended less than 2 hours ago are penalized. --- ##### Responses 200 successful operation ``` { "recommId": "768448ea-10b3-4028-bb76-4b2f95121d19", "recomms": [ { "id": "item-176" }, { "id": "item-141" }, { "id": "item-967" } ], "numberNextRecommsCalls": 0 } ``` --- 400 count is not a positive integer. --- 404 contextSegmentId not found in the context segmentation --- get #### Recommend Next Items Allowed on Client-Side Returns items that shall be shown to a user as next recommendations when the user e.g. scrolls the page down (_infinite scroll_) or goes to the next page. It accepts `recommId` of a base recommendation request (e.g., request from the first page) and the number of items that shall be returned (`count`). The base request can be one of: * [Recommend Items to Item](https://docs.recombee.com/api#recommend-items-to-item) * [Recommend Items to User](https://docs.recombee.com/api#recommend-items-to-user) * [Recommend Items to Item Segment](https://docs.recombee.com/api#recommend-items-to-item-segment) * [Search Items](https://docs.recombee.com/api#search-items) All the other parameters are inherited from the base request. _Recommend next items_ can be called many times for a single `recommId` and each call returns different (previously not recommended) items. The number of _Recommend next items_ calls performed so far is returned in the `numberNextRecommsCalls` field. _Recommend next items_ can be requested up to 30 minutes after the base request or a previous _Recommend next items_ call. For billing purposes, each call to _Recommend next items_ is counted as a separate recommendation request. ```js const result = await client.send(new recombee.RecommendNextItems(recommId, count)); ``` ```kotlin val result = client.sendAsync(RecommendNextItems(recommId, count)) result.onSuccess { response: RecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: RecommendationResponse = try await client.send(RecommendNextItems(recommId: recommId, count: count)) ``` ```js const result = await client.send(new requests.RecommendNextItems(recommId, count)); ``` ```python result = client.send(RecommendNextItems(recomm_id, count)) ``` ```ruby result = client.send(RecommendNextItems.new(recomm_id, count)) ``` ```java RecommendationResponse result = client.send(new RecommendNextItems(recommId, count)); ``` ```php $result = $client->send(new Reqs\RecommendNextItems($recomm_id, $count)); ``` ```csharp RecommendationResponse result = client.Send(new RecommendNextItems(recommId, count)); ``` ```go request := client.NewRecommendNextItems(recommId, count) result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/next/items/{recommId}?count=10 ``` --- Since version 3.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **3.1.0** ID of your database. --- recommId String Located in: **path** Required: **Yes** Since version: **3.1.0** ID of the base recommendation request for which next recommendations should be returned --- count Integer Located in: **query** Required: **Yes** Since version: **3.1.0** Number of items to be recommended --- ##### Responses 200 Successful operation. ``` { "recommId": "768448ea-10b3-4028-bb76-4b2f95121d19", "recomms": [ { "id": "item-176" }, { "id": "item-141" }, { "id": "item-967" } ], "numberNextRecommsCalls": 4 } ``` --- 400 Parameter `count` is not given or is not a positive integer. Parameter `recommId` is not an UUID. --- 404 Base request with the given `recommId` does not exist or has expired. --- ### Recommending Item Segments Recommendation endpoints that return the [Item Segments](https://docs.recombee.com/segmentations) (categories, genres, artists, etc.). get #### Recommend Item Segments to User Allowed on Client-Side Recommends the top Segments from a [Segmentation](https://docs.recombee.com/segmentations) for a particular user, based on the user's past interactions. Based on the used Segmentation, this endpoint can be used for example for: * Recommending the top categories for the user * Recommending the top genres for the user * Recommending the top brands for the user * Recommending the top artists for the user You need to set the used Segmentation the Admin UI in the [Scenario settings](https://docs.recombee.com/scenarios) prior to using this endpoint. The returned segments are sorted by relevance (first segment being the most relevant). It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters. ```js const result = await client.send(new recombee.RecommendItemSegmentsToUser(userId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean filter: '\'segmentId\' != "coupons"', // string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { countItems: 'size(segment_items("categories", \'segmentId\'))', }, // Object })); ``` ```kotlin val result = client.sendAsync(RecommendItemSegmentsToUser(userId, count, // optional parameters: scenario = "homepage", // String cascadeCreate = true, // Boolean filter = "'segmentId' != \"coupons\"", // String booster = "if 'segmentId' == \"Editors Pick\" then 2 else 1", // String logic = Logic(name = "recombee:default"), // Logic reqlExpressions = mapOf( "countItems" to "size(segment_items(\"categories\", 'segmentId'))", ), // Map )) result.onSuccess { response: RecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: RecommendationResponse = try await client.send(RecommendItemSegmentsToUser(userId: userId, count: count, // optional parameters: scenario: "homepage", // String cascadeCreate: true, // Bool filter: "'segmentId' != \"coupons\"", // String booster: "if 'segmentId' == \"Editors Pick\" then 2 else 1", // String logic: Logic(name: "recombee:default"), // Logic reqlExpressions: [ "countItems": "size(segment_items(\"categories\", 'segmentId'))", ] // JSONDictionary )) ``` ```js const result = await client.send(new requests.RecommendItemSegmentsToUser(userId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean filter: '\'segmentId\' != "coupons"', // string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { countItems: 'size(segment_items("categories", \'segmentId\'))', }, // Object })); ``` ```python result = client.send(RecommendItemSegmentsToUser(user_id, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean filter='\'segmentId\' != "coupons"', # string booster='if \'segmentId\' == "Editors Pick" then 2 else 1', # string logic='recombee:default', # string / dict reql_expressions={ 'countItems': 'size(segment_items("categories", \'segmentId\'))', }, # dict )) ``` ```ruby result = client.send(RecommendItemSegmentsToUser.new(user_id, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean filter: '\'segmentId\' != "coupons"', # string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', # string logic: 'recombee:default', # string / Hash reql_expressions: { 'countItems' => 'size(segment_items("categories", \'segmentId\'))', }, # Hash })) ``` ```java RecommendationResponse result = client.send(new RecommendItemSegmentsToUser(userId, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setFilter("'segmentId' != \"coupons\"") // String .setBooster("if 'segmentId' == \"Editors Pick\" then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("countItems", "size(segment_items(\"categories\", 'segmentId'))"); }}) // Map ); ``` ```php $result = $client->send(new Reqs\RecommendItemSegmentsToUser($user_id, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'filter' => '\'segmentId\' != "coupons"', // string 'booster' => 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'countItems' => 'size(segment_items("categories", \'segmentId\'))', ], // array (map) ])); ``` ```csharp RecommendationResponse result = client.Send(new RecommendItemSegmentsToUser(userId, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool filter: "'segmentId' != \"coupons\"", // string booster: "if 'segmentId' == \"Editors Pick\" then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "countItems", "size(segment_items(\"categories\", 'segmentId'))" }, } // Dictionary )); ``` ```go logicName := "recombee:default" request := client.NewRecommendItemSegmentsToUser(userId, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetFilter("'segmentId' != \"coupons\""). // string SetBooster("if 'segmentId' == \"Editors Pick\" then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "countItems": "size(segment_items(\"categories\", 'segmentId'))", }) // map[string]string result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/users/{userId}/item-segments/?count=10 &scenario=homepage &cascadeCreate=true &filter='segmentId' != "coupons" &booster=if 'segmentId' == "Editors Pick" then 2 else 1 &logic=recombee:default &reqlExpressions={"countItems":"size(segment_items(\"categories\", 'segmentId'))"} ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- userId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the user for whom personalized recommendations are to be generated. --- count Integer Located in: **query** Required: **Yes** Since version: **4.1.0** Number of item segments to be recommended (N for the top-N recommendation). --- scenario String Located in: **query** Required: **No** Since version: **4.1.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **4.1.0** If the user does not exist in the database, returns a list of non-personalized recommendations and creates the user in the database. This allows, for example, rotations in the following recommendations for that user, as the user will be already known to the system. --- filter String Located in: **query** Required: **No** Since version: **4.1.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression which allows you to filter recommended segments based on the `segmentationId`. --- booster String Located in: **query** Required: **No** Since version: **4.1.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression which allows you to boost recommendation rate of some segments based on the `segmentationId`. --- logic String Object Located in: **query** Required: **No** Since version: **4.1.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.1.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended Item Segment. This can be used to compute additional properties of the recommended Item Segments. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "countItems": "size(segment_items(\"categories\", 'segmentId'))" } } ``` Example response: ``` { "recommId": "a7ac55a4-8d6e-4f19-addc-abac4164d8a8", "recomms": [ { "id": "category-fantasy-books", "reqlEvaluations": { "countItems": 486 } }, { "id": "category-sci-fi-costumes", "reqlEvaluations": { "countItems": 19 } } ], "numberNextRecommsCalls": 0 } ``` --- ##### Responses 200 successful operation ``` { "recommId": "5fbd94fa-2553-422c-bdb5-af82687d8c6a", "recomms": [ { "id": "category-rap" }, { "id": "category-dnb" }, { "id": "category-electronic" } ], "numberNextRecommsCalls": 0 } ``` --- 400 Used Segmentation not configured for the scenario. userId does not match ^\[a-zA-Z0-9\_-:@.\]+$, count is not a positive integer. --- 404 userId not found in the database and cascadeCreate is false --- get #### Recommend Item Segments to Item Allowed on Client-Side Recommends Segments from a [Segmentation](https://docs.recombee.com/segmentations) that are the most relevant to a particular item. Based on the used Segmentation, this endpoint can be used for example for: * Recommending the related categories * Recommending the related genres * Recommending the related brands * Recommending the related artists You need to set the used Segmentation the Admin UI in the [Scenario settings](https://docs.recombee.com/scenarios) prior to using this endpoint. The returned segments are sorted by relevance (first segment being the most relevant). It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters. ```js const result = await client.send(new recombee.RecommendItemSegmentsToItem(itemId, targetUserId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean filter: '\'segmentId\' != "coupons"', // string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { countItems: 'size(segment_items("categories", \'segmentId\'))', }, // Object })); ``` ```kotlin val result = client.sendAsync(RecommendItemSegmentsToItem(itemId, targetUserId, count, // optional parameters: scenario = "homepage", // String cascadeCreate = true, // Boolean filter = "'segmentId' != \"coupons\"", // String booster = "if 'segmentId' == \"Editors Pick\" then 2 else 1", // String logic = Logic(name = "recombee:default"), // Logic reqlExpressions = mapOf( "countItems" to "size(segment_items(\"categories\", 'segmentId'))", ), // Map )) result.onSuccess { response: RecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: RecommendationResponse = try await client.send(RecommendItemSegmentsToItem(itemId: itemId, targetUserId: targetUserId, count: count, // optional parameters: scenario: "homepage", // String cascadeCreate: true, // Bool filter: "'segmentId' != \"coupons\"", // String booster: "if 'segmentId' == \"Editors Pick\" then 2 else 1", // String logic: Logic(name: "recombee:default"), // Logic reqlExpressions: [ "countItems": "size(segment_items(\"categories\", 'segmentId'))", ] // JSONDictionary )) ``` ```js const result = await client.send(new requests.RecommendItemSegmentsToItem(itemId, targetUserId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean filter: '\'segmentId\' != "coupons"', // string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { countItems: 'size(segment_items("categories", \'segmentId\'))', }, // Object })); ``` ```python result = client.send(RecommendItemSegmentsToItem(item_id, target_user_id, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean filter='\'segmentId\' != "coupons"', # string booster='if \'segmentId\' == "Editors Pick" then 2 else 1', # string logic='recombee:default', # string / dict reql_expressions={ 'countItems': 'size(segment_items("categories", \'segmentId\'))', }, # dict )) ``` ```ruby result = client.send(RecommendItemSegmentsToItem.new(item_id, target_user_id, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean filter: '\'segmentId\' != "coupons"', # string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', # string logic: 'recombee:default', # string / Hash reql_expressions: { 'countItems' => 'size(segment_items("categories", \'segmentId\'))', }, # Hash })) ``` ```java RecommendationResponse result = client.send(new RecommendItemSegmentsToItem(itemId, targetUserId, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setFilter("'segmentId' != \"coupons\"") // String .setBooster("if 'segmentId' == \"Editors Pick\" then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("countItems", "size(segment_items(\"categories\", 'segmentId'))"); }}) // Map ); ``` ```php $result = $client->send(new Reqs\RecommendItemSegmentsToItem($item_id, $target_user_id, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'filter' => '\'segmentId\' != "coupons"', // string 'booster' => 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'countItems' => 'size(segment_items("categories", \'segmentId\'))', ], // array (map) ])); ``` ```csharp RecommendationResponse result = client.Send(new RecommendItemSegmentsToItem(itemId, targetUserId, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool filter: "'segmentId' != \"coupons\"", // string booster: "if 'segmentId' == \"Editors Pick\" then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "countItems", "size(segment_items(\"categories\", 'segmentId'))" }, } // Dictionary )); ``` ```go logicName := "recombee:default" request := client.NewRecommendItemSegmentsToItem(itemId, targetUserId, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetFilter("'segmentId' != \"coupons\""). // string SetBooster("if 'segmentId' == \"Editors Pick\" then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "countItems": "size(segment_items(\"categories\", 'segmentId'))", }) // map[string]string result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/items/{itemId}/item-segments/?targetUserId=user-1 &count=10 &scenario=homepage &cascadeCreate=true &filter='segmentId' != "coupons" &booster=if 'segmentId' == "Editors Pick" then 2 else 1 &logic=recombee:default &reqlExpressions={"countItems":"size(segment_items(\"categories\", 'segmentId'))"} ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- itemId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the item for which the recommendations are to be generated. --- targetUserId String Located in: **query** Required: **Yes** Since version: **4.1.0** ID of the user who will see the recommendations. Specifying the _targetUserId_ is beneficial because: * It makes the recommendations personalized * Allows the calculation of Actions and Conversions in the graphical user interface, as Recombee can pair the user who got recommendations and who afterward viewed/purchased an item. If you insist on not specifying the user, pass `null`(`None`, `nil`, `NULL` etc., depending on the language) to _targetUserId_. Do not create some special dummy user for getting recommendations, as it could mislead the recommendation models, and result in wrong recommendations. For anonymous/unregistered users, it is possible to use, for example, their session ID. --- count Integer Located in: **query** Required: **Yes** Since version: **4.1.0** Number of item segments to be recommended (N for the top-N recommendation). --- scenario String Located in: **query** Required: **No** Since version: **4.1.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **4.1.0** If the user does not exist in the database, returns a list of non-personalized recommendations and creates the user in the database. This allows, for example, rotations in the following recommendations for that user, as the user will be already known to the system. --- filter String Located in: **query** Required: **No** Since version: **4.1.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression which allows you to filter recommended segments based on the `segmentationId`. --- booster String Located in: **query** Required: **No** Since version: **4.1.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression which allows you to boost recommendation rate of some segments based on the `segmentationId`. --- logic String Object Located in: **query** Required: **No** Since version: **4.1.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.1.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended Item Segment. This can be used to compute additional properties of the recommended Item Segments. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "countItems": "size(segment_items(\"categories\", 'segmentId'))" } } ``` Example response: ``` { "recommId": "a7ac55a4-8d6e-4f19-addc-abac4164d8a8", "recomms": [ { "id": "category-fantasy-books", "reqlEvaluations": { "countItems": 486 } }, { "id": "category-sci-fi-costumes", "reqlEvaluations": { "countItems": 19 } } ], "numberNextRecommsCalls": 0 } ``` --- ##### Responses 200 successful operation ``` { "recommId": "5fbd94fa-2553-422c-bdb5-af82687d8c6a", "recomms": [ { "id": "category-rap" }, { "id": "category-dnb" }, { "id": "category-electronic" } ], "numberNextRecommsCalls": 0 } ``` --- 400 Used Segmentation not configured for the scenario. itemId does not match ^\[a-zA-Z0-9\_-:@.\]+$, count is not a positive integer. --- 404 itemId not found in the database and cascadeCreate is false --- get #### Recommend Item Segments to Item Segment Allowed on Client-Side Recommends Segments from a result [Segmentation](https://docs.recombee.com/segmentations) that are the most relevant to a particular Segment from a context Segmentation. Based on the used Segmentations, this endpoint can be used for example for: * Recommending the related brands to particular brand * Recommending the related brands to particular category * Recommending the related artists to a particular genre (assuming songs are the Items) You need to set the used context and result Segmentation the Admin UI in the [Scenario settings](https://docs.recombee.com/scenarios) prior to using this endpoint. The returned segments are sorted by relevance (first segment being the most relevant). It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters. ```js const result = await client.send(new recombee.RecommendItemSegmentsToItemSegment(contextSegmentId, targetUserId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean filter: '\'segmentId\' != "coupons"', // string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { countItems: 'size(segment_items("categories", \'segmentId\'))', }, // Object })); ``` ```kotlin val result = client.sendAsync(RecommendItemSegmentsToItemSegment(contextSegmentId, targetUserId, count, // optional parameters: scenario = "homepage", // String cascadeCreate = true, // Boolean filter = "'segmentId' != \"coupons\"", // String booster = "if 'segmentId' == \"Editors Pick\" then 2 else 1", // String logic = Logic(name = "recombee:default"), // Logic reqlExpressions = mapOf( "countItems" to "size(segment_items(\"categories\", 'segmentId'))", ), // Map )) result.onSuccess { response: RecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: RecommendationResponse = try await client.send(RecommendItemSegmentsToItemSegment(contextSegmentId: contextSegmentId, targetUserId: targetUserId, count: count, // optional parameters: scenario: "homepage", // String cascadeCreate: true, // Bool filter: "'segmentId' != \"coupons\"", // String booster: "if 'segmentId' == \"Editors Pick\" then 2 else 1", // String logic: Logic(name: "recombee:default"), // Logic reqlExpressions: [ "countItems": "size(segment_items(\"categories\", 'segmentId'))", ] // JSONDictionary )) ``` ```js const result = await client.send(new requests.RecommendItemSegmentsToItemSegment(contextSegmentId, targetUserId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean filter: '\'segmentId\' != "coupons"', // string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { countItems: 'size(segment_items("categories", \'segmentId\'))', }, // Object })); ``` ```python result = client.send(RecommendItemSegmentsToItemSegment(context_segment_id, target_user_id, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean filter='\'segmentId\' != "coupons"', # string booster='if \'segmentId\' == "Editors Pick" then 2 else 1', # string logic='recombee:default', # string / dict reql_expressions={ 'countItems': 'size(segment_items("categories", \'segmentId\'))', }, # dict )) ``` ```ruby result = client.send(RecommendItemSegmentsToItemSegment.new(context_segment_id, target_user_id, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean filter: '\'segmentId\' != "coupons"', # string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', # string logic: 'recombee:default', # string / Hash reql_expressions: { 'countItems' => 'size(segment_items("categories", \'segmentId\'))', }, # Hash })) ``` ```java RecommendationResponse result = client.send(new RecommendItemSegmentsToItemSegment(contextSegmentId, targetUserId, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setFilter("'segmentId' != \"coupons\"") // String .setBooster("if 'segmentId' == \"Editors Pick\" then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("countItems", "size(segment_items(\"categories\", 'segmentId'))"); }}) // Map ); ``` ```php $result = $client->send(new Reqs\RecommendItemSegmentsToItemSegment($context_segment_id, $target_user_id, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'filter' => '\'segmentId\' != "coupons"', // string 'booster' => 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'countItems' => 'size(segment_items("categories", \'segmentId\'))', ], // array (map) ])); ``` ```csharp RecommendationResponse result = client.Send(new RecommendItemSegmentsToItemSegment(contextSegmentId, targetUserId, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool filter: "'segmentId' != \"coupons\"", // string booster: "if 'segmentId' == \"Editors Pick\" then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "countItems", "size(segment_items(\"categories\", 'segmentId'))" }, } // Dictionary )); ``` ```go logicName := "recombee:default" request := client.NewRecommendItemSegmentsToItemSegment(contextSegmentId, targetUserId, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetFilter("'segmentId' != \"coupons\""). // string SetBooster("if 'segmentId' == \"Editors Pick\" then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "countItems": "size(segment_items(\"categories\", 'segmentId'))", }) // map[string]string result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/item-segments/item-segments/?contextSegmentId=segment-1 &targetUserId=user-1 &count=10 &scenario=homepage &cascadeCreate=true &filter='segmentId' != "coupons" &booster=if 'segmentId' == "Editors Pick" then 2 else 1 &logic=recombee:default &reqlExpressions={"countItems":"size(segment_items(\"categories\", 'segmentId'))"} ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- contextSegmentId String Located in: **query** Required: **Yes** Since version: **4.1.0** ID of the segment from `contextSegmentationId` for which the recommendations are to be generated. --- targetUserId String Located in: **query** Required: **Yes** Since version: **4.1.0** ID of the user who will see the recommendations. Specifying the _targetUserId_ is beneficial because: * It makes the recommendations personalized * Allows the calculation of Actions and Conversions in the graphical user interface, as Recombee can pair the user who got recommendations and who afterward viewed/purchased an item. If you insist on not specifying the user, pass `null`(`None`, `nil`, `NULL` etc., depending on the language) to _targetUserId_. Do not create some special dummy user for getting recommendations, as it could mislead the recommendation models, and result in wrong recommendations. For anonymous/unregistered users, it is possible to use, for example, their session ID. --- count Integer Located in: **query** Required: **Yes** Since version: **4.1.0** Number of item segments to be recommended (N for the top-N recommendation). --- scenario String Located in: **query** Required: **No** Since version: **4.1.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **4.1.0** If the user does not exist in the database, returns a list of non-personalized recommendations and creates the user in the database. This allows, for example, rotations in the following recommendations for that user, as the user will be already known to the system. --- filter String Located in: **query** Required: **No** Since version: **4.1.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression which allows you to filter recommended segments based on the `segmentationId`. --- booster String Located in: **query** Required: **No** Since version: **4.1.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression which allows you to boost recommendation rate of some segments based on the `segmentationId`. --- logic String Object Located in: **query** Required: **No** Since version: **4.1.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.1.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended Item Segment. This can be used to compute additional properties of the recommended Item Segments. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "countItems": "size(segment_items(\"categories\", 'segmentId'))" } } ``` Example response: ``` { "recommId": "a7ac55a4-8d6e-4f19-addc-abac4164d8a8", "recomms": [ { "id": "category-fantasy-books", "reqlEvaluations": { "countItems": 486 } }, { "id": "category-sci-fi-costumes", "reqlEvaluations": { "countItems": 19 } } ], "numberNextRecommsCalls": 0 } ``` --- ##### Responses 200 successful operation ``` { "recommId": "5fbd94fa-2553-422c-bdb5-af82687d8c6a", "recomms": [ { "id": "category-rap" }, { "id": "category-dnb" }, { "id": "category-electronic" } ], "numberNextRecommsCalls": 0 } ``` --- 400 count is not a positive integer. --- 404 contextSegmentId not found in the context segmentation --- get #### Recommend Next Item Segments Allowed on Client-Side Returns [Item Segments](https://docs.recombee.com/segmentations) to be shown as the next recommendations when a user scrolls (e.g., within a carousel or feed of Item Segments such as brands, artists, topics, or categories). The request requires the `recommId` of a base recommendation request and the number of Segments to return (`count`). The base request can be one of: * [Recommend Item Segments to Item](https://docs.recombee.com/api#recommend-item-segments-to-item) * [Recommend Item Segments to User](https://docs.recombee.com/api#recommend-item-segments-to-user) * [Recommend Item Segments to Item Segment](https://docs.recombee.com/api#recommend-item-segments-to-item-segment) * [Search Item Segments](https://docs.recombee.com/api#search-item-segments) All other parameters are inherited from the base request associated with the provided `recommId`. This endpoint can be called multiple times for a single `recommId`. Each call returns different Item Segments that have not been recommended in previous calls. The number of calls made so far is returned in the `numberNextRecommsCalls` field. Requests can be made up to 30 minutes after the base request or the most recent Recommend Next Item Segments call. For billing purposes, each call to this endpoint is counted as a separate recommendation request. ```js const result = await client.send(new recombee.RecommendNextItemSegments(recommId, count)); ``` ```kotlin val result = client.sendAsync(RecommendNextItemSegments(recommId, count)) result.onSuccess { response: RecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: RecommendationResponse = try await client.send(RecommendNextItemSegments(recommId: recommId, count: count)) ``` ```js const result = await client.send(new requests.RecommendNextItemSegments(recommId, count)); ``` ```python result = client.send(RecommendNextItemSegments(recomm_id, count)) ``` ```ruby result = client.send(RecommendNextItemSegments.new(recomm_id, count)) ``` ```java RecommendationResponse result = client.send(new RecommendNextItemSegments(recommId, count)); ``` ```php $result = $client->send(new Reqs\RecommendNextItemSegments($recomm_id, $count)); ``` ```csharp RecommendationResponse result = client.Send(new RecommendNextItemSegments(recommId, count)); ``` ```go request := client.NewRecommendNextItemSegments(recommId, count) result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/next/item-segments/{recommId}?count=10 ``` --- Since version 6.2.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **6.2.0** ID of your database. --- recommId String Located in: **path** Required: **Yes** Since version: **6.2.0** ID of the base recommendation request for which next recommendations should be returned --- count Integer Located in: **query** Required: **Yes** Since version: **6.2.0** Number of item segments to be recommended --- ##### Responses 200 Successful operation. ``` { "recommId": "768448ea-10b3-4028-bb76-4b2f95121d19", "recomms": [ { "id": "Comedy" }, { "id": "Drama" }, { "id": "Action" } ], "numberNextRecommsCalls": 4 } ``` --- 400 Parameter `count` is not given or is not a positive integer. Parameter `recommId` is not an UUID. --- 404 Base request with the given `recommId` does not exist or has expired. --- ### Recommending Users Recommendation endpoints that return the Users. get #### Recommend Users to User Gets users similar to the given user, based on the user's past interactions (purchases, ratings, etc.) and values of properties. It is also possible to use POST HTTP method (for example in the case of a very long ReQL filter) - query parameters then become body parameters. The returned users are sorted by similarity (the first user being the most similar). ```js const result = await client.send(new requests.RecommendUsersToUser(userId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['username', 'country'], // array filter: '\'country\' == "US"', // string booster: 'if \'country\' == context_user["country"] then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object rotationRate: 0.1, // number rotationTime: 7200.0, // number })); ``` ```python result = client.send(RecommendUsersToUser(user_id, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean return_properties=True, # boolean included_properties=['username', 'country'], # array filter='\'country\' == "US"', # string booster='if \'country\' == context_user["country"] then 2 else 1', # string logic='recombee:default', # string / dict reql_expressions={ 'isInUsersCity': 'context_user["city"] in \'cities\'', }, # dict rotation_rate=0.1, # number rotation_time=7200.0, # number )) ``` ```ruby result = client.send(RecommendUsersToUser.new(user_id, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean return_properties: true, # boolean included_properties: ['username', 'country'], # array filter: '\'country\' == "US"', # string booster: 'if \'country\' == context_user["country"] then 2 else 1', # string logic: 'recombee:default', # string / Hash reql_expressions: { 'isInUsersCity' => 'context_user["city"] in \'cities\'', }, # Hash rotation_rate: 0.1, # number rotation_time: 7200.0, # number })) ``` ```java RecommendationResponse result = client.send(new RecommendUsersToUser(userId, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"username", "country"}) // String[] .setFilter("'country' == \"US\"") // String .setBooster("if 'country' == context_user[\"country\"] then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("isInUsersCity", "context_user[\"city\"] in 'cities'"); }}) // Map .setRotationRate(0.1) // double .setRotationTime(7200.0) // double ); ``` ```php $result = $client->send(new Reqs\RecommendUsersToUser($user_id, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'returnProperties' => true, // boolean 'includedProperties' => ['username', 'country'], // array 'filter' => '\'country\' == "US"', // string 'booster' => 'if \'country\' == context_user["country"] then 2 else 1', // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'isInUsersCity' => 'context_user["city"] in \'cities\'', ], // array (map) 'rotationRate' => 0.1, // number 'rotationTime' => 7200.0, // number ])); ``` ```csharp RecommendationResponse result = client.Send(new RecommendUsersToUser(userId, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool returnProperties: true, // bool includedProperties: new string[] { "username", "country" }, // string[] filter: "'country' == \"US\"", // string booster: "if 'country' == context_user[\"country\"] then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "isInUsersCity", "context_user[\"city\"] in 'cities'" }, }, // Dictionary rotationRate: 0.1, // double rotationTime: 7200.0 // double )); ``` ```go logicName := "recombee:default" request := client.NewRecommendUsersToUser(userId, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetReturnProperties(true). // bool SetIncludedProperties([]string{"username", "country"}). // []string SetFilter("'country' == \"US\""). // string SetBooster("if 'country' == context_user[\"country\"] then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "isInUsersCity": "context_user[\"city\"] in 'cities'", }). // map[string]string SetRotationRate(0.1). // float64 SetRotationTime(7200.0) // float64 result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/users/{userId}/users/?count=10 &scenario=homepage &cascadeCreate=true &returnProperties=true &includedProperties=username,country &filter='country' == "US" &booster=if 'country' == context_user["country"] then 2 else 1 &logic=recombee:default &reqlExpressions={"isInUsersCity":"context_user[\"city\"] in 'cities'"} &rotationRate=0.1 &rotationTime=7200.0 ``` --- Since version 2.0.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **2.0.0** ID of your database. --- userId String Located in: **path** Required: **Yes** Since version: **2.0.0** User to whom we find similar users --- count Integer Located in: **query** Required: **Yes** Since version: **2.0.0** Number of users to be recommended (N for the top-N recommendation). --- scenario String Located in: **query** Required: **No** Since version: **2.0.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **2.0.0** If the user does not exist in the database, returns a list of non-personalized recommendations and creates the user in the database. This allows, for example, rotations in the following recommendations for that user, as the user will be already known to the system. --- returnProperties Boolean Located in: **query** Required: **No** Since version: **2.0.0** With `returnProperties=true`, property values of the recommended users are returned along with their IDs in a JSON dictionary. The acquired property values can be used to easily display the recommended users. Example response: ``` { "recommId": "9cb9c55d-50ba-4478-84fd-ab456136156e", "recomms": [ { "id": "user-17", "values": { "country": "US", "sex": "F" } }, { "id": "user-2", "values": { "country": "CAN", "sex": "M" } } ], "numberNextRecommsCalls": 0 } ``` --- includedProperties Array Located in: **query** Required: **No** Since version: **2.0.0** Allows specifying which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. Example response for `includedProperties=country`: ``` { "recommId": "b326d82d-5d57-4b45-b362-c9d6f0895855", "recomms": [ { "id": "user-17", "values": { "country": "US" } }, { "id": "user-2", "values": { "country": "CAN" } } ], "numberNextRecommsCalls": 0 } ``` --- filter String Located in: **query** Required: **No** Since version: **2.0.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to filter recommended users based on the values of their attributes. Filters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- booster String Located in: **query** Required: **No** Since version: **2.0.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to boost the recommendation rate of some users based on the values of their attributes. Boosters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- logic String Object Located in: **query** Required: **No** Since version: **2.4.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.0.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended user. This can be used to compute additional properties of the recommended users that are not stored in the database. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "isInUsersCity": "context_user[\"city\"] in 'cities'", "distanceToUser": "earth_distance('location', context_user[\"location\"])" } } ``` Example response: ``` { "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "recomms": [ { "id": "restaurant-178", "reqlEvaluations": { "isInUsersCity": true, "distanceToUser": 5200.2 } }, { "id": "bar-42", "reqlEvaluations": { "isInUsersCity": false, "distanceToUser": 2516.0 } } ], "numberNextRecommsCalls": 0 } ``` --- rotationRate Number Located in: **query** Required: **No** Since version: **5.0.0** **Expert option:** If your users browse the system in real-time, it may easily happen that you wish to offer them recommendations multiple times. Here comes the question: how much should the recommendations change? Should they remain the same, or should they rotate? Recombee API allows you to control this per request in a backward fashion. You may penalize a user for being recommended in the near past. For the specific user, `rotationRate=1` means maximal rotation, `rotationRate=0` means absolutely no rotation. You may also use, for example, `rotationRate=0.2` for only slight rotation of recommended users. --- rotationTime Number Located in: **query** Required: **No** Since version: **5.0.0** **Expert option:** Taking _rotationRate_ into account, specifies how long it takes for a user to recover from the penalization. For example, `rotationTime=7200.0` means that users recommended less than 2 hours ago are penalized. --- ##### Responses 200 Successful operation. ``` { "recommId": "f88d970d-561c-460f-b4d4-faf0478244ca", "recomms": [ { "id": "user-64" }, { "id": "user-42" }, { "id": "user-23" } ], "numberNextRecommsCalls": 0 } ``` --- 400 userId does not match ^\[a-zA-Z0-9\_-:@.\]+$, count is not a positive integer, filter or booster is not valid [ReQL](https://docs.recombee.com/reql) expressions, filter expression does not return boolean, booster does not return double or integer. --- 404 userId not found in the database and cascadeCreate is false. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### Recommend Users to Item Recommends users that are likely to be interested in the given item. It is also possible to use POST HTTP method (for example in the case of a very long ReQL filter) - query parameters then become body parameters. The returned users are sorted by predicted interest in the item (the first user being the most interested). ```js const result = await client.send(new requests.RecommendUsersToItem(itemId, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['username', 'country'], // array filter: '\'country\' == "US"', // string booster: 'if \'country\' == context_user["country"] then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object })); ``` ```python result = client.send(RecommendUsersToItem(item_id, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean return_properties=True, # boolean included_properties=['username', 'country'], # array filter='\'country\' == "US"', # string booster='if \'country\' == context_user["country"] then 2 else 1', # string logic='recombee:default', # string / dict reql_expressions={ 'isInUsersCity': 'context_user["city"] in \'cities\'', }, # dict )) ``` ```ruby result = client.send(RecommendUsersToItem.new(item_id, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean return_properties: true, # boolean included_properties: ['username', 'country'], # array filter: '\'country\' == "US"', # string booster: 'if \'country\' == context_user["country"] then 2 else 1', # string logic: 'recombee:default', # string / Hash reql_expressions: { 'isInUsersCity' => 'context_user["city"] in \'cities\'', }, # Hash })) ``` ```java RecommendationResponse result = client.send(new RecommendUsersToItem(itemId, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"username", "country"}) // String[] .setFilter("'country' == \"US\"") // String .setBooster("if 'country' == context_user[\"country\"] then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("isInUsersCity", "context_user[\"city\"] in 'cities'"); }}) // Map ); ``` ```php $result = $client->send(new Reqs\RecommendUsersToItem($item_id, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'returnProperties' => true, // boolean 'includedProperties' => ['username', 'country'], // array 'filter' => '\'country\' == "US"', // string 'booster' => 'if \'country\' == context_user["country"] then 2 else 1', // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'isInUsersCity' => 'context_user["city"] in \'cities\'', ], // array (map) ])); ``` ```csharp RecommendationResponse result = client.Send(new RecommendUsersToItem(itemId, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool returnProperties: true, // bool includedProperties: new string[] { "username", "country" }, // string[] filter: "'country' == \"US\"", // string booster: "if 'country' == context_user[\"country\"] then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "isInUsersCity", "context_user[\"city\"] in 'cities'" }, } // Dictionary )); ``` ```go logicName := "recombee:default" request := client.NewRecommendUsersToItem(itemId, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetReturnProperties(true). // bool SetIncludedProperties([]string{"username", "country"}). // []string SetFilter("'country' == \"US\""). // string SetBooster("if 'country' == context_user[\"country\"] then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "isInUsersCity": "context_user[\"city\"] in 'cities'", }) // map[string]string result, err := request.Send() // result is of the type bindings.RecommendationResponse ``` ```http GET /{databaseId}/recomms/items/{itemId}/users/?count=10 &scenario=homepage &cascadeCreate=true &returnProperties=true &includedProperties=username,country &filter='country' == "US" &booster=if 'country' == context_user["country"] then 2 else 1 &logic=recombee:default &reqlExpressions={"isInUsersCity":"context_user[\"city\"] in 'cities'"} ``` --- Since version 2.0.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **2.0.0** ID of your database. --- itemId String Located in: **path** Required: **Yes** Since version: **2.0.0** ID of the item for which the recommendations are to be generated. --- count Integer Located in: **query** Required: **Yes** Since version: **2.0.0** Number of users to be recommended (N for the top-N recommendation). --- scenario String Located in: **query** Required: **No** Since version: **2.0.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **2.0.0** If an item of the given _itemId_ doesn't exist in the database, it creates the missing item. --- returnProperties Boolean Located in: **query** Required: **No** Since version: **2.0.0** With `returnProperties=true`, property values of the recommended users are returned along with their IDs in a JSON dictionary. The acquired property values can be used to easily display the recommended users. Example response: ``` { "recommId": "039b71dc-b9cc-4645-a84f-62b841eecfce", "recomms": [ { "id": "user-17", "values": { "country": "US", "sex": "F" } }, { "id": "user-2", "values": { "country": "CAN", "sex": "M" } } ], "numberNextRecommsCalls": 0 } ``` --- includedProperties Array Located in: **query** Required: **No** Since version: **2.0.0** Allows specifying which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. Example response for `includedProperties=country`: ``` { "recommId": "b2b355dd-972a-4728-9c6b-2dc229db0678", "recomms": [ { "id": "user-17", "values": { "country": "US" } }, { "id": "user-2", "values": { "country": "CAN" } } ], "numberNextRecommsCalls": 0 } ``` --- filter String Located in: **query** Required: **No** Since version: **2.0.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to filter recommended users based on the values of their attributes. Filters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- booster String Located in: **query** Required: **No** Since version: **2.0.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to boost the recommendation rate of some users based on the values of their attributes. Boosters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- logic String Object Located in: **query** Required: **No** Since version: **2.4.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.0.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended user. This can be used to compute additional properties of the recommended users that are not stored in the database. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "isInUsersCity": "context_user[\"city\"] in 'cities'", "distanceToUser": "earth_distance('location', context_user[\"location\"])", "isFromSameCompany": "'company' == context_item[\"company\"]" } } ``` Example response: ``` { "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "recomms": [ { "id": "restaurant-178", "reqlEvaluations": { "isInUsersCity": true, "distanceToUser": 5200.2, "isFromSameCompany": false } }, { "id": "bar-42", "reqlEvaluations": { "isInUsersCity": false, "distanceToUser": 2516.0, "isFromSameCompany": true } } ], "numberNextRecommsCalls": 0 } ``` --- ##### Responses 200 Successful operation. ``` { "recommId": "ee94fa8b-efe7-4b35-abc6-2bc3456d66ed", "recomms": [ { "id": "user-64" }, { "id": "user-42" }, { "id": "user-23" } ], "numberNextRecommsCalls": 0 } ``` --- 400 itemId does not match ^\[a-zA-Z0-9\_-:@.\]+$, count is not a positive integer, filter or booster is not valid [ReQL](https://docs.recombee.com/reql) expressions, filter expression does not return boolean, booster does not return double or integer. --- 404 itemId not found in the database and cascadeCreate is false. If there is no additional info in the JSON response, you probably have an error in your URL. --- ### Composite Recommendations Composite Recommendations return a source entity (e.g., an Item, or [Item Segment](https://docs.recombee.com/segmentations)) and a list of related recommendations in a single response, enabling multi-layered, highly personalized suggestions, such as _Because You Watched …_ in streaming services or _Top Products from Your Favorite Brand …_ in e-commerce. post #### Composite Recommendation Allowed on Client-Side Composite Recommendation returns both a _source entity_ (e.g., an Item or [Item Segment](https://docs.recombee.com/segmentations)) and a list of related recommendations in a single response. It is ideal for use cases such as personalized homepage sections (_Articles from _), _Because You Watched _, or _Artists Related to Your Favorite Artist _. See detailed **examples and configuration guidance** in the [Composite Scenarios documentation](https://docs.recombee.com/scenarios#composite-recommendations). **Structure** The endpoint operates in two stages: 1. Recommends the _source_ (e.g., an Item Segment or item) to the user. 2. Recommends _results_ (items or Item Segments) related to that _source_. For example, _Articles from _ can be decomposed into: * [Recommend Item Segments To User](https://docs.recombee.com/api#recommend-item-segments-to-user) to find the category. * [Recommend Items To Item Segment](https://docs.recombee.com/api#recommend-items-to-item-segment) to recommend articles from that category. Since the first step uses [Recommend Item Segments To User](https://docs.recombee.com/api#recommend-items-to-user), you must include the `userId` parameter in the _Composite Recommendation_ request. Each _Composite Recommendation_ counts as a single recommendation API request for billing. **Stage-specific Parameters** Additional parameters can be supplied via [sourceSettings](https://docs.recombee.com/api#composite-recommendation-param-sourceSettings) and [resultSettings](https://docs.recombee.com/api#composite-recommendation-param-resultSettings). In the example above: * `sourceSettings` may include any parameter valid for [Recommend Item Segments To User](https://docs.recombee.com/api#recommend-items-to-user) (e.g., `filter`, `booster`). * `resultSettings` may include any parameter valid for [Recommend Items To Item Segment](https://docs.recombee.com/api#recommend-items-to-item-segment). See [this example](https://docs.recombee.com/api#composite-recommendation-example-setting-parameters-for-individual-stages) for more details. ```js const result = await client.send(new recombee.CompositeRecommendation(scenario, count, { // optional parameters: itemId: 'item-1', // string userId: 'user-1', // string logic: 'recombee:items-from-top-segment-for-you', // string / Object segmentId: 'segment-1', // string searchQuery: 'shoes', // string cascadeCreate: true, // boolean sourceSettings: { returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number }, resultSettings: { returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number }, })); ``` ```kotlin val result = client.sendAsync(CompositeRecommendation(scenario, count, // optional parameters: itemId = "item-1", // String userId = "user-1", // String logic = Logic(name = "recombee:items-from-top-segment-for-you"), // Logic segmentId = "segment-1", // String searchQuery = "shoes", // String cascadeCreate = true, // Boolean sourceSettings = CompositeRecommendationStageParameters( returnProperties = true, // Boolean includedProperties = listOf("title", "price", "publishedAt"), // List filter = "price > 50", // String booster = "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic = Logic(name = "recombee:default"), // Logic reqlExpressions = mapOf( "isInUsersCity" to "context_user[\"city\"] in 'cities'", ), // Map minRelevance = "low", // String rotationRate = 0.1, // Double rotationTime = 7200.0, // Double ), resultSettings = CompositeRecommendationStageParameters( returnProperties = true, // Boolean includedProperties = listOf("title", "price", "publishedAt"), // List filter = "price > 50", // String booster = "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic = Logic(name = "recombee:default"), // Logic reqlExpressions = mapOf( "isInUsersCity" to "context_user[\"city\"] in 'cities'", ), // Map minRelevance = "low", // String rotationRate = 0.1, // Double rotationTime = 7200.0, // Double ), )) result.onSuccess { response: CompositeRecommendationResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: CompositeRecommendationResponse = try await client.send(CompositeRecommendation(scenario: scenario, count: count, // optional parameters: itemId: "item-1", // String userId: "user-1", // String logic: Logic(name: "recombee:items-from-top-segment-for-you"), // Logic segmentId: "segment-1", // String searchQuery: "shoes", // String cascadeCreate: true, // Bool sourceSettings: CompositeRecommendationStageParameters( returnProperties: true, // Bool includedProperties: ["title", "price", "publishedAt"], // [String] filter: "price > 50", // String booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic: Logic(name: "recombee:default"), // Logic reqlExpressions: [ "isInUsersCity": "context_user[\"city\"] in 'cities'", ], // JSONDictionary minRelevance: "low", // String rotationRate: 0.1, // Double rotationTime: 7200.0 // Double ), resultSettings: CompositeRecommendationStageParameters( returnProperties: true, // Bool includedProperties: ["title", "price", "publishedAt"], // [String] filter: "price > 50", // String booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic: Logic(name: "recombee:default"), // Logic reqlExpressions: [ "isInUsersCity": "context_user[\"city\"] in 'cities'", ], // JSONDictionary minRelevance: "low", // String rotationRate: 0.1, // Double rotationTime: 7200.0 // Double ) )) ``` ```js const result = await client.send(new requests.CompositeRecommendation(scenario, count, { // optional parameters: itemId: 'item-1', // string userId: 'user-1', // string logic: 'recombee:items-from-top-segment-for-you', // string / Object segmentId: 'segment-1', // string searchQuery: 'shoes', // string cascadeCreate: true, // boolean sourceSettings: { returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number }, resultSettings: { returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'recombee:default', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object minRelevance: 'low', // string rotationRate: 0.1, // number rotationTime: 7200.0, // number }, })); ``` ```python result = client.send(CompositeRecommendation(scenario, count, # optional parameters: item_id='item-1', # string user_id='user-1', # string logic='recombee:items-from-top-segment-for-you', # string / dict segment_id='segment-1', # string search_query='shoes', # string cascade_create=True, # boolean source_settings=CompositeRecommendationStageParameters( return_properties=True, # boolean included_properties=['title', 'price', 'publishedAt'], # array filter='price > 50', # string booster="if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic='recombee:default', # string / dict reql_expressions={ 'isInUsersCity': 'context_user["city"] in \'cities\'', }, # dict min_relevance='low', # string rotation_rate=0.1, # number rotation_time=7200.0, # number ), result_settings=CompositeRecommendationStageParameters( return_properties=True, # boolean included_properties=['title', 'price', 'publishedAt'], # array filter='price > 50', # string booster="if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic='recombee:default', # string / dict reql_expressions={ 'isInUsersCity': 'context_user["city"] in \'cities\'', }, # dict min_relevance='low', # string rotation_rate=0.1, # number rotation_time=7200.0, # number ), )) ``` ```ruby result = client.send(CompositeRecommendation.new(scenario, count, { # optional parameters: item_id: 'item-1', # string user_id: 'user-1', # string logic: 'recombee:items-from-top-segment-for-you', # string / Hash segment_id: 'segment-1', # string search_query: 'shoes', # string cascade_create: true, # boolean source_settings: CompositeRecommendationStageParameters.new( return_properties: true, # boolean included_properties: ['title', 'price', 'publishedAt'], # array filter: 'price > 50', # string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic: 'recombee:default', # string / Hash reql_expressions: { 'isInUsersCity' => 'context_user["city"] in \'cities\'', }, # Hash min_relevance: 'low', # string rotation_rate: 0.1, # number rotation_time: 7200.0, # number ), result_settings: CompositeRecommendationStageParameters.new( return_properties: true, # boolean included_properties: ['title', 'price', 'publishedAt'], # array filter: 'price > 50', # string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic: 'recombee:default', # string / Hash reql_expressions: { 'isInUsersCity' => 'context_user["city"] in \'cities\'', }, # Hash min_relevance: 'low', # string rotation_rate: 0.1, # number rotation_time: 7200.0, # number ), })) ``` ```java CompositeRecommendationResponse result = client.send(new CompositeRecommendation(scenario, count) .setItemId("item-1") // String .setUserId("user-1") // String .setLogic(new Logic("recombee:items-from-top-segment-for-you")) // Logic .setSegmentId("segment-1") // String .setSearchQuery("shoes") // String .setCascadeCreate(true) // boolean .setSourceSettings(new CompositeRecommendationStageParameters() .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"title", "price", "publishedAt"}) // String[] .setFilter("price > 50") // String .setBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("isInUsersCity", "context_user[\"city\"] in 'cities'"); }}) // Map .setMinRelevance("low") // String .setRotationRate(0.1) // double .setRotationTime(7200.0)) // double .setResultSettings(new CompositeRecommendationStageParameters() .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"title", "price", "publishedAt"}) // String[] .setFilter("price > 50") // String .setBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1") // String .setLogic(new Logic("recombee:default")) // Logic .setReqlExpressions(new HashMap() {{ put("isInUsersCity", "context_user[\"city\"] in 'cities'"); }}) // Map .setMinRelevance("low") // String .setRotationRate(0.1) // double .setRotationTime(7200.0)) // double ); ``` ```php $result = $client->send(new Reqs\CompositeRecommendation($scenario, $count, [ // optional parameters: 'itemId' => 'item-1', // string 'userId' => 'user-1', // string 'logic' => 'recombee:items-from-top-segment-for-you', // string / array (map) 'segmentId' => 'segment-1', // string 'searchQuery' => 'shoes', // string 'cascadeCreate' => true, // boolean 'sourceSettings' => [ 'returnProperties' => true, // boolean 'includedProperties' => ['title', 'price', 'publishedAt'], // array 'filter' => 'price > 50', // string 'booster' => "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'isInUsersCity' => 'context_user["city"] in \'cities\'', ], // array (map) 'minRelevance' => 'low', // string 'rotationRate' => 0.1, // number 'rotationTime' => 7200.0, // number ], 'resultSettings' => [ 'returnProperties' => true, // boolean 'includedProperties' => ['title', 'price', 'publishedAt'], // array 'filter' => 'price > 50', // string 'booster' => "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string 'logic' => 'recombee:default', // string / array (map) 'reqlExpressions' => [ 'isInUsersCity' => 'context_user["city"] in \'cities\'', ], // array (map) 'minRelevance' => 'low', // string 'rotationRate' => 0.1, // number 'rotationTime' => 7200.0, // number ], ])); ``` ```csharp CompositeRecommendationResponse result = client.Send(new CompositeRecommendation(scenario, count, // optional parameters: itemId: "item-1", // string userId: "user-1", // string logic: new Logic(name: "recombee:items-from-top-segment-for-you"), // Logic segmentId: "segment-1", // string searchQuery: "shoes", // string cascadeCreate: true, // bool sourceSettings: new CompositeRecommendationStageParameters( returnProperties: true, // bool includedProperties: new string[] { "title", "price", "publishedAt" }, // string[] filter: "price > 50", // string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "isInUsersCity", "context_user[\"city\"] in 'cities'" }, }, // Dictionary minRelevance: "low", // string rotationRate: 0.1, // double rotationTime: 7200.0 // double ), resultSettings: new CompositeRecommendationStageParameters( returnProperties: true, // bool includedProperties: new string[] { "title", "price", "publishedAt" }, // string[] filter: "price > 50", // string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string logic: new Logic(name: "recombee:default"), // Logic reqlExpressions: new Dictionary { { "isInUsersCity", "context_user[\"city\"] in 'cities'" }, }, // Dictionary minRelevance: "low", // string rotationRate: 0.1, // double rotationTime: 7200.0 // double ) )); ``` ```go logicName := "recombee:items-from-top-segment-for-you" returnProperties := true filter := "price > 50" booster := "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1" logicName2 := "recombee:default" minRelevance := "low" rotationRate := 0.1 rotationTime := 7200.0 request := client.NewCompositeRecommendation(scenario, count). // optional parameters: SetItemId("item-1"). // string SetUserId("user-1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetSegmentId("segment-1"). // string SetSearchQuery("shoes"). // string SetCascadeCreate(true). // bool SetSourceSettings(bindings.CompositeRecommendationStageParameters{ ReturnProperties: &returnProperties, // *bool IncludedProperties: &[]string{"title", "price", "publishedAt"}, // *[]string Filter: &filter, // *string Booster: &booster, // *string Logic: bindings.Logic{Name: &logicName2}, // bindings.Logic ReqlExpressions: &map[string]string{ "isInUsersCity": "context_user[\"city\"] in 'cities'", }, // *map[string]string MinRelevance: &minRelevance, // *string RotationRate: &rotationRate, // *float64 RotationTime: &rotationTime, // *float64 }). SetResultSettings(bindings.CompositeRecommendationStageParameters{ ReturnProperties: &returnProperties, // *bool IncludedProperties: &[]string{"title", "price", "publishedAt"}, // *[]string Filter: &filter, // *string Booster: &booster, // *string Logic: bindings.Logic{Name: &logicName2}, // bindings.Logic ReqlExpressions: &map[string]string{ "isInUsersCity": "context_user[\"city\"] in 'cities'", }, // *map[string]string MinRelevance: &minRelevance, // *string RotationRate: &rotationRate, // *float64 RotationTime: &rotationTime, // *float64 }) result, err := request.Send() // result is of the type bindings.CompositeRecommendationResponse ``` ```http POST /{databaseId}/recomms/composite/ Body (application/json): { "scenario": "homepage", "count": 10, "itemId": "item-1", "userId": "user-1", "logic": "recombee:items-from-top-segment-for-you", "segmentId": "segment-1", "searchQuery": "shoes", "cascadeCreate": true, "sourceSettings": { "returnProperties": true, "includedProperties": [ "title", "price", "publishedAt" ], "filter": "price > 50", "booster": "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", "logic": "recombee:default", "reqlExpressions": { "isInUsersCity": "context_user[\"city\"] in 'cities'" }, "minRelevance": "low", "rotationRate": 0.1, "rotationTime": 7200.0 }, "resultSettings": { "returnProperties": true, "includedProperties": [ "title", "price", "publishedAt" ], "filter": "price > 50", "booster": "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", "logic": "recombee:default", "reqlExpressions": { "isInUsersCity": "context_user[\"city\"] in 'cities'" }, "minRelevance": "low", "rotationRate": 0.1, "rotationTime": 7200.0 } } ``` --- Since version 6.0.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **6.0.0** ID of your database. --- scenario String Located in: **body** Required: **Yes** Since version: **6.0.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- count Integer Located in: **body** Required: **Yes** Since version: **6.0.0** Number of items to be recommended (N for the top-N recommendation). --- itemId String Located in: **body** Required: **No** Since version: **6.0.0** ID of the item for which the recommendations are to be generated. --- userId String Located in: **body** Required: **No** Since version: **6.0.0** ID of the user for which the recommendations are to be generated. --- logic String Object Located in: **body** Required: **No** Since version: **6.0.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- segmentId String Located in: **body** Required: **No** Since version: **6.0.0** ID of the segment from `contextSegmentationId` for which the recommendations are to be generated. --- searchQuery String Located in: **body** Required: **No** Since version: **6.2.0** Search query provided by the user. It is used for the full-text search. Only applicable if the _scenario_ corresponds to a search scenario. --- cascadeCreate Boolean Located in: **body** Required: **No** Since version: **6.0.0** If the entity for the source recommendation does not exist in the database, returns a list of non-personalized recommendations and creates the user in the database. This allows, for example, rotations in the following recommendations for that entity, as the entity will be already known to the system. --- sourceSettings Object Located in: **body** Required: **No** Since version: **6.0.0** Parameters applied for recommending the _Source_ stage. The accepted parameters correspond with the recommendation sub-endpoint used to recommend the _Source_. --- resultSettings Object Located in: **body** Required: **No** Since version: **6.0.0** Parameters applied for recommending the _Result_ stage. The accepted parameters correspond with the recommendation sub-endpoint used to recommend the _Result_. --- ##### Responses 200 Successful operation. ``` { "recommId": "ee94fa8b-efe7-4b35-abc6-2bc3456d66ed", "source": { "id": "category-4" }, "recomms": [ { "id": "item-64" }, { "id": "item-42" }, { "id": "item-23" } ], "numberNextRecommsCalls": 0 } ``` --- 400 Count is not a positive integer, provided scenario not found. --- 404 contextSegmentId not found in the context segmentation, userId not found in the database and cascadeCreate is false, itemId not found in the database and cascadeCreate is false. --- ##### Examples ###### Example Category Sections With Reordering Suppose you want to recommend three category sections on the homepage, but in a personalized order for each user. For example, in a news domain, one user might see _Politics–Culture–Technology_, while another might get _Sport–Technology–Politics_. You can achieve this by calling three Composite Recommendations within a single [Batch](https://docs.recombee.com/api#batch) request — retrieving both the personalized categories and the recommended items within each. The Batch ensures that three distinct categories are returned in the results. Example response: ``` [ { "code": 200, "json": { "recommId": "c8f25d2a-5c39-4c45-b42b-6a7d4e6b1c52", "source": { "id": "category-sport" }, "recomms": [ { "id": "article-1024" }, { "id": "article-2031" }, { "id": "article-3042" } ], "numberNextRecommsCalls": 0 } }, { "code": 200, "json": { "recommId": "b31f16e2-f4e9-43e8-b22f-9da78a5e8e33", "source": { "id": "category-technology" }, "recomms": [ { "id": "article-501" }, { "id": "article-507" }, { "id": "article-519" } ], "numberNextRecommsCalls": 0 } }, { "code": 200, "json": { "recommId": "3f6ad2f2-a3f1-4ba1-a690-f4f01f76d4eb", "source": { "id": "category-politics" }, "recomms": [ { "id": "article-146" }, { "id": "article-462" }, { "id": "article-463" } ], "numberNextRecommsCalls": 0 } } ] ``` Requesting recommendations: ```js const batchRequest = new recombee.Batch([ new recombee.CompositeRecommendation('homepage-category-section', 6, { userId: userId }), new recombee.CompositeRecommendation('homepage-category-section', 6, { userId: userId }), new recombee.CompositeRecommendation('homepage-category-section', 6, { userId: userId }) ], { distinctRecomms: true }); const responses = await client.send(batchRequest); ``` ```kotlin val requests = listOf( CompositeRecommendation(scenario = "homepage-category-section", count = 6, userId = userId), CompositeRecommendation(scenario = "homepage-category-section", count = 6, userId = userId), CompositeRecommendation(scenario = "homepage-category-section", count = 6, userId = userId) ) val responses = client.send(Batch(requests = requests, distinctRecomms = true)) ``` ```swift let requests: [any Request] = [ CompositeRecommendation(scenario: "homepage-category-section", count: 6, userId: userId), CompositeRecommendation(scenario: "homepage-category-section", count: 6, userId: userId), CompositeRecommendation(scenario: "homepage-category-section", count: 6, userId: userId) ] let batchRequest = Batch(requests: requests, distinctRecomms: true) let result = try await client.send(batchRequest) ``` ```python reqs = [ CompositeRecommendation("homepage-category-section", 6, user_id=user_id), CompositeRecommendation("homepage-category-section", 6, user_id=user_id), CompositeRecommendation("homepage-category-section", 6, user_id=user_id), ] responses = client.send(Batch(reqs, distinct_recomms=True)) ``` ```ruby batch = Batch.new([ CompositeRecommendation.new('homepage-category-section', 6, {:user_id => user_id}), CompositeRecommendation.new('homepage-category-section', 6, {:user_id => user_id}), CompositeRecommendation.new('homepage-category-section', 6, {:user_id => user_id}) ], distinct_recomms: true) responses = client.send(batch) ``` ```java Request[] requests = new Request[] { new CompositeRecommendation("homepage-category-section", 6).setUserId(userId), new CompositeRecommendation("homepage-category-section", 6).setUserId(userId), new CompositeRecommendation("homepage-category-section", 6).setUserId(userId) }; Batch batch = new Batch(requests).setDistinctRecomms(true); BatchResponse[] responses = client.send(batch); ``` ```js const batch = new rqs.Batch([ new rqs.CompositeRecommendation('homepage-category-section', 6, { userId: userId }), new rqs.CompositeRecommendation('homepage-category-section', 6, { userId: userId }), new rqs.CompositeRecommendation('homepage-category-section', 6, { userId: userId }) ], { distinctRecomms: true }); const responses = await client.send(batch); ``` ```php $reqs = [ new Reqs\CompositeRecommendation("homepage-category-section", 6, ["userId" => $userId]), new Reqs\CompositeRecommendation("homepage-category-section", 6, ["userId" => $userId]), new Reqs\CompositeRecommendation("homepage-category-section", 6, ["userId" => $userId]), ]; $batch = new Reqs\Batch($reqs, ["distinctRecomms" => true]); $responses = $client->send($batch); ``` ```csharp Request[] requests = new Request[] { new CompositeRecommendation("homepage-category-section", 6, userId: userId), new CompositeRecommendation("homepage-category-section", 6, userId: userId), new CompositeRecommendation("homepage-category-section", 6, userId: userId) }; BatchResponse batchResponse = await client.SendAsync(new Batch(requests, distinctRecomms: true)); ``` ```go import ( "github.com/recombee/go-api-client/v6/recombee/requests" ) reqs := []requests.Request{ requests.NewCompositeRecommendation("homepage-category-section", 6).SetUserId(userId), requests.NewCompositeRecommendation("homepage-category-section", 6).SetUserId(userId), requests.NewCompositeRecommendation("homepage-category-section", 6).SetUserId(userId), } batchRes, err := client.NewBatch(reqs).SetDistinctRecomms(true).Send() ``` ```http { "requests": [ { "method": "POST", "path": "/recomms/composite/", "body": { "scenario": "homepage-category-section", "count": 6, "userId": "user-123" } }, { "method": "POST", "path": "/recomms/composite/", "body": { "scenario": "homepage-category-section", "count": 6, "userId": "user-123" } }, { "method": "POST", "path": "/recomms/composite/", "body": { "scenario": "homepage-category-section", "count": 6, "userId": "user-123" } } ], "distinctRecomms": true } ``` --- ###### Example Setting Parameters For Individual Stages This example shows how to use parameters on both stages: * In `sourceSettings`, we enable rotation so the _source_ changes over time for the same user. * In `resultSettings`, we filter out promotions and return basic properties for rendering. Example response (truncated) with `returnProperties=true` on results: ``` { "recommId": "7b8d0f5e-42a4-4a71-b2b7-25f9c0cc0e9a", "source": { "id": "article-389" }, "recomms": [ { "id": "article-1024", "values": { "title": "5 Books That Will Change How You Think", "url": "newsportal.com/a/1024" } }, { "id": "article-2031", "values": { "title": "The Psychology of Habit Formation", "url": "newsportal.com/a/2031" } } ], "numberNextRecommsCalls": 0 } ``` Requesting recommendations: ```js const req = new recombee.CompositeRecommendation( 'because-you-read', 10, { userId: userId, sourceSettings: { rotationRate: 0.5, rotationTime: 7200 }, resultSettings: { filter: "'type' != \"promotion\"", returnProperties: true, includedProperties: ['title', 'url'] } } ); const response = await client.send(req); ``` ```kotlin val req = CompositeRecommendation( scenario = "because-you-read", count = 10, userId = userId, sourceSettings = CompositeRecommendationStageParameters( rotationRate = 0.5, rotationTime = 7200.0 ), resultSettings = CompositeRecommendationStageParameters( filter = "'type' != \"promotion\"", returnProperties = true, includedProperties = listOf("title", "url") ) ) val resp = client.send(req) ``` ```swift let req = CompositeRecommendation( scenario: "because-you-read", count: 10, userId: userId, sourceSettings: CompositeRecommendationStageParameters( rotationRate: 0.5, rotationTime: 7200 ), resultSettings: CompositeRecommendationStageParameters( returnProperties: true, includedProperties: ["title", "url"], filter: "'type' != \"promotion\"" ) ) let result = try await client.send(req) ``` ```python req = CompositeRecommendation( "because-you-read", 10, user_id=user_id, source_settings=CompositeRecommendationStageParameters( rotation_rate=0.5, rotation_time=7200, return_properties=True ), result_settings=CompositeRecommendationStageParameters( filter="'type' != \"promotion\"", return_properties=True, included_properties=["title", "url"] ), ) response = client.send(req) ``` ```ruby req = CompositeRecommendation.new( 'because-you-read', 10, { :user_id => user_id, :source_settings => CompositeRecommendationStageParameters.new( :rotation_rate => 0.5, :rotation_time => 7200, :return_properties => true ), :result_settings => CompositeRecommendationStageParameters.new( :filter => "'type' != \"promotion\"", :return_properties => true, :included_properties => ['title', 'url'] ) } ) response = client.send(req) ``` ```java CompositeRecommendation req = new CompositeRecommendation("because-you-read", 10) .setUserId(userId) .setSourceSettings( new CompositeRecommendationStageParameters() .setRotationRate(0.5) .setRotationTime(7200.0)) .setResultSettings( new CompositeRecommendationStageParameters() .setFilter("'type' != \"promotion\"") .setReturnProperties(true) .setIncludedProperties(Arrays.asList("title", "url"))); BatchResponse resp = client.send(req); ``` ```js const req = new rqs.CompositeRecommendation( 'because-you-read', 10, { userId, sourceSettings: { rotationRate: 0.5, rotationTime: 7200 }, resultSettings: { filter: "'type' != \"promotion\"", returnProperties: true, includedProperties: ['title', 'url'] } } ); const response = await client.send(req); ``` ```php $req = new Reqs\CompositeRecommendation( "because-you-read", 10, [ "userId" => $userId, "sourceSettings" => [ "rotationRate" => 0.5, "rotationTime" => 7200, "returnProperties" => true ], "resultSettings" => [ "filter" => "'type' != \"promotion\"", "returnProperties" => true, "includedProperties" => ["title", "url"] ] ] ); $response = $client->send($req); ``` ```csharp var req = new CompositeRecommendation( "because-you-read", 10, userId: userId, sourceSettings: new CompositeRecommendationStageParameters( rotationRate: 0.5, rotationTime: 7200 ), resultSettings: new CompositeRecommendationStageParameters( filter: "'type' != \"promotion\"", returnProperties: true, includedProperties: new[] { "title", "url" } ) ); var response = await client.SendAsync(req); ``` ```go import ( "github.com/recombee/go-api-client/v6/recombee/bindings" ) req := client.NewCompositeRecommendation("because-you-read", 10).SetUserId(userId) // Source settings (pointers required for optional fields) rot := 0.5 rt := 7200.0 rp := true src := bindings.CompositeRecommendationStageParameters{ ReturnProperties: &rp, RotationRate: &rot, RotationTime: &rt, } req = req.SetSourceSettings(src) // Result settings filter := "'type' != \"promotion\"" incl := []string{"title", "url"} res := bindings.CompositeRecommendationStageParameters{ Filter: &filter, ReturnProperties: &rp, IncludedProperties: &incl, } req = req.SetResultSettings(res) resp, err := req.Send() ``` ```http { "method": "POST", "path": "/recomms/composite/", "body": { "scenario": "because-you-read", "count": 10, "userId": "user-123", "sourceSettings": { "rotationRate": 0.5, "rotationTime": 7200 }, "resultSettings": { "filter": "'type' != \"promotion\"", "returnProperties": true, "includedProperties": ["title", "url"] } } } ``` ## Search Full-text personalized search. The results are based on the full-text matching of a search query and the preferences of a particular user. get #### Search Items Allowed on Client-Side Full-text personalized search. The results are based on the provided `searchQuery` and also on the user's past interactions (purchases, ratings, etc.) with the items (items more suitable for the user are preferred in the results). All the string and set item properties are indexed by the search engine. This endpoint should be used in a search box on your website/app. It can be called multiple times as the user is typing the query in order to get the most viable suggestions based on the current state of the query, or once after submitting the whole query. The returned items are sorted by relevance (the first item being the most relevant). Besides the recommended items, also a unique `recommId` is returned in the response. It can be used to: * Let Recombee know that this search was successful (e.g., user clicked one of the recommended items). See [Reported metrics](https://docs.recombee.com/admin_ui#reported-metrics). * Get subsequent search results when the user scrolls down or goes to the next page. See [Recommend Next Items](https://docs.recombee.com/api#recommend-next-items). It is also possible to use POST HTTP method (for example in the case of a very long ReQL filter) - query parameters then become body parameters. ```js const result = await client.send(new recombee.SearchItems(userId, searchQuery, count, { // optional parameters: scenario: 'search-bar', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'search:personalized', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object })); ``` ```kotlin val result = client.sendAsync(SearchItems(userId, searchQuery, count, // optional parameters: scenario = "search-bar", // String cascadeCreate = true, // Boolean returnProperties = true, // Boolean includedProperties = listOf("title", "price", "publishedAt"), // List filter = "price > 50", // String booster = "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic = Logic(name = "search:personalized"), // Logic reqlExpressions = mapOf( "isInUsersCity" to "context_user[\"city\"] in 'cities'", ), // Map )) result.onSuccess { response: SearchResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: SearchResponse = try await client.send(SearchItems(userId: userId, searchQuery: searchQuery, count: count, // optional parameters: scenario: "search-bar", // String cascadeCreate: true, // Bool returnProperties: true, // Bool includedProperties: ["title", "price", "publishedAt"], // [String] filter: "price > 50", // String booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // String logic: Logic(name: "search:personalized"), // Logic reqlExpressions: [ "isInUsersCity": "context_user[\"city\"] in 'cities'", ] // JSONDictionary )) ``` ```js const result = await client.send(new requests.SearchItems(userId, searchQuery, count, { // optional parameters: scenario: 'search-bar', // string cascadeCreate: true, // boolean returnProperties: true, // boolean includedProperties: ['title', 'price', 'publishedAt'], // array filter: 'price > 50', // string booster: 'if now() - \'publishedAt\' <= 7 * 24 * 3600 then 2 else 1', // string logic: 'search:personalized', // string / Object reqlExpressions: { isInUsersCity: 'context_user["city"] in \'cities\'', }, // Object })); ``` ```python result = client.send(SearchItems(user_id, search_query, count, # optional parameters: scenario='search-bar', # string cascade_create=True, # boolean return_properties=True, # boolean included_properties=['title', 'price', 'publishedAt'], # array filter='price > 50', # string booster="if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic='search:personalized', # string / dict reql_expressions={ 'isInUsersCity': 'context_user["city"] in \'cities\'', }, # dict )) ``` ```ruby result = client.send(SearchItems.new(user_id, search_query, count, { # optional parameters: scenario: 'search-bar', # string cascade_create: true, # boolean return_properties: true, # boolean included_properties: ['title', 'price', 'publishedAt'], # array filter: 'price > 50', # string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", # string logic: 'search:personalized', # string / Hash reql_expressions: { 'isInUsersCity' => 'context_user["city"] in \'cities\'', }, # Hash })) ``` ```java SearchResponse result = client.send(new SearchItems(userId, searchQuery, count) .setScenario("search-bar") // String .setCascadeCreate(true) // boolean .setReturnProperties(true) // boolean .setIncludedProperties(new String[]{"title", "price", "publishedAt"}) // String[] .setFilter("price > 50") // String .setBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1") // String .setLogic(new Logic("search:personalized")) // Logic .setReqlExpressions(new HashMap() {{ put("isInUsersCity", "context_user[\"city\"] in 'cities'"); }}) // Map ); ``` ```php $result = $client->send(new Reqs\SearchItems($user_id, $search_query, $count, [ // optional parameters: 'scenario' => 'search-bar', // string 'cascadeCreate' => true, // boolean 'returnProperties' => true, // boolean 'includedProperties' => ['title', 'price', 'publishedAt'], // array 'filter' => 'price > 50', // string 'booster' => "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string 'logic' => 'search:personalized', // string / array (map) 'reqlExpressions' => [ 'isInUsersCity' => 'context_user["city"] in \'cities\'', ], // array (map) ])); ``` ```csharp SearchResponse result = client.Send(new SearchItems(userId, searchQuery, count, // optional parameters: scenario: "search-bar", // string cascadeCreate: true, // bool returnProperties: true, // bool includedProperties: new string[] { "title", "price", "publishedAt" }, // string[] filter: "price > 50", // string booster: "if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1", // string logic: new Logic(name: "search:personalized"), // Logic reqlExpressions: new Dictionary { { "isInUsersCity", "context_user[\"city\"] in 'cities'" }, } // Dictionary )); ``` ```go logicName := "search:personalized" request := client.NewSearchItems(userId, searchQuery, count). // optional parameters: SetScenario("search-bar"). // string SetCascadeCreate(true). // bool SetReturnProperties(true). // bool SetIncludedProperties([]string{"title", "price", "publishedAt"}). // []string SetFilter("price > 50"). // string SetBooster("if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "isInUsersCity": "context_user[\"city\"] in 'cities'", }) // map[string]string result, err := request.Send() // result is of the type bindings.SearchResponse ``` ```http GET /{databaseId}/search/users/{userId}/items/?searchQuery=shoes &count=10 &scenario=search-bar &cascadeCreate=true &returnProperties=true &includedProperties=title,price,publishedAt &filter=price > 50 &booster=if now() - 'publishedAt' <= 7 * 24 * 3600 then 2 else 1 &logic=search:personalized &reqlExpressions={"isInUsersCity":"context_user[\"city\"] in 'cities'"} ``` --- Since version 3.0.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **3.0.0** ID of your database. --- userId String Located in: **path** Required: **Yes** Since version: **3.0.0** ID of the user for whom personalized search will be performed. --- searchQuery String Located in: **query** Required: **Yes** Since version: **3.0.0** Search query provided by the user. It is used for the full-text search. --- count Integer Located in: **query** Required: **Yes** Since version: **3.0.0** Number of items to be returned (N for the top-N results). --- scenario String Located in: **query** Required: **No** Since version: **3.0.0** Scenario defines a particular search field in your user interface. You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each field performs. The AI that optimizes models to get the best results may optimize different scenarios separately, or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **3.0.0** If the user does not exist in the database, returns a list of non-personalized search results and creates the user in the database. This allows, for example, rotations in the following recommendations for that user, as the user will be already known to the system. --- returnProperties Boolean Located in: **query** Required: **No** Since version: **3.0.0** With `returnProperties=true`, property values of the recommended items are returned along with their IDs in a JSON dictionary. The acquired property values can be used to easily display the recommended items to the user. Example response: ``` { "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "recomms": [ { "id": "tv-178", "values": { "description": "4K TV with 3D feature", "categories": ["Electronics", "Televisions"], "price": 342, "url": "myshop.com/tv-178" } }, { "id": "mixer-42", "values": { "description": "Stainless Steel Mixer", "categories": ["Home & Kitchen"], "price": 39, "url": "myshop.com/mixer-42" } } ], "numberNextRecommsCalls": 0 } ``` --- includedProperties Array Located in: **query** Required: **No** Since version: **3.0.0** Allows specifying which properties should be returned when `returnProperties=true` is set. The properties are given as a comma-separated list. Example response for `includedProperties=description,price`: ``` { "recommId": "a86ee8d5-cd8e-46d1-886c-8b3771d0520b", "recomms": [ { "id": "tv-178", "values": { "description": "4K TV with 3D feature", "price": 342 } }, { "id": "mixer-42", "values": { "description": "Stainless Steel Mixer", "price": 39 } } ], "numberNextRecommsCalls": 0 } ``` --- filter String Located in: **query** Required: **No** Since version: **2.0.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to filter recommended items based on the values of their attributes. Filters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- booster String Located in: **query** Required: **No** Since version: **2.0.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression, which allows you to boost the recommendation rate of some items based on the values of their attributes. Boosters can also be assigned to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- logic String Object Located in: **query** Required: **No** Since version: **2.4.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.0.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended item. This can be used to compute additional properties of the recommended items that are not stored in the database. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "isInUsersCity": "context_user[\"city\"] in 'cities'", "distanceToUser": "earth_distance('location', context_user[\"location\"])" } } ``` Example response: ``` { "recommId": "ce52ada4-e4d9-4885-943c-407db2dee837", "recomms": [ { "id": "restaurant-178", "reqlEvaluations": { "isInUsersCity": true, "distanceToUser": 5200.2 } }, { "id": "bar-42", "reqlEvaluations": { "isInUsersCity": false, "distanceToUser": 2516.0 } } ], "numberNextRecommsCalls": 0 } ``` --- ##### Responses 200 Successful operation. ``` { "recommId": "4fd901fe-4ba1-a3f1-a690-f4f01f76d4eb", "recomms": [ { "id": "item-476" }, { "id": "item-412" }, { "id": "item-773" } ], "numberNextRecommsCalls": 0 } ``` --- 400 userId does not match ^\[a-zA-Z0-9\_-:@.\]+$, count is not a positive integer, searchQuery is not provided, filter or booster are not valid [ReQL](https://docs.recombee.com/reql) expressions, filter expression does not return boolean, booster does not return double or integer. --- 404 userId not found in the database and cascadeCreate is false. If there is no additional info in the JSON response, you probably have an error in you URL. --- get #### Search Item Segments Allowed on Client-Side Full-text personalized search that returns Segments from a Segmentation. The results are based on the provided `searchQuery` and also on the user's past interactions (purchases, ratings, etc.). Based on the used Segmentation, this endpoint can be used for example for: * Searching within categories or brands * Searching within genres or artists For example if the user is searching for "iPhone" this endpoint can return "cell phones" category. You need to set the used Segmentation the Admin UI in the Scenario settings prior to using this endpoint. The returned segments are sorted by relevance (first segment being the most relevant). It is also possible to use POST HTTP method (for example in case of very long ReQL filter) - query parameters then become body parameters. ```js const result = await client.send(new recombee.SearchItemSegments(userId, searchQuery, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean filter: '\'segmentId\' != "coupons"', // string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string logic: 'search:personalized', // string / Object reqlExpressions: { countItems: 'size(segment_items("categories", \'segmentId\'))', }, // Object })); ``` ```kotlin val result = client.sendAsync(SearchItemSegments(userId, searchQuery, count, // optional parameters: scenario = "homepage", // String cascadeCreate = true, // Boolean filter = "'segmentId' != \"coupons\"", // String booster = "if 'segmentId' == \"Editors Pick\" then 2 else 1", // String logic = Logic(name = "search:personalized"), // Logic reqlExpressions = mapOf( "countItems" to "size(segment_items(\"categories\", 'segmentId'))", ), // Map )) result.onSuccess { response: SearchResponse -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: SearchResponse = try await client.send(SearchItemSegments(userId: userId, searchQuery: searchQuery, count: count, // optional parameters: scenario: "homepage", // String cascadeCreate: true, // Bool filter: "'segmentId' != \"coupons\"", // String booster: "if 'segmentId' == \"Editors Pick\" then 2 else 1", // String logic: Logic(name: "search:personalized"), // Logic reqlExpressions: [ "countItems": "size(segment_items(\"categories\", 'segmentId'))", ] // JSONDictionary )) ``` ```js const result = await client.send(new requests.SearchItemSegments(userId, searchQuery, count, { // optional parameters: scenario: 'homepage', // string cascadeCreate: true, // boolean filter: '\'segmentId\' != "coupons"', // string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string logic: 'search:personalized', // string / Object reqlExpressions: { countItems: 'size(segment_items("categories", \'segmentId\'))', }, // Object })); ``` ```python result = client.send(SearchItemSegments(user_id, search_query, count, # optional parameters: scenario='homepage', # string cascade_create=True, # boolean filter='\'segmentId\' != "coupons"', # string booster='if \'segmentId\' == "Editors Pick" then 2 else 1', # string logic='search:personalized', # string / dict reql_expressions={ 'countItems': 'size(segment_items("categories", \'segmentId\'))', }, # dict )) ``` ```ruby result = client.send(SearchItemSegments.new(user_id, search_query, count, { # optional parameters: scenario: 'homepage', # string cascade_create: true, # boolean filter: '\'segmentId\' != "coupons"', # string booster: 'if \'segmentId\' == "Editors Pick" then 2 else 1', # string logic: 'search:personalized', # string / Hash reql_expressions: { 'countItems' => 'size(segment_items("categories", \'segmentId\'))', }, # Hash })) ``` ```java SearchResponse result = client.send(new SearchItemSegments(userId, searchQuery, count) .setScenario("homepage") // String .setCascadeCreate(true) // boolean .setFilter("'segmentId' != \"coupons\"") // String .setBooster("if 'segmentId' == \"Editors Pick\" then 2 else 1") // String .setLogic(new Logic("search:personalized")) // Logic .setReqlExpressions(new HashMap() {{ put("countItems", "size(segment_items(\"categories\", 'segmentId'))"); }}) // Map ); ``` ```php $result = $client->send(new Reqs\SearchItemSegments($user_id, $search_query, $count, [ // optional parameters: 'scenario' => 'homepage', // string 'cascadeCreate' => true, // boolean 'filter' => '\'segmentId\' != "coupons"', // string 'booster' => 'if \'segmentId\' == "Editors Pick" then 2 else 1', // string 'logic' => 'search:personalized', // string / array (map) 'reqlExpressions' => [ 'countItems' => 'size(segment_items("categories", \'segmentId\'))', ], // array (map) ])); ``` ```csharp SearchResponse result = client.Send(new SearchItemSegments(userId, searchQuery, count, // optional parameters: scenario: "homepage", // string cascadeCreate: true, // bool filter: "'segmentId' != \"coupons\"", // string booster: "if 'segmentId' == \"Editors Pick\" then 2 else 1", // string logic: new Logic(name: "search:personalized"), // Logic reqlExpressions: new Dictionary { { "countItems", "size(segment_items(\"categories\", 'segmentId'))" }, } // Dictionary )); ``` ```go logicName := "search:personalized" request := client.NewSearchItemSegments(userId, searchQuery, count). // optional parameters: SetScenario("homepage"). // string SetCascadeCreate(true). // bool SetFilter("'segmentId' != \"coupons\""). // string SetBooster("if 'segmentId' == \"Editors Pick\" then 2 else 1"). // string SetLogic(bindings.Logic{Name: &logicName}). // bindings.Logic SetReqlExpressions(map[string]string{ "countItems": "size(segment_items(\"categories\", 'segmentId'))", }) // map[string]string result, err := request.Send() // result is of the type bindings.SearchResponse ``` ```http GET /{databaseId}/search/users/{userId}/item-segments/?searchQuery=shoes &count=10 &scenario=homepage &cascadeCreate=true &filter='segmentId' != "coupons" &booster=if 'segmentId' == "Editors Pick" then 2 else 1 &logic=search:personalized &reqlExpressions={"countItems":"size(segment_items(\"categories\", 'segmentId'))"} ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- userId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the user for whom personalized search will be performed. --- searchQuery String Located in: **query** Required: **Yes** Since version: **4.1.0** Search query provided by the user. It is used for the full-text search. --- count Integer Located in: **query** Required: **Yes** Since version: **4.1.0** Number of segments to be returned (N for the top-N results). --- scenario String Located in: **query** Required: **No** Since version: **4.1.0** Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing". You can set various settings to the [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). You can also see the performance of each scenario in the Admin UI separately, so you can check how well each application performs. The AI that optimizes models to get the best results may optimize different scenarios separately or even use different models in each of the scenarios. --- cascadeCreate Boolean Located in: **query** Required: **No** Since version: **4.1.0** If the user does not exist in the database, returns a list of non-personalized recommendations and creates the user in the database. This allows, for example, rotations in the following recommendations for that user, as the user will be already known to the system. --- filter String Located in: **query** Required: **No** Since version: **4.1.0** Boolean-returning [ReQL](https://docs.recombee.com/reql) expression which allows you to filter recommended segments based on the `segmentationId`. --- booster String Located in: **query** Required: **No** Since version: **4.1.0** Number-returning [ReQL](https://docs.recombee.com/reql) expression which allows you to boost recommendation rate of some segments based on the `segmentationId`. --- logic String Object Located in: **query** Required: **No** Since version: **4.1.0** Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case. See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details. The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users. Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com). --- reqlExpressions Object Located in: **query** Required: **No** Since version: **6.1.0** A dictionary of [ReQL](https://docs.recombee.com/reql) expressions that will be executed for each recommended Item Segment. This can be used to compute additional properties of the recommended Item Segments. The keys are the names of the expressions, and the values are the actual ReQL expressions. Example request: ``` { "reqlExpressions": { "countItems": "size(segment_items(\"categories\", 'segmentId'))" } } ``` Example response: ``` { "recommId": "a7ac55a4-8d6e-4f19-addc-abac4164d8a8", "recomms": [ { "id": "category-fantasy-books", "reqlEvaluations": { "countItems": 486 } }, { "id": "category-sci-fi-costumes", "reqlEvaluations": { "countItems": 19 } } ], "numberNextRecommsCalls": 0 } ``` --- ##### Responses 200 successful operation ``` { "recommId": "7acdc8b5-f731-44f8-b522-72625044666f", "recomms": [ { "id": "cell phones" }, { "id": "cell phone accessories" } ], "numberNextRecommsCalls": 0 } ``` --- 400 userId does not match ^\[a-zA-Z0-9\_-:@.\]+$, count is not a positive integer, searchQuery is not provided, filter or booster is not valid [ReQL](https://docs.recombee.com/reql) expressions, filter expression does not return boolean, booster does not return double or integer. --- 404 userId not found in the database and cascadeCreate is false. If there is no additional info in the JSON response, you probably have an error in your URL. --- ### Synonyms Define that some words or phrases should be considered equal by the full-text search engine. post #### Add Search Synonym Adds a new synonym for the [Search items](https://docs.recombee.com/api#search-items). When the `term` is used in the search query, the `synonym` is also used for the full-text search. Unless `oneWay=true`, it works also in the opposite way (`synonym` \-> `term`). An example of a synonym can be `science fiction` for the term `sci-fi`. ```js const result = await client.send(new requests.AddSearchSynonym(term, synonym, { // optional parameters: oneWay: false, // boolean })); ``` ```python result = client.send(AddSearchSynonym(term, synonym, # optional parameters: one_way=False, # boolean )) ``` ```ruby result = client.send(AddSearchSynonym.new(term, synonym, { # optional parameters: one_way: false, # boolean })) ``` ```java SearchSynonym result = client.send(new AddSearchSynonym(term, synonym) .setOneWay(false) // boolean ); ``` ```php $result = $client->send(new Reqs\AddSearchSynonym($term, $synonym, [ // optional parameters: 'oneWay' => false, // boolean ])); ``` ```csharp SearchSynonym result = client.Send(new AddSearchSynonym(term, synonym, // optional parameters: oneWay: false // bool )); ``` ```go request := client.NewAddSearchSynonym(term, synonym). // optional parameters: SetOneWay(false) // bool result, err := request.Send() // result is of the type bindings.SearchSynonym ``` ```http POST /{databaseId}/synonyms/items/ Body (application/json): { "term": "sofa", "synonym": "couch", "oneWay": false } ``` --- Since version 3.2.0 --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **3.2.0** ID of your database. --- term String Located in: **body** Required: **Yes** Since version: **3.2.0** A word to which the `synonym` is specified. --- synonym String Located in: **body** Required: **Yes** Since version: **3.2.0** A word that should be considered equal to the `term` by the full-text search engine. --- oneWay Boolean Located in: **body** Required: **No** Since version: **3.2.0** If set to `true`, only `term` \-> `synonym` is considered. If set to `false`, also `synonym` \-> `term` works. Default: `false`. --- ##### Responses 201 Successful operation. Returns data about the added synonym (including `id`). ``` { "id": "cc198c86-e015-bb74-b5f4-8f996fd26736", "term": "sci-fi", "synonym": "science fiction", "oneWay": false } ``` --- 400 Missing a field, or a field has a wrong type. --- 409 `synonym` and `term` pair already exists in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- get #### List Search Synonyms Gives the list of synonyms defined in the database. ```js const result = await client.send(new requests.ListSearchSynonyms({ // optional parameters: count: 10, // integer offset: 0, // integer })); ``` ```python result = client.send(ListSearchSynonyms( # optional parameters: count=10, # integer offset=0, # integer )) ``` ```ruby result = client.send(ListSearchSynonyms.new({ # optional parameters: count: 10, # integer offset: 0, # integer })) ``` ```java ListSearchSynonymsResponse result = client.send(new ListSearchSynonyms() .setCount(10) // long .setOffset(0) // long ); ``` ```php $result = $client->send(new Reqs\ListSearchSynonyms([ // optional parameters: 'count' => 10, // integer 'offset' => 0, // integer ])); ``` ```csharp ListSearchSynonymsResponse result = client.Send(new ListSearchSynonyms( // optional parameters: count: 10, // long offset: 0 // long )); ``` ```go request := client.NewListSearchSynonyms(). // optional parameters: SetCount(10). // int SetOffset(0) // int result, err := request.Send() // result is of the type bindings.ListSearchSynonymsResponse ``` ```http GET /{databaseId}/synonyms/items/?count=10 &offset=0 ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- count Integer Located in: **query** Required: **No** The number of synonyms to be listed. --- offset Integer Located in: **query** Required: **No** Specifies the number of synonyms to skip (ordered by `term`). --- ##### Responses 200 Successful operation. ``` { "synonyms": [ { "id": "cc198c86-e015-bb74-b5f4-8f996fd26736", "term": "sci-fi", "synonym": "science fiction", "oneWay": false }, { "id": "33bef0e5-f6ee-ac04-8b80-7ba8ece1fe63", "term": "sitcom", "synonym": "situation comedy", "oneWay": false } ] } ``` --- delete #### Delete All Search Synonyms Deletes all synonyms defined in the database. ```js client.send(new requests.DeleteAllSearchSynonyms()); ``` ```python client.send(DeleteAllSearchSynonyms()) ``` ```ruby client.send(DeleteAllSearchSynonyms.new()) ``` ```java client.send(new DeleteAllSearchSynonyms()); ``` ```php $client->send(new Reqs\DeleteAllSearchSynonyms()); ``` ```csharp client.Send(new DeleteAllSearchSynonyms()); ``` ```go request := client.NewDeleteAllSearchSynonyms() _, err := request.Send() ``` ```http DELETE /{databaseId}/synonyms/items/ ``` --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- ##### Responses 200 Successful operation. --- delete #### Delete Search Synonym Deletes synonym of the given `id`. This synonym is no longer taken into account in the [Search items](https://docs.recombee.com/api#search-items). ```js client.send(new requests.DeleteSearchSynonym(id)); ``` ```python client.send(DeleteSearchSynonym(id)) ``` ```ruby client.send(DeleteSearchSynonym.new(id)) ``` ```java client.send(new DeleteSearchSynonym(id)); ``` ```php $client->send(new Reqs\DeleteSearchSynonym($id)); ``` ```csharp client.Send(new DeleteSearchSynonym(id)); ``` ```go request := client.NewDeleteSearchSynonym(id) _, err := request.Send() ``` ```http DELETE /{databaseId}/synonyms/items/{id} ``` --- Calls Limit Per Minute 1000 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- id String Located in: **path** Required: **Yes** ID of the synonym that should be deleted. --- ##### Responses 200 Successful operation. --- 404 Synonym with the given `id` does not exist. --- ## Series Items in the catalog may be organized into series, expressing an explicit, known ordering of items, if there is any. Typical examples of series may be consecutive TV show episodes, book titles, etc. Each item may be added to zero or more series, and a series may also be added into another series, resulting in a "meta-series". This may be useful for modeling ordered seasons of a TV show that has the episodes in each season themselves ordered. ### Series definition Methods for managing series - creating, listing, and deleting them. put #### Add Series Creates a new series in the database. ```js client.send(new requests.AddSeries(seriesId, { // optional parameters: cascadeCreate: true, // boolean })); ``` ```python client.send(AddSeries(series_id, # optional parameters: cascade_create=True, # boolean )) ``` ```ruby client.send(AddSeries.new(series_id, { # optional parameters: cascade_create: true, # boolean })) ``` ```java client.send(new AddSeries(seriesId) .setCascadeCreate(true) // boolean ); ``` ```php $client->send(new Reqs\AddSeries($series_id, [ // optional parameters: 'cascadeCreate' => true, // boolean ])); ``` ```csharp client.Send(new AddSeries(seriesId, // optional parameters: cascadeCreate: true // bool )); ``` ```go request := client.NewAddSeries(seriesId). // optional parameters: SetCascadeCreate(true) // bool _, err := request.Send() ``` ```http PUT /{databaseId}/series/{seriesId} Body (application/json): { "cascadeCreate": true } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- seriesId String Located in: **path** Required: **Yes** ID of the series to be created. --- cascadeCreate Boolean Located in: **body** Required: **No** If set to `true`, the item will be created with the same ID as the series. Default is `true`. --- ##### Responses 201 Successful operation. --- 400 The `seriesId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 409 Series of the given `seriesId` is already present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Delete Series Deletes the series of the given `seriesId` from the database. Deleting a series will only delete assignment of items to it, not the items themselves! ```js client.send(new requests.DeleteSeries(seriesId, { // optional parameters: cascadeDelete: false, // boolean })); ``` ```python client.send(DeleteSeries(series_id, # optional parameters: cascade_delete=False, # boolean )) ``` ```ruby client.send(DeleteSeries.new(series_id, { # optional parameters: cascade_delete: false, # boolean })) ``` ```java client.send(new DeleteSeries(seriesId) .setCascadeDelete(false) // boolean ); ``` ```php $client->send(new Reqs\DeleteSeries($series_id, [ // optional parameters: 'cascadeDelete' => false, // boolean ])); ``` ```csharp client.Send(new DeleteSeries(seriesId, // optional parameters: cascadeDelete: false // bool )); ``` ```go request := client.NewDeleteSeries(seriesId). // optional parameters: SetCascadeDelete(false) // bool _, err := request.Send() ``` ```http DELETE /{databaseId}/series/{seriesId} Body (application/json): { "cascadeDelete": false } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- seriesId String Located in: **path** Required: **Yes** ID of the series to be deleted. --- cascadeDelete Boolean Located in: **body** Required: **No** If set to `true`, item with the same ID as seriesId will be also deleted. Default is `false`. --- ##### Responses 200 Successful operation. --- 400 The `seriesId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Series of the given `seriesId` is not present in the database. In many cases, you may consider this code a success – it only tells you that nothing has been deleted from the database since the series was already not present. If there is no additional info in the JSON response, you probably have an error in your URL. --- get #### List Series Gets the list of all the series currently present in the database. ```js const result = await client.send(new requests.ListSeries()); ``` ```python result = client.send(ListSeries()) ``` ```ruby result = client.send(ListSeries.new()) ``` ```java Series[] result = client.send(new ListSeries()); ``` ```php $result = $client->send(new Reqs\ListSeries()); ``` ```csharp IEnumerable result = client.Send(new ListSeries()); ``` ```go request := client.NewListSeries() result, err := request.Send() // result is of the type []bindings.Series ``` ```http GET /{databaseId}/series/list/ ``` --- Calls Limit Per Minute 100 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- ##### Responses 200 Successful operation. ``` [ "series-1", "series-2", "series-3" ] ``` --- 404 Invalid URL. --- ### Series items Methods for adding items (or even series themselves) to series. get #### List Series Items Lists all the items present in the given series, sorted according to their time index values. ```js const result = await client.send(new requests.ListSeriesItems(seriesId)); ``` ```python result = client.send(ListSeriesItems(series_id)) ``` ```ruby result = client.send(ListSeriesItems.new(series_id)) ``` ```java SeriesItem[] result = client.send(new ListSeriesItems(seriesId)); ``` ```php $result = $client->send(new Reqs\ListSeriesItems($series_id)); ``` ```csharp IEnumerable result = client.Send(new ListSeriesItems(seriesId)); ``` ```go request := client.NewListSeriesItems(seriesId) result, err := request.Send() // result is of the type []bindings.SeriesItem ``` ```http GET /{databaseId}/series/{seriesId}/items/ ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- seriesId String Located in: **path** Required: **Yes** ID of the series whose items are to be listed. --- ##### Responses 200 Successful operation. ``` [ { "itemType": "item", "itemId": "item-x", "time": 1 }, { "itemType": "item", "itemId": "item-y", "time": 2 }, { "itemType": "item", "itemId": "item-z", "time": 3 } ] ``` --- 400 The `seriesId` does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- 404 Series of the given `seriesId` is not present in the database. If there is no additional info in the JSON response, you probably have an error in your URL. --- post #### Insert to Series Inserts an existing item/series into a series of the given seriesId at a position determined by time. ```js client.send(new requests.InsertToSeries(seriesId, itemType, itemId, time, { // optional parameters: cascadeCreate: true, // boolean })); ``` ```python client.send(InsertToSeries(series_id, item_type, item_id, time, # optional parameters: cascade_create=True, # boolean )) ``` ```ruby client.send(InsertToSeries.new(series_id, item_type, item_id, time, { # optional parameters: cascade_create: true, # boolean })) ``` ```java client.send(new InsertToSeries(seriesId, itemType, itemId, time) .setCascadeCreate(true) // boolean ); ``` ```php $client->send(new Reqs\InsertToSeries($series_id, $item_type, $item_id, $time, [ // optional parameters: 'cascadeCreate' => true, // boolean ])); ``` ```csharp client.Send(new InsertToSeries(seriesId, itemType, itemId, time, // optional parameters: cascadeCreate: true // bool )); ``` ```go request := client.NewInsertToSeries(seriesId, itemType, itemId, time). // optional parameters: SetCascadeCreate(true) // bool _, err := request.Send() ``` ```http POST /{databaseId}/series/{seriesId}/items/ Body (application/json): { "itemType": "item", "itemId": "item-1", "time": 1, "cascadeCreate": true } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- seriesId String Located in: **path** Required: **Yes** ID of the series to be inserted into. --- itemType String Located in: **body** Required: **Yes** `item` iff the regular item from the catalog is to be inserted, `series` iff series is inserted as the item. --- itemId String Located in: **body** Required: **Yes** ID of the item iff `itemType` is `item`. ID of the series iff `itemType` is `series`. --- time Number Located in: **body** Required: **Yes** Time index used for sorting items in the series. According to time, items are sorted within series in ascending order. In the example of TV show episodes, the episode number is a natural choice to be passed as time. --- cascadeCreate Boolean Located in: **body** Required: **No** Indicates that any non-existing entity specified within the request should be created (as if corresponding PUT requests were invoked). This concerns both the `seriesId` and the `itemId`. If `cascadeCreate` is set to true, the behavior also depends on the `itemType`. In case of `item`, an item is created, in case of `series` a series + corresponding item with the same ID is created. --- ##### Responses 200 Successful operation. --- 400 `seriesId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$, or `itemType`∉{item,series}, or `time` is not a real number. --- 404 Series of the given `seriesId` is not present in the database. Item of the given `itemId` is not present in the database if `itemType` is item. Series of the given `itemId` is not present in the database if `itemType` is series. If there is no additional info in the JSON response, you probably have an error in your URL. --- 409 A series item of the exact same (`itemType`, `itemId`, `time`) is already present in the series of `seriesId`. In many cases, you may consider this code a success – it only tells you that nothing has been written to the database. --- delete #### Remove from Series Removes an existing series item from the series. ```js client.send(new requests.RemoveFromSeries(seriesId, itemType, itemId)); ``` ```python client.send(RemoveFromSeries(series_id, item_type, item_id)) ``` ```ruby client.send(RemoveFromSeries.new(series_id, item_type, item_id)) ``` ```java client.send(new RemoveFromSeries(seriesId, itemType, itemId)); ``` ```php $client->send(new Reqs\RemoveFromSeries($series_id, $item_type, $item_id)); ``` ```csharp client.Send(new RemoveFromSeries(seriesId, itemType, itemId)); ``` ```go request := client.NewRemoveFromSeries(seriesId, itemType, itemId) _, err := request.Send() ``` ```http DELETE /{databaseId}/series/{seriesId}/items/ Body (application/json): { "itemType": "item", "itemId": "item-1" } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- seriesId String Located in: **path** Required: **Yes** ID of the series from which a series item is to be removed. --- itemType String Located in: **body** Required: **Yes** Type of the item to be removed. --- itemId String Located in: **body** Required: **Yes** ID of the item iff `itemType` is `item`. ID of the series iff `itemType` is `series`. --- ##### Responses 200 Successful operation. --- 400 The `seriesId` or `itemId` does not match ^\[a-zA-Z0-9\_-:@.\]+$ or `itemType`∉{`item`, `series`}. --- 404 Series of the given `seriesId` is not present in the database. Series item given by pair (`itemType`, `itemId`) is not present in series of `seriesId`. If there is no additional info in the JSON response, you probably have an error in your URL. --- ## Segmentations Definition Segmentations allow you to group the Items into various segments: For example segment articles or products by categories, segment movies by genres, etc. The Segmentations can be used in recommendations (e.g. return the most relevant categories for a user). See [this section](https://docs.recombee.com/segmentations) for more info. ### Property Based Segmentation Property-based Segmentation groups the Items by the value of a particular property. See [this section](https://docs.recombee.com/segmentations#property-based-segmentation) for more info. put #### Create Property Based Segmentation Creates a Segmentation that splits the items into segments based on values of a particular item property. A segment is created for each unique value of the property. In case of `set` properties, a segment is created for each value in the set. Item belongs to all these segments. ```js client.send(new requests.CreatePropertyBasedSegmentation(segmentationId, sourceType, propertyName, { // optional parameters: title: 'Categories', // string description: 'Segmentation based on item categories.', // string })); ``` ```python client.send(CreatePropertyBasedSegmentation(segmentation_id, source_type, property_name, # optional parameters: title='Categories', # string description='Segmentation based on item categories.', # string )) ``` ```ruby client.send(CreatePropertyBasedSegmentation.new(segmentation_id, source_type, property_name, { # optional parameters: title: 'Categories', # string description: 'Segmentation based on item categories.', # string })) ``` ```java client.send(new CreatePropertyBasedSegmentation(segmentationId, sourceType, propertyName) .setTitle("Categories") // String .setDescription("Segmentation based on item categories.") // String ); ``` ```php $client->send(new Reqs\CreatePropertyBasedSegmentation($segmentation_id, $source_type, $property_name, [ // optional parameters: 'title' => 'Categories', // string 'description' => 'Segmentation based on item categories.', // string ])); ``` ```csharp client.Send(new CreatePropertyBasedSegmentation(segmentationId, sourceType, propertyName, // optional parameters: title: "Categories", // string description: "Segmentation based on item categories." // string )); ``` ```go request := client.NewCreatePropertyBasedSegmentation(segmentationId, sourceType, propertyName). // optional parameters: SetTitle("Categories"). // string SetDescription("Segmentation based on item categories.") // string _, err := request.Send() ``` ```http PUT /{databaseId}/segmentations/property-based/{segmentationId} Body (application/json): { "sourceType": "items", "propertyName": "categories", "title": "Categories", "description": "Segmentation based on item categories." } ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the newly created Segmentation --- sourceType String Located in: **body** Required: **Yes** Since version: **4.1.0** What type of data should be segmented. Currently only `items` are supported. --- propertyName String Located in: **body** Required: **Yes** Since version: **4.1.0** Name of the property on which the Segmentation should be based --- title String Located in: **body** Required: **No** Since version: **4.1.0** Human-readable name that is shown in the Recombee Admin UI. --- description String Located in: **body** Required: **No** Since version: **4.1.0** Description that is shown in the Recombee Admin UI. --- ##### Responses 201 successful operation --- 400 segmentationId does not match ^\[a-zA-Z0-9\_-:@.\]+$, property is not of supported type (`string` or `set`). --- 404 Property does not exist. --- post #### Update Property Based Segmentation Updates a Property Based Segmentation ```js client.send(new requests.UpdatePropertyBasedSegmentation(segmentationId, { // optional parameters: propertyName: 'categories', // string title: 'Categories', // string description: 'Segmentation based on item categories.', // string })); ``` ```python client.send(UpdatePropertyBasedSegmentation(segmentation_id, # optional parameters: property_name='categories', # string title='Categories', # string description='Segmentation based on item categories.', # string )) ``` ```ruby client.send(UpdatePropertyBasedSegmentation.new(segmentation_id, { # optional parameters: property_name: 'categories', # string title: 'Categories', # string description: 'Segmentation based on item categories.', # string })) ``` ```java client.send(new UpdatePropertyBasedSegmentation(segmentationId) .setPropertyName("categories") // String .setTitle("Categories") // String .setDescription("Segmentation based on item categories.") // String ); ``` ```php $client->send(new Reqs\UpdatePropertyBasedSegmentation($segmentation_id, [ // optional parameters: 'propertyName' => 'categories', // string 'title' => 'Categories', // string 'description' => 'Segmentation based on item categories.', // string ])); ``` ```csharp client.Send(new UpdatePropertyBasedSegmentation(segmentationId, // optional parameters: propertyName: "categories", // string title: "Categories", // string description: "Segmentation based on item categories." // string )); ``` ```go request := client.NewUpdatePropertyBasedSegmentation(segmentationId). // optional parameters: SetPropertyName("categories"). // string SetTitle("Categories"). // string SetDescription("Segmentation based on item categories.") // string _, err := request.Send() ``` ```http POST /{databaseId}/segmentations/property-based/{segmentationId} Body (application/json): { "propertyName": "categories", "title": "Categories", "description": "Segmentation based on item categories." } ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the updated Segmentation --- propertyName String Located in: **body** Required: **No** Since version: **4.1.0** Name of the property on which the Segmentation should be based --- title String Located in: **body** Required: **No** Since version: **4.1.0** Human-readable name that is shown in the Recombee Admin UI. --- description String Located in: **body** Required: **No** Since version: **4.1.0** Description that is shown in the Recombee Admin UI. --- ##### Responses 201 successful operation --- 400 segmentationId does not match ^\[a-zA-Z0-9\_-:@.\]+$, property is not of supported type (`string` or `set`). --- 404 Property does not exist. Segmentation with given ID does not exist. --- ### Manual ReQL Segmentation Segmentation whose Segments are defined by ReQL filters. See [this section](https://docs.recombee.com/segmentations#manual-reql-segmentation) for more info. put #### Create Manual ReQL Segmentation Segment the items using multiple [ReQL](https://docs.recombee.com/reql) filters. Use the Add Manual ReQL Items Segment endpoint to create the individual segments. ```js client.send(new requests.CreateManualReqlSegmentation(segmentationId, sourceType, { // optional parameters: title: 'Homepage Rows', // string description: 'Segmentation grouping items into rows shown on the homepage.', // string })); ``` ```python client.send(CreateManualReqlSegmentation(segmentation_id, source_type, # optional parameters: title='Homepage Rows', # string description='Segmentation grouping items into rows shown on the homepage.', # string )) ``` ```ruby client.send(CreateManualReqlSegmentation.new(segmentation_id, source_type, { # optional parameters: title: 'Homepage Rows', # string description: 'Segmentation grouping items into rows shown on the homepage.', # string })) ``` ```java client.send(new CreateManualReqlSegmentation(segmentationId, sourceType) .setTitle("Homepage Rows") // String .setDescription("Segmentation grouping items into rows shown on the homepage.") // String ); ``` ```php $client->send(new Reqs\CreateManualReqlSegmentation($segmentation_id, $source_type, [ // optional parameters: 'title' => 'Homepage Rows', // string 'description' => 'Segmentation grouping items into rows shown on the homepage.', // string ])); ``` ```csharp client.Send(new CreateManualReqlSegmentation(segmentationId, sourceType, // optional parameters: title: "Homepage Rows", // string description: "Segmentation grouping items into rows shown on the homepage." // string )); ``` ```go request := client.NewCreateManualReqlSegmentation(segmentationId, sourceType). // optional parameters: SetTitle("Homepage Rows"). // string SetDescription("Segmentation grouping items into rows shown on the homepage.") // string _, err := request.Send() ``` ```http PUT /{databaseId}/segmentations/manual-reql/{segmentationId} Body (application/json): { "sourceType": "items", "title": "Homepage Rows", "description": "Segmentation grouping items into rows shown on the homepage." } ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the newly created Segmentation --- sourceType String Located in: **body** Required: **Yes** Since version: **4.1.0** What type of data should be segmented. Currently only `items` are supported. --- title String Located in: **body** Required: **No** Since version: **4.1.0** Human-readable name that is shown in the Recombee Admin UI. --- description String Located in: **body** Required: **No** Since version: **4.1.0** Description that is shown in the Recombee Admin UI. --- ##### Responses 201 successful operation --- 400 segmentationId does not match ^\[a-zA-Z0-9\_-:@.\]+$. --- ##### Examples ###### Example Create a Manual ReQL Segmentation and set up its Segments Each Segment is defined by a ReQL filter: Items passing the filter belong to the Segment. Here we create two Segments in the `homepage-rows` Segmentation: * `made-in-us` contains items that were created in the US * `short-laughs` contains comedies with runtime under 30 minutes See [this section](https://docs.recombee.com/segmentations#manual-reql-based-segmentation) for more info. ```python reqs = [ CreateManualReqlSegmentation("homepage-rows", "items"), AddManualReqlSegment("homepage-rows", "made-in-us", "'country' == \"US\" "), AddManualReqlSegment("homepage-rows", "short-laughs", "\"Comedy\" in 'genres' and 'runtime' < 30") ] responses = client.send(Batch(reqs)) ``` ```ruby batch = Batch.new([ CreateManualReqlSegmentation.new('homepage-rows', 'items'), AddManualReqlSegment.new('homepage-rows', 'made-in-us', "'country' == \"US\" "), AddManualReqlSegment.new('homepage-rows', 'short-laughs', "\"Comedy\" in 'genres' and 'runtime' < 30") ]) response = client.send(batch) ``` ```java Request[] requests = new Request[] { new CreateManualReqlSegmentation("homepage-rows", "items"), new AddManualReqlSegment("homepage-rows", "made-in-us", "'country' == \"US\" "), new AddManualReqlSegment("homepage-rows", "short-laughs", "\"Comedy\" in 'genres' and 'runtime' < 30") }; BatchResponse[] responses = client.send(new Batch(requests)); ``` ```js const batch = new Batch([ new CreateManualReqlSegmentation('homepage-rows', 'items'), new AddManualReqlSegment('homepage-rows', 'made-in-us', "'country' == \"US\" "), new AddManualReqlSegment('homepage-rows', 'short-laughs', "\"Comedy\" in 'genres' and 'runtime' < 30") ]); const responses = await client.send(batch); ``` ```php $reqs = [ new Reqs\CreateManualReqlSegmentation("homepage-rows", "items"), new Reqs\AddManualReqlSegment("homepage-rows", "made-in-us", "'country' == \"US\" "), new Reqs\AddManualReqlSegment("homepage-rows", "short-laughs", "\"Comedy\" in 'genres' and 'runtime' < 30") ]; $responses = $client->send(new Reqs\Batch($reqs)); ``` ```csharp Request[] requests = new Request[] { new CreateManualReqlSegmentation("homepage-rows", "items"), new AddManualReqlSegment("homepage-rows", "made-in-us", "'country' == \"US\" "), new AddManualReqlSegment("homepage-rows", "short-laughs", "\"Comedy\" in 'genres' and 'runtime' < 30") }; BatchResponse batchResponse = await client.SendAsync(new Batch(requests)); ``` ```go import ( "github.com/recombee/go-api-client/v6/recombee" "github.com/recombee/go-api-client/v6/recombee/requests" ) reqs := []requests.Request{ // Assuming methods similar to the Java SDK exist in the Go SDK client.NewCreateManualReqlSegmentation("homepage-rows", "items"), client.NewAddManualReqlSegment("homepage-rows", "made-in-us", "'country' == \"US\""), client.NewAddManualReqlSegment("homepage-rows", "short-laughs", "\"Comedy\" in 'genres' and 'runtime' < 30"), } // Send the batch request batchRes, err := client.NewBatch(reqs).Send() ``` post #### Update Manual ReQL Segmentation Update an existing Segmentation. ```js client.send(new requests.UpdateManualReqlSegmentation(segmentationId, { // optional parameters: title: 'Homepage Rows', // string description: 'Segmentation grouping items into rows shown on the homepage.', // string })); ``` ```python client.send(UpdateManualReqlSegmentation(segmentation_id, # optional parameters: title='Homepage Rows', # string description='Segmentation grouping items into rows shown on the homepage.', # string )) ``` ```ruby client.send(UpdateManualReqlSegmentation.new(segmentation_id, { # optional parameters: title: 'Homepage Rows', # string description: 'Segmentation grouping items into rows shown on the homepage.', # string })) ``` ```java client.send(new UpdateManualReqlSegmentation(segmentationId) .setTitle("Homepage Rows") // String .setDescription("Segmentation grouping items into rows shown on the homepage.") // String ); ``` ```php $client->send(new Reqs\UpdateManualReqlSegmentation($segmentation_id, [ // optional parameters: 'title' => 'Homepage Rows', // string 'description' => 'Segmentation grouping items into rows shown on the homepage.', // string ])); ``` ```csharp client.Send(new UpdateManualReqlSegmentation(segmentationId, // optional parameters: title: "Homepage Rows", // string description: "Segmentation grouping items into rows shown on the homepage." // string )); ``` ```go request := client.NewUpdateManualReqlSegmentation(segmentationId). // optional parameters: SetTitle("Homepage Rows"). // string SetDescription("Segmentation grouping items into rows shown on the homepage.") // string _, err := request.Send() ``` ```http POST /{databaseId}/segmentations/manual-reql/{segmentationId} Body (application/json): { "title": "Homepage Rows", "description": "Segmentation grouping items into rows shown on the homepage." } ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the updated Segmentation --- title String Located in: **body** Required: **No** Since version: **4.1.0** Human-readable name that is shown in the Recombee Admin UI. --- description String Located in: **body** Required: **No** Since version: **4.1.0** Description that is shown in the Recombee Admin UI. --- ##### Responses 201 successful operation --- 400 segmentationId does not match ^\[a-zA-Z0-9\_-:@.\]+$. Given Segmentation is of different type. --- 404 Segmentation with given ID does not exist. --- put #### Add Manual ReQL Segment Adds a new Segment into a Manual ReQL Segmentation. The new Segment is defined by a [ReQL](https://docs.recombee.com/reql) filter that returns `true` for an item in case that this item belongs to the segment. ```js client.send(new requests.AddManualReqlSegment(segmentationId, segmentId, filter, { // optional parameters: title: 'Newly published', // string })); ``` ```python client.send(AddManualReqlSegment(segmentation_id, segment_id, filter, # optional parameters: title='Newly published', # string )) ``` ```ruby client.send(AddManualReqlSegment.new(segmentation_id, segment_id, filter, { # optional parameters: title: 'Newly published', # string })) ``` ```java client.send(new AddManualReqlSegment(segmentationId, segmentId, filter) .setTitle("Newly published") // String ); ``` ```php $client->send(new Reqs\AddManualReqlSegment($segmentation_id, $segment_id, $filter, [ // optional parameters: 'title' => 'Newly published', // string ])); ``` ```csharp client.Send(new AddManualReqlSegment(segmentationId, segmentId, filter, // optional parameters: title: "Newly published" // string )); ``` ```go request := client.NewAddManualReqlSegment(segmentationId, segmentId, filter). // optional parameters: SetTitle("Newly published") // string _, err := request.Send() ``` ```http PUT /{databaseId}/segmentations/manual-reql/{segmentationId}/segments/{segmentId} Body (application/json): { "filter": "true", "title": "Newly published" } ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the Segmentation to which the new Segment should be added --- segmentId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the newly created Segment --- filter String Located in: **body** Required: **Yes** Since version: **4.1.0** ReQL filter that returns `true` for items that belong to this Segment. Otherwise returns `false`. --- title String Located in: **body** Required: **No** Since version: **4.1.0** Human-readable name of the Segment that is shown in the Recombee Admin UI. --- ##### Responses 201 successful operation --- 400 segmentationId or segmentId does not match ^\[a-zA-Z0-9\_-:@.\]+$. Segmentation is of wrong type. --- 404 Segmentation with given ID does not exist. --- post #### Update Manual ReQL Segment Update definition of the Segment. ```js client.send(new requests.UpdateManualReqlSegment(segmentationId, segmentId, filter, { // optional parameters: title: 'Newly published', // string })); ``` ```python client.send(UpdateManualReqlSegment(segmentation_id, segment_id, filter, # optional parameters: title='Newly published', # string )) ``` ```ruby client.send(UpdateManualReqlSegment.new(segmentation_id, segment_id, filter, { # optional parameters: title: 'Newly published', # string })) ``` ```java client.send(new UpdateManualReqlSegment(segmentationId, segmentId, filter) .setTitle("Newly published") // String ); ``` ```php $client->send(new Reqs\UpdateManualReqlSegment($segmentation_id, $segment_id, $filter, [ // optional parameters: 'title' => 'Newly published', // string ])); ``` ```csharp client.Send(new UpdateManualReqlSegment(segmentationId, segmentId, filter, // optional parameters: title: "Newly published" // string )); ``` ```go request := client.NewUpdateManualReqlSegment(segmentationId, segmentId, filter). // optional parameters: SetTitle("Newly published") // string _, err := request.Send() ``` ```http POST /{databaseId}/segmentations/manual-reql/{segmentationId}/segments/{segmentId} Body (application/json): { "filter": "true", "title": "Newly published" } ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the Segmentation to which the updated Segment belongs --- segmentId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the Segment that will be updated --- filter String Located in: **body** Required: **Yes** Since version: **4.1.0** ReQL filter that returns `true` for items that belong to this Segment. Otherwise returns `false`. --- title String Located in: **body** Required: **No** Since version: **4.1.0** Human-readable name of the Segment that is shown in the Recombee Admin UI. --- ##### Responses 201 successful operation --- 400 segmentationId or segmentId does not match ^\[a-zA-Z0-9\_-:@.\]+$. Segmentation is of wrong type. --- 404 Segmentation with given ID does not exist. Segment with given ID does not exist in the Segmentation. --- delete #### Delete Manual ReQL Segment Delete a Segment from a Manual ReQL Segmentation. ```js client.send(new requests.DeleteManualReqlSegment(segmentationId, segmentId)); ``` ```python client.send(DeleteManualReqlSegment(segmentation_id, segment_id)) ``` ```ruby client.send(DeleteManualReqlSegment.new(segmentation_id, segment_id)) ``` ```java client.send(new DeleteManualReqlSegment(segmentationId, segmentId)); ``` ```php $client->send(new Reqs\DeleteManualReqlSegment($segmentation_id, $segment_id)); ``` ```csharp client.Send(new DeleteManualReqlSegment(segmentationId, segmentId)); ``` ```go request := client.NewDeleteManualReqlSegment(segmentationId, segmentId) _, err := request.Send() ``` ```http DELETE /{databaseId}/segmentations/manual-reql/{segmentationId}/segments/{segmentId} ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the Segmentation from which the Segment should be deleted --- segmentId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the Segment that should be deleted --- ##### Responses 201 successful operation --- 400 segmentationId or segmentId does not match ^\[a-zA-Z0-9\_-:@.\]+$. Segmentation is of wrong type. --- 404 Segmentation with given ID does not exist. Segment with given ID does not exist in the Segmentation. --- ### Auto ReQL Segmentation Auto ReQL Segmentation is specified by a ReQL expression that for each Item returns a set of Segments to which the Item belongs. See [this section](https://docs.recombee.com/segmentations#auto-reql-segmentation) for more info. put #### Create Auto ReQL Segmentation Segment the items using a [ReQL](https://docs.recombee.com/reql) expression. For each item, the expression should return a set that contains IDs of segments to which the item belongs to. ```js client.send(new requests.CreateAutoReqlSegmentation(segmentationId, sourceType, expression, { // optional parameters: title: 'Country and Genre', // string description: 'Segmentation combining item genre and country of origin.', // string })); ``` ```python client.send(CreateAutoReqlSegmentation(segmentation_id, source_type, expression, # optional parameters: title='Country and Genre', # string description='Segmentation combining item genre and country of origin.', # string )) ``` ```ruby client.send(CreateAutoReqlSegmentation.new(segmentation_id, source_type, expression, { # optional parameters: title: 'Country and Genre', # string description: 'Segmentation combining item genre and country of origin.', # string })) ``` ```java client.send(new CreateAutoReqlSegmentation(segmentationId, sourceType, expression) .setTitle("Country and Genre") // String .setDescription("Segmentation combining item genre and country of origin.") // String ); ``` ```php $client->send(new Reqs\CreateAutoReqlSegmentation($segmentation_id, $source_type, $expression, [ // optional parameters: 'title' => 'Country and Genre', // string 'description' => 'Segmentation combining item genre and country of origin.', // string ])); ``` ```csharp client.Send(new CreateAutoReqlSegmentation(segmentationId, sourceType, expression, // optional parameters: title: "Country and Genre", // string description: "Segmentation combining item genre and country of origin." // string )); ``` ```go request := client.NewCreateAutoReqlSegmentation(segmentationId, sourceType, expression). // optional parameters: SetTitle("Country and Genre"). // string SetDescription("Segmentation combining item genre and country of origin.") // string _, err := request.Send() ``` ```http PUT /{databaseId}/segmentations/auto-reql/{segmentationId} Body (application/json): { "sourceType": "items", "expression": "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", "title": "Country and Genre", "description": "Segmentation combining item genre and country of origin." } ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the newly created Segmentation --- sourceType String Located in: **body** Required: **Yes** Since version: **4.1.0** What type of data should be segmented. Currently only `items` are supported. --- expression String Located in: **body** Required: **Yes** Since version: **4.1.0** ReQL expression that returns for each item a set with IDs of segments to which the item belongs --- title String Located in: **body** Required: **No** Since version: **4.1.0** Human-readable name that is shown in the Recombee Admin UI. --- description String Located in: **body** Required: **No** Since version: **4.1.0** Description that is shown in the Recombee Admin UI. --- ##### Responses 201 successful operation --- 400 segmentationId does not match ^\[a-zA-Z0-9\_-:@.\]+$, ReQL expression is invalid. --- ##### Examples ###### Example Create an Auto ReQL Segmentation Create a Segmentation, whose Segments combine the country of origin and the genre. See [this section](https://docs.recombee.com/segmentations#auto-reql-based-segmentation) for more info. ```python req = CreateAutoReqlSegmentation( "country-and-genre", "items", "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", ) response = client.send(req) ``` ```ruby req = CreateAutoReqlSegmentation.new( "country-and-genre", "items", "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", ) response = client.send(req) ``` ```java CreateAutoReqlSegmentation req = new CreateAutoReqlSegmentation( "country-and-genre", "items", "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", ); client.send(req); ``` ```js const req = new CreateAutoReqlSegmentation( "country-and-genre", "items", "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", ); const response = await client.send(req); ``` ```php $req = new Reqs\CreateAutoReqlSegmentation( "country-and-genre", "items", "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", ); $response = $client->send($req); ``` ```csharp var req = new CreateAutoReqlSegmentation( "country-and-genre", "items", "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", ); client.Send(req); ``` ```go req := client.NewCreateAutoReqlSegmentation( "country-and-genre", "items", "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", ) _, err = req.Send() ``` post #### Update Auto ReQL Segmentation Update an existing Segmentation. ```js client.send(new requests.UpdateAutoReqlSegmentation(segmentationId, { // optional parameters: expression: 'map(lambda \'genre\': \'genre\' + "-" + \'country\', \'genres\')', // string title: 'Country and Genre', // string description: 'Segmentation combining item genre and country of origin.', // string })); ``` ```python client.send(UpdateAutoReqlSegmentation(segmentation_id, # optional parameters: expression='map(lambda \'genre\': \'genre\' + "-" + \'country\', \'genres\')', # string title='Country and Genre', # string description='Segmentation combining item genre and country of origin.', # string )) ``` ```ruby client.send(UpdateAutoReqlSegmentation.new(segmentation_id, { # optional parameters: expression: 'map(lambda \'genre\': \'genre\' + "-" + \'country\', \'genres\')', # string title: 'Country and Genre', # string description: 'Segmentation combining item genre and country of origin.', # string })) ``` ```java client.send(new UpdateAutoReqlSegmentation(segmentationId) .setExpression("map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')") // String .setTitle("Country and Genre") // String .setDescription("Segmentation combining item genre and country of origin.") // String ); ``` ```php $client->send(new Reqs\UpdateAutoReqlSegmentation($segmentation_id, [ // optional parameters: 'expression' => 'map(lambda \'genre\': \'genre\' + "-" + \'country\', \'genres\')', // string 'title' => 'Country and Genre', // string 'description' => 'Segmentation combining item genre and country of origin.', // string ])); ``` ```csharp client.Send(new UpdateAutoReqlSegmentation(segmentationId, // optional parameters: expression: "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", // string title: "Country and Genre", // string description: "Segmentation combining item genre and country of origin." // string )); ``` ```go request := client.NewUpdateAutoReqlSegmentation(segmentationId). // optional parameters: SetExpression("map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')"). // string SetTitle("Country and Genre"). // string SetDescription("Segmentation combining item genre and country of origin.") // string _, err := request.Send() ``` ```http POST /{databaseId}/segmentations/auto-reql/{segmentationId} Body (application/json): { "expression": "map(lambda 'genre': 'genre' + \"-\" + 'country', 'genres')", "title": "Country and Genre", "description": "Segmentation combining item genre and country of origin." } ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the updated Segmentation --- expression String Located in: **body** Required: **No** Since version: **4.1.0** ReQL expression that returns for each item a set with IDs of segments to which the item belongs --- title String Located in: **body** Required: **No** Since version: **4.1.0** Human-readable name that is shown in the Recombee Admin UI. --- description String Located in: **body** Required: **No** Since version: **4.1.0** Description that is shown in the Recombee Admin UI. --- ##### Responses 201 successful operation --- 400 segmentationId does not match ^\[a-zA-Z0-9\_-:@.\]+$. ReQL expression is invalid. Given Segmentation is of different type. --- 404 Segmentation with given ID does not exist. --- ### General get #### List Segmentations Return all existing items Segmentations. ```js const result = await client.send(new requests.ListSegmentations(sourceType)); ``` ```python result = client.send(ListSegmentations(source_type)) ``` ```ruby result = client.send(ListSegmentations.new(source_type)) ``` ```java ListSegmentationsResponse result = client.send(new ListSegmentations(sourceType)); ``` ```php $result = $client->send(new Reqs\ListSegmentations($source_type)); ``` ```csharp ListSegmentationsResponse result = client.Send(new ListSegmentations(sourceType)); ``` ```go request := client.NewListSegmentations(sourceType) result, err := request.Send() // result is of the type bindings.ListSegmentationsResponse ``` ```http GET /{databaseId}/segmentations/list/?sourceType=items ``` --- Since version 4.1.0 --- Calls Limit Per Minute 60 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- sourceType String Located in: **query** Required: **Yes** Since version: **4.1.0** List Segmentations based on a particular type of data. Currently only `items` are supported. --- ##### Responses 200 ``` { "segmentations": [ { "segmentationId": "category", "sourceType": "items", "segmentationType": "property", "title": "Category Segmentation", "description": "Groups items by their category" }, { "segmentationId": "homepage-rows", "sourceType": "items", "segmentationType": "manualReQL", "title": "Homepage Rows", "description": "Defines individual content rows that can be shown on the homepage" } ] } ``` --- get #### Get Segmentation Get existing Segmentation. ```js const result = await client.send(new requests.GetSegmentation(segmentationId)); ``` ```python result = client.send(GetSegmentation(segmentation_id)) ``` ```ruby result = client.send(GetSegmentation.new(segmentation_id)) ``` ```java Segmentation result = client.send(new GetSegmentation(segmentationId)); ``` ```php $result = $client->send(new Reqs\GetSegmentation($segmentation_id)); ``` ```csharp Segmentation result = client.Send(new GetSegmentation(segmentationId)); ``` ```go request := client.NewGetSegmentation(segmentationId) result, err := request.Send() // result is of the type bindings.Segmentation ``` ```http GET /{databaseId}/segmentations/list/{segmentationId} ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the Segmentation that should be returned --- ##### Responses 200 ``` { "segmentationId": "category", "sourceType": "items", "segmentationType": "property", "title": "Category Segmentation", "description": "Groups items by their category" } ``` --- 404 Segmentation with given ID does not exist. --- delete #### Delete Segmentation Delete existing Segmentation. ```js client.send(new requests.DeleteSegmentation(segmentationId)); ``` ```python client.send(DeleteSegmentation(segmentation_id)) ``` ```ruby client.send(DeleteSegmentation.new(segmentation_id)) ``` ```java client.send(new DeleteSegmentation(segmentationId)); ``` ```php $client->send(new Reqs\DeleteSegmentation($segmentation_id)); ``` ```csharp client.Send(new DeleteSegmentation(segmentationId)); ``` ```go request := client.NewDeleteSegmentation(segmentationId) _, err := request.Send() ``` ```http DELETE /{databaseId}/segmentations/{segmentationId} ``` --- Since version 4.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of your database. --- segmentationId String Located in: **path** Required: **Yes** Since version: **4.1.0** ID of the Segmentation that should be deleted --- ##### Responses 200 successful operation --- 404 Segmentation with given ID does not exist. --- ## Miscellaneous post #### Batch Allowed on Client-Side Batch processing allows you to submit arbitrary sequence of requests within a single HTTPS request. Any type of request from the above documentation may be used in the Batch, and the Batch may combine different types of requests arbitrarily as well. Using Batch requests is beneficial for example, when synchronizing the catalog of items or uploading historical interaction data, as sending the data in Batch is considerably faster than sending the individual requests (thanks to optimizations and reducing network and HTTPS overhead). ```js const result = await client.send(new recombee.Batch(requests, { // optional parameters: distinctRecomms: true, // boolean })); ``` ```kotlin val result = client.sendAsync(Batch(requests, // optional parameters: distinctRecomms = true, // Boolean )) result.onSuccess { response: List -> // Handle response }.onFailure { exception -> // ApiException // Handle exception } ``` ```swift let result: [BatchResponse] = try await client.send(Batch(requests: requests, // optional parameters: distinctRecomms: true // Bool )) ``` ```js const result = await client.send(new requests.Batch(reqs, { // optional parameters: distinctRecomms: true, // boolean })); ``` ```python result = client.send(Batch(requests, # optional parameters: distinct_recomms=True, # boolean )) ``` ```ruby result = client.send(Batch.new(requests, { # optional parameters: distinct_recomms: true, # boolean })) ``` ```java BatchResponse[] result = client.send(new Batch(requests) .setDistinctRecomms(true) // boolean ); ``` ```php $result = $client->send(new Reqs\Batch($requests, [ // optional parameters: 'distinctRecomms' => true, // boolean ])); ``` ```csharp BatchResponse result = client.Send(new Batch(requests, // optional parameters: distinctRecomms: true // bool )); ``` ```go request := client.NewBatch(reqs). // optional parameters: SetDistinctRecomms(true) // bool result, err := request.Send() // result is of the type []bindings.BatchResponse ``` ```http POST /{databaseId}/batch/ Body (application/json): { "requests": [], "distinctRecomms": true } ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- requests Array Located in: **body** Required: **Yes** JSON array containing the requests. --- distinctRecomms Boolean Located in: **body** Required: **No** Since version: **1.2.4** Makes all the recommended items for a certain user distinct among multiple recommendation requests in the batch. --- ##### Responses 200 Successful operation. There is an array with responses. The order of the responses in the array follows the order of the sent requests. ``` [ { "code": 200, "json": "ok" }, { "code": 200, "json": "ok" }, { "code": 200, "json": { "recommId": "3f6ad2f2-a3f1-4ba1-a690-f4f01f76d4eb", "recomms": [ { "id": "item-146" }, { "id": "item-462" }, { "id": "item-463" } ], "numberNextRecommsCalls": 0 } } ] ``` --- 400 Many possibilities, see the error description in the result JSON. Examples: invalid or missing Content-type (not `application/json`), request body is not a valid JSON, request JSON does not have the prescribed structure. --- 404 There is at least one request in the batch with an invalid (non-existing) URL. In such a case, the batch as a whole **is not executed** and you'll get HTTP 404, because the batch is apriori erroneous. --- 413 Too large batch (containing more than 10,000 requests in case of a server side request). --- ##### Examples ###### Example Sending multiple requests in a single Batch request Batch can encapsulate requests of various types. ```js let reqs = [new recombee.AddDetailView(userId, itemId), new recombee.RecommendItemsToUser(userId, 5, {scenario: 'just_for_you'}), new recombee.RecommendItemsToItem(itemId, userId, 5, {scenario: 'similar_products'}) ]; const responses = await client.send(new recombee.Batch(reqs)); ``` ```kotlin val requests = listOf( AddDetailView( userId = "userId", itemId = "itemId", cascadeCreate = true ), RecommendItemsToUser( userId = "userId", count = 5, scenario = "just_for_you", cascadeCreate = true ), RecommendItemsToItem( itemId = "itemId", targetUserId = "userId", count = 5, scenario = "similar_products", cascadeCreate = true ), ) val responses = client.send(Batch(requests)) ``` ```swift let requests: [any Request] = [ AddDetailView( userId: "userId", itemId: "itemId", cascadeCreate: true ), RecommendItemsToUser( userId: "userId", count: 5, scenario: "just_for_you", cascadeCreate: true ), RecommendItemsToItem( itemId: "itemId", targetUserId: "userId", count: 5, scenario: "similar_products", cascadeCreate: true ) ] let batchRequest = Batch(requests: requests) let responses = try await client.send(batchRequest) ``` ```python reqs = [AddDetailView(user_id, item_id, cascade_create=True), RecommendItemsToUser(user_id, 5, scenario="just_for_you", cascade_create=True), RecommendItemsToItem(item_id, user_id, 5, scenario="similar_products", cascade_create=True), SetItemValues(item_id, {"price": 200, "category": "furniture"}, cascade_create=True) ] responses = client.send(Batch(reqs)) ``` ```ruby requests = [AddDetailView.new(user_id, item_id, {:cascade_create => true}), RecommendItemsToUser.new(user_id, 5, {:scenario => 'just_for_you', :cascade_create => true}), RecommendItemsToItem.new(item_id, user_id, 5, {:scenario => 'similar_products', :cascade_create => true}), SetItemValues(item_id, {"price" => 200, "category" => "furniture"}, {:cascade_create => true}) ] responses = client.send(Batch.new(requests)) ``` ```java Request[] requests = new Request[] { new AddDetailView(userId, itemId).setCascadeCreate(true), new RecommendItemsToUser(userId, 5).setScenario("just_for_you").setCascadeCreate(true), new RecommendItemsToItem(itemId, userId, 5).setScenario("similar_products").setCascadeCreate(true), new SetItemValues(itemId, new HashMap(){{put("price", 200); put("category", "furniture");}}) }; BatchResponse[] responses = client.send(new Batch(requests)); ``` ```js let reqs = [new rqs.AddDetailView(userId, itemId, {cascadeCreate: true}), new rqs.RecommendItemsToUser(userId, 5, {scenario: 'just_for_you', cascadeCreate: true}), new rqs.RecommendItemsToItem(itemId, userId, 5, {scenario: 'similar_products', cascadeCreate: true}), new rqs.SetItemValues(itemId, {price: 200, category: 'furniture'}, {cascadeCreate: true}) ]; const responses = await client.send(new rqs.Batch(reqs)); ``` ```php $reqs = [ new Reqs\AddDetailView(userId, itemId, ['cascadeCreate' => true]), new Reqs\RecommendItemsToUser(userId, 5, ['scenario' => 'just_for_you', 'cascadeCreate' => true]), new Reqs\RecommendItemsToItem(userId, itemId, 5, ['scenario' => 'similar_products', 'cascadeCreate' => true]), new Reqs\SetItemValues(itemId, ['price' => 200, 'category' => 'furniture'], ['cascadeCreate' => true]), ]; $replies = $client->send(new Reqs\Batch($reqs)); ``` ```csharp Request[] requests = new Request[] { new AddDetailView(userId, itemId, cascadeCreate: true), new RecommendItemsToUser(userId, 5, scenario: "just_for_you", cascadeCreate: true), new RecommendItemsToItem(itemId, userId, 5, scenario: "similar_products", cascadeCreate: true), new SetItemValues(itemId, new Dictionary(){{"price", 200}, {"category", "furniture"}}) }; BatchResponse batchResponse = await client.SendAsync(new Batch(requests)); ``` ```go import ( "github.com/recombee/go-api-client/v6/recombee" "github.com/recombee/go-api-client/v6/recombee/requests" ) requestsBatch := []requests.Request{ client.NewAddDetailView(userId, itemId).SetCascadeCreate(true), client.NewRecommendItemsToUser(userId, 5).SetScenario("just_for_you").SetCascadeCreate(true), client.NewRecommendItemsToItem(itemId, userId, 5).SetScenario("similar_products").SetCascadeCreate(true), client.NewSetItemValues(itemId, map[string]interface{}{ "price": 200, "category": "furniture", }).SetCascadeCreate(true), } // Send batch request batchRes, err := client.NewBatch(requestsBatch).Send() ``` ```http # If you use the REST API directly, than the body of a batch request consists of a JSON object. # The individual requests are given as a JSON array associated with key *requests*. # # In the array, each request is encoded as a JSON object containing the following fields: # # * method – required string with HTTP method of the request (one of PUT, POST, GET, DELETE, case insensitive), # * path – required string with path of the request from the root of the database, excluding the query string, # * params – optional (or required if also required by the request type) object containing values # of the request's parameters (GET or POST, depending on the request type) # # The `params` property may be omitted if there are no attributes to be passed for the request; # if some attributes are optional, you may or may not include them as in regular request, # # Example of executing three requests (setting the item values, adding a detail view, # and getting user based recommendation) in a batch: { "requests": [ { "method": "POST", "path": "/items/item-24", "params": { "product_description": "4K TV with 3D feature", "categories": ["Electronics", "Televisions"], "price_usd": 342, "!cascadeCreate": true } }, { "method": "POST", "path": "/detailviews/", "params": { "userId": "user-123", "itemId": "item-x", "timestamp": 1404727253, "cascadeCreate": true } }, { "method": "GET", "path": "/recomms/users/user-123/items/", "params": { "count": 3 } } ] } ``` --- ###### Example Checking the result of the individual requests You should check that the requests in the Batch succeeded. A request can fail for example due to invalid parameters - the returned error mesage gives you a hint what went wrong. ```js try { const responses = await client.send(new recombee.Batch(reqs)); for (const response of responses) { if (response.code < 200 || response.code > 299) { // A request in the Batch did not succeed console.log(response); } } } catch (error) { // The whole Batch request failed } ``` ```kotlin val result = client.sendAsync(Batch(requests)) result.onSuccess {batchResponses: List -> // Check individual requests batchResponses.forEach { response -> if (!response.successful) { // A request in the Batch did not succeed // response.getResponse() will throw corresponding ApiException } } }.onFailure { exception -> // ApiException // The whole Batch failed } ``` ```swift do { let responses: [BatchResponse] = try await client.send(batchRequest) // Iterate through each individual batch response for responseWrapper in responses { if !responseWrapper.isSuccessful { // A request in the Batch did not succeed // Accessing the response property (responseWrapper.response) will throw the corresponding ClientError } } } catch { // Handle error for the whole batch request print("The entire batch request failed: \(error)") } ``` ```python responses = client.send(Batch(requests)) for response in responses: if not (200 <= response["code"] < 300): # A request in the Batch did not succeed print(response) ``` ```ruby responses = client.send(Batch.new(requests)) responses.each do |response| if response['code'] < 200 || response['code'] > 299 # A request in the Batch did not succeed puts response end end ``` ```java // Send the Batch to the Recombee API BatchResponse[] responses = client.send(batch); // Check if the Batch was successful for (BatchResponse response : responses) { if (!response.isSuccessful()) { // A request in the Batch did not succeed // response.getResponse() will throw corresponding ApiException } } ``` ```js try { const responses = await client.send(new rqs.Batch(reqs)); for (const response of responses) { if (response.code < 200 || response.code > 299) { // A request in the Batch did not succeed console.log(response); } } } catch (error) { // The whole Batch request failed } ``` ```php // Send the Batch to the Recombee API $responses = $client->send($batch); // Check if the Batch was successful foreach ($responses as $response) { if (200 < $response["code"] || $response["code"] >= 300) { // A request in the Batch did not succeed print($response); } } ``` ```csharp var responses = client.Send(batch); for (int i = 0; i < responses.StatusCodes.Length; i++) { if (((int)responses.StatusCodes[i]) < 200 || ((int)responses.StatusCodes[i]) >= 300) { // A request in the Batch did not succeed // Accessing responses[i] will throw corresponding ApiException } } ``` ```go batchRes, err := client.NewBatch(requestsBatch).Send() if err != nil { fmt.Println(err) panic(err) } for i, resp := range batchRes { if resp.StatusCode < 200 || resp.StatusCode >= 300 { fmt.Printf("Request #%d failed with status code %d: %s\n", i, resp.StatusCode, resp.Error.ErrorMessage) } } ``` --- ###### Example Using distinctRecomms parameter to deduplicate results in multiple boxes If you show multiple boxes with recommendations on a single page, you may want to ensure that the same item is not recommended in multiple boxes. You can achieve that by specifying `distinctRecomms=true`. ```js const batchRequest = new rqs.Batch([ new RecommendItemsToUser('user-id', 5, {scenario:'new_releases', cascadeCreate: true}), new RecommendItemsToUser('user-id', 5, {scenario:'just_for_you', cascadeCreate: true}) ], { distinctRecomms: true }); const responses = await client.send(batchRequest); ``` ```kotlin val requests = listOf( RecommendItemsToUser(userId = "userId", count = 5, scenario = "new_releases", cascadeCreate = true), RecommendItemsToUser(userId = "userId", count = 5, scenario = "just_for_you", cascadeCreate = true) ) val result = client.sendAsync(Batch(requests=requests, distinctRecomms = true)) ``` ```swift let requests: [any Request] = [ RecommendItemsToUser( userId: "userId", count: 5, scenario: "new_releases", cascadeCreate: true ), RecommendItemsToUser( userId: "userId", count: 5, scenario: "just_for_you", cascadeCreate: true ) ] let batchRequest = Batch(requests: requests, distinctRecomms: true) let result = try await client.send(batchRequest) ``` ```python requests = [RecommendItemsToUser(user_id, 5, scenario="new_releases", cascade_create=True), RecommendItemsToUser(user_id, 5, scenario="just_for_you", cascade_create=True),] responses = client.send(Batch(requests, distinct_recomms=True)) ``` ```ruby batch = Batch.new([ RecommendItemsToUser.new(user_id, 5, scenario: "new_releases", cascade_create: true), RecommendItemsToUser.new(user_id, 5, scenario: "just_for_you", cascade_create: true), ], distinct_recomms: true) responses = client.send(batch) ``` ```java Request[] requests = new Request[] { new RecommendItemsToUser(userId, 5).setScenario("new_releases").setCascadeCreate(true), new RecommendItemsToUser(userId, 5).setScenario("just_for_you").setCascadeCreate(true) }; Batch batch = new Batch(requests).setDistinctRecomms(true); BatchResponse[] responses = client.send(batch); ``` ```js const batchRequest = new rqs.Batch([ new RecommendItemsToUser('user-id', 5, {scenario:'new_releases', cascadeCreate: true}), new RecommendItemsToUser('user-id', 5, {scenario:'just_for_you', cascadeCreate: true}) ], { distinctRecomms: true }); const responses = await client.send(batchRequest); ``` ```php $batchRequest = new Reqs\Batch([ new Reqs\RecommendItemsToUser('user-id', 5, ['scenario' => 'new_releases', 'cascadeCreate' => true]), new Reqs\RecommendItemsToUser('user-id', 5, ['scenario' => 'just_for_you', 'cascadeCreate' => true]) ], [ 'distinctRecomms' => true ]); $replies = $client->send($batchRequest); ``` ```csharp Request[] requests = new Request[] { new RecommendItemsToUser(userId, 5, scenario: "new_releases", cascadeCreate: true), new RecommendItemsToUser(userId, 5, scenario: "just_for_you", cascadeCreate: true) }; BatchResponse batchResponse = await client.SendAsync(new Batch(requests, distinctRecomms: true)); ``` ```go batchRes, err := client.NewBatch([]requests.Request{ client.NewRecommendItemsToUser(userId, 5).SetScenario("new_releases").SetCascadeCreate(true), client.NewRecommendItemsToUser(userId, 5).SetScenario("just_for_you").SetCascadeCreate(true), }).SetDistinctRecomms(true).Send() ``` ```http { "requests": [ { "method": "GET", "path": "/recomms/users/user-123/items/", "params": { "count": 3, "scenario": "recent_releases" } }, { "method": "GET", "path": "/recomms/users/user-123/items/", "params": { "count": 3, "scenario": "just_for_you" } } ], "distinctRecomms": true } ``` ##### Notes Executing the requests in a Batch is equivalent as if they were executed one-by-one individually; there are, however, many optimizations to make batch execution as fast as possible. The status code of the Batch request itself is 200 even if the individual requests result in error – you have to inspect the code values in the resulting array. If the status code of the whole batch is not 200, then there is an error in the Batch request itself; in such a case, the error message returned should help you to resolve the problem. The batch size is limited to 10,000 requests when sent from the server side; if you wish to execute even larger number of requests, please split the Batch into multiple parts. Client libraries do the splitting automatically. In case of the client side integration, the limit is 30 requests and only the requests that can be called from the client side are allowed. get #### List Scenarios Get all [Scenarios](https://docs.recombee.com/scenarios) of the given database. ```js const result = await client.send(new requests.ListScenarios()); ``` ```python result = client.send(ListScenarios()) ``` ```ruby result = client.send(ListScenarios.new()) ``` ```java Scenario[] result = client.send(new ListScenarios()); ``` ```php $result = $client->send(new Reqs\ListScenarios()); ``` ```csharp IEnumerable result = client.Send(new ListScenarios()); ``` ```go request := client.NewListScenarios() result, err := request.Send() // result is of the type []bindings.Scenario ``` ```http GET /{databaseId}/scenarios/ ``` --- Since version 5.1.0 --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- ##### Responses 200 Successful operation. ``` [ { "id": "relatedArticles", "endpoint": "recommendItemsToItem" }, { "id": "justForYou", "endpoint": "recommendItemsToUser" }, { "id": "homepageSectionsOrdering", "endpoint": "recommendItemSegmentsToUser" }, { "id": "homepageSectionContent", "endpoint": "recommendItemsToItemSegment" } ] ``` --- delete #### Reset Database Completely erases all your data, including items, item properties, series, user database, purchases, ratings, detail views, and bookmarks. Make sure the request is never executed in the production environment! Resetting your database is irreversible. ```js client.send(new requests.ResetDatabase()); ``` ```python client.send(ResetDatabase()) ``` ```ruby client.send(ResetDatabase.new()) ``` ```java client.send(new ResetDatabase()); ``` ```php $client->send(new Reqs\ResetDatabase()); ``` ```csharp client.Send(new ResetDatabase()); ``` ```go request := client.NewResetDatabase() _, err := request.Send() ``` ```http DELETE /{databaseId}/ ``` --- ##### Parameters databaseId String Located in: **path** Required: **Yes** ID of your database. --- ##### Responses 200 Successful operation. --- **Table of contents** * [Items](#items) * [Add Item](#add-item) * [Delete Item](#delete-item) * [List Items](#list-items) * [Delete More Items](#delete-more-items) * [Item Properties](#item-properties) * [Item properties definition](#item-properties-definition) * [Add Item Property](#add-item-property) * [Delete Item Property](#delete-item-property) * [Get Item Property Info](#get-item-property-info) * [List Item Properties](#list-item-properties) * [Values of item properties](#values-of-item-properties) * [Set Item Values](#set-item-values) * [Get Item Values](#get-item-values) * [Update More Items](#update-more-items) * [Users](#users) * [Add User](#add-user) * [Delete User](#delete-user) * [Merge Users](#merge-users) * [List Users](#list-users) * [User Properties](#user-properties) * [User properties definition](#user-properties-definition) * [Add User Property](#add-user-property) * [Delete User Property](#delete-user-property) * [Get User Property Info](#get-user-property-info) * [List User Properties](#list-user-properties) * [Values of user properties](#values-of-user-properties) * [Set User Values](#set-user-values) * [Get User Values](#get-user-values) * [User-Item Interactions](#user-item-interactions) * [Detail Views](#detail-views) * [Add Detail View](#add-detail-view) * [Delete Detail View](#delete-detail-view) * [List Item Detail Views](#list-item-detail-views) * [List User Detail Views](#list-user-detail-views) * [Purchases](#purchases) * [Add Purchase](#add-purchase) * [Delete Purchase](#delete-purchase) * [List Item Purchases](#list-item-purchases) * [List User Purchases](#list-user-purchases) * [Ratings](#ratings) * [Add Rating](#add-rating) * [Delete Rating](#delete-rating) * [List Item Ratings](#list-item-ratings) * [List User Ratings](#list-user-ratings) * [Cart Additions](#cart-additions) * [Add Cart Addition](#add-cart-addition) * [Delete Cart Addition](#delete-cart-addition) * [List Item Cart Additions](#list-item-cart-additions) * [List User Cart Additions](#list-user-cart-additions) * [Bookmarks](#bookmarks) * [Add Bookmark](#add-bookmark) * [Delete Bookmark](#delete-bookmark) * [List Item Bookmarks](#list-item-bookmarks) * [List User Bookmarks](#list-user-bookmarks) * [View Portions](#view-portions) * [Set View Portion](#set-view-portion) * [Delete View Portion](#delete-view-portion) * [List Item View Portions](#list-item-view-portions) * [List User View Portions](#list-user-view-portions) * [Recommendations](#recommendations) * [Recommending Items](#recommending-items) * [Recommend Items to User](#recommend-items-to-user) * [Recommend Items to Item](#recommend-items-to-item) * [Recommend Items to Item Segment](#recommend-items-to-item-segment) * [Recommend Next Items](#recommend-next-items) * [Recommending Item Segments](#recommending-item-segments) * [Recommend Item Segments to User](#recommend-item-segments-to-user) * [Recommend Item Segments to Item](#recommend-item-segments-to-item) * [Recommend Item Segments to Item Segment](#recommend-item-segments-to-item-segment) * [Recommend Next Item Segments](#recommend-next-item-segments) * [Recommending Users](#recommending-users) * [Recommend Users to User](#recommend-users-to-user) * [Recommend Users to Item](#recommend-users-to-item) * [Composite Recommendations](#composite-recommendations) * [Composite Recommendation](#composite-recommendation) * [Search](#search) * [Search Items](#search-items) * [Search Item Segments](#search-item-segments) * [Synonyms](#synonyms) * [Add Search Synonym](#add-search-synonym) * [List Search Synonyms](#list-search-synonyms) * [Delete All Search Synonyms](#delete-all-search-synonyms) * [Delete Search Synonym](#delete-search-synonym) * [Series](#series) * [Series definition](#series-definition) * [Add Series](#add-series) * [Delete Series](#delete-series) * [List Series](#list-series) * [Series items](#series-items) * [List Series Items](#list-series-items) * [Insert to Series](#insert-to-series) * [Remove from Series](#remove-from-series) * [Segmentations Definition](#segmentations-definition) * [Property Based Segmentation](#property-based-segmentation) * [Create Property Based Segmentation](#create-property-based-segmentation) * [Update Property Based Segmentation](#update-property-based-segmentation) * [Manual ReQL Segmentation](#manual-reql-segmentation) * [Create Manual ReQL Segmentation](#create-manual-reql-segmentation) * [Update Manual ReQL Segmentation](#update-manual-reql-segmentation) * [Add Manual ReQL Segment](#add-manual-reql-segment) * [Update Manual ReQL Segment](#update-manual-reql-segment) * [Delete Manual ReQL Segment](#delete-manual-reql-segment) * [Auto ReQL Segmentation](#auto-reql-segmentation) * [Create Auto ReQL Segmentation](#create-auto-reql-segmentation) * [Update Auto ReQL Segmentation](#update-auto-reql-segmentation) * [General](#general) * [List Segmentations](#list-segmentations) * [Get Segmentation](#get-segmentation) * [Delete Segmentation](#delete-segmentation) * [Miscellaneous](#miscellaneous) * [Batch](#batch) * [List Scenarios](#list-scenarios) * [Reset Database](#reset-database) --- # Admin UI > Source: https://docs.recombee.com/admin_ui > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Sections](#sections) * [My Dashboard](#my-dashboard) * [Database](#admin-ui-database-sections) * [KPI](#kpi) * [Items and Users](#items-and-users) * [Series](#series) * [Scenarios](#scenarios) * [Business Rules](#business-rules) * [Segmentations](#segmentations) * [No-Code Widgets](#no-code-widgets) * [Catalog Feed](#catalog-feed) * [Settings](#settings) * [Organization](#organization) * [Invites & Access Levels](#invites-access-levels) * [Access to Database](#access-to-database) * [View](#view) * [Edit](#edit) * [Access to Organization](#access-to-organization) * [View](#view) * [Edit](#edit) * [Finance](#finance) * [Success Metrics in KPI](#success-metrics-kpi) * [Estimated Metrics](#estimated-metrics) * [Reported Metrics](#reported-metrics) # Admin UI Recombee Admin UI is available at [admin.recombee.com](https://admin.recombee.com) * On registration an **Organization** is created for your company. * An Organization can contain multiple **Databases**, each with separate data and recommendation models. * Two Databases are created on registration - one for development purposes and one for production usage. [![KPI console in the ,[object Object]](/img/gui/kpi.webp)](/img/gui/kpi.webp) KPI console in the [Admin UI](https://admin.recombee.com) ## Sections ### My Dashboard * Place for pinning the widgets that are the most important for you, so you see them right after logging in. * Use the star symbol for pinning. [![Pin widget to My Dashboard](/img/gui/pin_to_dashboard.webp)](/img/gui/pin_to_dashboard.webp) ### Database #### KPI Console that contains widgets showing important data such as number of recommendations, number of ingested interactions or success rate of the recommendations per [scenario](/scenarios). Read more about the [success metrics](#success-metrics-kpi). #### Items and Users Catalog of the items and users that are contained in the Recombee database with their properties. [![Items Catalog](/img/gui/items_catalog.png)](/img/gui/items_catalog.png) Items Catalog #### Series Catalog of uploaded [Series](/api#series). Series are used in use-cases such VoD to express the order of episodes. #### Scenarios Section for setting behavior of recommendations in each [scenario](/scenarios). Read more about the scenarios [here](/scenarios). [![Setting Logic to a Scenario](/img/gui/set_logic.png)](/img/gui/set_logic.png) Setting Logic to a Scenario #### Business Rules Section for creating your custom [business rules](/reql#business-rules) that can be then applied to your [scenarios](/scenarios). Read more about the business rules [here](/reql#business-rules). #### Segmentations [Segmentations](/segmentations) are used for recommending categories, genres, brands, artists, etc. #### No-Code Widgets Section for creating [No-Code Widgets](/scenarios#scenarios-html-widget) that are used for displaying recommendations at your site. #### Catalog Feed Section for setting a [catalog feed](/catalog_feeds), which can be used for synchronizing the items to Recombee. #### Settings Section for getting Database ID & tokens for connecting to the Recombee API and managing access to the Database (_Manage Access_ button). ### Organization Section for admins of the Organization for managing access (_Manage Access_ button), getting information about limits/usage on Organization level and about selected [Billing Plan](https://www.recombee.com/pricing). ## Invites & Access Levels Colleagues can be invited to the whole Organization or just particular Database (use the _Manage Access_ button in _Settings_). Optionally, it is also possible to integrate Recombee Admin UI with your SSO provider - see [Third Party Login / SSO](/third_party_login_sso) for details. [![Manage access](/img/gui/manage_access.webp)](/img/gui/manage_access.webp) ### Access to Database #### View * Can view the Database (see KPI, Items & Users, Scenarios ...) but cannot change any settings * Cannot see the API tokens for manipulating the Database #### Edit * Can make changes to the Database * Can see the API tokens for manipulating the Database ### Access to Organization #### View * Can view all the Databases in the Organizations but cannot change any settings * Cannot see the API tokens of these Databases #### Edit * Can make changes to all the Databases in the Organizations * Can see the API tokens for manipulating these Databases #### Finance * Can see and change the billing info of the Organization. ## Success Metrics in KPI You can see in the KPI how many clicks / purchases / bookmarks etc. were based on the recommendations. For each of the metrics there are **estimated** and **reported** values. [![Reported vs. Estimated metric](/img/gui/estimated_reported.webp)](/img/gui/estimated_reported.webp) Reported vs. Estimated metric ### Estimated Metrics * Estimates are based on a _time window_: If an item is recommended to a user, and this user subsequently interacts with that item within a time window, it is considered a successful recommendation * These metrics don't need any implementation and usually give reasonable estimates of the success. However, they don't work for example in case of emailing (users look at the recommendations usually hours later, so their clicks are not counted as they are out of the the time window) or at sites where items can be easily found by different means than recommendations. In these cases explicit reporting of recommendations' success is a must. ### Reported Metrics ![](/img/gui/reported-metrics.png) * Successful recommendations explicitly reported to Recombee. * Each recommendation request returns a unique `recommId` (e.g. _3f6ad2f2-a3f1-4ba1-a690-f4f01f76d4eb_) that can be passed to `recommId` parameter of an interaction (Detail View, Purchase, etc.) in order to mark that interaction as based on recommendation. * When properly integrated, the reported metrics should give you exact numbers about successful recommendations. * Therefore we suggest to implement sending of `recommId` in interactions whenever possible. --- # Insights > Source: https://docs.recombee.com/insights > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Video Tutorial](#video-tutorial) * [Library of Predefined Insights](#library-of-predefined-insights) * [Predefined Insight Types](#predefined-insight-types) * [Performance Metrics](#performance-metrics) * [Top Items](#top-items) * [Category-Based Metrics](#category-based-metrics) * [Item-Segment Based Metrics](#item-segment-based-metrics) * [Creating Custom Insights](#creating-custom-insights) * [Insight Types](#insight-types) * [Insights Settings](#insights-settings) * [Data Sources](#data-sources) * [Available Data Sources](#available-data-sources) * [Recommendations Data Sources](#recommendations-data-sources) * [Interactions Data Sources](#interactions-data-sources) * [Interactions Based on Recommendations Data Sources](#interactions-based-on-recommendations-data-sources) * [Ratio Data Sources](#ratio-data-sources) * [Filters](#filters) * [Example - The CTR of a Scenario](#example-the-ctr-of-a-scenario) * [Example - The Most Recommended Items from a Category](#example-the-most-recommended-items-from-a-category) * [Data Source Specific Filters](#data-source-specific-filters) * [Example - Total Number of Detail Views and Number of Detail Views for Items from a Category](#example-total-number-of-detail-views-and-number-of-detail-views-for-items-from-a-category) * [Example - The Ratio of the Number of Viewed Items from a Category on All the Views of Items](#example-the-ratio-of-the-number-of-viewed-items-from-a-category-on-all-the-views-of-items) * [Splits](#splits) * [Example - Count of Recommendation Requests Split by Used Scenario](#example-count-of-recommendation-requests-split-by-used-scenario) * [Example - Count of Recommended Items Split by Their Genres Item Property](#example-count-of-recommended-items-split-by-their-genres-item-property) * [Example - Sum of Price of Purchases Based on Recommendations Split by Scenario and User ID](#example-sum-of-price-of-purchases-based-on-recommendations-split-by-scenario-and-user-id) * [Sorting & Number of Results](#sorting-number-of-results) * [Sort Direction](#sort-direction) * [Number of Results](#number-of-results) * [Splits on Multiple Data Sources](#splits-on-multiple-data-sources) * [Splitting by Item Property of the Type Set](#splitting-by-item-property-of-the-type-set) * [Example](#example) # Insights Insights allow you to take a deep dive into your data. ![](/img/insights/main.png) You can explore what items are the most recommended, which categories of items are being interacted with thanks to recommendations, or what portion of views is based on previous successful recommendations. ## Video Tutorial ## Library of Predefined Insights We have created a library of Insights covering frequently used analytical data views. [![Recombee Insights Library](/img/insights/recombee-library.png)](/img/insights/recombee-library.png) ### Predefined Insight Types For easier orientation we group the predefined Insights in the library into the following groups. #### Performance Metrics * Metrics such as Click Through Rate, Cart Conversion Rate, or Conversion Rate #### Top Items * Insights showing the top items according to various metrics * For example the most recommended items, the most interacted items, or the items that are the most clicked in the recommendation boxes #### Category-Based Metrics * These Insights group the recommended or interacted items by their category item property * You can therefore see which categories are the most interesting for users, either thanks to recommendations or in general #### Item-Segment Based Metrics * Similarly to grouping by the category item property, you can also group the recommended or interacted items by any [Items Segmentation](/segmentations) that you use in your Database [![Top Items Insight with the most recommended items per scenario](/img/insights/top-items.png)](/img/insights/top-items.png) Top Items Insight with the most recommended items per scenario ## Creating Custom Insights One of the best ways to start with custom Insights is to duplicate an existing Insight from the library and change particular settings. However, you can also start entirely from scratch by clicking the **Create Insight** button. ### Insight Types You can choose from the following types of visualization. ![Bar Chart](/img/insights/type-bar-chart.png) Bar Chart ![Line Chart](/img/insights/type-line-chart.png) Line Chart ![Area Chart](/img/insights/type-area-chart.png) Area Chart ![Table](/img/insights/type-table.png) Table ![Top Items](/img/insights/type-top-items.png) Top Items Shows a list of e.g., most recommended, interacted, or profitable items ### Insights Settings **There are three main settings:** **[Data Sources](#data-sources)** \- What kind of data and what metric will be used (e.g., _Count of Recommended Items_ or _Sum of Price of Purchases Based on Recommendations_). **[Filters](#filters)** include only particular data in the result (e.g., show data only for a particular Item, for a particular Scenario, or for a category). **[Splits](#splits)** break down the data by fields (e.g., by Scenario or per a property such as category). ### Data Sources The Data Source **describes the queried data and applied metric**. Some examples can be the _Count of Recommended Items_ or the _Average price of Purchases_. It also defines what [Filters](#filters) and [Splits](#splits) can be applied - for example, recommendation requests can be filtered per a Scenario, while the [Rating interactions](/api#add-rating) can be filtered to positive or negative ratings based on the submitted value. You can add **multiple Data Sources** to your Insight. If you add multiple Data Sources,then only the [Splits](#splits) that are applicable to all the Data Sources can be added. #### Available Data Sources The available Data Sources can be categorized by their topic into the following 3 groups: * Recommendations * Interactions * Interactions Based on Recommendations [![Picking a Data Source](/img/insights/picking-a-data-source.png)](/img/insights/picking-a-data-source.png) Picking a Data Source ##### Recommendations Data Sources Data Sources from this category present data about: * **Recommendation Requests** * Recommendation requests sent to the Recombee API * Based on the selected _Metric_, you can see for example the count of the requests or the number of distinct users that requested the recommendations * **Recommended Items / Recommended Users / Recommended Item Segments** * The individual Items / Users / [Items Segments](/segmentations) that were recommended * Based on the selected _Metric_, you get for example the total count of recommended Items or the number of distinct recommended Items ![The difference between Recommendation Requests and Recommended Items](/img/insights/ask-for-recommendations.png) The difference between Recommendation Requests and Recommended Items ##### Interactions Data Sources Data Sources in this category present data about ingested interactions. * **Individual interaction types: Detail Views / Ratings / Purchases …** * Interactions of a particular type * All the Data Sources offer _Metrics_ like count, count of distinct users, or count of distinct items * Particular interaction types offer specific _Metrics_ \- for example, _Purchases_ offer Price (with operators such as sum or maximum), while _Ratings_ offer the value of the rating (so you can see e.g., average rating) * **All interactions** * Interactions of all types together View Portions vs. View Portion Events The **View Portion** Data Source aggregates the ingested View Portions by sent (User, Item, Session). Therefore, if the user watches a video and you send 5 milestones to Recombee, it will still be counted as a single View Portion. This way, the View Portions are shown in the KPI console and counted in the _All Interactions_ Data Source and also in pricing. The **View Portion Events** Data Source contains each Set View Portion request sent to the API. Therefore, if the user watches a video and you send 5 milestones to Recombee, there will be 5 View Portion Events. ![View Portion / View Portion Events comparison](/img/insights/insights-view-portions.png) View Portion / View Portion Events comparison ##### Interactions Based on Recommendations Data Sources Data Sources in this category present data about interactions that happened **thanks to previous successful recommendations**. Their types follow the same pattern as [Interactions](#interactions-data-sources). You can see either [Reported (based on sent recommId) or Estimated (based on time window) Interactions Based on Recommendations](/admin_ui#success-metrics-in-kpi). #### Ratio Data Sources When adding a Data Source, you can switch from a _Simple Data Source_, which shows a single metric, to a _Ratio Data Source_, which is a ratio of two Data Sources. The Ratio Data Source can be used for showing various percentual metrics, such as: **Click-Through-Rate** * Numerator - _Count of Detail Views Based on Recommendations_ * Denominator - _Count of Recommendation requests_ ![](/img/insights/ctr-ratio.png) **Ratio of profit from recommendations on the total profit** * Numerator: _Profit of Purchases Based on Recommendations_ * Denominator: _Profit of all Purchases_ **Ratio of recommended items from a category on all recommended items** * Numerator: _Count of Recommended Items_ with a [Filter](#filters) set to a particular category * Denominator: _Count of Recommended Items_ [![Example of setting up a Ratio Data Source](/img/insights/data-source-settings.png)](/img/insights/data-source-settings.png) Example of setting up a Ratio Data Source ### Filters The Filters allow you to include only part of the data in the Insight, or exclude it. You can see the data for example, only for a particular Scenario, for a particular User, or for a particular [Segment](/segmentations) of your data (e.g., one category). You can either add a Filter in the Filters section or click on a value in the graph or table and choose to include it or exclude it. [![Adding a Filter directly in the table](/img/insights/filter-in-table.png)](/img/insights/filter-in-table.png) Adding a Filter directly in the table ##### Example - The CTR of a Scenario Add a Filter on a particular Scenario. [![The CTR of a Scenario](/img/insights/ctr-of-a-scenario.png)](/img/insights/ctr-of-a-scenario.png) ##### Example - The Most Recommended Items from a Category Add a Filter on an Item Property, choose the _category_ property, and fill in the name of a particular category. [![The Most Recommended Items from a Category](/img/insights/most-recommended-items-from-category.png)](/img/insights/most-recommended-items-from-category.png) #### Data Source Specific Filters By default, the Filters are applied to all the Data Sources. However, you can also add a Filter only to a particular Data Source. In the case of the [Ratio Data Sources](#ratio-data-sources), you can also choose whether to apply the Filter to both numerator and denominator or only one of them. ##### Example - Total Number of Detail Views and Number of Detail Views for Items from a Category You can add the _Count of Detail Views_ Data Source twice (with an _Alias_ to distinguish them), and for one of them, set the Filter. _Data Sources_ ![](/img/insights/data-source-specific-filters-example-1-1.png) ![](/img/insights/data-source-specific-filters-example-1-2.png) _Filter_ ![](/img/insights/data-source-specific-filters-example-1-3.png) Which yields the following result ![](/img/insights/data-source-specific-filters-example-1-4.png) ##### Example - The Ratio of the Number of Viewed Items from a Category on All the Views of Items This Insight is set as a [Ratio Data Source](#ratio-data-sources), where both the numerator and denominator are set to the Count of Detail Views, and the Filter on a category is applied to the numerator. _Data Source_ ![](/img/insights/data-source-specific-filters-example-2-1.png) _Filter_ ![](/img/insights/data-source-specific-filters-example-2-2.png) The result is the portion of the views of Items from the particular property on all the views ![](/img/insights/data-source-specific-filters-example-2-3.png) ### Splits A Split breaks down the data by a field. The field must be available in all the added Data Sources. #### Example - Count of Recommendation Requests Split by Used Scenario Adding Split on Scenario shows the number of requests per Scenario. ![](/img/insights/splits-example-1-1.png) **↓** ![](/img/insights/splits-example-1-2.png) #### Example - Count of Recommended Items Split by Their Genres Item Property Adding the Split on Item Property called `genres` shows the number of recommended items (in this case movies) per their genre. ![](/img/insights/splits-example-2-1.png) **↓** ![](/img/insights/splits-example-2-2.png) #### Example - Sum of Price of Purchases Based on Recommendations Split by Scenario and User ID This Insight **requires two Splits:** * The first one **on Scenario** ![](/img/insights/splits-example-3-1.png) * The second one **on the User ID** ![](/img/insights/splits-example-3-2.png) It works in the way that first the Scenarios with the highest _Sum of Price of Purchases Based on Recommendations_ are selected. For each of these top Scenarios, results for users with the highest _Sum of Price of Purchases Based on Recommendations_ within the Scenario are presented. ![](/img/insights/splits-example-3-3.png) You can see that the order of the Splits matters: If you added the Split on _User_ first and then the Split on _Scenario_, the top Users according to _Sum of Price of Purchases Based on Recommendations_ would be selected (no matter the Scenarios), and for these users the sum of price would be split by the Scenario of the successful recommendation. ![](/img/insights/splits-example-3-4.png) You can drag & drop the Splits in the list to change their order. #### Sorting & Number of Results ##### Sort Direction By default, the resulting split groups are ordered by the _Metric_: For example, in the case of _Count of Recommendation Requests_ Data Source and split by Scenario, you will get the Scenarios with the highest number of recommendation requests during the time period (in descending order by the count). ![](/img/insights/splits-sort-1.png) If you would instead want to order by the values from the Split themselves, in this case, the Scenarios, you can change the _Sort Direction_ to _Ascending_ or _Descending_, and you will get Scenarios ordered alphabetically in ascending or descending order. ![](/img/insights/splits-sort-2.png) **↓** ![](/img/insights/splits-sort-3.png) ##### Number of Results You can limit the number of groups produced by the Split by setting the _Max Groups_ parameter (default: 10). It will show at most this number of top groups according to the _Sort direction_. If there are more groups in the data than _Max Groups_, you can see the aggregate of all the other groups by enabling the _Other Group_ option. ![](/img/insights/splits-number-of-results.png) ##### Splits on Multiple Data Sources If you have multiple [Data Sources](#data-sources), then their order matters: The Split groups are picked according to the first Data Source in the list. For example, if you have two Data Sources: _Recommendation Requests_ and _Detail Views Based on Recommendations_ with a Scenario Split, then the Scenarios with the highest count of _Recommendation Requests_ are selected, and for these Scenarios the count of _Detail Views Based on Recommendations_ is displayed. ![](/img/insights/splits-multi-data-sources-1.png) If the Data Sources were in a different order: _Detail Views Based on Recommendations_ first and _Recommendation Requests_ second, then the picked Scenarios depend on the number of _Detail Views Based on Recommendations_. ![](/img/insights/splits-multi-data-sources-2.png) You can drag & drop the Data Sources in the list to change their order. #### Splitting by Item Property of the Type Set If you split by an [Item Property](/api#add-item-property) of type set (which contains multiple values), or by a [Segmentation](/segmentations) that gives multiple Segments for an Item, the Item is counted towards each yielded item property value / Segment. ##### Example Assume _Count of Recommended Items_ Data Source: ![](/img/insights/splitting-by-item-property-example-1.png) If there are Items with their _genres_ property set to `{"action", "science_fiction"}`, then after adding the Split on the genres property, those Items are counted towards both _genres_: ![](/img/insights/splitting-by-item-property-example-2.png) --- # Scenarios > Source: https://docs.recombee.com/scenarios > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Setting Up a Scenario](#setting-up-a-scenario) * [Requesting a Scenario](#requesting-a-scenario) * [Scenario Settings in the Admin UI](#scenarios-in-admin-ui) * [Logic](#logic) * [Filters](#filters) * [Global Settings](#scenarios-in-admin-ui-global-settings) * [Boosters](#boosters) * [Constraints](#constraints) * [Limit Type](#limit-type) * [Window Size](#window-size) * [Composite Recommendations](#composite-recommendations) * [Examples](#examples) * [Because You Watched ](#because-you-watched-movie-) * [Articles from ](#articles-from-category-) * [Artists Related to ](#artists-related-to-artist-) * [Fully Personalized Homepage](#fully-personalized-homepage) * [Structure](#structure) * [Setup Mode](#setup-mode) * [Templates](#templates) * [Custom](#custom) * [Configuration](#configuration) * [A/B Testing](#ab-testing) * [Setting Up an Experiment](#ab-testing-setup) * [Metrics](#ab-testing-setup-metrics) * [Variants](#ab-testing-setup-variants) * [Report](#ab-testing-report) # Scenarios **Scenario** defines a specific application of recommendations on your website, mobile app, or email campaign. For example, you might create scenarios such as _homepage_, _watch-next_,_cart_, or _emailing-after-purchase_. You can configure different recommendation behaviors for each scenario and then monitor their performance in the[KPI section](/admin_ui#admin-ui-database-sections) and the [Insights](/insights). ## Setting Up a Scenario In the Recombee **[Admin UI](https://admin.recombee.com)**, navigate to the **[Scenarios](/scenarios)** section. Choose **Create Scenario** and enter a name for your new scenario. [![Create scenario](/img/gui/create_scenario.png)](/img/gui/create_scenario.png) Then, select its **Type**: [![Create scenario](/img/scenarios/ranked-list-vs-composite.png)](/img/scenarios/ranked-list-vs-composite.png) **Ranked List** * Returns a single set of recommended **items**, **users**, or **[Item Segments](/segmentations)**. * Ideal for typical [recommendation](/api#recommendations) and [search](/api#search) use cases. **Composite** * Suitable for cases such as _Because You Watched _ or _Items from for You_. * Produces a composite response with two parts: * **Source** — a single item, user, or [Item Segment](/segmentations) * **Result** — a set of recommended items, users, or [Item Segments](/segmentations) related to the _Source_ * See [Composite Recommendations](#composite-recommendations) for more details. ## Requesting a Scenario Use the Scenario in [API Requests](/getting_started#getting-started-recomms) or [No-Code Widgets](/no-code-widgets). When using the API: * Pass the name of the created scenario to the `scenario` parameter of the recommendation request. * Example for scenario `homepage`: ```js const result = await client.send( new recombee.RecommendItemsToUser(userId, count, { scenario: 'homepage', }) ); ``` ```kotlin val request = RecommendItemsToUser( userId = userId, count = count, scenario = "homepage" ) val result = client.sendAsync(request) ``` ```swift let request = RecommendItemsToUser( userId: userId, count: count, scenario: "homepage" ) let result = try await client.send(request) ``` ```js const result = await client.send( new rqs.RecommendItemsToUser(userId, count, { scenario: 'homepage', }) ); ``` ```python result = client.send(RecommendItemsToUser(user_id, count, scenario='homepage')) ``` ```ruby result = client.send(RecommendItemsToUser.new(userId, count, { 'scenario' => 'homepage' })) ``` ```java RecommendationResponse result = client.send( new RecommendItemsToUser(userId, count).setScenario("homepage") ); ``` ```php $result = $client->send(new RecommendItemsToUser($user_id, $count, [ 'scenario' => 'homepage' ])); ``` ```csharp RecommendationResponse result = client.Send( RecommendItemsToUser(userId, count, scenario: "homepage") ); ``` ```go req := client.NewRecommendItemsToUser(userId, count).SetScenario("homepage") recommRes, err := req.Send() ``` ```http GET /{databaseId}/recomms/users/userId/items/?count=10&scenario=homepage ``` Tip Not sure which scenarios are best for your use case? See our [Integration Tips](/integration_tips). ## Scenario Settings in the Admin UI You can customize each scenario individually. [![Setting Logic & Filter in the Admin UI](/img/gui/setting_scenario.webp)](/img/gui/setting_scenario.webp) Setting Logic & Filter in the Admin UI ### Logic [Logic](/recommendation_logics) defines the **behavior of the recommendation model**. [![Setting Logic in the Admin UI](/img/gui/set_logic.png)](/img/gui/set_logic.png) ### Filters Filters determine **which items can be recommended** in this scenario. You can select filters from the Recombee library or create your own [Business Rules](/reql#business-rules). An item can be recommended only if all filter rules assigned to the scenario are satisfied. Tip If you specify a `filter` as an [API parameter](/api#recommend-items-to-user-param-filter), the filters from the Admin UI will be combined with it using the `AND` operator. [![Set filter](/img/gui/set_filter.png)](/img/gui/set_filter.png) #### Global Settings To apply filters to all scenarios, use **Global Settings**—for example, to always exclude unavailable items. [Rules](/reql#business-rules) defined in Global Settings are applied automatically to all scenarios, ensuring consistency across your application. [![This Filter rule is applied to all Scenarios](/img/gui/global_settings.png)](/img/gui/global_settings.png) This Filter rule is applied to all Scenarios ### Boosters Boosters allow you to **prioritize certain items** within a scenario to support your business goals. You can use predefined booster rules or create your own [Business Rules](/reql#business-rules). Each booster rule produces a numeric score for each item. The final boosting score is the product of the scores from all applied booster rules. Tip If you specify a `booster` as an [API parameter](/api#recommend-items-to-user-param-booster), it will be combined with the Admin UI boosters using the `*` operator. [![Set booster](/img/gui/set_booster.png)](/img/gui/set_booster.png) ### Constraints Constraints define **how frequently items sharing certain conditions can appear** in recommendation results. Examples: * At most 2 items per category * No more than 50% of items from a single genre * Only one product per parent product ID To use constraints, first create an [Item Segmentation](/segmentations) that represents the shared condition (e.g., category, genre, or brand). Then, add the constraint to your scenario and set how many items per segment are allowed in the recommendations. [![Constraints in Admin UI](/img/gui/constraints.png)](/img/gui/constraints.png) #### Limit Type * **Absolute** — sets a fixed number of items per segment (e.g., max 3 per brand). * **Percentage** — sets a proportion (e.g., max 25% from one brand). #### Window Size When using the **Absolute** limit type, the limit applies to all recommended items by default. To apply it to smaller groups, set a **window size**. For example, with a max of 2 items per segment and a window size of 4, each consecutive group of 4 recommendations will contain at most 2 from the same segment. ![](/img/gui/constraints_window_size.svg) ## Composite Recommendations Composite Recommendations return both a _source entity_ (e.g., an Item or [Item Segment](/segmentations)) and a related list of recommendations in a single response. They are requested via the **[Composite Recommendation API endpoint](/api#composite-recommendation)**. ### Examples #### Because You Watched * _Source_: The movie (Item) watched by the user * _Result_: Movies related to the watched one [![Because You Watched Example](/img/gui/composite_because_you_watched.png)](/img/gui/composite_because_you_watched.png) Tip Check out the Because You Watched [Scenario Recipe](/recipes/video/fully-personalized-homepage/because-you-watched) for more info #### Articles from * _Source_: The user’s favorite category ([Item Segment](/segmentations)) * _Result_: Recommended articles from that category [![Articles from Category Example](/img/gui/composite_items_from_category.png)](/img/gui/composite_items_from_category.png) #### Artists Related to * _Source_: The user’s favorite artist ([Item Segment](/segmentations)) * _Result_: Recommended artists related to the favorite artist [![Related Artists Example](/img/gui/composite_artists_to_artist.png)](/img/gui/composite_artists_to_artist.png) #### Fully Personalized Homepage Often, multiple _Composite Recommendations_ are requested in a [Batch](https://docs.recombee.com/api#batch) to fully personalize the homepage or other sections of a website or app. For example, to display five rows on the homepage — each representing one of the user’s **top five categories** and showing the most relevant content within that category — you can send **five Composite Recommendation requests** in a single Batch, set as: * _Source:_ category (_[Item Segment](/segmentations)_) * _Result:_ content (_Items_) This approach enables the homepage to consist of dynamically personalized sections. The API automatically ensures that five distinct categories are returned in the response, avoiding duplicates. See the [API code example](/api#composite-recommendation-example-category-sections-with-reordering) for implementation details. Tip Check out the Fully Personalized Homepage Scenario Recipes for: * [Video](/recipes/video/fully-personalized-homepage/personalized-re-ordering-of-rows-advanced) * [News](/recipes/news/homepage/personalized-sections-with-reordering) * [E-Commerce](/recipes/e-commerce/fully-personalized-homepage/personalized-re-ordering-of-sections-advanced) ### Structure Composite Recommendations can be viewed as two sequential requests: 1. Recommend the _Source_. 2. Recommend the _Result_ for that _Source_. For instance, _Articles from _ involves: * [Recommend Item Segments To User](/api#recommend-items-to-user) to find the category. * [Recommend Items To Item Segment](/api#recommend-items-to-item-segment) to get articles from that category. Each _Composite Recommendation_ counts as **one API request** for billing. ### Setup Mode When creating a _Composite Recommendation_ scenario, you can choose a **Template** or a **Custom** configuration. #### Templates Predefined templates are available for common cases such as _Because You Purchased_ or _Videos From Top Genre For You_. Templates define both the [endpoints](#structure) used for each stage and the [Logic](/recommendation_logics). #### Custom Custom configuration allows you to manually define the endpoints for each stage and assign different [Logics](/recommendation_logics) as needed. ### Configuration In the Admin UI, you can set distinct [Filters](#filters) and [Boosters](#boosters) for each stage (_Source_ and _Result_). You can also specify these settings using the [sourceSettings](/api#composite-recommendation-param-sourceSettings) and [resultSettings](/api#composite-recommendation-param-resultSettings) API parameters. ## A/B Testing A/B Testing lets you compare different recommendation configurations within a Scenario and measure their effect on your key metrics. Each experiment runs on top of a specific Scenario, with traffic split between a **Control** (the current Scenario configuration) and one or more **Variants**. ### Setting Up an Experiment You can create an experiment either from the **A/B Testing** tab inside a Scenario's detail view, or from the standalone **A/B Testing** section in the Admin UI. When creating an experiment, provide a title (or leave it blank to have one generated automatically), then select the **Scenario** it should run on. Set the **start date** — and optionally an **end date** — to define the experiment's time window. [![Create Experiment form](/img/ab_testing/ab_testing_create.png)](/img/ab_testing/ab_testing_create.png) #### Metrics Metrics define what you want to measure. You must choose at least one metric before the experiment can be created. Recombee provides a **library of predefined metrics** organized by vertical (Video, E-Commerce, Articles & News, etc.) — including metrics such as _Conversion Rate_, _Click-Through Rate (CTR)_, _Watch Time from Recommendations_, and _Income from Recommendations_. [![Choose Metrics panel](/img/ab_testing/ab_testing_choose_metrics.png)](/img/ab_testing/ab_testing_choose_metrics.png) You can also create **custom metrics** based on [Insights](/insights). A custom metric lets you specify a data source (e.g., _Detail Views from Recommendations_) and apply filters — for example, to track views from recommendations only for items from a particular category, or to measure the purchase rate exclusively for items above a certain price threshold. #### Variants Each experiment has a **Control** — the Scenario's current configuration — and one or more **Variants** that modify it. When creating a Variant, you can change any combination of: * **Logic** — the whole recommendation model ensemble or its individual parameters * **Filters** — which items are eligible to be recommended * **Boosters** — how items are ranked within results * **Constraints** — limits on how frequently certain [Segment of items](/segmentations) appear The Admin UI clearly shows what has been changed in each Variant relative to the Control. [![Create Variant panel](/img/ab_testing/ab_testing_create_variant.png)](/img/ab_testing/ab_testing_create_variant.png) Once Variants are defined, assign a **traffic allocation** (percentage) to each using the sliders. Use the **lock icon** to fix a Variant's allocation so it is not affected when adjusting others. Click **Distribute Evenly** to split traffic equally across all Variants. [![Variants allocation sliders](/img/ab_testing/ab_testing_variants_allocation.png)](/img/ab_testing/ab_testing_variants_allocation.png) ### Report The report shows the effect of each Variant on every selected metric, including whether the results are **statistically significant**. For each metric, the table displays: * **Users** — number of users in the Variant and their share of total traffic * **Improvement** — change relative to the Control baseline * **Probability to be best** — likelihood that this Variant outperforms all others * **Probability to beat baseline** — likelihood that this Variant outperforms the Control * **Distribution** — the mean and variance of the metric's value across users The best-performing Variant is highlighted in the results. [![A/B Testing results report](/img/ab_testing/ab_testing_report.png)](/img/ab_testing/ab_testing_report.png) --- # Catalog Feeds > Source: https://docs.recombee.com/catalog_feeds > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [A Step-by-Step Video Tutorial on Setting Up a Catalog Feed](#a-step-by-step-video-tutorial-on-setting-up-a-catalog-feed) * [General Notes](#general-notes) * [Google Merchant Feed](#google-merchant-feed) * [Format](#format) * [Tips & Tricks](#tips-tricks) * [Atom / RSS](#atom-rss-feed) * [How to Set Up](#how-to-set-up) * [IDs with Special Characters](#feeds-md5-item-id) * [Custom XML](#custom-xml-feed) * [How to Set Up](#id3) * [Tips & Tricks](#id11) * [Custom JSON](#custom-json-feed) * [How to Set Up](#id6) * [Custom CSV](#custom-csv-feed) * [How to Set Up](#id7) * [Heureka XML Feed](#heureka-xml-feed) * [Format](#id9) * [Tips & Tricks](#id10) * [Handling of Removed Items](#feeds-availability-property) # Catalog Feeds Setting a catalog feed in the [Recombee Admin UI](https://admin.recombee.com) is an alternative to[uploading the items catalog using our API](/getting_started#getting-started-catalog). We periodically download your feed and update items accordingly. The default update period is 4 hours - if it does not match your specific needs, please contact [support@recombee.com](mailto:support@recombee.com). * Supported protocols for fetching: `http`, `https`, `ftp` and `sftp`. * Supported feeds compressions: `.zip` and `.gz`. We support the following types of feed formats: * [Google Merchant XML / TSV](#google-merchant-feed) * [Atom / RSS](#atom-rss-feed) * [Custom XML](#custom-xml-feed) * [Custom JSON](#custom-json-feed) * [Custom CSV](#custom-csv-feed) * [Heureka XML](#heureka-xml-feed) ## A Step-by-Step Video Tutorial on Setting Up a Catalog Feed ## General Notes * Property name _itemId_ is reserved * Items deleted from feeds are not deleted in Recombee catalog. Instead, they can be updated as _not available_. For more details see [Handling of removed items](#feeds-availability-property). ## Google Merchant Feed ![](/img/headings/catalog-feed-google-merchant.png) ### Format * Specification: * We support both `.xml` and `.tsv` (tab separated text file) variants. Both `.zip` and `.gz` compression is supported. * In addition, we support `.csv` (comma separated) variant (not officially supported by Google) ### Tips & Tricks * You can use item property `availability` for[filtering out](/reql_filtering_and_boosting) from the recommendations the items that are not available anymore. The filter that should be passed to[recommendation requests](/api#recommendations) is: ReQL ``` 'availability' == "in stock" ``` Only items in stock will be recommended. You can achieve this also by setting the predefined Filter [Business Rule](/scenarios#filters) _Items in stock \[Google Merchant\]_ to your [Scenario](/scenarios). * Ids of items are case sensitive - please check that you are using the same case as is used in the feed when you[send interactions](/getting_started#getting-started-interactions). * You can use for example following JavaScript snippet to get recommended items along with their title, description, link, image link and price: JS ``` client.send(new recombee.RecommendItemsToItem(itemId, userId, 3, { returnProperties: true, includedProperties: ['title', 'description', 'link', 'image_link', 'price'], filter: "'availability' == \"in stock\"", scenario: 'related_items' }), (err, resp) => { if(err) { console.log("Could not load recomms: ", err); return; } console.log(resp); // Show recommendations ); ``` For more info see the [JavaScript library](https://github.com/recombee/js-api-client). ## Atom / RSS Atom / RSS feeds are used by the news websites and also many blog pages or podcasts to provide structured information about the offered content. ![](/img/headings/catalog-feed-rss.png) ### How to Set Up 1. Set the URL of your Atom / RSS feed. 2. The feed gets processed and a list of properties that were recognized in the feed is presented in the Suggested properties section. You can pick from this list the properties that you want to synchronize to Recombee. You can also create a custom new property and set an [XPath](https://www.w3schools.com/xml/xpath_syntax.asp) for it (relative to the item entry). This is needed especially in the case of large _.zip_ feeds which cannot be fully processed in this step to obtain the suggested properties. 3. Continue to _Preview_ and check that you are getting expected data for all the properties. When you are satisfied, confirm the settings and the feed will get scheduled for processing. [![Setting RSS feed](/img/feeds/setting_feed.gif)](/img/feeds/setting_feed.gif) ### IDs with Special Characters The IDs of the items in Recombee may consist of digits, latin letters, underscores, colons, minus signs, at sign, and dot. If the IDs in your feed do not follow this format (the ID is for example the URL of the item), enable the _MD5 Item IDs_ option in the_Settings_. An [MD5 hash](https://en.wikipedia.org/wiki/MD5) of the original ID value is then used as the ID. You then need to use the MD5 hash also when you send interactions to Recombee and when you request[Items to Item recommendation](/api#request-recommend-items-to-item). In JavaScript the MD5 hash of the original ID can be obtained for example like this: HTML ``` ``` ## Custom XML An XML that contains structured information about the items. ![](/img/headings/catalog-feed-xml.png) ### How to Set Up 1. Set the URL of your XML feed. 2. Set _Items Path_ \- the [XPath](https://www.w3schools.com/xml/xpath_syntax.asp) to the root element of the items records 3. Set _Item ID Path_ \- Path (relative to the items path) to the element that contains the itemId. If your IDs contain some special characters, enable the _MD5 Item IDs_ option (see [this section](#feeds-md5-item-id) for more details). 4. The feed gets processed and a list of properties that were recognized in the feed is presented in the Suggested properties section. You can pick from this list the properties that you want to synchronize to Recombee. You can also create a custom new property and set an [XPath](https://www.w3schools.com/xml/xpath_syntax.asp) for it (relative to the item entry). This is needed especially in the case of large _.zip_ feeds which cannot be fully processed in this step to obtain the suggested properties. 5. Continue to _Preview_ and check that you are getting expected data for all the properties. When you are satisfied, confirm the settings and the feed will get scheduled for processing. For information about handling items deletion and updating items availability see [Handling of removed items](#feeds-availability-property). ### Tips & Tricks * Arrays in XML: if we have set item property `categories` and we want to fill its data, we need to define multiple fields with the same ID inside item entry. It's relative path is `/categories`. It will correctly process and assign 3 values to the property. xml ``` Drama Horror Thriller ``` ## Custom JSON A JSON that contains structured information about the items. ![](/img/headings/catalog-feed-json.png) ### How to Set Up 1. Set the URL of your JSON feed. 2. Set _Items Path_ \- a path defined by keys of JSON objects to the array with items records ![JSON Structure Selector](/img/feeds/json_structure_selector.png) 3. Set _Item ID Path_ \- a path (relative to the item entry) to the element that contains the itemId. If your IDs contain some special characters, enable the _MD5 Item IDs_ option (see[this section](#feeds-md5-item-id) for more details). 4. The feed gets processed and a list of properties that were recognized in the feed is presented in the Suggested properties section. You can pick from the list properties that you want to synchronize to Recombee. You can also create a new property and set a path of keys for it (relative to the item entry). This is needed especially in the case of large _.zip_ feeds which cannot be fully processed in this step to obtain the suggested properties. 5. Continue to _Preview_ and check that you are getting expected data for all the properties. When you are satisfied, confirm the settings and the feed will get scheduled for processing. For information about handling items deletion and updating items availability see[Handling of removed items](#feeds-availability-property). ## Custom CSV A CSV file where each line contains data for a single item. ![](/img/headings/catalog-feed-csv.png) It is expected that: * The IDs of the items are contained in the first column * The first row of the CSV file is a header (contains names of the columns) The file is automatically analyzed to determine the used delimiter and quoting. ### How to Set Up 1. Set the URL of your CSV feed. 2. The feed gets processed and a list of properties (columns) that were recognized in the feed is presented in the Suggested properties section. You can pick from this list the properties that you want to synchronize to Recombee. You need to set the correct data type for each of the properties. You can also create a custom new property and set the column name for it. This is needed especially in the case of large _.zip_ feeds which cannot be fully processed in this step to obtain the suggested properties. 3. Continue to _Preview_ and check that you are getting expected data for all the properties. When you are satisfied, confirm the settings and the feed will get scheduled for processing. For information about handling items deletion and updating items availability see [Handling of removed items](#feeds-availability-property). ## Heureka XML Feed ![](/img/headings/catalog-feed-heureka.png) ### Format * Specification: ### Tips & Tricks * You can use item property `AVAILABLE` for[filtering out](/reql_filtering_and_boosting) from the recommendations the items that are not available anymore. The filter that should be passed to[recommendation requests](/api#recommendations) is: ReQL ``` 'AVAILABLE' ``` ## Handling of Removed Items The Feeds processor can automatically set items that have been removed from the feed as unavailable. To use this feature, pick the item property that determines availability, and provide the value which denotes the unavailable items: [![Setting Availability property](/img/feeds/feeds_availability_property.png)](/img/feeds/feeds_availability_property.png) You can then use this item property in your [Filters](/reql). --- # No-Code Widgets > Source: https://docs.recombee.com/no-code-widgets > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [No-Code Widget Types](#no-code-widget-types) * [Displaying Recommendations](#displaying-recommendations) * [Recommending Items to User](#html-widget-recommending-items-to-user) * [Recommending Items to Item](#html-widget-recommending-items-to-item) * [Providing the Item ID](#providing-the-item-id) * [Sending Interactions](#sending-interactions) * [Quick Search No-Code Widget](#html-widget-full-text-search) * [Widget Sections](#widget-sections) * [Form Behavior](#form-behavior) * [Deployment](#deployment) * [Using Custom Styles](#html-widget-visual-fine-tuning) * [No-Code Widgets](#no-code-widgets) * [Class Name Templates](#class-name-templates) * [Quick Search No-Code Widget](#quick-search-no-code-widget) * [Optional Embed Code Parameters](#html-widget-optional-embed-code-params) * [Filter](#filter) * [Booster](#booster) * [Logic](#logic) * [Widget Positioning](#html-integration-positioning-of-the-widget) * [Hiding an Empty Widget](#html-integration-hiding-empty-widget) * [Using Widget Data Programmatically](#using-widget-data-programmatically) * [Usage with Google Tag Manager](#html-integration-gtm) * [Cookies Information](#cookies-information) * [Cookies Set by the Recombee Widget Integration](#cookies-set-by-the-recombee-widget-integration) * [Users with Disabled Cookies](#users-with-disabled-cookies) * [Custom User Tracking](#html-widget-own-user-tracking) * [Example](#example) # No-Code Widgets No-Code Widgets are the easiest way to get recommendations and full-text search into your site. ![Setting No-Code Widget in the Admin UI](/img/gui/html-widget-header.png) Setting No-Code Widget in the Admin UI ## No-Code Widget Types No-Code Widgets can be configured in the Admin UI. They are deployed into a website or app using an embed code. We provide widgets both for displaying recommended items ([Recommend Items To User](#html-widget-recommending-items-to-user),[Recommend Items To Item](#html-widget-recommending-items-to-item)) and for [full-text search](#html-widget-full-text-search). ![Grid No-Code Widget](/img/widgets/widget-grid.png) Grid No-Code Widget A box with an adjustable number of items depending on available width (e.g. 5 items horizontally on desktop and 3 items vertically on mobile). ![Quick Search No-Code Widget](/img/widgets/widget-quick-search.png) Quick Search No-Code Widget A widget showing full-text search results based on the user’s query. See the [Full-text Search Widget](#html-widget-full-text-search) section for more details. ![Infinite Feed No-Code Widget](/img/widgets/widget-feed.png) Infinite Feed No-Code Widget A feed of items that incrementally loads more content upon reaching the end of the box. ![Carousel No-Code Widget](/img/widgets/widget-carousel.png) Carousel No-Code Widget A box that loads additional recommendations upon clicking the arrow button. ## Displaying Recommendations Each No-Code Widget is linked to a [Scenario](/scenarios) \- a place on your site where the recommendations are displayed. You can set various settings for each Scenario in the Admin UI. Learn more in the [Scenarios page](/scenarios#scenarios-in-admin-ui). **The Scenario also defines the type (endpoint) of the recommendations:** * **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. * **Search Items** \- A personalized full-text search based on the user's query. To create a new No-Code Widget, go to the [Create No-Code Widget](https://admin.recombee.com/go-to-database/create-recommendation-widget) page in the Admin UI and select the type of the widget that you want to create (e.g. Carousel or Grid). If you don't have a [Scenario](/scenarios) for the Widget yet, you will be prompted to create one at this point. You can set which Item Properties will be shown in the Widget and also all kinds of visual settings (e.g. font, colors, borders, and many more). You can also set how many items will be shown on different types of devices. ### Recommending Items to User In the case of [Recommend Items To User](/api#request-recommend-items-to-user) [Scenarios](/scenarios), no additional data needs to be provided to the widget - simply copying the embed code into your website is enough. You may want to use some of the embed code's [optional parameters](#html-widget-optional-embed-code-params) (such as a dynamic filter),[fine-tune the visual appearance using your own CSS](#html-widget-visual-fine-tuning) or [provide your own user IDs](#html_widget_own_user_tracking). ### Recommending Items to Item #### Providing the Item ID In case of the [Recommend Items To Item](/api#request-recommend-items-to-item) [Scenarios](/scenarios)(e.g. at product detail, read next, watch next, etc.), the ID of the currently displayed item needs to be provided to the embed code snippet. [![Item ID placeholder in the Embed Code](/img/gui/html_widget_item_id.png)](/img/gui/html_widget_item_id.png) Item ID placeholder in the Embed Code Different systems have different ways to acquire the item ID. Here is an example of setting the item ID in a [Shopify](https://www.shopify.com/)theme, using the [product object](https://shopify.dev/docs/themes/liquid/reference/objects/product): HTML ``` ``` #### Sending Interactions In the case of [Recommend Items To Item](/api#request-recommend-items-to-item) [Scenarios](/scenarios), besides showing recommendations to users, the No-Code Widget can also automatically send the information that the user viewed the item (e.g. product, article, etc.) to Recombee. This simplifies the basic integration of Recombee into your website, as the only step left which is not covered by the No-Code Widget is providing the catalog of your Items. This can be done by setting up a [Catalog Feed](/catalog_feeds) in the [Recombee Admin UI](https://admin.recombee.com) or by [using an SDK](/getting_started#getting-started-catalog). Sending the interaction can be enabled in the _Embed Code_ section. The interaction which is being sent is a [Detail View](/api#request-add-detail-view). [![To send the interaction, enable the "Also send Detail View interaction" option](/img/gui/html_widget_send_interaction.png)](/img/gui/html_widget_send_interaction.png) To send the interaction, enable the "Also send Detail View interaction" option ## Quick Search No-Code Widget The Quick Search No-Code Widget enables you to show items or even [Item Segments](/segmentations) (categories, genres, artists, etc.) based on the user's full-text search query. [![Setting Quick Search No-Code Widget in the Admin UI](/img/gui/quick-search-widget.png)](/img/gui/quick-search-widget.png) Setting Quick Search No-Code Widget in the Admin UI ### Widget Sections The Quick Search No-Code Widget can contain multiple sections. Each of these is connected to a [Scenario](/scenarios). The number of Search requests sent by the Widget is equal to the number of used sections. In the _Layout_ menu, you can change the order of the displayed sections by moving them (drag and drop), as well as the layout of the sections (e.g. from horizontal to vertical). [![Quick Search No-Code Widget with 3 sections: Segments, Hero, and Items](/img/gui/search-widget-sections.png)](/img/gui/search-widget-sections.png) Quick Search No-Code Widget with 3 sections: Segments, Hero, and Items The following sections are available: * **Items** \- This section is always present and shows the Items that match your search query. You can present these as a grid or a list. * **Hero** \- An optional section that highlights the top found Item. This Item is often the most relevant one and takes up the most space in the widget. * **Segments** \- An optional section that displays matching [Item Segments](/segmentations) (categories, genres, artists, vendors, etc.) by internally using the [Search Item Segments](/api#request-search-item-segments) endpoint. **Items** and **Hero** sections show the following elements of each Item: * Title, * Image, * Description, * Highlighted Information (often the price of the item). You can specify which Item Properties will be used within these elements. In the **Segments** section, only the Segment ID is shown. This can be the name of the category, genre, artist, vendor, etc. --- All Items and Item Segments shown in the widget are clickable and will redirect the user to a specified URL. For Items, this URL is constructed from an Item Property that you specify. This property should be the entire URL or contain a unique identifier of the Item (e.g. an Item ID or a URL slug). For Item Segments, the URL is constructed from the Segment ID. For all URLs, you can specify a prefix and a suffix. This is useful when you want to construct the URL manually. Examples **Constructing a URL from an Item Segment ID:** * Prefix: `https://mypage.com/categories/` * Suffix: `.html` * Segment ID: `Office Electronics` The resulting URL will be `https://mypage.com/categories/office-electronics.html`. **Constructing a URL from an Item ID:** * Prefix: `https://mypage.com/products/` * Suffix: _none_ * Link Property: `item_id` * Item Property `item_id`: `product-42` The resulting URL will be `https://mypage.com/products/product-42`. **Using a URL Item Property:** * Prefix: _none_ * Suffix: _none_ * Link Property: `url` * Item Property `url`: `https://mypage.com/products/product-42` The resulting URL will be `https://mypage.com/products/product-42`. ### Form Behavior The _Form Behavior_ tab in the No-Code Widget editor (shown as a gear icon) allows you to fine-tune the behavior of the search input. There you can set the following settings: * **Start on** \- How many characters the search query should contain before the search requests are fired. * **Debounce** \- The time in milliseconds that the widget waits before sending another search request. * **Submit URL** \- Whether there should be a submit button that redirects the user to a dedicated search page, as well as the path of this search page and the name of the _search string_ query parameter. ### Deployment To deploy the No-Code Widget, simply copy the embed code into the place where the search input should be rendered. ## Using Custom Styles The No-Code Widget Editor offers a wide range of settings to customize the visual appearance of the widget. However, you may want to further fine-tune the appearance to match the style of your website. You can do this by using your own _CSS (Cascading Style Sheets)_ to change the appearance of the widget elements. ### No-Code Widgets You can add your custom class names in four places in the No-Code Widget Editor using the `{}` icon: * The _Grid Box_ around the whole widget, * The _Item Box_ around a single recommended item, * _Image_ of a recommended item - both the `img` element and the wrapper around it, * Individual _Properties_ of a recommended item. [![Setting the price-row class name to the row with the price](/img/gui/html_widget_class_names.png)](/img/gui/html_widget_class_names.png) Setting the `price-row` class name to the row with the _price_ #### Class Name Templates When applying the class names to elements that belong to a particular recommended item (_Image_ and _Properties_ sections), you can use the property values of the particular item to construct the class names using the `${context.entity.propertyName}` syntax. Assume the following item: | Item ID | isOnSale Boolean | reviewRating Integer | | ------- | ---------------- | -------------------- | | item-42 | true | 5 | The following class names can be created: * `on-sale-${context.entity.isOnSale}` sets the class `on-sale-true` on the element * `rating rating-${context.entity.reviewRating}` sets the classes `rating rating-5` on the element ### Quick Search No-Code Widget Search Widget DOM elements have static class names in the form of `recombee-quick-search-widget-*`, which do not change. You can use these classes to provide custom CSS. Please do not use class names in the form of `rcmbws-*`, as these are generated and can change in future releases. ## Optional Embed Code Parameters You may want to filter the recommendations, boost items, or set the logic of the recommendations. If possible, we recommend setting these parameters in the Scenario in the Admin UI. However, you may also want to set them dynamically. This can be done by adding optional parameters to the `InitializeRecommendationWidget` call: ### Filter Use the `filter` parameter to apply a custom [ReQL](/reql) filter. For example, you can restrict displayed items to a specific category: HTML ``` ``` ### Booster Use the `booster` parameter to apply a custom [ReQL](/reql) booster. For example, you can boost items that are near the current position of the user: HTML ``` ``` ### Logic Use the `logic` parameter to set the [Logic](/recommendation_logics) for the used recommendation requests, including their settings. For example, you can set the Logic to recommend popular items in the country of the user: HTML ``` ``` ### Widget Positioning By default, the position of the widget on your page is determined by the position of the _div_ element generated for you in the embed code snippet. However, in some cases, you may want to set the position of the widget programmatically, such as when deploying the widget using a tag manager (such as [Google Tag Manager](#html_integration_gtm)). You can specify where the widget will be rendered by giving its relative position to another element. Use one of these optional parameters to specify this element: * `insertBeforeElementSelector`: The widget will be inserted before the first element matching this selector (id, class, etc.). * `insertAfterElementSelector`: The widget will be inserted after the first element matching this selector. * `prependToElementSelector`: The widget will be inserted as the first child of the first element matching this selector. * `appendToElementSelector`: The widget will be inserted as the last child of the first element matching this selector. HTML ``` ``` ### Hiding an Empty Widget In some cases, such as your database being empty or the widget scenario produces no results due to e.g. applied filters, the widget may fetch zero items. You may want to hide the widget itself and/or some other elements in your page such as a heading preceding the widget content. * `hideOnEmptyRecommendations`: The widget is hidden when no items are available. * `hideOnEmptyRecommendationsElementsSelectors`: Selected elements in page are hidden when no items are available. HTML ``` ``` ### Using Widget Data Programmatically You can supply a callback function that receives data about each recommendation request made by the widget: HTML ``` ``` * Callback parameters: * `recombeeRequest`: Recombee API client request, either a single request or a [Batch](/api#batch). * `recombeeResponse`: Resulting recommendations data, either a single response or a Batch response. * `url`: [Recombee API URL](/regions) to which the request was sent. * `request`: Standard `fetch` `RequestInit` object. * `response`: Standard `fetch` `Response` object. ## Usage with Google Tag Manager To deploy a widget using GTM, create a _Custom HTML Tag_ and copy-paste the widget embed code to the Tag HTML content. Set a _Page View_ trigger for pages where the widget should be deployed and use [positioning parameters](#html-integration-positioning-of-the-widget) to insert the widget to a specific place on your page. ## Cookies Information To provide the most relevant recommendations, Recombee by default identifies the user using first-party cookies on the user's browser. The cookie is set by Recombee Integration script, which is used to track interactions or render recommended items in No-Code Widget. The cookie doesn't identify your users personally. Important You may need to notify your users about the use of tracking cookies depending on your user's country privacy laws. This is usually done by using a cookie manager deployed to your website. Please consult your legal team to determine whether this step is necessary. As we use first-party cookies, Recombee tracks your users only on your website - Recombee does no cross-site tracking. Read more about the difference between first-party and third-party cookies [here](https://clearcode.cc/blog/difference-between-first-party-third-party-cookies/). ### Cookies Set by the Recombee Widget Integration | Name | Description | Duration | Data Type | | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------- | --------- | | _\_rcmbid_ | \_rcmbid is set each time a user lands on a page with the Recombee Integration script. The cookie is used to preserve the unique Recombee User ID. This ensures that all interactions performed by the unique visitor are attributed to a common anonymous ID. | 365 days, refreshed on each visit | String | ### Users with Disabled Cookies Recombee doesn't track or record users who have cookies disabled. ### Custom User Tracking If you already track the users on your site, you can provide the ID of the user to the Recombee Integration script. You can select this option in the _Embed Code_ section when creating the No-Code Widget. In this case, no cookie is set by the widget. #### Example Here is an example of using the Recombee with Google Analytics user IDs: HTML ```
``` --- # Introduction to ReQL > Source: https://docs.recombee.com/reql > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Filtering and Boosting](#filtering-and-boosting) * [Business Rules](#business-rules) * [ReQL Code Assistant](#reql-code-assistant) * [Code Generation](#code-generation) * [Explanation of Existing Code](#explanation-of-existing-code) * [Conversations History](#conversations-history) # Introduction to ReQL Recombee Query Language (ReQL) provides an elegant way for applying business rules or any other rules to the recommendations. It allows expressions to be evaluated on candidate **items**, telling the recommender how to handle each item based on the **values** of the item's**properties**. There are two types of the ReQL expressions: * [**filter**](/reql_filtering_and_boosting#reql-filtering) \- for selecting a subset of items which can be used in recommendation * [**booster**](/reql_filtering_and_boosting#reql-boosting) \- for preferring some items over the others You can create your custom filter/booster [Business Rules](#business-rules) in the [Recombee Admin UI](https://admin.recombee.com) and apply them to your [Scenarios](/scenarios). [AI ReQL Code Assistant](#reql-code-assistant) within the Admin UI can help you with creating the rules - just describe the desired behavior in your natural language. [![Creating your own Business Rule in Admin UI using ReQL](/img/gui/br1.png)](/img/gui/br1.png) Creating your own Business Rule in Admin UI using ReQL Alternatively you can send `filter` and `booster` as parameters of [API recommendation requests](/api#recommendations). Filters and boosters use the[property values](/api#subsection-values-of-item-properties) of the individual items (or users). Read[this part of Getting Started guide](/getting_started#getting-started-catalog) or[this tutorial](/tutorial#tutorial-catalog) for more information on uploading the item catalog. All the items have one automatically created property `itemId`. ## Filtering and Boosting In **filtering**, the expression must return **boolean** value for each item. If the value returned is `true`, the item passed the filter; if the value is `false`, the item does not pass and will be discarded. [Read more about filtering](/reql_filtering_and_boosting#reql-filtering) In advanced applications, besides filtering, you may wish to **boost**recommendation rates of some items. In contrast to filtering, where items may be completely blocked, in boosting, you may tell the recommender to **prefer** some items over others. Indeed, by default, it is a task of the recommender itself to select the items which are the most relevant. However, it may be your policy to purposefully bias the recommender toward your business goals. [Read more about boosting](/reql_filtering_and_boosting#reql-boosting) ## Business Rules The _Business Rules_ section in the Admin UI provides a [ReQL](/reql) editor with result previews, along with an [AI ReQL Code Assistant](/reql#reql-code-assistant) that helps generate rules from natural language. You can define _Input Values_ to reuse a single _Business Rule_ with different configurations across multiple [Scenarios](/scenarios). For example, you might create a rule that recommends only short (less than 30 minutes), English-language movies: [![Creating a Business Rule](/img/gui/br1.png)](/img/gui/br1.png) If you have multiple scenarios requiring different limits, you can make certain values (e.g., max runtime) configurable via **input parameters**: [![Adding Input Value](/img/gui/br2.png)](/img/gui/br2.png) [![Adding Input Value](/img/gui/br3.png)](/img/gui/br3.png) When applying such a rule to a scenario, you can specify the desired input (e.g., runtime in minutes): [![Applying Business Rule to Scenario](/img/gui/br4.png)](/img/gui/br4.png) ## ReQL Code Assistant [![ReQL AI Assistant in Admin UI using ReQL](/img/gui/reql_assistant.png)](/img/gui/reql_assistant.png) ReQL AI Assistant in Admin UI using ReQL The AI ReQL Code Assistant can help you create ReQL filters and boosters or even [ReQL-based Segmentations](/segmentations#advanced-creating-segmentations). You can access the assistant by clicking the _Code Assistant_ button in the Business Rules and Item Segmentations sections of the Recombee Admin UI. ### Code Generation Describe what you want to be the outcome of the rule in **natural language** (it even does not have to be English) and watch the Assistant generate the ReQL code for you. We recommend that you always validate the generated filters and boosters before applying them. If you need to make some amendments to the generated code, just continue in the conversation and the assistant will modify the rule according to your needs. ### Explanation of Existing Code Open the Assistant on an existing rule and get a detailed explanation of how the rule works. ### Conversations History You can access your conversation history with the Assistant and pick up where you left off. --- # Filtering and Boosting > Source: https://docs.recombee.com/reql_filtering_and_boosting > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Filtering](#filtering) * [Example 1](#example-1) * [Example 2](#example-2) * [Example 3](#example-3) * [Handling Deleted Items](#handling-deleted-items) * [Boosting](#boosting) * [Examples](#examples) * [Exclude Some Items from Recommendations Using Their IDs](#exclude-some-items-from-recommendations-using-their-ids) * [Re-rank a Given Set of Items](#re-rank-a-given-set-of-items) * [Recommend Related Items by the Same Manufacturer](#recommend-related-items-by-the-same-manufacturer) * [Boost Items That Were Published in Last 24 Hours](#boost-items-that-were-published-in-last-24-hours) * [Up-Sell](#up-sell) * [Recommend Only Items Available in User’s City](#recommend-only-items-available-in-user-s-city) * [Recommend Only Items from Subscribed Topics](#recommend-only-items-from-subscribed-topics) * [Value Types and Operators](#value-types-and-operators) * [Numbers](#numbers) * [Notation](#numbers-notation) * [Operations](#numbers-operations) * [Comparison](#numbers-comparison) * [Strings](#strings) * [Notation](#strings-notation) * [Comparison](#strings-comparison) * [Containment](#strings-containment) * [Concatenation](#strings-concatenation) * [Indexing and Slicing](#strings-indexing-and-slicing) * [Sets](#sets) * [Notation](#sets-notation) * [Properties](#sets-properties) * [Value Containment](#sets-value-containment) * [Comparison](#sets-comparison) * [Union](#sets-union) * [Difference](#sets-difference) * [Intersection](#sets-intersection) * [Symmetric Difference](#sets-symetric-difference) * [Arrays](#arrays) * [Notation](#arrays-notation) * [Value Containment](#arrays-value-containment) * [Comparison](#arrays-comparison) * [Concatenation](#arrays-concatenation) * [Indexing and Slicing](#arrays-indexing-and-slicing) * [Logical Operators](#logical-operators) * [Negation (NOT)](#logical-operators-negation-not) * [Disjunction (OR)](#logical-operators-disjunction-or) * [Conjunction (AND)](#logical-operators-conjuction-and) * [Conditional Operator](#conditional-operator) * [Comments in ReQL](#comments-in-reql) # Filtering and Boosting ## Filtering In filtering, the expression must return **boolean** value for each item. If the returned value is `true`, the item passed the filter; if the value is `false`, the item does not pass and will be discarded. The value is computed from set property values of the individual items. Consider the following table of items in sample movie-recommendation domain: | Name String | Year Integer | Director String | Genres Set | Parental-Advisory Boolean | | --------------------------------------------- | ------------ | ----------------- | ------------------------------------------------------------------------- | ------------------------- | | Pulp Fiction | 1994 | Quentin Tarantino | {"Crime Fiction","Drama", "Thriller" } | true | | King Kong | 2005 | Peter Jackson | {"Action", "Drama", "Adventure" } | false | | Fight Club | 1999 | David Fincher | {"Drama", "Existentialism"} | true | | The Lord of the Rings: The Return of the King | 2003 | Peter Jackson | { "Adventure", "Fantasy", "Action" } | false | | The Dark Knight | 2008 | Christopher Nolan | {"Superhero","Drama" ,"Action", "Adventure", "Thriller", "Crime Fiction"} | false | | Silence of the Lambs | 1991 | Jonathan Demme | {"Crime Fiction", "Drama", "Thriller", "Horror" } | true | | Dead Alive | 1992 | Peter Jackson | {"Horror", "Comedy"} | true | | _… and 10000 other movies_ | | | | | ### Example 1 By default, when items are to be recommended to a given user, the recommender selects any items which seem relevant to the user. However, it may be your policy not to recommend items with Parental-Advisory flag set on. Hence you may use the following simple ReQL filtering expression: ReQL ``` not 'Parental-Advisory' ``` Then the recommender may only choose from the following movies: | Name String | Year Integer | Director String | Genres Set | Parental-Advisory Boolean | | --------------------------------------------- | ------------ | ----------------- | ------------------------------------------------------------------------- | ------------------------- | | King Kong | 2005 | Peter Jackson | {"Action", "Drama", "Adventure" } | false | | The Lord of the Rings: The Return of the King | 2003 | Peter Jackson | { "Adventure", "Fantasy", "Action" } | false | | The Dark Knight | 2008 | Christopher Nolan | {"Superhero","Drama" ,"Action", "Adventure", "Thriller", "Crime Fiction"} | false | | _… and 5926 other movies_ | | | | | ### Example 2 If you want to allow only items without `Parental-Advisory` which were directed by Peter Jackson (for example because a user selected such a filter at your site) you can do it by: ReQL ``` (not 'Parental-Advisory') and ('Director' == "Peter Jackson") ``` Note You can **access value** of a property by putting name of the property into the **single quotes**. Strings are enclosed in **double quotes**. Only the following items can be recommended: | Name String | Year Integer | Director String | Genres Set | Parental-Advisory Boolean | | --------------------------------------------- | ------------ | --------------- | ------------------------------------ | ------------------------- | | King Kong | 2005 | Peter Jackson | {"Action", "Drama", "Adventure" } | false | | The Lord of the Rings: The Return of the King | 2003 | Peter Jackson | { "Adventure", "Fantasy", "Action" } | false | ### Example 3 As another example, consider that user entered the _Thriller_ section of your system’s catalog. Then you sure wish to recommend thrillers, ignoring the fact that usually, the user likes comedies. As the _Genres_ is a `set` property, you can use the `in` operator for checking whether _Thriller_ is listed in the item’s genres: ReQL ``` "Thriller" in 'Genres' ``` Only the following items pass the filter: | Name String | Year Integer | Director String | Genres Set | Parental-Advisory Boolean | | ------------------------- | ------------ | ----------------- | ------------------------------------------------------------------------- | ------------------------- | | Pulp Fiction | 1994 | Quentin Tarantino | {"Crime Fiction","Drama", "Thriller" } | true | | The Dark Knight | 2008 | Christopher Nolan | {"Superhero","Drama" ,"Action", "Adventure", "Thriller", "Crime Fiction"} | false | | Silence of the Lambs | 1991 | Jonathan Demme | {"Crime Fiction", "Drama", "Thriller", "Horror" } | true | | _… and 3141 other movies_ | | | | | ### Handling Deleted Items Filtering offers you an elegant way of handling deleted/obsolete items in the catalog. In many situations, it may happen that some items become unavailable and hence should not be recommended anymore. Considering interaction data, however, such items may still be important for the recommender. For example, the recommender may find out that users who liked a no more available item, `x`, will probably like another item, `y`, which is still available. Therefore, it is undesirable to simply delete `x`, deleting also all the related interactions in cascade. **With filtering, you may handle item deletes using the following scheme:** * Create a dedicated [item property](/api#item-properties), such as `deleted`, of type `boolean` (the implicit value for all items will be `null`, which is OK). * For deleted items, set the value of `deleted` `true`. * For [recommendations](/api#recommendations), use the following filter: ReQL ``` not 'deleted' ``` * If the item becomes available again, you may set `deleted` to `false`. Such a mechanism cay easily be extended to control availability over different regions, customer licenses, etc. ## Boosting In advanced applications, besides filtering, you may wish to **boost** recommendation rates of some items. In contrast to filtering, where items may be completely blocked, in boosting, you may tell the recommender to **prefer** some items among others. Indeed, by default, it is a task of the recommender itself to select the items which are the most relevant. However, it may be your policy to purposefully bias the recommender toward your business goals. For example, considering the above table of movies, one may wish to promote the movies which are new and were filmed after 2000, especially if they were filmed after 2005\. Then the following boosting query can handle that: ReQL ``` if 'Year' <= 2000 then 1 else (if 'Year' <= 2005 then 1.5 else 2) ``` As you can see, boosting expressions return **numbers** rather than booleans as in case of filtering. Specifically, they provide the items with **coefficients** by which the internal scores determined by the recommender will be multiplied. The boosting coefficients assigned by the query are shown in the following table: | Name String | Year Integer | Boosting | | --------------------------------------------- | ------------ | -------- | | Pulp Fiction | 1994 | 1.0 | | King Kong | 2005 | 1.5 | | Fight Club | 1999 | 1.0 | | The Lord of the Rings: The Return of the King | 2003 | 1.5 | | The Dark Knight | 2008 | 2.0 | | Silence of the Lambs | 1991 | 1.0 | | Dead Alive | 1992 | 1.0 | | _… and 10000 other movies_ | | | ## Examples ### Exclude Some Items from Recommendations Using Their IDs Use `filter`: ReQL ``` 'itemId' not in {"item-127", "item-756", "item-568"} ``` The three items will not be recommended. ### Re-rank a Given Set of Items Use `filter` (usually sent as a dynamic parameter of the [API recommendation request](api#recommend-items-to-user-param-filter)): ReQL ``` 'itemId' in {"item-42", "item-77", "item-1992"} ``` * The recommendation engine will re-rank the given set of items for the particular user. * It is supported to provide thousands of IDs in the query ### Recommend Related Items by the Same Manufacturer Suppose that the items have a _string_ property `manufacturer` and the user is viewing a product detail page. If you want to give the user related items using [Recommend Items to Item](/api#request-recommend-items-to-item), but restrict them to the manufacturer of the currently viewed item, use `filter`: ReQL ``` 'manufacturer' == context_item["manufacturer"] ``` [context\_item](/reql_functions#reql-func-context-item) function is used for retrieving property values of the item, that is currently viewed by the user. ### Boost Items That Were Published in Last 24 Hours Suppose that the items have a _timestamp_ property `published_date`. Then you can use this `booster`: ReQL ``` if 'published_date' >= now() - 24 * 60 * 60 then 2 else 1 ``` [now](/reql_functions#reql-func-now) returns current UTC timestamp in seconds. `24 * 60 * 60` is the number of seconds in 24 hours. ### Up-Sell Suppose that the items have a _double_ property `price`. Slightly boost items that are more expensive than the currently viewed one with the following `booster` in [Recommend Items to Item](/api#request-recommend-items-to-item): ReQL ``` if 'price' > context_item["price"] then 1.2 else 1 ``` ### Recommend Only Items Available in User’s City * Suppose that the items have a _set_ property `cities`. It contains cities in which the items are available. * Suppose that the users have a _string_ property `city` giving the city where each user live. To recommend only items available in a user’s city, use `filter`: ReQL ``` context_user["city"] in 'cities' ``` [context\_user](/reql_functions#reql-func-context-user) function is used for retrieving property values of the user for which you request the recommendations. ### Recommend Only Items from Subscribed Topics Assume your site contains articles about various topics. The users can choose which topics are interesting for them in order to receive personalized newsletters with articles from these topics. The subscribed topics are stored for each user in a User property of type _set_ called `subscribed_topics`. Each article can belong to multiple topics, stored in the `topics` item property of the type _set_. The following `filter` allows only items that contain at least one matching topic to be recommended: ReQL ``` size(context_user["subscribed_topics"] & 'topics') > 0 ``` The `&` operator returns the intersection of the two sets, which must be non-empty. ## Value Types and Operators ReQL supports the following value types: * `int` – signed integer (currently 64bit), * `double` – double-precision floating-point number (IEEE 754 compliant), * `timestamp` – UTC timestamp, similar to `double`, * `string` – sequence of Unicode characters, * `boolean` – binary data type of two possible values: `true` or `false`, * `set` – unordered collection of values. * `array` – ordered collection of values. Except for `set` and `array` types, all of the types include special value of `null`, which, again, corresponds to the fact that `null` is an allowed and also default value for the item / user property values in the API. ### Numbers #### Notation | Expression | Equivalent | Comment | | ---------- | ---------- | ----------------------------------------------------------------------------- | | 0123.000 | 123.0 | Leading and trailing zeros are ignored. | | 1.23e+3 | 1230.0 | Exponential notation may be used. | | 1e9 | 1000000000 | Using simple exponential notation for huge numbers. | | 123E-2 | 1.23 | Negative exponents may also be used. Case of the e character does not matter. | #### Operations | Expression | Result | Comment | | ------------------------ | ------ | ---------------------------------------------------------------------- | | 1 + 2 | 3 | Addition. | | 1 + 2 + 3 + 4 | 10 | Chain of additions. | | 1 - 2 | \-1 | Subtraction. | | 1 - 2 - 3 - 4 | \-9 | Chain of subtractions. | | \-(1 + 2) | \-3 | Unary minus. | | 2 \* 3 | 6 | Multiplication. | | 1 + 2 \* 3 - 4 | 3 | Standard operator precedence. | | (1 + 2) \* (3 - (4 + 5)) | \-18 | Bracketing. | | 10 / 5 | 2.0 | Division. | | 1 / 2 | 0.5 | Division always results in double, event if the operands are integers! | | 5 / 0 | NaN | If the divisor is 0, the result is NaN. | | 9 % 4 | 1 | Modulo division. | | 3.14 % 2.5 | 0.64 | Modulo division also works for doubles. | | 5 % 0 | NaN | If the divisor is 0, the result is NaN. | #### Comparison | Expression | Result | Comment | | ----------------------------- | ------ | ----------------------------------------------------------------------------------------- | | 1 < 2.0 | true | Integers, doubles, and timestamps may be compared using standard comparison operators. | | 1 < 2 <= 2 == 2 != 1 >= 1 > 0 | true | Comparison operators may be arbitrarily chained. | | 1 < 2 <= 2 == 3 != 1 >= 1 > 0 | false | Chain of comparisons returns true if and only if all the individual comparisons are true. | | 2 == 2.0 | true | In comparison, there is no difference between integers, doubles, and timestamps. | ### Strings #### Notation | Expression | Comment | | ---------------------- | ------------------------------------------------ | | "foo" | Strings constants are enclosed in double quotes. | | "" | Empty string. | | "she said \\"hello\\"" | Double quotes must be escaped. | | "she said 'hello'" | Single quotes needn’t be escaped. | #### Comparison | Expression | Result | Comment | | ----------------------------------- | ------ | ----------------------------------------------------------- | | "foo" == "foo" | true | Strings are compared for equality with \==. | | "Alice" != null | true | Strings can be compared to null. | | "Alice" < "Bob" | true | Strings are ordered in lexicographic order. | | "Alice" < "Bob" < "Carol" < "Dan" | true | Comparisons may be chained arbitrarily. | | "Alice" < "Bob" <= "Carol" != "Dan" | true | Comparisons in the chain may be of different types. | | "Alice" < "Bob" >= "Carol" != "Dan" | false | All the comparisons must hold for the chain to return true. | | "Alice" < 5 | error | Strings are only comparable with strings. | | "Alice" \~ "A\[a-z\]+" | true | Strings can be matched with regular expressions (regex). | #### Containment | Expression | Result | Comment | | -------------------- | ------ | --------------------------------------------------------------------------------------------- | | "ice" in "Alice" | true | in operator between strings tests whether the first string is contained in the second string. | | "Ice" in "Alice" | false | Containment test is case sensitive. | | "ice" not in "Alice" | false | in operator may be negated for better readability. | | "" in "abc" | true | Empty string is contained in every string. | | "abc" in "" | false | No non-empty string is contained in empty string. | | 5 in "abc" | error | Both operands must be strings for string containment testing. | #### Concatenation | Expression | Result | Comment | | --------------- | ---------- | -------------------------------------------------- | | "foo" + "bar" | "foobar" | Strings can be concatenated using the + operator. | | "" + "foo" + "" | "foo" | Empty string is neutral element for concatenation. | | "foo" + 123 | "foo123" | Strings can be concatenated with integers. | | "foo" + 123.0 | "foo123.0" | Strings can be concatenated with numbers. | #### Indexing and Slicing | Expression | Result | Comment | | -------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | "abcd"\[1\] | "b" | A character in the string can be accessed by its index (starting from 0). | | "abcd"\[10\] | "" | Requesting an index outside the array boundaries results in an empty string. | | "abcd"\[-1\] | "d" | Negative indices are interpreted as counting from the end of the string. \-1 therefore means the last character. | | "abcd"\[1:3\] | "bc" | It is possible to get a sub-string between two indices. | | "abcd"\[1:\] | "bcd" | If the second index is omitted, all characters until the end of the string are returned. | | "abcd"\[1::2\] | "bd" | Size of step can be provided to only take every n-th character. | | "abcd"\[::-3\] | "da" | Size of step can be negative. If first index is omitted, the slice begins with the last character.If the second index is omitted, the slice goes until the first character (inclusive). | ### Sets #### Notation | Expression | Comment | | ---------------------------- | -------------------------------------------------------------------------------------------------------------------- | | {} | Empty set. | | {1, 2, 3} | Set containing three integers. | | {1, 2.0, false, "foo", null} | Sets may contain values of different types. This is an extension to sets in the API, which may only contain strings. | | {{1,2}, {2,3}} | Sets may be nested. | #### Properties | Expression | Result | Comment | | ---------------- | --------- | ---------------------------------------------- | | { 1, 1, 1, 2 } | { 1, 2 } | Sets only contain unique elements. | | { 1, 1.0 } | { 1.0 } | Integers, doubles, and timestamps, are merged. | | { {1,2}, {2,1} } | { {1,2} } | Merging also works for nested sets. | #### Value Containment | Expression | Result | Comment | | ---------------------------- | ------ | ------------------------------------------------------------------------------------------ | | 2 in { 1, 2, 3 } | true | Using in operator, you may test whether a value is contained in given set (the ∈ relation) | | 4 not in { 1, 2, 3 } | true | The in operator may be negated for better readability (the ∉ relation). | | 2.0 in { 1, 2, 3 } | true | There is no difference between integers, doubles, and timestamps when testing containment. | | "2" in { 1, 2, 3 } | false | There is a difference between numbers and strings. | | { 1, 2 } in { 1, 2, 3 } | false | in stands for ∈, not ⊆! | | { 1, 2 } in { {1,2}, {3,4} } | true | in stands for ∈. | #### Comparison | Expression | Result | Comment | | ----------------------- | ------ | -------------------------------------------------------------------------------------------------------------- | | { 1, 2 } < { 1, 2, 3 } | true | Using < operator, you may test whether one test is a proper subset of another set (⊂ operator in set algebra). | | { 1, 2 } < { 1, 2 } | false | No set is a proper subset of itself. | | {} < { 1, 2 } | true | Empty set is a proper subset of every non-empty set. | | {} < {} | false | Empty set is not a proper subset of itself. | | { 1, 2 } <= { 1, 2, 3 } | true | Using <= operator, you may test whether one set is a subset of another set (⊆ operator is set algebra). | | { 1, 2 } <= { 1, 2 } | true | Every set is a subset of itself. | | { 1, 2 } == { 1, 2 } | true | \== tests whether two sets are identical. | | { 1, 2 } != { 1, 2 } | false | != tests whether two sets are different. | | { 1, 2, 3 } >= { 1, 2 } | true | \>= operator tests whether one set is a superset of another set (⊇ operator in set algebra). | | { 1, 2 } >= { 1, 2 } | true | Every set is a superset of itself. | | { 1, 2, 3 } > { 1, 2 } | true | \> operator tests whether one set is a proper superset of another set (⊃ operator in set algebra). | | { 1, 2 } > { 1, 2 } | false | A non-empty set in not a proper superset of itself. | | { 1, 2 } > {} | true | Every non-empty set is a proper superset of an empty set. | | {} > {} | false | Empty set is not a proper subset of itself. | #### Union | Expression | Result | Comment | | --------------------------- | ------------------ | ---------------------------------------------------------------- | | { 1, 2 } + { 2, 3 } | { 1, 2, 3 } | Sets may be unified using the + operator (∪ in set algebra). | | { 1, 2.0 } + { 2, 3 } | { 1, 2.0, 3 } | Integers, doubles, and timestamps are merged when unifying sets. | | { 1, 2 } + { 2, 3 } + { 4 } | { 1, 2, 3, 4 } | Unions may be chained. | | { 1, 2 } + {} | { 1, 2 } | Unification with empty set has no effect on the original set. | | { 1, 2 } + { "2", "3" } | { 1, 2, "2", "3" } | Strings and numbers are handled as different values. | #### Difference | Expression | Result | Comment | | ----------------------------- | -------- | ------------------------------------------------------------------------------- | | { 1, 2 } - { 2, 3 } | { 1 } | Set difference may be obtained using the \- operator (operator is set algebra). | | { 1, 2 } - { 2.0, 3.0 } | { 1 } | Integers, doubles, and timestamps are considered equal if they equal in values. | | { 1, 2 } - {} | { 1, 2 } | Subtracting an empty set has no effect. | | { 1, 2 } - { 1 } - { 2 } | {} | Chaining of set subtractions works from left to rights. | | { 1, 2 } - ({ 1, 2 } - { 2 }) | { 2 } | Parenthesizing also works. | #### Intersection | Expression | Result | Comment | | --------------------------------- | ------- | ------------------------------------------------------------------------------- | | { 1, 2 } & { 2, 3 } | { 2 } | Set intersection may be obtained using the & operator. | | { 1, 2 } & { 2.0, 3.0 } | { 2 } | Integers, doubles, and timestamps are considered equal if they equal in values. | | { 1, 2 } & {"1", "2"} | {} | Strings and numbers are handled as different values. | | {"a", { 1, 2 }} & {"b", { 1, 2 }} | {{1,2}} | Works with subsets. | #### Symmetric Difference | Expression | Result | Comment | | --------------------------------- | ---------------- | ------------------------------------------------------------------------------- | | { 1, 2 } / { 2, 3 } | { 1, 3 } | Symmetric difference of sets may be obtained using the / operator. | | { 1, 2 } / { 2.0, 3.0 } | { 1, 3 } | Integers, doubles, and timestamps are considered equal if they equal in values. | | { 1, 2 } / {"1", "2"} | {1, 2, "1", "2"} | Strings and numbers are handled as different values. | | {"a", { 1, 2 }} / {"b", { 1, 2 }} | {"a", "b"} | Works with subsets. | ### Arrays #### Notation | Expression | Result | Comment | | ------------------------------ | --------------------------------------------- | ------- | | \[\] | Empty array. | | | \[1, 2, 3\] | Array containing three integers. | | | \[1, 2.0, false, "foo", null\] | Arrays may contain values of different types. | | | \[\[1,2\], \[2,3\]\] | Arrays may be nested. | | #### Value Containment | Expression | Result | Comment | | ---------------------- | ------ | ------------------------------------------------------------------------------------------ | | 2 in \[ 1, 2, 3 \] | true | Using the in operator, you may test whether a value is contained in a given array. | | 4 not in \[ 1, 2, 3 \] | true | The in operator may be negated for better readability. | | 2.0 in \[ 1, 2, 3 \] | true | There is no difference between integers, doubles, and timestamps when testing containment. | | "2" in \[ 1, 2, 3 \] | false | There is a difference between numbers and strings. | #### Comparison | Expression | Result | Comment | | ------------------------ | ------ | ------------------------------------------------------------------ | | \[ 1, 2 \] == \[ 1, 2 \] | true | \== tests whether two arrays are identical. | | \[ 1, 2 \] != \[ 1, 2 \] | false | != tests whether two arrays are different. | | \[ 1, 2 \] != \[ 2, 1 \] | true | Order of the elements must be the same in both arrays for equality | #### Concatenation | Expression | Result | Comment | | ------------------------------ | ---------------- | ----------------------------------------------------------------- | | \[ 1, 2 \] + \[ 3, 4 \] | \[ 1, 2, 3, 4 \] | Arrays may be concatenated using the + operator. | | \[ 1 \] + \[ 2, 3 \] + \[ 4 \] | \[ 1, 2, 3, 4 \] | Concatenations may be chained. | | \[ 1, 2 \] + \[\] | \[ 1, 2 \] | Concatenating an empty array has no effect on the original array. | #### Indexing and Slicing | Expression | Result | Comment | | -------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | \[ "a", "b", "c", "d" \]\[1\] | "b" | Value can be accessed by their index (starting from 0). | | \[ "a", "b", "c", "d" \]\[10\] | null | Requesting an index outside the array boundaries results in _null_. | | \[ "a", "b", "c", "d" \]\[-1\] | "d" | Negative indices are interpreted as counting from the end of the array. \-1 therefore means the last element. | | \[ "a", "b", "c", "d" \]\[1:3\] | \["b", "c"\] | It is possible to get a sub-array between two indices | | \[ "a", "b", "c", "d" \]\[1:\] | \["b", "c", "d"\] | If the second index is omitted, all elements until the end of the array are returned. | | \[ "a", "b", "c", "d" \]\[1::2\] | \["b", "d"\] | Size of step can be provided to only take every n-th element. | | \[ "a", "b", "c", "d" \]\[::-3\] | \["d", "a"\] | Size of step can be negative. If first index is omitted, the slice begins with the last element. If the second index is omitted, the slice goes until the first element (inclusive). | ### Logical Operators #### Negation (NOT) | Expression | Comment | | -------------- | ---------- | | not 'a' == 'b' | 'a' != 'b' | | not 'a' > 'b' | 'a' <= 'b' | | not true | false | | not false | true | Implicit conversion to boolean (for advanced uses only!): | Expression | Result | Comment | | ----------- | ------ | ----------------------------- | | not -1 | false | Negative numbers are truthy. | | not 0 | true | Zero numbers are falsy. | | not 1.23 | false | Positive numbers are truthy. | | not "" | true | Empty strings are falsy. | | not "foo" | false | Non-empty strings are truthy. | | not {} | true | Empty sets are falsy. | | not {1,2,3} | false | Non-empty sets are truthy. | | not null | true | null is falsy. | #### Disjunction (OR) | Expression | a | b | c | Result | Comment | | ---------------------- | - | - | - | ------ | ---------------------------------------------------------------- | | 'a' > 'b' or 'a' > 'c' | 1 | 2 | 3 | false | If both operands are false, false is returned. | | 'a' > 'b' or 'a' > 'c' | 2 | 1 | 3 | true | If at least one of boolean operands is true, the result is true. | | 'a' > 'b' or 'a' > 'c' | 2 | 3 | 1 | true | If at least one of boolean operands is true, the result is true. | | 'a' > 'b' or 'a' > 'c' | 3 | 1 | 2 | true | If- both the operands are true, the result is true. | Advanced uses: Implicit conversion to boolean. | Expression | Result | Comment | | -------------- | ------ | -------------------------------------------------------------- | | "foo" or "bar" | "foo" | If the first operand truthy, it is returned. | | "" or false | false | If the first operand is falsy, the second operand is returned. | | false or "" | "" | If the first operand is falsy, the second operand is returned. | #### Conjunction (AND) | Expression | a | b | c | Result | Comment | | ----------------------- | - | - | - | ------ | ------------------------------------------------------------------ | | 'a' > 'b' and 'a' > 'c' | 1 | 2 | 3 | false | If both operands are false, false is returned. | | 'a' > 'b' and 'a' > 'c' | 2 | 1 | 3 | false | If at least one of boolean operands is false, the result is false. | | 'a' > 'b' and 'a' > 'c' | 2 | 3 | 1 | false | If at least one of boolean operands is false, the result is false. | | 'a' > 'b' and 'a' > 'c' | 3 | 1 | 2 | true | If both the operands are true, the result is true. | Advanced uses: Implicit conversion to boolean. | Expression | Result | Comment | | --------------- | ------ | ------------------------------------------------------------ | | "foo" and "bar" | "bar" | If the first operand truthy, the second operand is returned. | | "" and false | "" | If the first operand is falsy, it is returned. | | false and "" | false | If the first operand is falsy, it is returned. | ### Conditional Operator | Expression | a | b | Result | Comment | | ----------------------------------------------------------------- | -- | - | ------ | ---------------------------------------------------------- | | if 'a' > 'b' then "foo" else "bar" | 10 | 5 | "foo" | then\-value is returned if the condition is satisfied. | | if 'a' < 'b' then "foo" else "bar" | 10 | 5 | "bar" | else\-value is returned if the condition is not satisfied. | | if 'a' < 'b' then "foo" | | | error | else clause must always be present. | | if 'a' < 'b' then "foo" else (if 'a' > 'b' then "bar" else "bah") | 5 | 5 | "bah" | if\-else statements may be nested using parentheses. | | Expression | Result | Comment | | -------------------------------- | ------ | ----------------------------- | | if -1 then "foo" else "bar" | "foo" | Negative numbers are truthy. | | if 0 then "foo" else "bar" | "bar" | Zero numbers are falsy. | | if 1.23 then "foo" else "bar" | "foo" | Positive numbers are truthy. | | if "" then "foo" else "bar" | "bar" | Empty strings are falsy. | | if "bah" then "foo" else "bar" | "foo" | Non-empty strings are truthy. | | if {} then "foo" else "bar" | "bar" | Empty sets are falsy | | if {1,2,3} then "foo" else "bar" | "foo" | Non-empty sets are truthy. | | if null then "foo" else "bar" | "bar" | null is falsy. | ## Comments in ReQL For more complex expressions, you might want to add comments to your ReQL code as documentation. ReQL uses C-style comments, `//` for single-line comments, and `/* */` for multi-line comments: ReQL ``` // explain why you want to only show thrillers "Thriller" in 'Genres' ``` ReQL ``` [ "apple", "banana", /* This is a multi-line comment explaining why we include "cherry" in this list. */ "cherry" ] ``` --- # ReQL Functions > Source: https://docs.recombee.com/reql_functions > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Quick Overview](#quick-overview) * [Context Functions](#context-functions) * [Context Item Function](#context-item-function) * [Definition](#context-item-function-definition) * [Examples](#context-item-function-examples) * [Example 1](#context-item-function-example-1) * [Example 2 - Up-Sell](#context-item-function-example-2-up-sell) * [Context User Function](#context-user-function) * [Definition](#context-user-function-definition) * [Example](#context-user-function-example) * [Context Segment Function](#context-segment-function) * [Definition](#context-segment-function-definition) * [Examples](#context-segment-function-examples) * [Miscellaneous Functions](#miscellaneous-functions) * [Now](#now) * [Definition](#now-definition) * [Example](#now-example) * [Random](#random) * [Definition](#random-definition) * [Size](#size) * [Definition](#size-definition) * [Examples](#size-examples) * [Item Values](#item-values) * [Definition](#item-values-definition) * [Example](#item-values-example) * [Reduce](#reduce) * [Definition](#reduce-definition) * [Example](#reduce-example) * [Lambda Functions](#lambda-functions) * [Map](#map) * [Definition](#map-definition) * [Examples](#map-examples) * [Select](#select) * [Definition](#select-definition) * [Examples](#select-examples) * [Exists](#exists) * [Definition](#exists-definition) * [Examples](#exists-examples) * [Type Conversion Functions](#type-conversion-functions) * [Boolean Conversion Function](#boolean-conversion-function) * [Definition](#boolean-conversion-function-definition) * [Examples](#boolean-conversion-function-examples) * [Number Conversion Function](#number-conversion-function) * [Definition](#number-conversion-function-definition) * [Examples](#number-conversion-function-examples) * [String Conversion Function](#string-conversion-function) * [Definition](#string-conversion-function-definition) * [Examples](#string-conversion-function-examples) * [Timestamp Conversion Function](#timestamp-conversion-function) * [Definition](#timestamp-conversion-function-definition) * [Examples](#timestamp-conversion-function-examples) * [Math Functions](#math-functions) * [Max](#max) * [Definition](#max-definition) * [Example](#max-example) * [Min](#min) * [Definition](#min-definition) * [Example](#min-example) * [Avg](#avg) * [Definition](#avg-definition) * [Example](#avg-example) * [Round](#round) * [Definition](#round-definition) * [Example](#round-example) * [Floor](#floor) * [Definition](#floor-definition) * [Example](#floor-example) * [Ceil](#ceil) * [Definition](#ceil-definition) * [Example](#ceil-example) * [Absolute Value](#absolute-value) * [Definition](#absolute-value-definition) * [Example](#absolute-value-example) * [Square Root](#square-root) * [Definition](#square-root-definition) * [Example](#square-root-example) * [Power Function](#power-function) * [Definition](#power-function-definition) * [Example](#power-function-example) * [Logarithm](#logarithm) * [Definition](#logarithm-definition) * [Example](#logarithm-example) * [String Functions](#string-functions) * [Convert to Upper Case](#convert-to-upper-case) * [Definition](#convert-to-upper-case-definition) * [Example](#convert-to-upper-case-example) * [Convert to Lower Case](#convert-to-lower-case) * [Definition](#convert-to-lower-case-definition) * [Example](#convert-to-lower-case-example) * [Split String](#split-string) * [Definition](#split-string-definition) * [Example](#split-string-example) * [Interactions Listing Functions](#interactions-listing-functions) * [User Interactions](#user-interactions) * [Definition](#user-interactions-definition) * [Example](#user-interactions-example) * [Interactions Statistics Functions](#interactions-statistics-functions) * [Number of Bookmarks](#number-of-bookmarks) * [Definition](#number-of-bookmarks-definition) * [Example](#number-of-bookmarks-example) * [Number of Detail Views](#number-of-detail-views) * [Definition](#number-of-detail-views-definition) * [Example](#number-of-detail-views-example) * [Number of Purchases](#number-of-purchases) * [Definition](#number-of-purchases-definition) * [Example](#number-of-purchases-example) * [Number of Ratings](#number-of-ratings) * [Definition](#number-of-ratings-definition) * [Example](#number-of-ratings-example) * [Item Segments Handling Functions](#item-segments-handling-functions) * [Items in a Segment](#items-in-a-segment) * [Definition](#segment-items-definition) * [Example](#segment-items-example) * [Item Segments of an Item](#item-segments-of-an-item) * [Definition](#item-segments-definition) * [Example](#item-segments-example) * [Geographical Functions](#geographical-functions) * [Earth Distance](#earth-distance) * [Definition](#earth-distance-definition) * [Example](#earth-distance-example) * [Geographical Point](#geographical-point) * [Geographical Polygon](#geographical-polygon) * [Definition](#geographical-polygon-definition) * [Example](#geographical-polygon-example) * [Geographical Radius](#geographical-radius) * [Definition](#geographical-radius-definition) * [Example](#geographical-radius-example) * [Geographical Containment](#geographical-containment) * [Examples](#geographical-containment-examples) # ReQL Functions Functions may be used to enhance your [ReQL](/reql) queries – for example[up-sell](/reql_functions#reql-func-context-item) or [getting nearby items](/reql_functions#reql-func-earth-distance) can be achieved easily by functions. There are various functions like [math functions](/reql_functions#reql-func-math) (rounding, computing square root …), [string functions](/reql_functions#reql-func-string-functions) (converting case), function for [getting size of set or string](/reql_functions#reql-func-size), [getting current timestamp](/reql_functions#reql-func-timestamp), functions for [conversions between types](/reql_functions#reql-func-type-conversion) (for example conversion between date in a text representation and timestamp) or even [lambda functions](/reql_functions#reql-func-lambda). If you are missing some function that you would like to use, please let us know. ReQL function can take arguments and returns a single value. Arguments are placed between parentheses and are separated by commas – for example computing base 2 logarithm of 8 looks like this: `log(8,2)`. If the function takes no arguments the parentheses may be omitted (for e.g. `now`). If the function is given wrong number of arguments, or the arguments have unsupported type, an error is produced. If any of the arguments is null, then result is also a null value. ## Quick Overview **[Context Functions](#context-functions)** | Name | Description | Example | | ---------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------- | | [context\_item](#reql-func-context-item) | Retrieves property value of the item, that is currently viewed by the user. | context\_item\["price"\] | | [context\_user](#reql-func-context-user) | Retrieves property value of the user, that is about to obtain the recommendations. | context\_user\["country"\] | | [context\_segment](#reql-func-context-segment) | Retrieves the Segment on which the recommendations are based. | context\_segment\["segmentId"\] | **[Miscellaneous Functions](#miscellaneous-functions)** | Name | Description | Example | | -------------------------------------- | ------------------------------------------------------------ | ----------------------------------------- | | [now](#reql-func-now) | Returns current timestamp | now() > timestamp("2015-06-24T17:35:50Z") | | [random](#reql-func-random) | Returns a random number between 0 and 1 | 1\>=random()>=0 | | [size](#reql-func-size) | Returns the length of a string or number of objects in a set | size("Recombee") == 8 | | [item\_values](#reql-func-item-values) | Returns property values of a particular item as a dictionary | item\_values("item-42")\["description"\] | | [reduce](#reql-func-reduce) | Reduces a set into a single value using an operator | reduce("+", {1, 2, 3}) == 6 | **[Lambda Functions](#lambda-functions)** | Name | Description | Example | | --------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------- | | [map](#reql-func-map) | Applies the lambda expression to every member of a set | map(lambda 'x': 2\*'x', {1, 2, 3}) == {2, 4, 6} | | [select](#reql-func-select) | Returns only those values of input set for which the lambda expression returns true | select(lambda 'x': 'x' \> 5, {10, 2, 13, 1}) == {10, 13} | | [exists](#reql-func-exists) | Returns _true_ if lambda expression is satisfied for at least one element of the input set | exists(lambda 'x': 'x' \> 5, {2, 13, 4}) | **[Type Conversion Functions](#type-conversion-functions)** | Name | Description | Example | | --------------------------------- | ---------------------------------- | ---------------------------------------------------------- | | [boolean](#reql-func-boolean) | Converts the argument to boolean | boolean("") == False | | [number](#reql-func-number) | Converts the argument to number | number("456") == 456 | | [string](#reql-func-string) | Converts the argument to string | string(123) == "123" | | [timestamp](#reql-func-timestamp) | Converts the argument to timestamp | timestamp("2015-06-25T11:08:44Z") == timestamp(1435230524) | **[Math Functions](#math-functions)** | Name | Description | Example | | ------------------------- | --------------------------------------------------------------------- | ----------------------- | | [max](#reql-func-max) | Returns the maximum of _n_ arguments | max(147,42,81.9) == 147 | | [min](#reql-func-min) | Returns the minimum of _n_ arguments | min(147,42,81.9) == 42 | | [avg](#reql-func-avg) | Returns the average of _n_ numbers | avg(2, 4) == 3 | | [round](#reql-func-round) | Returns closest integer | round(4.5) == 5 | | [floor](#reql-func-floor) | Returns largest preceding integer | floor(4.3) == 4 | | [ceil](#reql-func-ceil) | Returns smallest following integer | ceil(4.3) == 5 | | [abs](#reql-func-abs) | Returns non-negative value of the argument without regard to its sign | abs(-4.3) == 4.3 | | [sqrt](#reql-func-sqrt) | Returns the square root of the argument | sqrt(4) == 2 | | [pow](#reql-func-pow) | Returns 𝑓𝑖𝑟𝑠𝑡\_𝑎𝑟𝑔𝑢𝑚𝑒𝑛𝑡𝑠𝑒𝑐𝑜𝑛𝑑\_𝑎𝑟𝑔𝑢𝑚𝑒𝑛𝑡 | pow(10,3) == 1000 | | [log](#reql-func-log) | Returns the logarithm of the argument | log(1000) == 3 | **[String Functions](#string-functions)** | Name | Description | Example | | ------------------------- | -------------------------------------------------- | ---------------------------------------------------- | | [upper](#reql-func-upper) | Converts all letters to the capital letters | upper("AbCdefG") == "ABCDEFG" | | [lower](#reql-func-lower) | Converts all letters to the small letters | lower("AbCdefG") == "abcdefg | | [split](#reql-func-split) | Splits a string into sub-strings using a separator | split("abc,def,ghi", ",") == \["abc", "def", "ghi"\] | **[Interactions Listing Functions](#interactions-listing-functions)** | Name | Description | Example | | -------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------ | | [user\_interactions](#reql-func-user-interactions) | Returns list of interactions by a particular user | user\_interactions(context\_user\["userId"\], {"purchases"}) | **[Interactions Statistics Functions](#interactions-statistics-functions)** | Name | Description | Example | | ------------------------------------------------------------ | --------------------------------------------- | --------------------------------------------- | | [num\_item\_bookmarks](#reql-func-num-item-bookmarks) | Returns the number of bookmarks of an item | num\_item\_bookmarks('itemId') < 10 | | [num\_item\_detail\_views](#reql-func-num-item-detail-views) | Returns the number of detail views of an item | num\_item\_detail\_views('itemId') < 10 | | [num\_item\_purchases](#reql-func-num-item-purchases) | Returns the number of purchases of an item | num\_item\_purchases('itemId') < 10 | | [num\_item\_ratings](#reql-func-num-item-ratings) | Returns the number of ratings of an item | num\_item\_ratings('itemId', "negative") < 10 | **[Item Segments Handling Functions](#item-segments-handling-functions)** | Name | Description | Example | | ------------------------------------------ | ------------------------------------------- | ------------------------------------------------ | | [segment\_items](#reql-func-segment-items) | Get items in a Segment | 'itemId' in segment\_items("genres", "thriller") | | [item\_segments](#reql-func-item-segments) | Get Item Segments to which the item belongs | "thriller" in item\_segments("genres", 'itemId') | **[Geographical Functions](#geographical-functions)** | Name | Description | Example | | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | | [earth\_distance](#reql-func-earth-distance) | Returns the orthodromic distance between two points (given as their latitude and longitude in degrees) in meters | earth\_distance(50.075538,14.437800,52.520007,13.404954) < 282000 | | [geo\_polygon](#reql-func-geo-polygon) | Creates a spherical polygon represented by points with geographical coordinates | geo\_polygon(\[\[40.800, -73.957\], \[40.767, -73.981\], \[40.764, -73.972\], \[40.796, -73.949\]\]) | | [geo\_radius](#reql-func-geo-radius) | Creates a spherical cap represented by a center with geographical coordinates and a radius in km | geo\_radius(\[40.689167, -74.044444\], 10) | ## Context Functions | Name | Description | Example | | ---------------------------------------------- | ---------------------------------------------------------------------------------- | ------------------------------- | | [context\_item](#reql-func-context-item) | Retrieves property value of the item, that is currently viewed by the user. | context\_item\["price"\] | | [context\_user](#reql-func-context-user) | Retrieves property value of the user, that is about to obtain the recommendations. | context\_user\["country"\] | | [context\_segment](#reql-func-context-segment) | Retrieves the Segment on which the recommendations are based | context\_segment\["segmentId"\] | ### Context Item Function Context item function is used in [Recommend Items to Item](/api#request-recommend-items-to-item) and [Recommend Item Segments to Item](/api#request-recommend-item-segments-to-item)for retrieving property values of the item, that is currently viewed by the user. #### Definition ``` context_item[property_name] ``` | Key | Type | Meaning | | -------------- | ------ | ------------------------------------------------------------------------------------------------ | | property\_name | string | Name of property to be retrieved. If property of this name does not exist, an error is produced. | _(Note that Context item function is a bit special function – it takes no arguments and returns a map `name of property -> value` representing the context item. `propertyname` placed in square brackets is the key to this map.)_ #### Examples Consider following sample items. | name String | price Number | category String | | ------------------- | ------------ | --------------- | | "television-42" | 369 | "television" | | "television-49" | 449 | "television" | | "remote-control-13" | 25 | remote-control | ##### Example 1 Suppose that the user is currently viewing `television-42`. Then the following expression returns `369`, because that is the price of the context item. ``` context_item["price"] ``` ##### Example 2 - Up-Sell Suppose that the user is currently viewing `television-42`. You can recommend him products from the same category with higher price. The _filter_ would look like this: ``` 'price' > context_item["price"] and 'category' == context_item["category"] ``` Considering the sample items above, only `television-49` will pass the filter. If you don’t want to be so restrictive about the cheaper products, you shall use _booster_ instead of _filter_ and boost the products with higher price. The _booster_ could look like this: ``` if 'category' != context_item["category"] then 0.1 else if 'price' > context_item["price"] then 1 else 0.5 ``` ### Context User Function Context user function is used for retrieving property values of the user that the recommendations are for. #### Definition ``` context_user[property_name] ``` | Key | Type | Meaning | | -------------- | ------ | ------------------------------------------------------------------------------------------------ | | property\_name | string | Name of property to be retrieved. If property of this name does not exist, an error is produced. | _(Note that Context user function is a bit special function – it takes no arguments and returns a map `name of property -> value` representing the context user. `propertyname` placed in square brackets is the key to this map.)_ #### Example Consider following sample users, which have specified languages they understand: | userId String | languages Set | | ------------- | -------------- | | "user-27" | \["EN"\] | | "user-29" | \["EN", "FR"\] | And sample items, which are some movies: | itemId String | language String | | ------------------------------------- | --------------- | | "Pulp Fiction" | "EN" | | "Le fabuleux destin d Amelie Poulain" | "FR" | | "Fight Club" | "EN" | | "Kolja" | "CS" | Suppose that I want to recommend movies to users, but only movies that the users can understand. I can use the following filter: ``` 'language' in context_user["languages"] ``` For _user-27_ (which can speak only english) _Pulp Fiction_ or _Fight Club_ can be recommended. For _user-29_ (which can speak english and french) _Pulp Fiction, Fight Club_ or _Le fabuleux destin d Amelie Poulain_ can be recommended. ### Context Segment Function Context Segment function is used in [Recommend Item Segments to Item Segment](/api#request-recommend-item-segments-to-item-segment)for retrieving the [Item Segment](/segmentations) to which is being recommended. #### Definition ``` context_segment[property_name] ``` | Key | Type | Meaning | | -------------- | ------ | ------------------------------------------------------------------------ | | property\_name | string | Name of property to be retrieved. Currently only segmentId is supported. | #### Examples ``` // If the context Segment is "fairy tales" // then explicitly disallow "tabloid news" Segment to be ever recommended if context_segment["segmentId"] == "fairy tales" then 'segmentId' != "tabloid news" else true ``` ## Miscellaneous Functions | Name | Description | Example | | -------------------------------------- | ------------------------------------------------------------ | ----------------------------------------- | | [now](#reql-func-now) | Returns current timestamp | now() > timestamp("2015-06-24T17:35:50Z") | | [random](#reql-func-random) | Returns a random number between 0 and 1 | 1\>=random()>=0 | | [size](#reql-func-size) | Returns the length of a string or number of objects in a set | size("Recombee") == 8 | | [item\_values](#reql-func-item-values) | Returns property values of a particular item as a dictionary | item\_values("item-42")\["description"\] | | [reduce](#reql-func-reduce) | Reduces a set into a single value using an operator | reduce("+", {1, 2, 3}) == 6 | ### Now Returns current timestamp. #### Definition ``` now() ``` #### Example The following expression results in `true`: ``` now() > timestamp("2015-06-24T17:35:50Z") ``` ### Random Returns a random number between 0 and 1. #### Definition ``` random() ``` ### Size Returns the length of a string or number of objects in a set. #### Definition ``` size(value) ``` | Argument | Type | | -------- | ---------- | | value | string set | #### Examples All the following expressions result in `true`: ``` size("Recombee") == 8 size("") == 0 size({"abc", 4, {} } ) == 3 // Objects in nested set are not counted size({ {1,2,3} } ) == 1 ``` ### Item Values Returns property values of a particular item as a dictionary. #### Definition ``` item_values(item_id) ``` | Argument | Type | Meaning | | -------- | ------ | ------------- | | value | string | ID of an item | #### Example ``` // Returns value of property "category" for item with ID "item-42" item_values("item-42")["category"] ``` ### Reduce Reduces a set into a single value using an operator. #### Definition ``` reduce(operator, input_set, initial_value) ``` | Argument | Type | Meaning | | -------------- | ---------------------------------- | --------------------------------------------------------------- | | operator | string | One of +, \*, &, and, or | | input\_set | set | Set that will be reduced | | initial\_value | Same type as members of input\_set | _Optional._ Value used as left operand for the first operation. | #### Example All the following expressions result in `true`: ``` reduce("+", {2, 3, 4}) == 9 reduce("+", {2, 3, 4}, 1) == 10 reduce("*", {2, 3, 4}) == 24 reduce("and", {true, false, true}) == false reduce("or", {true, false, true}) == true ``` ## Lambda Functions ReQL Lambda functions can be used for computations on sets of values. Lambda functions take two arguments: a lambda expression and a set. Lambda functions evaluate the lambda expression on every element of the set. The lambda expression can be any valid ReQL expression, and therefore can contain for example item properties or functions. | Name | Description | Example | | --------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------- | | [map](#reql-func-map) | Applies the lambda expression to every member of a set | map(lambda 'x': 2\*'x', {1, 2, 3}) == {2, 4, 6} | | [select](#reql-func-select) | Returns only those values of input set for which the lambda expression returns true | select(lambda 'x': 'x' \> 5, {10, 2, 13, 1}) == {10, 13} | | [exists](#reql-func-exists) | Returns _true_ if lambda expression is satisfied for at least one element of the input set | exists(lambda 'x': 'x' \> 5, {2, 13, 4}) | ### Map Map applies the expression to every element and returns the result as set. #### Definition ``` map(lambda 'x': EXPRESSION, input_set) ``` | Argument | Type | | ----------------- | ----------------- | | lambda expression | lambda expression | | input\_set | set | #### Examples All the following expressions result in `true`: ``` // Multiplies every element of the input set by two map(lambda 'x': 2\*'x', {1, 2, 3}) == {2, 4, 6} // Converts every element from the input set to number map(lambda 'x': number('x'), {"1", "2", "3"}) == {1, 2, 3} // Map applied on empty set is empty set map(lambda 'x': 'x'*'x', {}) == {} ``` ### Select Select returns only those values of input set for which the lambda expression returns true. The lambda expression have to return a boolean. #### Definition ``` select(lambda 'x': EXPRESSION, input_set) ``` | Argument | Type | | ----------------- | ----------------------------------- | | lambda expression | lambda expression returning boolean | | input\_set | set | #### Examples All the following expressions result in `true`: ``` // Selects only the values that are greater than five select(lambda 'x': 'x'>5, {10, 2, 13, 8, 3, 4, 7}) == {10, 13, 8, 7} // ''true'' is satisfied for every element select(lambda 'x': true , {1, "a", {}}) == {1, "a", {}} // Selects only the strings, that are lowercase select(lambda 'x': lower('x') == 'x', {"HELLO", "hello", "Hello", "a"}) == {"hello", "a"} // No element represents a number with value less then 100 select(lambda 'x': number('x')<100 , {"125", "123", "251"}) == {} ``` ### Exists Exists returns _true_ if lambda expression returns _true_ for at least one element of the input set. Otherwise returns _false_. `exists(lambda 'x': ...)` can be though as shorthand for `size(select(lambda 'x': ...)) > 0.` #### Definition ``` exists(lambda 'x': EXPRESSION, input_set) ``` | Argument | Type | | ----------------- | ----------------------------------- | | lambda expression | lambda expression returning boolean | | input\_set | set | #### Examples All the following expressions result in `true`: ``` // Returns true, as 13 > 5 exists(lambda 'x': 'x'>5, {2, 13, 4}) // None of the elements is larger than 5 exists(lambda 'x': 'x'>5, {2, 1, 4}) == false ``` ## Type Conversion Functions | Name | Description | Example | | --------------------------------- | ---------------------------------- | ---------------------------------------------------------- | | [boolean](#reql-func-boolean) | Converts the argument to boolean | boolean("") == False | | [number](#reql-func-number) | Converts the argument to number | number("456") == 456 | | [string](#reql-func-string) | Converts the argument to string | string(123) == "123" | | [timestamp](#reql-func-timestamp) | Converts the argument to timestamp | timestamp("2015-06-25T11:08:44Z") == timestamp(1435230524) | ### Boolean Conversion Function Boolean conversion function is used for getting the truth value of any expression. #### Definition ``` boolean(value_to_be_converted) ``` | Argument | Type | Meaning | | ------------------------ | -------- | ------------------------------------ | | value\_to\_be\_converted | any type | Value to be converted into a boolean | #### Examples All the following expressions result in `true`: ``` boolean("Recombee") == true boolean("") == False boolean(42) == true boolean(0) == False boolean({""}) == true boolean({}) == False ``` ### Number Conversion Function Number conversion function is used for converting strings, booleans and timestamps into numbers. #### Definition ``` number(value_to_be_converted) ``` | Argument | Type | Meaning | | ------------------------ | ------------------------------- | ----------------------------------- | | value\_to\_be\_converted | string boolean timestamp number | Value to be converted into a number | #### Examples All the following expressions result in `true`: ``` number("456") == 456 number("1E4") == 10000 number(true) == 1 // String "Recombee" cannot be converted into a number number("Recombee") == null ``` ### String Conversion Function String conversion function is used for converting numbers, booleans, sets and timestamps into their textual representations. #### Definition ``` string(value_to_be_converted [, date_time_format (only if value_to_be_converted is a timestamp)]) ``` | Argument | Type | Meaning | | ------------------------ | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | value\_to\_be\_converted | string boolean timestamp set number | Value to be converted into a string | | date\_time\_format | string | _(Optional and only if value\_to\_be\_converted is a timestamp)_ String specifying the format of textual representation of the timestamp after conversion. [See supported date and time format specifiers](/time_specifiers). If date\_time\_format is not specified, [ISO 8601](https://en.wikipedia.org/?title=ISO_8601) format is used. | #### Examples All the following expressions result in `true`: ``` string(123) == "123" string(true) == "true" // Suppose that 'time' is a timestamp with value 1435230524. No format string is specified, so ISO 8601 is used. string('time') == "2015-06-25T11:08:44Z" // Suppose that 'time' is a timestamp with value 1435230524. string('time', "%d.%m.%Y %H:%M:%S") == "25.06.2015 11:08:44" ``` ### Timestamp Conversion Function Timestamp conversion function is used for converting numbers and strings into timestamps. #### Definition ``` timestamp(value_to_be_converted [, date_time_format (only if value_to_be_converted is a string) ] ) ``` | Argument | Type | Meaning | | ------------------------ | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | value\_to\_be\_converted | string number timestamp | Value to be converted into a string | | date\_time\_format | string | _(Optional and only if value\_to\_be\_converted is a string)_ String specifying the format of value\_to\_be\_converted. [See supported date and time format specifiers](/time_specifiers). If date\_time\_format is not specified, [ISO 8601](https://en.wikipedia.org/?title=ISO_8601) format is used. | #### Examples All the following expressions result in `true`: ``` // No format string is specified, so ISO 8601 is used. timestamp("2015-06-25T11:08:44Z") == timestamp(1435230524) timestamp("25.06.2015 11:08:44", "%d.%m.%Y %H:%M:%S") == timestamp(1435230524) ``` ## Math Functions | Name | Description | Example | | ------------------------- | --------------------------------------------------------------------- | ----------------------- | | [max](#reql-func-max) | Returns the maximum of _n_ arguments | max(147,42,81.9) == 147 | | [min](#reql-func-min) | Returns the minimum of _n_ arguments | min(147,42,81.9) == 42 | | [avg](#reql-func-avg) | Returns the average of _n_ numbers | avg(2, 4) == 3 | | [round](#reql-func-round) | Returns closest integer | round(4.5) == 5 | | [floor](#reql-func-floor) | Returns largest preceding integer | floor(4.3) == 4 | | [ceil](#reql-func-ceil) | Returns smallest following integer | ceil(4.3) == 5 | | [abs](#reql-func-abs) | Returns non-negative value of the argument without regard to its sign | abs(-4.3) == 4.3 | | [sqrt](#reql-func-sqrt) | Returns the square root of the argument | sqrt(4) == 2 | | [pow](#reql-func-pow) | Returns 𝑓𝑖𝑟𝑠𝑡\_𝑎𝑟𝑔𝑢𝑚𝑒𝑛𝑡𝑠𝑒𝑐𝑜𝑛𝑑\_𝑎𝑟𝑔𝑢𝑚𝑒𝑛𝑡 | pow(10,3) == 1000 | | [log](#reql-func-log) | Returns the logarithm of the argument | log(1000) == 3 | ### Max Returns the maximum of n arguments. Alternatively, if you provide a single set/array, it returns the maximum of its values. The arguments must be comparable using `>`. #### Definition ``` max(val1, val2, [val3, val4 ...]) max(set/array value) ``` | Argument | Type | | -------- | ---- | | val1 | any | | val2 | any | | ... | | #### Example ``` max(147,42,81.9) == 147 max("abc", "bac") == "bac" max({5}, {}) == {5} max({147,42,81.9}) == 147 ``` ### Min Returns the minimum of _n_ arguments. Alternatively, if you provide a single set/array, it returns the minimum of its values. The arguments must be comparable using `<`. #### Definition ``` min(val1, val2, [val3, val4 ...]) min(set/array value) ``` | Argument | Type | | -------- | ---- | | val1 | any | | val2 | any | | ... | | #### Example ``` min(147,42,81.9) == 42 min("abc", "bac") == "abc" min({5}, {}) == {} min({147,42,81.9}) == 42 ``` ### Avg Returns the average of _n_ numbers. Alternatively, if you provide a single set/array of values, it returns the average of its values. #### Definition ``` avg(val1, val2, [val3, val4 ...]) avg(set/array value) ``` | Argument | Type | | -------- | ---- | | val1 | any | | val2 | any | | ... | | #### Example ``` avg(2, 1, 5) == 4 avg({2, 1, 5}) == 4 ``` ### Round #### Definition ``` round(x) ``` | Argument | Type | Meaning | | ---------------- | ------ | -------------------- | | x | number | | | **Return value** | number | Integer closest to x | #### Example All the following expressions result in `true`: ``` round(4.3) == 4 round(4.5) == 5 ``` ### Floor #### Definition ``` floor(x) ``` | Argument | Type | Meaning | | ---------------- | ------ | --------------------------- | | x | number | | | **Return value** | number | Largest integer preceding x | #### Example All the following expressions result in `true`: ``` floor(4.3) == 4 floor(4.5) == 4 ``` ### Ceil #### Definition ``` ceil(x) ``` | Argument | Type | Meaning | | ---------------- | ------ | ---------------------------- | | x | number | | | **Return value** | number | Smallest integer following x | #### Example All the following expressions result in `true`: ``` ceil(4.3) == 5 ceil(4.5) == 5 ``` ### Absolute Value #### Definition ``` abs(x) ``` | Argument | Type | Meaning | | ---------------- | ------ | -------------------------------------------------- | | x | number | | | **Return value** | number | Non-negative value of x without regard to its sign | #### Example All the following expressions result in `true`: ``` abs(-4.3) == 4.3 abs(4.3) == 4.3 ``` ### Square Root #### Definition ``` sqrt(x) ``` | Argument | Type | Meaning | | ---------------- | ------------------- | ---------------------------- | | x | Non-negative number | | | **Return value** | number | Number 𝑎, such that 𝑎2\=𝑥 | #### Example All the following expressions result in `true`: ``` sqrt(4) == 2 // Square root is defined only for non-negative numbers sqrt(-16) == null ``` ### Power Function #### Definition ``` pow(base, exponent) ``` | Argument | Type | Meaning | | ---------------- | ------ | ------------------------------------------------------------ | | base | number | | | exponent | number | | | **Return value** | number | Base raised to the power exponent (𝑏𝑎𝑠𝑒𝑒𝑥𝑝𝑜𝑛𝑒𝑛𝑡) | #### Example All the following expressions result in `true`: ``` pow(10,3) == 1000 pow(5,-2) == 0.04 pow(-2,5) == -32 ``` ### Logarithm #### Definition ``` log(x [, base]) ``` | Argument | Type | Meaning | | ---------------- | ------------------- | ------------------------------------ | | x | Non-negative number | | | base | Non-negative number | _Optional._ Default base is decadic. | | **Return value** | number | Number 𝑦, such that 𝑏𝑎𝑠𝑒𝑦\=𝑥 | #### Example All the following expressions result in `true`: ``` log(1000) == 3 log(16,2) == 4 // Logarithm is defined only for non-negative numbers log(-2) == null ``` ## String Functions | Name | Description | Example | | ------------------------- | -------------------------------------------------- | ---------------------------------------------------- | | [upper](#reql-func-upper) | Converts all letters to the capital letters | upper("AbCdefG") == "ABCDEFG" | | [lower](#reql-func-lower) | Converts all letters to the small letters | lower("AbCdefG") == "abcdefg | | [split](#reql-func-split) | Splits a string into sub-strings using a separator | split("abc,def,ghi", ",") == \["abc", "def", "ghi"\] | ### Convert to Upper Case Converts all letters to the capital letters. #### Definition ``` upper(str) ``` | Argument | Type | | -------- | ------ | | str | string | #### Example All the following expressions result in `true`: ``` upper("AbCdefG") == "ABCDEFG" upper("7b&*#č汉字") == "7B&*#Č汉字" ``` ### Convert to Lower Case Converts all letters to small letters. #### Definition ``` lower(str) ``` | Argument | Type | | -------- | ------ | | str | string | #### Example All the following expressions result in `true`: ``` lower("AbCdefG") == "abcdefg" lower("7B&*#Č汉字") == "7b&*#č汉字" ``` ### Split String Splits a string into sub-strings using a separator. #### Definition ``` split(str, separator) ``` | Argument | Type | Meaning | | --------- | ------ | ------------------ | | str | string | String to be split | | separator | string | Separator | #### Example All the following expressions result in `true`: ``` split("abc,def,ghi", ",") == ["abc", "def", "ghi"] ``` ## Interactions Listing Functions Note These functions are not enabled by default due to higher resource consumption. Contact [support@recombee.com](mailto:support@recombee.com) if you need to enable them, and please specify the types of interactions needed in your request. | Name | Description | Example | | -------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------ | | [user\_interactions](#reql-func-user-interactions) | Returns list of interactions by a particular user | user\_interactions(context\_user\["userId"\], {"purchases"}) | ### User Interactions Returns a list of interactions by a particular user. These interactions are of given `interaction_types` and are ordered by timestamp from the oldest to the most recent. Each interaction is a dictionary with the following fields: ``` { "userId": string, "itemId": string, "timestamp": timestamp, "type": string } ``` #### Definition ``` user_interactions(user_id, interaction_types, num_interactions) ``` | Argument | Type | Meaning | | ------------------ | -------------------- | ------------------------------------------------------------------------ | | user\_id | string | Id of a user | | interaction\_types | set | [Interaction types](/api#user-item-interactions) that should be returned | | num\_interactions | Non negative integer | _Optional._ Return only that number of latest interactions. | #### Example ``` // Get IDs of items that the user purchased or viewed map(lambda 'it': 'it'["itemId"], user_interactions(context_user["userId"], {"detail_views", "purchases"})) // Returns true if the user consumed some content in French exists(lambda 'it': item_values('it'["itemId"])["language"] == "FR", user_interactions(context_user["userId"], {"purchases"})) ``` ## Interactions Statistics Functions Note These functions are not enabled by default due to higher resource consumption.. Contact[support@recombee.com](mailto:support@recombee.com) if you need to enable them. | Name | Description | Example | | ------------------------------------------------------------ | --------------------------------------------- | --------------------------------------------- | | [num\_item\_bookmarks](#reql-func-num-item-bookmarks) | Returns the number of bookmarks of an item | num\_item\_bookmarks('itemId') < 10 | | [num\_item\_detail\_views](#reql-func-num-item-detail-views) | Returns the number of detail views of an item | num\_item\_detail\_views('itemId') < 10 | | [num\_item\_purchases](#reql-func-num-item-purchases) | Returns the number of purchases of an item | num\_item\_purchases('itemId') < 10 | | [num\_item\_ratings](#reql-func-num-item-ratings) | Returns the number of ratings of an item | num\_item\_ratings('itemId', "negative") < 10 | ### Number of Bookmarks Returns number of bookmarks of an item specified by its ID. #### Definition ``` num_item_bookmarks(id) ``` | Argument | Type | Meaning | | -------- | ------ | ------------- | | id | string | ID of an item | #### Example ``` // Only items with less than 5 bookmarks pass the filter num_item_bookmarks('itemId') < 5 ``` ### Number of Detail Views Returns number of detail views of an item specified by its ID. #### Definition ``` num_item_detail_views(id) ``` | Argument | Type | Meaning | | -------- | ------ | ------------- | | id | string | ID of an item | #### Example ``` // Only items with less than 5 detail views pass the filter num_item_detail_views('itemId') < 5 ``` ### Number of Purchases Returns number of purchases of an item specified by its ID. You can use this function for example for recommending only items that have just few purchases and you need to sell them. #### Definition ``` num_item_purchases(id) ``` | Argument | Type | Meaning | | -------- | ------ | ------------- | | id | string | ID of an item | #### Example ``` // Only items with less than 5 purchases pass the filter num_item_purchases('itemId') < 5 ``` ### Number of Ratings Returns number of ratings of an item specified by its ID. Optionally you can get number of only the `positive` ratings (> 0) or `negative` (< 0) ratings. You can use this function for example for recommending only items that have already a certain number of positive ratings. #### Definition ``` num_item_ratings(id, rating_type) ``` | Argument | Type | Meaning | | ------------ | ------ | ---------------------------------------------------------------------- | | id | string | ID of an item | | rating\_type | string | _Optional._ Take into consideration only positive or negative ratings. | #### Example ``` // Only items with more than 5 positive ratings pass the filter num_item_ratings('itemId', "positive") > 5 ``` ## Item Segments Handling Functions | Name | Description | Example | | ------------------------------------------ | ------------------------------------------- | ------------------------------------------------ | | [segment\_items](#reql-func-segment-items) | Get items in a Segment | 'itemId' in segment\_items("genres", "thriller") | | [item\_segments](#reql-func-item-segments) | Get Item Segments to which the item belongs | "thriller" in item\_segments("genres", 'itemId') | ### Items in a Segment Gets Items belonging to an [Item Segment](/segmentations) #### Definition ``` segment_items(segmentation_id, segment_id) ``` | Argument | Type | Meaning | | ---------------- | ------ | ------------------------------------------- | | segmentation\_id | string | ID of an Item Segmentation | | segment\_id | string | ID of a Segment from the given Segmentation | #### Example ``` // Allow only thrillers 'itemId' in segment_items("genres", "thriller") ``` ### Item Segments of an Item Given an [Item Segmentation](/segmentations) and an Item, get a set of Item Segments to which the Item belongs #### Definition ``` item_segments(segmentation_id, item_id) ``` | Argument | Type | Meaning | | ---------------- | ------ | -------------------------- | | segmentation\_id | string | ID of an Item Segmentation | | item\_id | string | ID of an Item | #### Example ``` // Allow only thrillers "thriller" in item_segments("genres", 'itemId') ``` ## Geographical Functions | Name | Description | Example | | -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | | [earth\_distance](#reql-func-earth-distance) | Returns the orthodromic distance between two points (given as their latitude and longitude in degrees) in meters | earth\_distance(50.075538,14.437800,52.520007,13.404954) < 282000 | | [geo\_polygon](#reql-func-geo-polygon) | Creates a spherical polygon represented by points with geographical coordinates | geo\_polygon(\[\[40.800, -73.957\], \[40.767, -73.981\], \[40.764, -73.972\], \[40.796, -73.949\]\]) | | [geo\_radius](#reql-func-geo-radius) | Creates a spherical cap represented by a center with geographical coordinates and a radius in km | geo\_radius(\[40.689167, -74.044444\], 10) | Geographical functions `geo_polygon` and `geo_radius` construct geographical values, on which queries for testing geographic containment may be applied. For a detailed description and examples of usage, see the [Geographical Containment section](/reql_functions#reql-func-geo-containment). ### Earth Distance Returns the orthodromic distance in meters between two points specified by their latitude and longitude in degrees. #### Definition ``` earth_distance(lat1,lon1,lat2,lon2) ``` | Argument | Type | Meaning | | -------- | ------ | ---------------------------------------- | | lat1 | number | Latitude of the first point in degrees | | lon1 | number | Longitude of the first point in degrees | | lat2 | number | Latitude of the second point in degrees | | lon2 | number | Longitude of the second point in degrees | #### Example All the following expressions result in `true`: ``` earth_distance(10,10,10,10) == 0 // Distance between Prague (50.075538,14.437800) and Berlin (52.520007,13.404954) 281000 < earth_distance(50.075538,14.437800,52.520007,13.404954) < 282000 ``` ### Geographical Point To specify a point with geographical coordinates, use an[array](/reql_filtering_and_boosting#arrays) of length two, which contains number values latitude and longitude as its elements, respectively: ``` // Geographical coordinates of One World Trade Center [40.713056, -74.013333] ``` ### Geographical Polygon Creates a spherical polygon represented by [points](#reql-func-geo-point) with geographical coordinates, on which queries of testing for [geographical containment](#reql-func-geo-containment) may be applied. #### Definition ``` geo_polygon(polygon points, strict) ``` | Argument | Type | Meaning | | -------------- | --------------------------------------- | ----------------------------------------------------------------------------------------------------------- | | polygon points | array of [points](#reql-func-geo-point) | The boundary of the polygon | | strict | boolean | _Optional._ Boolean specifying if any non-valid polygon results in an error. Default if not provided: false | * A polygon is specified as an array of geographical coordinates of at least 3 [points](#reql-func-geo-point) * The points of a polygon can be specified in both CW and CCW orders * The interior of a polygon is such that the polygon encloses at most half of the sphere (from two possible interpretations of a polygon, the one with the smaller area is considered). The interior does not include the boundary, except for the points To avoid ambiguity of the requests, the following requirements should be kept: * No two points of a polygon may share coordinates (the first and the last point are presumed to be connected automatically), * Edges of a polygon may not cross anywhere but in the points By default, if any of the requirements above are not fulfilled, the geo containment query will be handled on a best-effort basis. Should you want to enable strict checking, set the boolean parameter `strict` to `true`. In that case, any failure to comply with the requirements will result in an error. #### Example ``` // A geo_polygon roughly encompassing NYC's Manhattan geo_polygon([[40.878273, -73.925268], [40.711673, -74.027338], [40.698674, -73.984877], [40.761036, -73.957467], [40.794154, -73.913269], [40.834948, -73.934384], [40.872342, -73.908634]]) // A geo_polygon roughly encompassing NYC's Manhattan with strict checking geo_polygon([[40.878273, -73.925268], [40.711673, -74.027338], [40.698674, -73.984877], [40.761036, -73.957467], [40.794154, -73.913269], [40.834948, -73.934384], [40.872342, -73.908634]], true) ``` ### Geographical Radius Creates a spherical cap represented by a center [point](#reql-func-geo-point) with geographical coordinates and a radius in km, on which queries of testing for [geographical containment](#reql-func-geo-containment) may be applied. #### Definition ``` geo_radius(center point, radius) ``` | Argument | Type | Meaning | | ------------ | ----------------------------- | -------------------------------------------- | | center point | [point](#reql-func-geo-point) | Coordinates of the center of the geo\_radius | | radius | number | Length of the geo\_radius radius in km | Everything that is within the orthodromic distance of a given radius to the center point is contained within the `geo_radius` (inclusively). Nothing is contained within a `geo_radius` with a negative radius, and everything is contained within a `geo_radius` with a radius larger than half of the Earth Equator’s length. #### Example ``` // A geo_radius of 10km around Statue of Liberty geo_radius([40.689167, -74.044444], 10) ``` ### Geographical Containment Geographical values `geo_polygon` and `geo_radius` support the `in` operator for checking containtment of a [geographical point](#reql-func-geo-point). The result of the operator is truthy if the [point](#reql-func-geo-point) is contained within the given geographical value. The syntax of such a query is: `point` in `geographical value`. #### Examples All the following expressions result in `true`: ``` // One World Trade Center is contained within a geo_polygon roughly encompassing NYC's Manhattan [40.713056, -74.013333] in geo_polygon([[40.878273, -73.925268], [40.711673, -74.027338], [40.698674, -73.984877], [40.761036, -73.957467], [40.794154, -73.913269], [40.834948, -73.934384], [40.872342, -73.908634]]) // One World Trade Center is contained within a geo_radius of 10km around Statue of Liberty [40.713056, -74.013333] in geo_radius([40.689167, -74.044444], 10) ``` --- # API Clients (SDKs) > Source: https://docs.recombee.com/api_clients > For the complete documentation index, see [llms.txt](/llms.txt). # API Clients (SDKs) We provide clients for multiple programming languages. These helper libraries make the integration of our service into your web or application faster and easier. ![](/img/headings/api-clients.png) We offer both _client-side_ and _server-side_ SDKs. The differences are summarized in the table below: | Client-side SDK | Server-side SDK | | | ------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------------------------- | | Running in | Browser or mobile apps | Server-side scripts | | Supported endpoints | [Interactions](/api#user-item-interactions), [Recommendations](/api#recommendations) & [Search](/api#search) | Everything from [API Reference](/api) | | Type of token used | Public token (for security reasons) | Private token | The following languages are supported via client-side SDKs: [JavaScript](/js_client)[Kotlin (Android)](/kotlin_client)[Swift (iOS)](/swift_client) The following languages are supported via server-side SDKs: [Java](https://github.com/recombee/java-api-client)[Ruby](https://github.com/recombee/ruby-api-client)[Node.js](https://github.com/recombee/node-api-client)[PHP](https://github.com/recombee/php-api-client)[Python](https://github.com/recombee/python-api-client)[.NET](https://github.com/recombee/net-api-client)[Go](https://github.com/recombee/go-api-client) You can combine multiple SDKs - for example you can use [JavaScript](/js_client) for sending interactions and getting recommendations, but [synchronize the Catalog](/getting_started#getting-started-catalog) using a server-side SDK (e.g. [Python](/python_client)). For more information on the available API endpoints, including examples for all supported languages, see the [API Reference](/api). --- # Widget SDKs > Source: https://docs.recombee.com/widget-sdks > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Supported Environments](#supported-environments) * [Available Widgets](#available-widgets) * [Carousel](#carousel) * [Quick Search](#quick-search) * [Grid](#grid) * [Feed](#feed) # Widget SDKs Recombee Widget SDKs offer pre-built, customizable components designed to help you quickly embed personalized recommendations into your website or application. Whether you’re looking to highlight trending articles in a carousel, showcase recommended products in a visually appealing grid, power a dynamic feed of relevant content, or deliver instant results via a quick search box, these widgets make it easy to deliver real-time, AI-driven recommendations to your users. ## Supported Environments Each widget type is available as two separate npm packages: * **Vanilla JavaScript** \- Can be directly included in any website without requiring a build or compilation step. * **React** \- Designed for projects using React to render user interfaces. ## Available Widgets ### Carousel Displays recommendations in a horizontally scrollable carousel format, allowing users to browse through items with ease. [![Carousel (JS)](/img/widgets/widget-carousel.png)Carousel (JS)@recombee/carousel-widget-js](/widget-sdks/carousel-widget-js)[![Carousel (React)](/img/widgets/widget-carousel.png)Carousel (React)@recombee/carousel-widget-react](/widget-sdks/carousel-widget-react) ### Quick Search Enables instant, personalized search suggestions as the user types. [![Quick Search (JS)](/img/widgets/widget-quick-search.png)Quick Search (JS)@recombee/quick-search-widget-js](/widget-sdks/quick-search-widget-js)[![Quick Search (React)](/img/widgets/widget-quick-search.png)Quick Search (React)@recombee/quick-search-widget-react](/widget-sdks/quick-search-widget-react) ### Grid Displays recommended items in a fixed or responsive grid layout. [![Grid (JS)](/img/widgets/widget-grid.png)Grid (JS)@recombee/grid-widget-js](/widget-sdks/grid-widget-js)[![Grid (React)](/img/widgets/widget-grid.png)Grid (React)@recombee/grid-widget-react](/widget-sdks/grid-widget-react) ### Feed Presents an infinite, scrollable list of items, with new recommendations loading automatically as the user scrolls or on click. [![Feed (JS)](/img/widgets/widget-feed.png)Feed (JS)@recombee/feed-widget-js](/widget-sdks/feed-widget-js)[![Feed (React)](/img/widgets/widget-feed.png)Feed (React)@recombee/feed-widget-react](/widget-sdks/feed-widget-react) --- # Segment Integration > Source: https://docs.recombee.com/segment > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Getting Started](#getting-started) * [Settings](#settings) * [Supported Mappings](#supported-mappings) * [Page](#page) * [Track](#track) * [Screen](#screen) * [Alias](#alias) * [Delete User](#delete-user) * [Custom Mappings](#custom-mappings) * [Reporting Successful Recommendations](#reporting-successful-recommendations) # Segment Integration [Segment](https://segment.com) is a Customer Data Platform (CDP). ![](/img/segment/recombee-segment-header.png) Segment simplifies collecting and using data from the users of your digital properties (websites, apps, etc). Using it, you can collect, transform, send, and archive your first-party customer data. The Recombee destination in Segment can send your interaction data (views, purchases, plays, etc.) to Recombee. Note This page describes the new version of the Recombee Destination in Segment, called just **Recombee**. For documentation of the old version, called _Recombee AI_, visit the [Segment Documentation](https://segment.com/docs/connections/destinations/catalog/recombee-ai/). ## Getting Started 1. In the Segment web app, navigate to **Connections > Destinations** and click **Add Destination**. 2. Find and select [Recombee](https://app.segment.com/goto-my-workspace/destinations/catalog/actions-recombee) and click **Add Destination**. [![The Recombee integration in the Segment Destination Catalog](/img/segment/segment_ui.png)](/img/segment/segment_ui.png) 3. Select a Source to connect to the **Recombee** destination. 4. Navigate to the [Recombee Admin UI](https://admin.recombee.com) and complete the following actions: * Choose the Recombee Database where you want to send the interactions. * Click **Settings** in the menu on the left. * In the **API ID & Tokens** settings section, find the **Database ID** and the **Private Token** of the Database. 5. Back in the Segment app, navigate to the settings page of the Recombee destination you created. * Copy the **Database ID** from the Recombee Admin UI and paste it into the **Database ID** field in the destination settings. * Copy the **Private Token** from the Recombee Admin UI and paste it into the **Private Token** field in the destination settings. [![Setting API Identifier and Private Token](/img/segment/segment_settings.png)](/img/segment/segment_settings.png) Once you send the data from Segment to the Recombee destination, you can: * Open the KPI console of the [Recombee Admin UI](https://admin.recombee.com) to see the numbers of the ingested interactions (updated in realtime). * Select the ID of an Item (or User) in the Items (or Users) catalog section in the Admin UI to view a specific ingested interaction. ## Settings Database ID Required: **Yes** The ID of the Recombee Database into which the interactions will be sent. --- Private Token Required: **Yes** The private token for the Recombee Database used. --- Database Region Required: **Yes** The Recombee cluster where your Database is located. [Learn more](/regions) --- API URI Required: **No** URI of the Recombee API that should be used. _Keep this field empty unless you are calling the Recombee cluster based in a specific region or you were assigned a custom URI by the Recombee Support team._ --- ## Supported Mappings ### Page If you're new to the Segment Spec, check out the [Page method documentation](https://segment.com/docs/connections/spec/page/) to understand how it works. Here's an example of a Page method call: JavaScript ``` analytics.page(); ``` Segment sends Page calls to Recombee as a [Detail View](/api#request-add-detail-view). ### Track If you aren't familiar with the Segment Spec, take a look at the [Track method documentation](https://segment.com/docs/connections/spec/track/)to learn about what it does. Here's an example: JavaScript ``` analytics.track('Video Content Playing', { session_id: '12345', asset_id: '0129370', position: 20, total_length: 360, recomm_id: 'ce52ada4-e4d9-4885-943c-407db2dee837', }); ``` The Recombee Destination can process several [Semantic Events](https://segment.com/docs/connections/spec/semantic/). **Supported [Ecommerce](https://segment.com/docs/connections/spec/ecommerce/v2/) events:** | Segment Event | Sent Interaction | | ---------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | | [Product Viewed](https://segment.com/docs/connections/spec/ecommerce/v2/#product-viewed) | [Detail View](/api#request-add-detail-view) | | [Product Added](https://segment.com/docs/connections/spec/ecommerce/v2/#product-added) | [Cart Addition](/api#request-add-cart-addition) | | [Product Removed](https://segment.com/docs/connections/spec/ecommerce/v2/#product-removed) | [Delete Cart Addition](/api#request-delete-cart-addition) | | [Order Completed](https://segment.com/docs/connections/spec/ecommerce/v2/#order-completed) | [Purchase](/api#request-add-purchase) for each of the ordered products | | [Product Added to Wishlist](https://segment.com/docs/connections/spec/ecommerce/v2/#product-added-to-wishlist) | [Bookmark](/api#request-add-bookmark) | | [Product Removed from Wishlist](https://segment.com/docs/connections/spec/ecommerce/v2/#product-removed-from-wishlist) | [Delete Bookmark](/api#request-delete-bookmark) | | [Product Shared](https://segment.com/docs/connections/spec/ecommerce/v2/#product-shared) | [Bookmark](/api#request-add-bookmark) | **Supported [Video](https://segment.com/docs/connections/spec/video/) events:** | Segment Event | Sent Interaction | | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | | [Video Playback Started](https://segment.com/docs/connections/spec/video/#video-playback-started) | [View Portion](/api#request-set-view-portion) with portion = 0 | | [Video Content Playing](https://segment.com/docs/connections/spec/video/#video-content-playing) | [View Portion](/api#request-set-view-portion) with portion = position / total\_length | | [Video Playback Paused](https://segment.com/docs/connections/spec/video/#video-playback-paused) | [View Portion](/api#request-set-view-portion) with portion = position / total\_length | | [Video Playback Completed](https://segment.com/docs/connections/spec/video/#video-playback-completed) | [View Portion](/api#request-set-view-portion) with portion = 1 | If you want to send interactions from other types of events, you can create your own custom mappings in the Segment web app. [Learn more below](#custom-mappings) ### Screen For more details on the Screen method, refer to the [Screen method documentation](https://segment.com/docs/connections/spec/screen/). Here's an example call: Objective-C ``` [[SEGAnalytics sharedAnalytics] screen:@"Home"]; ``` Segment converts Screen calls to [Detail View](/api#request-add-detail-view) interactions. ### Alias For information about Alias, visit the [Alias method documentation](https://segment.com/docs/connections/spec/alias/). Here's an example of an Alias call: JavaScript ``` analytics.alias('507f191e81'); ``` These Alias calls are mapped to [Merge Users](/api#request-merge-users) calls. ### Delete User Segment sends a [Delete User](/api#request-delete-user) call to Recombee on deleting a user. All the associated data associated with the user (including interactions) are removed from Recombee. ### Custom Mappings The new Action Destinations framework in Segment, which this integration uses, allows you to create custom mappings for your events directly in the Segment web app. To create a custom mapping, open the destination in the Segment web app, navigate to the **Mappings** tab, and click **New Mapping**. You can add a predefined mapping, but more importantly, right below the predefined mappings, there is a list of all available actions that you can use to create your own custom mappings. [![Selecting an available action in Segment](/img/segment/segment_mapping_actions.png)](/img/segment/segment_mapping_actions.png) After selecting an action, you can continue below the list and configure the mapping. There you can define the event trigger, the fields of the event, and how they correspond to the fields of the interaction. [![Defining a custom event trigger in Segment](/img/segment/segment_mapping_trigger.png)](/img/segment/segment_mapping_trigger.png) ## Reporting Successful Recommendations You should inform Recombee that a specific interaction resulted from a successful recommendation (meaning the recommendations were presented to a user, and the user clicked on one of the items) by setting the ID of the successful recommendation request in the `Recommendation ID` field of the action (this is the `recomm_id` property by default). You can read more about this setting in [Reported Metrics](/admin_ui#reported-metrics). Sending the `Recommendation ID` gives you precise numbers about successful recommendations in the KPI section of the [Recombee Admin UI](https://admin.recombee.com). This explicit feedback also helps improve the output of the recommendation models. --- # Keboola Integration > Source: https://docs.recombee.com/keboola > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Data Destination](#data-destination) * [✨ Features](#data-destination-features) * [⚙️ Configuration](#data-destination-configuration) * [🧱 Input Structure](#data-destination-input-structure) * [Catalog](#data-destination-input-structure-catalog) * [Interactions](#data-destination-input-structure-interactions) * [Notes](#data-destination-input-structure-notes) * [📤 Example Input - detail\_views.csv](#data-destination-example-input-detail-views) * [📤 Example Input - items.csv](#data-destination-example-input-items) * [Data Source](#data-source) * [✨ Features](#data-source-features) * [⚙️ Configuration](#data-source-configuration) * [🧱 Input Structure](#data-source-input-structure) * [Example Input](#data-source-example-input) * [📤 Output Format](#data-source-output-format) * [Example Output - recomms.csv](#data-source-output-format-example) * [Notes](#data-source-output-format-notes) # Keboola Integration Keboola is a data platform that helps organizations build scalable, automated data pipelines by orchestrating data collection, transformation, and delivery. ![](/img/keboola/recombee-keboola-header.png) Recombee provides two components in Keboola: * [**Data Destination**](#data-destination) for uploading items, users, and interactions * [**Data Source**](#data-source) for requesting recommendations ## Data Destination The Recombee Data Destination for [Keboola](https://keboola.com) uploads items, users, and interactions from CSV tables in Keboola to Recombee to power personalized recommendations and search. It supports all major Recombee APIs for catalog and behavior data ingestion. ### ✨ Features * Uploads **Items Catalog** and **Users Catalog** * Supports all standard **Recombee interactions**: * `AddDetailView` * `AddPurchase` * `AddRating` * `AddBookmark` * `AddCartAddition` * `SetViewPortion` * Supports **optional fields** (e.g., `timestamp`, `recomm_id`, `additional_data`) * Gracefully handles bad data (e.g. `NaN`, invalid types) and logs summarizations ### ⚙️ Configuration You can configure the component directly in the Keboola UI when setting up the component. | Field | Description | | ------------- | ------------------------------------------------------------------ | | Database ID | Your Recombee Database ID | | Private Token | Associated private token | | Region | Recombee cluster region of your DB (eu-west, us-west, ap-se, etc.) | | Batch Size | \[Optional\] Number of requests sent per batch. Defaults to 1000. | [![Recombee Data Destination configuration in Keboola](/img/keboola/keboola_data_destination_configuration.png)](/img/keboola/keboola_data_destination_configuration.png) ### 🧱 Input Structure Place CSV files in `in/tables/`. #### Catalog | Filename | Recombee API | Required Columns | Optional Columns | | --------- | --------------------------------------------- | ---------------- | ----------------------------------------------------------------------------------------- | | items.csv | [SetItemValues](/api#request-set-item-values) | item\_id | All others based on your Recombee item properties (e.g. title, price, tags) | | users.csv | [SetUserValues](/api#request-set-user-values) | user\_id | All others based on your Recombee user properties (e.g. subscribed\_topics, age, country) | #### Interactions | Filename | Recombee API | Required Columns | Optional Columns | | ------------------- | ------------------------------------------------- | --------------------------- | -------------------------------------------------------------- | | bookmarks.csv | [AddBookmark](/api#request-add-bookmark) | user\_id, item\_id | timestamp, recomm\_id, additional\_data | | cart\_additions.csv | [AddCartAddition](/api#request-add-cart-addition) | user\_id, item\_id | timestamp, recomm\_id, amount, additional\_data | | detail\_views.csv | [AddDetailView](/api#request-add-detail-view) | user\_id, item\_id | timestamp, recomm\_id, duration, additional\_data | | purchases.csv | [AddPurchase](/api#request-add-purchase) | user\_id, item\_id | timestamp, recomm\_id, amount, price, profit, additional\_data | | ratings.csv | [AddRating](/api#request-add-rating) | user\_id, item\_id, rating | timestamp, recomm\_id, additional\_data | | view\_portions.csv | [SetViewPortion](/api#request-set-view-portion) | user\_id, item\_id, portion | timestamp, recomm\_id, additional\_data | #### Notes * `item_id` / `user_id` must always be in the **first column** for catalog files. * Columns such as `tags`, `additional_data`, `imageList` should be passed as valid JSON strings. ### 📤 Example Input - detail\_views.csv ``` user_id,item_id,timestamp,recomm_id,additional_data user-1,item-10,2025-07-06T21:12:43Z,644c005f-aa99-4bce-aa55-a0c610e80df0,"{""source"": ""newsletter""}" user-2,item-09,2025-07-06T21:09:13Z,,"{""source"": ""newsletter""}" user-3,item-05,2025-07-06T21:14:45Z,2d2eb48f-cd65-421a-943c-0e015055fd8e,"{""source"": ""homepage""}" ``` ### 📤 Example Input - items.csv Item properties must be created in the [Recombee Admin UI](https://admin.recombee.com). ``` item_id,title,price,available,date_added,tags item-01,Wireless Mouse,25.99,true,2025-07-20T10:11:49.039302,"[""electronics"", ""accessory"", ""mouse""]" item-42,Mechanical Keyboard,75.49,false,2025-08-04T10:11:49.039318,"[""electronics"", ""keyboard""]" item-77,USB-C Hub,34.9,true,2025-08-19T10:11:49.039321,"[""electronics"", ""usb"", ""hub""]" ``` ## Data Source The Recombee Data Source fetches recommendations from [Recombee](https://www.recombee.com/) via selected recommendation endpoint and exports the results as structured CSV tables. ### ✨ Features * Supports following **Recombee recommendation endpoints**: * [Recommend Items to User](https://docs.recombee.com/api.html#recommend-items-to-user) * [Recommend Items to Item](https://docs.recombee.com/api.html#recommend-items-to-item) * [Recommend Item Segments to User](https://docs.recombee.com/api.html#recommend-item-segments-to-user) * Uses batch requests with automatic retry handling * Supports using [Scenarios](https://docs.recombee.com/scenarios) * Supports [returning item properties](https://docs.recombee.com/api#recommend-items-to-user-param-includedProperties) (metadata) of the recommended items * Outputs results with full Recombee API response for auditability [![Recombee Data Source in Keboola](/img/keboola/keboola_data_source.png)](/img/keboola/keboola_data_source.png) ### ⚙️ Configuration You can configure the component directly in the Keboola UI when setting up the component. | Field | Description | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Database ID | The ID of your Recombee database (e.g., "your-database-id"). | | Private Token | The private token used to authenticate requests to Recombee. | | Region | Region where your Recombee database is hosted (ap-se, ca-east, eu-west, us-west). Defaults to eu-west. | | Scenario | The recommendation scenario to be used (e.g., "emailing", "related-items"). Should match the scenario set up in Recombee Admin UI. | | Recommendation Endpoint | Which Recombee endpoint to use for fetching recommendations. Must align with the selected scenario (e.g., Recommend Items to User, Recommend Items to Item, etc.). | | Number of Recommendations | How many recommended items to fetch per user or item. Integer from 1 to 30\. Defaults to 5. | | Included Properties | Optional. List of item properties to include in the response (e.g., \["title", "url", "image"\]). | | Batch Size | Number of users or items to fetch recommendations for in one batch. Optional. Defaults to 100\. Range: 10–10000. | [![Recombee Data Source configuration in Keboola](/img/keboola/keboola_data_source_configuration.png)](/img/keboola/keboola_data_source_configuration.png) ### 🧱 Input Structure Place one CSV file into `in/tables/`, depending on the selected recommendation endpoint. | Filename | Used For Endpoint(s) | | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | users.csv | [Recommend Items to User](https://docs.recombee.com/api#recommend-items-to-user) / [Recommend Item Segments to User](https://docs.recombee.com/api#recommend-item-segments-to-user) | | items.csv | [Recommend Items to Item](https://docs.recombee.com/api#recommend-items-to-item) | The CSV file must contain a single column with IDs of users / items for which recommendations should be generated. ### Example Input ``` user_id user_3fa8c1 user_4b92d8 user_7c13f0 user_1d8a9e ``` ### 📤 Output Format The recommendations are exported to `out/tables/recomms.csv`. | Column | Description | | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- | | user\_id / item\_id | The ID the recommendation was generated for | | recomm\_id | Recombee [recommId](https://docs.recombee.com/getting_started#reporting-successful-recommendations) used for tracking | | recommended\_items / recommended\_item\_segments | List of recommended item or segment IDs | | api\_response | Full JSON response from Recombee (including e.g., the returned properties) | #### Example Output - recomms.csv ``` user_id,recomm_id,recommended_items,api_response user_3fa8c1,cc08bcf0-9d8e-4726-8b21-e47f770316e1,"[""item-165"", ""item-69"", ""item-857""]","{""recommId"": ""cc08bcf0-9d8e-4726-8b21-e47f770316e1"", ""recomms"": [{""id"": ""item-165""}, {""id"": ""item-69""}, {""id"": ""item-857""}], ""numberNextRecommsCalls"": 0}" user_4b92d8,9c291302-abcd-4ab4-b926-aceac05ad15a,"[""item-165"", ""item-69"", ""item-857""]","{""recommId"": ""9c291302-abcd-4ab4-b926-aceac05ad15a"", ""recomms"": [{""id"": ""item-165""}, {""id"": ""item-69""}, {""id"": ""item-857""}], ""numberNextRecommsCalls"": 0}" ``` #### Notes * Use the `Included Properties` configuration parameter to include item metadata such as `title`, `url`, `category`, or `price` in the `api_response` column. * All values in `recommended_items` or `recommended_item_segments` are exported as JSON arrays. --- # Recombee Shoptet GTM Integration > Source: https://docs.recombee.com/shoptet_gtm_integration > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Shoptet Setup](#shoptet-setup) * [Creating Triggers](#creating-triggers) * [DOM Ready Event](#dom-ready-event) * [AddToCart Event](#addtocart-event) * [Creating Tags](#creating-tags) * [GTM Gallery Integration](#gtm-gallery-integration) * [Manual Template Import](#manual-template-import) * [Initialization Tag](#initialization-tag) * [Interaction Tags](#interaction-tags) * [Detail View](#detail-view) * [Rating](#rating) * [Purchase](#purchase) * [Cart Addition](#cart-addition) * [Done!](#done-) # Recombee Shoptet GTM Integration In order to set up GTM integration, you will need to create a [Google Tag Manager](https://tagmanager.google.com/) account. ![](/img/headings/shoptet-gtm.png) Recombee GTM integration supports four types of user interactions in the Shoptet platform: * Add to cart * Detail view * Purchase * Rating ## Shoptet Setup Follow instructions for initial setup. ## Creating Triggers Triggers are needed in order to add support for sending Add to cart and Purchase interactions. Select Triggers in the menu and add a new trigger on the **DOM Ready event** and also **Custom Events** called _“AddToCart”_ and_“Purchase”_. ### DOM Ready Event 1. Navigate to the **Triggers** section 2. Click the **New** button and choose the **DOM Ready** type 3. On the triggers fire selection keep the **All DOM Ready Events** and name the trigger accordingly [![Create trigger - DOM Ready Event - Step 1](/img/shoptet_gtm/shoptet-gtm-dom-ready-event.png)](/img/shoptet_gtm/shoptet-gtm-dom-ready-event.png) [![Create trigger - DOM Ready Event - Step 2](/img/shoptet_gtm/shoptet-gtm-dom-ready-event-2.png)](/img/shoptet_gtm/shoptet-gtm-dom-ready-event-2.png) ### AddToCart Event 1. Navigate to the **Triggers** section 2. Click the **New** button and choose the **Custom Event** type 3. Fill the **Event name** with _“addToCart”_ and select the **All Custom Events** option below. [![Create trigger - AddToCart Event - Step 1](/img/shoptet_gtm/shoptet-gtm-addtocart.png)](/img/shoptet_gtm/shoptet-gtm-addtocart.png) [![Create trigger - AddToCart Event - Step 2](/img/shoptet_gtm/shoptet-gtm-addtocart-2.png)](/img/shoptet_gtm/shoptet-gtm-addtocart-2.png) ## Creating Tags Our custom GTM tags will send interactions to Recombee. You can create tags for all supported interactions or just those you want to send. ### GTM Gallery Integration We have published [Recombee Shoptet integration](https://tagmanager.google.com/gallery/#/owners/recombee/templates/shoptet-gtm-integration), which you can use for easy setup. Go to the **Tags section**, click **New** and search for the **Recombee Shoptet interactions** template. ### Manual Template Import While we are waiting for Google approval to be included in the GTM template gallery, you can simply import the Recombee Shoptet template for use. Download the template file from our Github repository ([GTM Integration Github](https://github.com/recombee/shoptet-gtm-integration) \- _template.tpl_) 1. In GTM select **Templates** in the left side menu and click on**New** 2. Import the template by clicking on the dots and select **Import** 3. Select downloaded _template.tpl_ file and save your new template Now you can use our template when creating your tags. ### Initialization Tag We provide one tag with multiple types. You always need to create an initialization tag. Tag that initializes the environment for sending interactions. You will need it for sending interactions to work. 1. Select **Initialization** type in **Tag Interaction Type** 2. Fill the **Database ID** with the ID of your Recombee database_(e.g., \`shoptet-gtm-example-prod\`)_ 3. Fill **region** of your database _(e.g., eu-west)_ 4. Fill **public key** **You can find all the information in the settings of your database in the Recombee admin.** [![Initialization tag](/img/shoptet_gtm/shoptet-gtm-Initialization-tag.png)](/img/shoptet_gtm/shoptet-gtm-Initialization-tag.png) ### Interaction Tags You can choose which interactions to send by creating a tag for each type. #### Detail View To create a tag for Detail view interaction, select a **Detail View**option in **Tag Interaction Use Case** and name it accordingly. Click on **Advanced Settings** and **Tag Sequencing**, choose **Fire tag before xxx fires**, and select your **initialization tag** created before. For **triggering**, select the **DOM Ready** trigger created in the first steps. [![Detail view](/img/shoptet_gtm/shoptet-gtm-interaction-tag-detail-view.png)](/img/shoptet_gtm/shoptet-gtm-interaction-tag-detail-view.png) #### Rating To create a tag for Rating interaction, select a **Rating** option in**Tag Interaction Use Case** and name it accordingly. Click on **Advanced Settings** and **Tag Sequencing**, choose **Fire tag before xxx fires**, and select your **initialization tag** created before. For **triggering**, select the **DOM Ready** trigger created in the first steps. [![Rating](/img/shoptet_gtm/shoptet-gtm-interaction-tag-rating.png)](/img/shoptet_gtm/shoptet-gtm-interaction-tag-rating.png) #### Purchase To create a tag for Purchase interaction, select a **Purchase** option in **Tag Interaction Use Case** and name it accordingly. Click on **Advanced Settings** and **Tag Sequencing**, choose **Fire tag before xxx fires**, and select your **initialization tag** created before. For **triggering**, select the **DOM Ready** trigger created in the first steps. [![Purchase](/img/shoptet_gtm/shoptet-gtm-interaction-tag-purchase.png)](/img/shoptet_gtm/shoptet-gtm-interaction-tag-purchase.png) #### Cart Addition To create a tag for Cart addition interaction, select a **Cart addition**option in **Tag Interaction Use Case** and name it accordingly. Click on **Advanced Settings** and **Tag Sequencing**, choose **Fire tag before xxx fires**, and select your **initialization tag** created before. For **triggering**, select the **AddToCart** trigger created in the first steps. [![Cart addition](/img/shoptet_gtm/shoptet-gtm-interaction-cart-addition.png)](/img/shoptet_gtm/shoptet-gtm-interaction-cart-addition.png) ## Done! --- # Video Recipes > Source: https://docs.recombee.com/recipes/video > For the complete documentation index, see [llms.txt](/llms.txt). # Video Recipes Discover how to personalize various use cases within your video platform. ![](/img/recipes/video/video.png) Follow our guides and configure Recombee [Scenarios](/scenarios) to personalize your whole video platform. From a fully personalized homepage, to video details, smart search, or marketing campaigns and newsletters, enhance the user experience to match that of leading platforms like Netflix. Let's do it! **Before setting up individual [Scenarios](/scenarios)** based on recipes, make sure you have the basic integration in place. To get started step by step, follow the [Getting Started Guide](/getting_started) and review the [integration tips for video](/integration_tips#integration-tips-content-videos), which cover topics such as catalog upload and series modeling. ## Fully Personalized Homepage A fully personalized homepage is made of many personalized rows, each with specific content, where the rows themselves are ordered to reflect the user's tastes. [![“Recommended For You” Rows](/img/recipes/video/recommended-for-you-rows.png)“Recommended For You” Rows](/recipes/video/fully-personalized-homepage/recommended-for-you-rows)[![Personalized Re-ordering of Rows](/img/recipes/video/personalized-re-ordering-of-rows-advanced.png)Personalized Re-ordering of Rows](/recipes/video/fully-personalized-homepage/personalized-re-ordering-of-rows-advanced)[![Editors’ Picks For You](/img/recipes/video/editors-picks-for-you.png)Editors’ Picks For You](/recipes/video/fully-personalized-homepage/editors-picks-for-you)[![Continue Watching](/img/recipes/video/continue-watching.png)Continue Watching](/recipes/video/fully-personalized-homepage/continue-watching)[![Popular & Trending](/img/recipes/video/popular-and-trending.png)Popular & Trending](/recipes/video/fully-personalized-homepage/popular-and-trending)[![Because You Watched](/img/recipes/video/because-you-watched.png)Because You Watched](/recipes/video/fully-personalized-homepage/because-you-watched)[![Actors For You](/img/recipes/video/actors-for-you.png)Actors For You](/recipes/video/fully-personalized-homepage/actors-for-you) ## Short Videos Feed A short videos swiping feed (TikTok / Instagram Reels / YouTube Shorts–style) is a continuously personalized stream of bite-sized videos, where each item is selected and ranked in real time to match the user’s immediate interests and engagement patterns. [![Short Videos Swiping Feed](/img/recipes/video/short-videos-feed.png)Short Videos Swiping Feed](/recipes/video/feed/swiping-feed) ## Asset Detail & Player Enhance your video detail page by showing various related content and keep your users engaged after watching a video with personalized watch-next recommendations. [![More Like This](/img/recipes/video/more-like-this.png)More Like This](/recipes/video/asset-detail-and-player/more-like-this)[![Watch Next](/img/recipes/video/watch-next.png)Watch Next](/recipes/video/asset-detail-and-player/watch-next) ## Search, Emailing Say goodbye to endless scrolling and time-consuming searches. With our full-text search functionality, desired titles are just a few keystrokes away. Our search feature ensures that you can locate the content you're looking for quickly and effortlessly. Or Send personalized emails that perfectly align with your users' individual taste. [![Search Movies/Series](/img/recipes/video/search-movies-and-series.png)Search Movies/SeriesHelp users find what they want](/recipes/video/search-movies-and-series)[![Personalized Emailing](/img/recipes/video/personalized-emailing.png)Personalized EmailingKeep your users in the loop](/recipes/video/personalized-emailing) --- # E-Commerce Recipes > Source: https://docs.recombee.com/recipes/e-commerce > For the complete documentation index, see [llms.txt](/llms.txt). # E-Commerce Recipes Discover how to personalize various use cases within your e-commerce site. ![](/img/recipes/e-commerce/e-commerce.png) Personalizing the shopping experience is essential in the e-commerce domain. By tailoring recommendations to individual users, you can significantly improve customer satisfaction, boost conversion rates, and increase average order value. From a personalized homepage to customized product recommendations, explore our recipes to transform your e-commerce platform into a user-centric marketplace. **Before you can set up individual [Scenarios](/scenarios)** according to recipes, you need to have the basic integration ready. To get started step by step with the integration continue to the [Getting Started Guide](/getting_started). ## Fully Personalized Homepage Automate and tailor all your homepage sections 1:1 for each user. A fully personalized homepage is made of multiple personalized boxes and provides the users with a variety of recommendations. [!["For You" Sections](/img/recipes/e-commerce/for-you-sections.png)"For You" Sections](/recipes/e-commerce/fully-personalized-homepage/for-you-sections)[![Personalized Re-ordering of Sections](/img/recipes/e-commerce/personalized-re-ordering-of-sections-advanced.png)Personalized Re-ordering of Sections](/recipes/e-commerce/fully-personalized-homepage/personalized-re-ordering-of-sections-advanced)[![Bestsellers](/img/recipes/e-commerce/bestsellers.png)Bestsellers](/recipes/e-commerce/fully-personalized-homepage/bestsellers)[![Recently Viewed Products](/img/recipes/e-commerce/recently-viewed.png)Recently Viewed Products](/recipes/e-commerce/fully-personalized-homepage/recently-viewed)[![Brands for You](/img/recipes/e-commerce/brands-for-you.png)Brands for You](/recipes/e-commerce/fully-personalized-homepage/brands-for-you) ## Product Detail Enhance product pages with personalized recommendations for similar products and complementary accessories to boost upselling and cross-selling. [![Alternative Products & Upsell](/img/recipes/e-commerce/alternative-products-and-upsell.png)Alternative Products & Upsell](/recipes/e-commerce/product-detail/alternative-products-and-upsell)[![Bought Together & Accessories](/img/recipes/e-commerce/bought-together-and-accessories.png)Bought Together & Accessories](/recipes/e-commerce/product-detail/bought-together-and-accessories) ## Cart, Category, Emailing Ensure a personalized experience throughout the customer's journey. From the cart to category pages and personalized email campaigns, keep your users engaged and informed with tailored content. [![Cart](/img/recipes/e-commerce/shopping-cart.png)Cart](/recipes/e-commerce/cart)[![Category Page](/img/recipes/e-commerce/personalized-reordering-of-products.png)Category Page](/recipes/e-commerce/category/reordering-of-category-products)[![Personalized Emailing](/img/recipes/e-commerce/personalized-emailing.png)Personalized Emailing](/recipes/e-commerce/personalized-emailing) ## Search Optimize the search functionality to provide users with quick and precise results. Implement advanced search features like faceted search to help users find exactly what they are looking for with ease. [![Quick Search](/img/recipes/e-commerce/quick-search.png)Quick Search](/recipes/e-commerce/search/quick-search)[![Faceted Search](/img/recipes/e-commerce/faceted-search.png)Faceted Search](/recipes/e-commerce/search/faceted-search) --- # News Recipes > Source: https://docs.recombee.com/recipes/news > For the complete documentation index, see [llms.txt](/llms.txt). # News Recipes Discover how to personalize key use cases within your news platform. ![](/img/recipes/news/news.png) Follow these guides to configure Recombee [Scenarios](/scenarios) and personalize your entire news experience. From personalized homepage sections and article detail pages to category-based feeds and newsletter campaigns — deliver the experience users expect from a modern news platform. Let’s get started! **Before setting up individual [Scenarios](/scenarios)** based on these recipes, ensure your basic integration is in place. To begin step by step, head over to the [Getting Started Guide](/getting_started). ## Homepage A modern news homepage is made of many personalized sections, each with specific content, where the sections themselves are ordered to reflect the user's tastes. [![Top Stories](/img/recipes/news/top-stories.png)Top Stories](/recipes/news/homepage/top-stories)[![Personalized Sections With Reordering](/img/recipes/news/personalized-sections-with-reordering.png)Personalized Sections With Reordering](/recipes/news/homepage/personalized-sections-with-reordering)[![Cross-Site Recommendations](/img/recipes/news/cross-site-recommendations-on-homepage.png)Cross-Site Recommendations](/recipes/news/homepage/cross-site-recommendations)[![Latest News](/img/recipes/news/latest-news.png)Latest News](/recipes/news/homepage/latest-news)[![Personalized Feed](/img/recipes/news/personalized-feed.png)Personalized Feed](/recipes/news/homepage/personalized-feed)[![Personalized Editors’ Picks](/img/recipes/news/personalized-editors-picks.png)Personalized Editors’ Picks](/recipes/news/homepage/personalized-editors-picks) ## Article Page Enhance your article pages by displaying relevant and engaging content from across your platform. Keep users reading with personalized _Read Next_ suggestions or even recommendations from other sites in your network. [![Read Next](/img/recipes/news/read-next.png)Read Next](/recipes/news/article/read-next)[![Cross-Site Recommendations](/img/recipes/news/cross-site-recommendations-on-article-page.png)Cross-Site Recommendations](/recipes/news/article/cross-site-recommendations) ## Search Help readers find the right article faster. With personalized full-text search, users can search for topics, headlines, authors, or keywords and receive results that are not only textually relevant, but also aligned with what is fresh, trending, and personally interesting to them. [![Search Articles](/img/recipes/news/search-articles.png)Search Articles](/recipes/news/search-articles) ## Emailing Send emails combining a personalized selection of articles with key unread articles to ensure the users stay informed about the most important news they haven’t seen yet. [![Personalized Emailing](/img/recipes/news/personalized-emailing.png)Personalized Emailing](/recipes/news/personalized-emailing) --- # Third Party Login / SSO > Source: https://docs.recombee.com/third_party_login_sso > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [OpenID Connect](#openid-connect) * [Microsoft Entra (Azure AD)](#microsoft-entra-azure-ad-) * [1\. Register a New Microsoft Entra Application](#-register-a-new-microsoft-entra-application) * [2\. Create a New Microsoft Entra Application Secret](#-create-a-new-microsoft-entra-application-secret) * [3\. Create a Development User](#-create-a-development-user) * [4\. Look Up Your Login Domain](#-look-up-your-login-domain) * [5\. Contact Recombee Support](#-contact-recombee-support) # Third Party Login / SSO Organizations on Pro and Premium plans can use their own services for authentication with Recombee Admin UI. ## OpenID Connect Any service with support for the OpenID Connect can be used for authenticating the access to the Recombee Admin UI. Please contact our support team for more details regarding the integration. ## Microsoft Entra (Azure AD) ### 1\. Register a New Microsoft Entra Application 1. Pick an application name 2. Set "Supported account types" to "Accounts in this organizational directory only (Single tenant)" 3. Set "Redirect URI" to `Web` and `https://oauth.recombee.com/oauth2/callback` 4. Proceed by clicking "Register" ![](/img/third_party_login_sso/entra.microsoft.com_app-registration.png) Once the application has been created, note the `Application (client) ID` and the `Directory (tenant) ID`. ![](/img/third_party_login_sso/entra.microsoft.com_app-detail.png) ### 2\. Create a New Microsoft Entra Application Secret Navigate to _Microsoft Entra -> App Registrations -> \[Your Application\] -> Certificates & secrets -> New client secret_ to create a new Microsoft Entra Application Client Secret. ![](/img/third_party_login_sso/entra.microsoft.com_create-client-secret.png) Copy the `Value` of the newly created client secret using the copy button. This information can be copied just once, right after secret creation. ![](/img/third_party_login_sso/entra.microsoft.com_certs-secrets.png) ### 3\. Create a Development User Add new user in your Microsoft Entra account with an access to the configured application for Recombee to be able to verify the authentication setup. ### 4\. Look Up Your Login Domain Note the domain name of email addresses assigned to your users. For example if your users have email addresses like _[john.doe@mycompany.com](mailto:john.doe@mycompany.com)_, then your login domain is _mycompany.com_. This might be the domain name visible under "Primary domain" at the Tenant overview page but might be configured to be a different domain by your Microsoft Entra administrator. ![](/img/third_party_login_sso/entra.microsoft.com_tenant-overview.png) ### 5\. Contact Recombee Support Assemble the noted information: * Your company Microsoft Entra "Primary domain" (e.g. `mycompany.com`). * `Application (client) ID` * `Directory (tenant) ID` * Client secret `Value`. * Development user email and password. and contact Recombee support to start authentication integration. --- # Integration Guide for AI Assistants > Source: https://docs.recombee.com/ai_assistant_guide > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [What is Recombee?](#what-is-recombee) * [API Prerequisites](#api-prerequisites) * [Authentication](#authentication) * [The Identity Model](#identity-model) * [Catalog / Items](#catalog-items) * [Recording Interactions](#recording-interactions) * [Getting Recommendations](#getting-recommendations) * [Common Mistakes](#common-mistakes) * [Verifying It Works](#verifying-it-works) * [Error & Edge-case Reference](#error-edge-case-reference) # Integration Guide for AI Assistants This document is meant for AI-based tools and contains operational knowledge for wiring an application up to Recombee, written to sit between the official docs and the reality of an integration. It is deliberately repository-agnostic. Where it describes behavior, that behavior is server-side API behavior and holds regardless of language or SDK. Note on intended audience This document is written for machine readers — AI coding assistants, agents, chatbots, and similar automated tools tasked with carrying out a Recombee integration. It assumes its reader is executing the work rather than casually browsing, and it is structured and phrased accordingly: explicit behavior over narrative, pitfalls flagged directly. ## What is Recombee? Recombee is a hosted recommendation and search engine. You feed it three things and it gives you back two things: **In:** * **Item Catalog** — your items (articles, products, videos, …) and their properties. * **User Catalog** (optional) — your users and their properties. * **Interactions** — events describing what users do with those items (detail views, purchases, ratings, bookmarks, …). **Out:** * **Recommendations** — ranked items for a user, for an item, or for the next page of a feed, produced by models Recombee trains on your data. * **Search** — full-text search over the catalog, ranked with the same personalization. The mental model is simple: **interactions + catalog in, recommendations + search out.**Everything else in this document is about doing that cleanly. --- ## API Prerequisites **Prefer an official SDK over hand-rolling HTTP.** Recombee publishes client libraries for most common languages. They handle request signing, request/response shapes and batching, and are kept up to date with the API. If your stack has an SDK, use it. * **Server-side SDKs:** Java, Ruby, Node.js, PHP, Python, .NET, Go. * **Client-side SDKs:** JavaScript, Kotlin (Android), Swift (iOS). The difference between the two families matters — see [Authentication](#authentication). **API reference:** [docs.recombee.com/api.md](https://docs.recombee.com/api.md). The API client list is at [docs.recombee.com/api\_clients.md](https://docs.recombee.com/api_clients.md). **Start from a Scenario Recipe.** [docs.recombee.com/llms.txt](https://docs.recombee.com/llms.txt)is an LLM-oriented index of the whole documentation set, and it contains a **Scenario Recipes** section that is the single most useful starting point when implementing a concrete surface. Recipes are organized by vertical and then by use case, at`docs.recombee.com/recipes/{vertical}/{use-case}/{recipe}`. Each recipe gives the **recommended scenario settings** for that use case — which logic to pick and its parameters, plus the filters, boosters and constraints worth configuring — and then basic **integration guidance** for requesting the recommendations. Since scenario configuration is a manual Admin UI step you have to specify precisely ([Getting recommendations](#getting-recommendations)), read the matching recipe _before_ designing a surface and follow its settings rather than inventing your own. Fetch `llms.txt` first to find the recipe that fits; append `.md` to a recipe URL for its plain-markdown form. For implementing use cases not covered by a recipe, use the rest of this document as a reference and consult the API docs. **Let the SDK be your reference.** The SDKs ship with extensive inline documentation — every request class and parameter is commented, and those comments track the API reference. In most cases the fastest, most reliable way to pick the right endpoint and its parameters is to **install the SDK and read its built-in comments and type definitions** directly, rather than working from memory or from this file. The installed source is version-matched to what you'll actually call, so it won't drift the way a hand-written guide can. This document may be out of date Available SDKs, endpoint names, and defaults change. Before relying on a specific SDK, endpoint, or parameter, confirm it against the live docs pages above — or the SDK's own comments. Treat this file as orientation, not as the source of truth. --- ## Authentication There are **two tokens per database**, and they map onto the two SDK families: | Private token | Public token | | | ------------- | ----------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | | Used by | Server-side SDKs | Client-side SDKs | | Runs in | Your backend / serverless functions | Browser / mobile app, talking to Recombee directly | | API surface | **Everything** (catalog, properties, batch, interactions, recommendations, search, admin) | **Interactions, recommendations, and search only** (see note on merging) | | Exposure | **Must never reach the client.** Anyone holding it can read/modify the whole database. | Designed to ship in client bundles; scoped by Recombee to safe operations. | **Best practices:** * Keep the private token in server-side configuration/secrets only. Do not inline it into client code, commit it, or send it to the browser. * Use the public token (via a client-side SDK) for calls that legitimately originate on the client — recording interactions, requesting recommendations, running search. These go directly from client to Recombee; you do **not** need to build a signing proxy for them. * **Merge Users is the exception: it is server-side only by default.** The public token can only call it if the database has client-side merging enabled, so route it through a backend endpoint that uses the private token (or ask Recombee support to enable client-side merging for your database). Don't design the login flow around a browser-side merge until you've confirmed it's enabled. * Use the private token (via a server-side SDK) for everything the public token can't do — catalog and property management, batch uploads, admin operations. * Load the database name and tokens from environment/secrets. **Never** hard-code a fallback database name (e.g. `env.RECOMBEE_DB || "some-db"`) — a wrong default silently points production at the wrong database. Fail loudly when configuration is missing. **Direct REST for unsupported languages.** If no SDK exists for your stack, call the REST API directly. Authentication is HMAC-SHA1: sign the full request path — **including** the`/{databaseId}` prefix and the query string — with the private token, append`hmac_timestamp`, then append `&hmac_sign=`. Because this uses the private token, it must run server-side behind your own proxy; the proxy should pass Recombee's status code**and response body** through unchanged. Sign the _final_ path (query params included), then append the signature. This is exactly the mechanical work an SDK exists to remove, so reach for REST only when you have no SDK option. --- ## The Identity Model Every user and every item is referenced by a **string ID**. Keep IDs stable, URL-safe, and within Recombee's allowed character set (alphanumerics plus a small set of symbols — check the docs for the exact rules). The ID is your join key between systems. **Anonymous vs. authenticated users:** * For a not-yet-logged-in visitor, **generate a random, persistent ID** (e.g. a UUID) and store it (cookie/local storage/device store). Use it for all of that visitor's interactions and recommendation requests. * When that visitor **logs in**, call the **Merge Users** endpoint to merge the anonymous ID into the authenticated user's ID. This folds the anonymous interaction history into the real profile so nothing learned before login is lost. This call needs the private token unless specified otherwise — see [Authentication](#authentication) — so it belongs on your backend, not in the browser. **Identity consistency is a hard requirement.** The `userId` and `itemId` you send in interaction events **must be byte-for-byte identical** to the IDs used in recommendation requests and catalog updates. If a recommendation returns item `article-42` and the user clicks it, the resulting detail-view interaction must reference `article-42` — not`Article-42`, not `42`, not an internal database primary key. Any mismatch silently breaks attribution and model training: Recombee treats the two spellings as different entities, interactions never connect to the items they concern, and recommendation quality quietly degrades with no error to alert you. Decide on one canonical ID per user and per item, and use it everywhere. --- ## Catalog / Items Recombee needs to know about your items and their properties before it can recommend them or filter on them. There are two ways to get the catalog in: **A) Catalog feed (JSON, XML, RSS).** Configure a feed URL in the Recombee **Admin UI** and Recombee pulls and refreshes the catalog on a schedule. This is the better choice when the app already publishes a product/article feed, or when you'd rather not write bespoke sync code.**If a feed fits, prefer directing the user to set one up in the Admin UI**instead of writing an uploader. However, if real-time updates are important, or if you want to control the sync process in your own codebase, use the API instead. **B) Direct API integration.** Define item properties and push item values through the API. Property definitions are **not** created lazily — writing a value to an undefined property fails until the property exists. Make property definition an **idempotent part of your sync** (re-declare on every run; it's cheap). For the actual upload, **use Batch requests**— sending N items as N sequential calls is slow and will hit serverless execution limits. One batched request carries hundreds of operations. **Put everything you'll need into the catalog.** Recombee can return item metadata as part of a recommendation response (request the item properties you want back). So anything that will be **displayed in the UI**, used for **analytics**, consumed by **recommender logic**, or referenced by **business rules / filters** should live in the catalog as an item property. If it isn't in the catalog, you can't render it from a recommendation response or filter/boost on it. **Users are catalogued the same way.** The optional user catalog works exactly like the item catalog: define user properties, then set values on them (in bulk via Batch). Populating it is optional — users are also created implicitly when you record their first interaction (see`cascadeCreate` in [Recording interactions](#recording-interactions)) — but user properties are worth setting when you want to filter, boost, or segment on them. --- ## Recording Interactions Interactions are the signal Recombee learns from. Recombee models several **interaction data types**, including: * **Detail view** — user looked at an item. * **Purchase** — user bought an item. * **Rating** — user gave an explicit score. * **Cart addition** — user added an item to a cart. * **Bookmark** — user saved an item. * **View portion** — how much of an item was consumed (e.g. video/article progress). These will **not always map cleanly** onto your application's existing event types. Pick the Recombee type whose _intent_ best matches each of your events rather than forcing a one-to-one mapping, and don't invent semantics a type doesn't have. **Two rules that matter:** * **Always allow entity creation on interactions** (the `cascadeCreate` option) so an event for a brand-new user or item doesn't fail because the entity isn't known yet. * **For any interaction that resulted from a recommendation, always include the`recommId`** from that recommendation's response. This is how Recombee attributes outcomes back to the model that produced them — it's what makes reporting and A/B evaluation meaningful. Thread the `recommId` from the recommendation response through to the interaction call. (And remember [The identity model](#identity-model): the IDs on the interaction must match the ones from the recommendation.) **Writes are not immediately readable.** An interaction takes roughly **5 seconds** to become visible to the listing endpoints (`ListUserDetailViews`, `ListUserRatings`, …). Code that writes an interaction and reads it straight back will see nothing and conclude the write failed. Anywhere you need read-after-write, poll with a timeout (\~30s) rather than asserting once, and distinguish "not visible yet" (lag) from "visible but wrong" (a real bug). The same applies to **Merge Users**: wait for the source user's history to actually land before merging, or there is nothing there to move. **`recommId` values are dash-insensitive.** Recombee may hand back a UUID formatted differently from the one it issued, so never compare `recommId`s with string equality — normalize both sides first (e.g. `id.replaceAll("-", "")`). --- ## Getting Recommendations Use the recommendation request that fits the surface. Requests vary along two axes: **what**you want back (items, users, or item segments) and **what it's based on** (a user, an item, an item segment, or a search query). The request names follow this pattern — e.g. _Recommend Items to User_ for a personalized feed, _Recommend Items to Item_ for related items on a detail page, or _Search Items_ when the user types a query. Consult the SDK/docs for the full set, since the available combinations change. **Every request must name a `scenario` — and you must create it first.** A scenario identifies the surface a recommendation is for ("homepage-rail", "product-detail-related"). This is not a stylistic nicety: scenarios are **never auto-created**, and a request naming one that doesn't exist is rejected outright: ``` {"message": "Scenario does not exist. Please create the Scenario in the Recombee Admin UI"} ← HTTP 403 ``` Scenarios are also where per-surface filters, boosters and recommendation logic are configured, and they're how Recombee reports each surface's performance separately — one shared scenario across every rail throws all of that away. The extra setup step is the intended Recombee workflow, so accept the cost rather than designing around it. Because the integration is **dead until the user creates them**, your setup documentation must list **every scenario ID together with its type** (Ranked List, Composite, …) and its stage configuration. Treat that list as a hard deliverable of the integration, not an appendix. Don't invent that configuration from scratch — find the matching **Scenario Recipe** ([API prerequisites](#api-prerequisites)) and take its recommended logic, parameters, filters, boosters and constraints as your starting point. **Item Segments.** An _item segment_ is a named group of items derived from the catalog — for example a genre, a brand, a topic, or any grouping you define with a ReQL expression over item properties. Alongside recommending individual items, Recombee can **recommend segments**: instead of "which items should this user see," you ask "which topics/brands is this user interested in." Use segments to build things like a personalized list of categories, a "browse by topic" rail ordered per user, or the row _titles_ of a homepage whose contents are then filled with item recommendations. Segments do not have properties or interactions. Check the SDK/docs for the exact segment requests available and how to configure the segmentations themselves (in the Admin UI or via the API). Note that`ListSegmentations` returns an object — `{"segmentations": [...]}` — not a bare array. **Composite Recommendations — reach for these first.** A composite request returns a**source** entity together with the **result** entities recommended for it — for example a source segment ("Science Fiction") plus the result items within it. The source can be based on a user, item, segment, or search query, and the results can be items, users, or segments. The sample response below shows the resulting `source` \+ `recomms` shape. **Whenever a surface is "source + results", use a composite request.** That covers genre and category rails, a personalized 2D homepage (each row is one source with its results), and "Because you liked X". Do **not** hand-roll it as _Recommend Item Segments to User_ followed by _Recommend Items to Item Segment_ — composite is the current idiomatic API for exactly this shape. To fill a page with N rows, send **N composite requests in a single Batch with`distinctRecomms: true`**. That flag is what makes N otherwise-identical requests return N_different_ sources; without it you get N copies of the same top row. **Never set `rotationRate` (with or without `rotationTime`).** Rotation works by penalising items purely for having been recommended recently, which demotes the genuinely best-matching items and can significantly harm recommendation quality. Don't reach for it to make a rail look "fresh" between page loads. If a surface really needs more variety, use `diversity` or configure it at the scenario level, and otherwise let the models rank freely. **Pagination / subsequent pages.** After an initial recommendation, load further pages with**Recommend Next Items** (or **Recommend Next Item Segments** for segment-based rails) rather than re-requesting from scratch. This continues the same recommendation, keeps results consistent, and preserves attribution. **Multiple rails at once.** When instead a page needs several _independent_ recommendation requests together, **batch them into a single request** — it's fewer round trips, lower latency than firing the calls sequentially, and with `distinctRecomms: true`, the results are deduplicated, which is preferred. This applies to both composite and non-composite requests. For example, a homepage with three rails of "Science Fiction", "Romance", and "Mystery" should be a single batch of three _Recommend Items to Item Segment_calls, not three separate calls. A sample recommendation response looks as follows: ``` { "recommId": "ee94fa8b-efe7-4b35-abc6-2bc3456d66ed", "source": { "id": "category-4", "values": { "name": "Science Fiction" } }, "recomms": [ { "id": "item-64", "values": { "title": "The Martian", "author": "Andy Weir" } }, { "id": "item-42", "values": { "title": "Dune", "author": "Frank Herbert" } }, { "id": "item-23", "values": { "title": "Neuromancer", "author": "William Gibson" } } ], "numberNextRecommsCalls": 0 } ``` This JSON is mapped onto the SDK's response objects, but the fields are the same. The `recommId` is the unique identifier for this recommendation response, and must be included in any interaction events that result from it. The `source` object is present only for composite recommendations; a plain request (e.g. _Recommend Items to User_) returns just `recommId` and `recomms`. The `values` object contains the requested item/user properties for each recommended item/user, but is only present if `returnProperties` was set in the request. For requesting only certain properties, use `returnProperties` with `includedProperties`.`numberNextRecommsCalls` reports how many times _Recommend Next Items_ has been called for this `recommId` so far: a single recommendation can be extended by repeated _Recommend Next Items_ calls, each returning further, previously-unrecommended items, and this field tracks how many such calls have happened. --- ## Common Mistakes 1. **Hand-rolling REST + HMAC signing when an SDK exists.** Signing, request shapes, and batching are exactly what the SDKs handle. Check the API clients page first. 2. **Crossing the token/side boundary.** Private token in client code (a full-database leak) or expecting the public token to do server-only work. Keep private→server, public→client. 3. **Inconsistent IDs.** Interaction IDs that don't match recommendation/catalog IDs — see[The identity model](#identity-model). Silent, and corrosive to quality. 4. **Forgetting `recommId`.** Interactions from recommendations without it can't be attributed; your reporting and experiments go dark. 5. **Writing to undefined properties.** Define item/user properties (both namespaces) before writing values; make it part of an idempotent sync. 6. **Hard-coded database fallbacks.** A default DB name masks misconfiguration and can point production at the wrong database. Fail loudly instead. 7. **Error handling that discards the upstream body.** Wrapping failures in a generic`{"error": "request failed"}` throws away the one thing that explains the failure. 8. **Assuming a 404 means "wrong URL".** In Recombee it almost always means "the referenced entity doesn't exist" — read the body (see [Error & edge-case reference](#error-edge-case-reference)). 9. **Infinite client retries on 4xx.** A 4xx is an answer, not an outage. Retry only network errors and 5xx, with a cap. 10. **Sequential uploads / per-rail calls.** Use Batch for catalog sync and for multi-rail recommendation pages. 11. **Omitting `scenario`, or naming one nobody created.** A 403 that stops the surface dead — see [Getting recommendations](#getting-recommendations). Ship the scenario list as part of the setup instructions. 12. **Hand-rolling composite as a segments-then-items two-step.** Use _Composite Recommendation_; batch N of them with `distinctRecomms: true` for N distinct rows. 13. **Using `rotationRate` for "freshness".** It trades real relevance for the appearance of variety. Leave rotation parameters out entirely. 14. **Asserting on an interaction immediately after writing it.** \~5s of read-back lag makes this a false failure; poll instead ([Recording interactions](#recording-interactions)). 15. **Comparing `recommId`s with `---`.** Dashes are not significant — normalize first ([Recording interactions](#recording-interactions)). --- ## Verifying It Works * **Read the response body, always.** Log the status code **and** a snippet of the response body at every Recombee call site. Recombee encodes the reason for a failure in the body; debugging on `status + URL` alone is debugging blind. * **Test the call sites that actually fail — with their real payloads.** A smoke test that only exercises recommendations will pass while catalog or user-property writes fail in production. Replay each distinct call-site payload, not just the convenient endpoints. * **Verify identity end-to-end.** Confirm that the ID on a recorded interaction is identical to the ID that came back in the recommendation the user acted on. This is the check that catches the silent identity-model failures. * **Confirm `recommId` round-trips.** Trace a recommendation's `recommId` all the way into the interaction it produces — comparing on the dash-stripped form. * **Budget for write lag in every check.** Interactions take \~5s to become readable, so any verification that reads back what it just wrote must poll to a \~30s timeout. A test that asserts immediately reports a bug that isn't there and sends you hunting it. * **Check the Admin UI.** After a catalog sync or a batch of interactions, confirm items and events actually appear in the database in the Recombee Admin UI. --- ## Error & Edge-case Reference **The one rule:** Recombee uses HTTP status codes semantically. **Always read the response body before theorizing about a status.** A `404` usually does not mean "wrong URL" — it means "the entity you referenced does not exist," and the body names which one: ``` {"message": "user property \"prefLens\" does not exist!"} ← HTTP 404 ``` **Status → meaning cheat sheet:** | Status | Body says | Actual meaning | Fix | | ------ | ------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | | 401 | invalid token/db | wrong token, wrong DB name, or token↔db mismatch | check the token and DB name together — a valid token for the _wrong_ DB is still 401 | | 404 | ... property "X" does not exist | you wrote to an **undefined property** | define the property first (both item and user namespaces exist) | | 404 | item/user "X" does not exist | referenced entity missing and creation wasn't allowed | enable cascadeCreate on the request | | 403 | Scenario does not exist ... | the request named a scenario that hasn't been created | create it in the Admin UI — scenarios are never auto-created ([Getting recommendations](#getting-recommendations)) | | 405 | Method not allowed | newer clusters reject GET listing endpoints | use the POST equivalents; on an SDK this is handled for you | | 409 | duplicate | the write already happened | treat as success — don't retry | | 400 | Error in expression ... single quotes ... double quotes | ReQL filter quoting: 'x' \= property access, "x" \= string constant | fix the filter; filtering on an undefined property errors the same way | **Batch results are per-entry.** A Batch request can return `200` overall while individual sub-requests inside it fail. Inspect each entry's own status rather than assuming the batch succeeded or failed as a unit. **Retry policy.** Any HTTP response settles the request. Retry only genuine network errors and 5xx, with a small cap. Never retry a 4xx in a loop — an offline queue re-sending a 404 forever produces console noise that masks the real signal. **Two separate property namespaces.** Item properties and user properties are defined independently. It's easy to define all your item properties and forget the user ones; then every user-property write fails in production while item-only smoke tests pass. --- # Property Roles > Source: https://docs.recombee.com/api/property_roles_metadata > For the complete documentation index, see [llms.txt](/llms.txt). **Table of Contents & Filters** DomainAllUniversalVideoMusic & PodcastsArticles, News & MediaData TypeAllStringSetImageImage ListIntegerDoubleTimestamp **Table of Contents** * [Roles](#roles) * [Title](#title) * [Summary](#summary) * [URL](#url) * [Tags](#tags) * [Categories](#categories) * [Category](#category) * [Genres](#genres) * [Genre](#genre) * [Primary image](#primaryimage) * [Price](#price) * [Publish date](#publishdate) # Property Roles Property roles allow you to describe the semantic meaning of your item properties, enabling the recommendation engine to better understand and utilize your data. Property roles are assigned when [adding item properties](/api#add-item-property). ## Roles Roles define the semantic purpose of a property. By assigning a role, you help the recommendation engine understand what kind of information the property holds and how to best use it. #### Title The primary human-readable name of the item. --- ID title --- Data types String #### Summary A short textual description of the item, providing additional context or details beyond the title. --- ID summary --- Data types String #### URL A canonical web address pointing to the item’s detail page or primary location, used for navigation and linking from user interfaces. --- ID url --- Data types String #### Tags A set of descriptive keywords or labels assigned to the item. --- ID tags --- Data types Set #### Categories A set of categories describing the item’s placement within a taxonomy. Multiple values are allowed. --- ID categories --- Data types Set --- Cannot be used with category #### Category A single primary category describing the item’s placement within a taxonomy. --- ID category --- Data types String --- Cannot be used with categories #### Genres A set of genres describing the content type or style of the item (e.g. drama, comedy, rock). --- ID genres --- Data types Set --- Available in domains Video, Music & Podcasts --- Cannot be used with genre #### Genre A single primary genre describing the content type or style of the item (e.g. drama, comedy, rock). --- ID genre --- Data types String --- Available in domains Video, Music & Podcasts --- Cannot be used with genres #### Primary image The main visual representation of the item. --- ID primaryImage --- Data types Image Image List #### Price The monetary value of the item. --- ID price --- Data types Integer Double #### Publish date The timestamp indicating when the item was made publicly available. --- ID publishDate --- Data types Timestamp --- Available in domains Articles, News & Media --- # Authentication (HMAC) > Source: https://docs.recombee.com/authentication > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Hash Examples](#hash-examples) * [Authentication of Client-Side Requests](#authentication-of-client-side-requests) * [Postman](#postman) * [Example Implementations](#example-implementations) * [Python](#python) * [Ruby](#ruby) * [PHP](#php) * [Java](#java) * [JavaScript](#javascript) # Authentication (HMAC) The authentication is already implemented in the [API clients (SDKs)](/api_clients). **HMAC-based authentication** is the single preferred way of authentication to Recombee APIs. Thanks to the nature of our APIs, our authentication is based on a simple shared-secret approach with the signature generated according to the HMAC-SHA1 standard. To use HMAC-based authentication, you will need a token, which you can obtain in the [Recombee Admin UI](/admin_ui). In the case of a server-side implementation, use the _Private Token_ (which needs to remain secret and known only to you and Recombee), and in the case of a client-side implementation (e.g. in a mobile app), use the_Public Token_ (see [this section](#authentication-of-client-side-requests) for details). **There are two query parameters that you need to attach to every API call:** * `hmac_timestamp` \- the current UTC Unix timestamp (integer) * `hmac_sign` \- the signature computed from your request URI without protocol and host Every signature has a limited lifetime (currently 30s). It is therefore important for your server time to be synchronized via NTP or other source of precise time. For example, let's consider a call to the following URL: ``` https://rapi.recombee.com/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7 ``` The initial input to the signing method does not contain the protocol and host parts. We'll also add the `hmac_timestamp` parameter: ``` /recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7&hmac_timestamp=1396859079 ``` We then compute the signature of the above string and append it as the `hmac_sign` parameter. The result should then look like this: ``` /recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7&hmac_timestamp=1396859079&hmac_sign=c608b597456d0760aee0e5a95017c63a8a24b4eb ``` ## Hash Examples To see whether you are hashing properly, you can try to hash the following strings and verify the results: ``` TOKEN = "gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G" ``` | String | Hash | | ------------------------------------------------------------------------------------------------------------------ | ---------------------------------------- | | Hello world | 1291b164d8332792233dcc8ce94e1c9ea6113fb8 | | /recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7&hmac\_timestamp=1398463889 | 090eafba456488622a6d6f0dc37d3a1508536338 | As mentioned above, the hash is calculated from the URL with the`hmac_timestamp` and **without** the domain or protocol. **Example of a _correct_ hash string:** ``` /recombee/items/9346/recomms/?count=5 &targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7 &hmac_timestamp=1398463889 ``` **Example of an _incorrect_ hash string:** ``` https://rapi.recombee.com/recombee/items/9346/recomms/?count=5 &targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7 &hmac_timestamp=1398463889 ``` ## Authentication of Client-Side Requests The same authentication method is used also for client-side (frontend) requests. **The differences are as follows:** * The _Public Token_ is used for signing, * The parameters have different names - use `frontend_timestamp` instead of`hmac_timestamp` and `frontend_sign` instead of `hmac_sign`, * The RAPI endpoint is at `client-rapi.recombee.com`. See [this example](#JavaScript-authentication-example). ## Postman If you want to call the Recombee API using [Postman](https://www.postman.com/), you can use the following script to authenticate your requests:. ## Example Implementations The description itself can be a bit cumbersome, but the actual implementations are very simple and straightforward: ### Python ``` import time import hmac from hashlib import sha1 key = 'gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G' url = '/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7'\ '&hmac_timestamp=%s' % int(time.time()) sign = hmac.new(str.encode(key), str.encode(url), sha1).hexdigest() print('%s&hmac_sign=%s' % (url, sign)) ``` ### Ruby ``` require 'securerandom' require 'digest/hmac' KEY = "gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G" url = '/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7' + "&hmac_timestamp=#{Time.now.utc.to_i}" sign = Digest::HMAC.hexdigest(url, KEY, Digest::SHA1) puts "#{url}&hmac_sign=#{sign}" ``` ### PHP ``` $key = 'gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G'; $url = '/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7'; $url = $url . '&hmac_timestamp=' . time(); $sign = hash_hmac("sha1", $url, $key); echo $url . "&hmac_sign=" . $sign; ``` ### Java ``` import org.apache.commons.codec.binary.Hex; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; String key = "gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G"; String url = "/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7"+ "&hmac_timestamp="+System.currentTimeMillis() / 1000; Mac mac = Mac.getInstance("HmacSHA1"); SecretKeySpec secret = new SecretKeySpec(key.getBytes(),"HmacSHA1"); mac.init(secret); byte[] rawHmac = mac.doFinal(url.getBytes()); String sign = Hex.encodeHexString(rawHmac); System.out.println(url+"&hmac_sign="+sign); ``` ### JavaScript Using `sha1.js` from [jsSHA](https://github.com/Caligatio/jsSHA/). ``` ``` --- # Go API Client > Source: https://docs.recombee.com/go_client > For the complete documentation index, see [llms.txt](/llms.txt). # Go API Client [GitHubInstallation info and more examples](https://github.com/Recombee/go-api-client)[API ReferenceList of all available endpoints with examples](/api) Example Go ``` package main import ( "fmt" "math/rand" "os" "github.com/recombee/go-api-client/v6/recombee" "github.com/recombee/go-api-client/v6/recombee/requests" ) func main() { client, err := recombee.NewRecombeeClient("--your-database-id--", "--your-db-private-token--", "us-west") if err != nil { fmt.Println(err) panic(err) } const numItemsAndUsers = 100 const probabilityInteracted = 0.1 var addDetailViewInteractions []requests.Request for i := 0; i < numItemsAndUsers; i++ { for j := 0; j < numItemsAndUsers; j++ { if rand.Float64() < probabilityInteracted { userId := fmt.Sprintf("user-%d", i) itemId := fmt.Sprintf("item-%d", j) request := client.NewAddDetailView(userId, itemId).SetCascadeCreate(true) addDetailViewInteractions = append(addDetailViewInteractions, request) } } } fmt.Println("Send all interactions in Batch") batchRes, err := client.NewBatch(addDetailViewInteractions).Send() if err != nil { fmt.Println(err) panic(err) } fmt.Println(batchRes) // Contains responses for all requests // Get 5 recommendations for user 'user-25' recommendReq := client.NewRecommendItemsToUser("user-25", 5).SetCascadeCreate(true) recommendRes, err := recommendReq.Send() if err != nil { fmt.Println(err) panic(err) } fmt.Println("Recommended items:") for _, rec := range recommendRes.Recomms { fmt.Println(rec.Id) } // User scrolled down - get next 3 recommended items fmt.Println("Next recommended items:") recommendNextRes, err := client.NewRecommendNextItems(recommendRes.RecommId, 3).Send() if err != nil { fmt.Println(err) panic(err) } for _, rec := range recommendNextRes.Recomms { fmt.Println(rec.Id) } } ``` --- # Java API Client > Source: https://docs.recombee.com/java_client > For the complete documentation index, see [llms.txt](/llms.txt). # Java API Client [GitHubInstallation info and more examples](https://github.com/Recombee/java-api-client)[API ReferenceList of all available endpoints with examples](/api) Example Java ``` RecombeeClient client = new RecombeeClient("--your-database-id--", "--your-db-private-token--").setRegion(Region.US_WEST); try { final int NUM = 100; // Generate some random purchases of items by users final double PROBABILITY_PURCHASED = 0.1; Random r = new Random(); ArrayList addPurchaseRequests = new ArrayList(); for (int i = 0; i < NUM; i++) for (int j = 0; j < NUM; j++) if (r.nextDouble() < PROBABILITY_PURCHASED) { AddPurchase request = new AddPurchase(String.format("user-%s", i),String.format("item-%s", j)) .setCascadeCreate(true); // Use cascadeCreate parameter to create // the yet non-existing users and items addPurchaseRequests.add(request); } System.out.println("Send purchases"); client.send(new Batch(addPurchaseRequests)); //Use Batch for faster processing of larger data // Get 5 recommendations for user 'user-25' RecommendationResponse recommendationResponse = client.send(new RecommendItemsToUser("user-25", 5)); System.out.println("Recommended items:"); for(Recommendation rec: recommendationResponse) System.out.println(rec.getId()); // User scrolled down - get next 3 recommended items recommendationResponse = client.send(new RecommendNextItems(recommendationResponse.getRecommId(), 3)); System.out.println("Next recommended items:"); for(Recommendation rec: recommendationResponse) System.out.println(rec.getId()); } catch (ApiException e) { e.printStackTrace(); //use fallback } ``` --- # JavaScript API Client > Source: https://docs.recombee.com/js_client > For the complete documentation index, see [llms.txt](/llms.txt). # JavaScript API Client **Table of contents** * [Install](#install) * [Configure](#configure) * [Send Interactions](#send-interactions) * [Get Recommendations](#get-recommendations) * [Personalized Search](#personalized-search) * [Recommend Next Items](#recommend-next-items) * [Batch Requests](#batch-requests) * [Optional Parameters](#optional-parameters) * [Error Handling](#error-handling) * [Integration Example](#integration-example) * [1\. Create a Recombee Account](#-create-a-recombee-account) * [2\. Upload the Catalog](#-upload-the-catalog) * [3\. Integrate Recombee into Your Website](#-integrate-recombee-into-your-website) * [Identifying Users Using Google Analytics](#identifying-users-using-google-analytics) This library allows you to request recommendations and send interactions between users and items (such as views, bookmarks, or purchases) to Recombee. It is a thin wrapper around the [Recombee API](/api) and provides a simple way to interact with it. Client-side SDK This SDK is designed for use in browser-based or other client-side applications, including frameworks like React Native and NativeScript. For server-side integration with the Recombee API, use our dedicated [Node.js library](https://github.com/recombee/node-api-client)or other available [server-side SDKs](/api_clients#server-side). To use this client-side SDK in a full-stack framework (e.g., Nuxt or Next.js), additional configuration is required. See [Usage in Full-stack frameworks](#usage-in-full-stack-frameworks) for more information. For security reasons, it is not possible to change the item catalog, such as the properties of items, using this SDK. To send your Catalog to Recombee, use one of the following methods: * Use one of our server-side SDKs, for example using a script which runs periodically (see [Managing Item Catalog](/getting_started#getting-started-catalog) for more details), * Or set up a [Catalog Feed](/catalog_feeds) in the [Admin UI](https://admin.recombee.com/). [GitHubSee the implementation, contribute, or report issues](https://github.com/Recombee/js-api-client)[API ReferenceList of all available endpoints with examples](/api) ## Install There are two ways to include the library in your project: **1\. ``` If you require, you can download [recombee-api-client.min.js](https://github.com/recombee/js-api-client/blob/master/dist/recombee-api-client.min.js) and host it on your site or CDN. ``` ``` After this script is included, you can access the API Client using the global `recombee` object. Alternatively, if you want to use the library in ESM code, you can import `recombee-api-client.min.mjs` as follows: ``` ``` **2\. Package managers:** Alternatively, you can install the SDK via a package manager: ```npm npm install recombee-js-api-client ``` ```yarn yarn add recombee-js-api-client ``` ```pnpm pnpm add recombee-js-api-client ``` ```bun bun add recombee-js-api-client ``` Afterwards, you can import the `recombee` object as follows: ``` import recombee from 'recombee-js-api-client' // or const recombee = require('recombee-js-api-client'); ``` The library ships with types, so you should get autocompletion in your IDE out of the box. If you're using TypeScript, it should recognize these correctly and warn you about any type errors. ## Configure In order to use the API, you will need to create an instance of the `ApiClient` class. You will need: * the **ID of your database**, * the **public token**. You can find these in the Admin UI, in [your Database's Settings page](https://admin.recombee.com/go-to-database/settings), under **API ID & Tokens**. Along with this information, you can also find the full code snippet for initializing the client, including the above-mentioned parameters. Ideally, you should only have one instance of the `ApiClient` in your application, as it is a lightweight object and can be reused for multiple requests. Feel free to export it from a module and import it wherever you need it. ``` // Initialize the API client with the ID of your database and the associated PUBLIC token export const client = new recombee.ApiClient('database-id', '...db-public-token...', { region: 'us-west', // the region of your database (default: 'eu-west') }); ``` You can also set several optional parameters when initializing the client: ``` const client = new recombee.ApiClient('database-id', '...db-public-token...', { // Use this if you were assigned a custom URI by the Recombee Support team (default: none) baseUri: 'custom-uri.recombee.com', // Whether to use HTTPS - can be used for debugging (default: true) useHttps: true, } ); ``` ## Send Interactions After you have initialized the client, you can send interactions between users and items. The individual interactions are classes within the `recombee` object (e.g. `recombee.AddBookmark`, `recombee.AddPurchase`, etc.). After you create an instance of the interaction, you can send it using the `send` method of the client. Each interaction has both mandatory and optional parameters. The most important optional parameter is `recommId` \- the ID of the recommendation to which the interaction belongs. Providing this ID allows you to track successful recommendations. For more information, read about [Reported Metrics](/admin_ui#reported-metrics). For a full list of interactions, along with their parameters, refer either to the types in the library or the [API Reference](/api). ``` // Either create the interaction first and then send it const bookmark = new recombee.AddBookmark('user-13434', 'item-256'); await client.send(bookmark); // Or send it directly await client.send(new recombee.AddCartAddition('user-4395', 'item-129', { recommId: '23eaa09b-0e24-4487-ba9c-8e255feb01bb', })); await client.send(new recombee.AddDetailView('user-9318', 'item-108')); await client.send(new recombee.AddPurchase('user-7499', 'item-750')); await client.send(new recombee.AddRating('user-3967', 'item-365', 0.5)); await client.send(new recombee.SetViewPortion('user-4289', 'item-487', 0.3)); ``` If you want to send multiple interactions at once, you can use the `Batch` request: ``` const batch = new recombee.Batch([ new recombee.AddBookmark('user-13434', 'item-256'), new recombee.AddCartAddition('user-4395', 'item-129', { cascadeCreate: true }), new recombee.AddDetailView('user-9318', 'item-108'), ]); await client.send(batch); ``` You can then use `try/catch` to handle any errors that may occur. ``` try { await client.send( new recombee.AddPurchase('user-14125', 'item-137', { cascadeCreate: true }) ); console.log('Purchase sent'); } catch (err) { console.error('Error sending purchase:', err); } // Console: Purchase sent ``` ## Get Recommendations With an initialized client, you can also request recommendations. There are multiple types of recommendations, such as: * [Recommend Items to User](/api#recommend-items-to-user), * [Recommend Items to Item](/api#recommend-items-to-item), * [Recommend Item Segments to User](/api#recommend-item-segments-to-user) (these can be categories, genres, artists, etc.), * or [others](/api#recommendations). Each recommendation request is a class within the `recombee` object (e.g. `recombee.RecommendItemsToUser`, `recombee.RecommendItemsToItem`, etc.). After you create an instance of the recommendation request, you can send it using the `send` method of the client. | Promise | | | ---------- | --------------------------------- | | On success | Return value is a Response object | | On error | Throws an Error | ``` // Get 5 recommendations related to 'item-356' for 'user-13434' const response = await client.send( new recombee.RecommendItemsToItem("item-356", "user-13434", 5) ); console.log(response); // { // recommId: 'f080784b-1e8b-4328-8d59-28d962301007', // recomms: [ // { // id: 'item-123', // values: { title: 'Product 123', img_url: 'https://example.com/img123.jpg' } // }, // { // id: 'item-456', // values: { title: 'Product 456', img_url: 'https://example.com/img456.jpg' } // }, // ... // ] // } ``` For a full list of request parameters and possible responses, visit the [API Reference](/api#recommendations). ### Personalized Search [Personalized full-text search](/api#search-items) is requested in the same way as recommendations: ``` const searchQuery = " ... search query from search field ...."; const response = await client.send( new recombee.SearchItems("user-13434", searchQuery, 5) ); console.log(response); // { // recommId: 'f080784b-1e8b-4328-8d59-28d962301007', // recomms: [ // { // id: 'item-123', // values: { title: 'Product 123', img_url: 'https://example.com/img123.jpg' } // }, // { // id: 'item-456', // values: { title: 'Product 456', img_url: 'https://example.com/img456.jpg' } // }, // ... // ] // } ``` ### Recommend Next Items If you are implementing features like infinite scroll or pagination, you can use the `RecommendNextItems` request to load recommendations progressively. This means you can fetch the next set of recommended items without repeating the ones you have already displayed. To use this functionality, you must provide the `recommId` from the initial recommendation request. For more details, see the [Recommend Next Items](/api#recommend-next-items) documentation. ``` // Fetch the initial set of 5 recommendations for user-13434 const initialRecomms = await client.send( new recombee.RecommendItemsToUser("user-13434", 5) ); // Get the next 3 recommendations as user-13434 scrolls down const nextRecomms = await client.send( new recombee.RecommendNextItems(initialRecomms.recommId, 3) // Use the recommId from the previous request ^ ); ``` ### Batch Requests You may encounter a situation where you display recommendations in multiple places on your website. In such cases, you can use the `Batch` request to send multiple recommendation requests at once. This can help reduce the number of HTTP requests and improve performance. For example, you can request the most popular items, as well as items related to a specific user or item, in a single Batch: ``` const batch = new recombee.Batch( [ new recombee.RecommendItemsToItem("item-356", "user-13434", 5, { scenario: "because-you-watched" }), new recombee.RecommendItemsToUser("user-13434", 5, { scenario: "new-releases" }), new recombee.RecommendItemsToUser("user-13434", 5, { scenario: "popular" }), ], { distinctRecomms: true, } ); const responses = await client.send(batch); for (const response of responses) { console.log("Because You Watched:", response[0]); // Because You Watched: { recommId: '...', recomms: [ ... ] } console.log("New Releases:", response[1]); // New Releases: { recommId: '...', recomms: [ ... ] } console.log("Popular:", response[2]); // Popular: { recommId: '...', recomms: [ ... ] } } ``` The optional parameter `distinctRecomms` of the `Batch` ensures that the recommended items are not repeated across the responses. You can find more information about Batch requests in the [API Reference](/api#batch). ### Optional Parameters Recommendation requests support various optional parameters to customize their behavior. For a comprehensive list, refer to the [API Reference](/api#recommendations). Below is an example showcasing some commonly used parameters: ``` const response = await client.send(new recombee.RecommendItemsToUser('user-13434', 5, { // Scenarios help identify the context where recommendations are displayed // and can be customized in the Admin UI at https://admin.recombee.com scenario: 'homepage', // Include detailed properties of the recommended items in the response returnProperties: true, // Specify which properties to include (requires returnProperties = true) includedProperties: ['title', 'img_url', 'url', 'price'], // Apply a ReQL filter to refine recommendations, // e.g., "Recommend only items with a title that are in stock." filter: "'title' != null AND 'availability' == \"in stock\"" // Note: You can define scenario-specific filters in the Admin UI. } )); ``` ## Error Handling The API client throws errors when an error occurs. The possible errors are: | Error | Cause | | ------------------------------ | ------------------------------------------------------- | | ApiError | Base class for all errors | | ResponseError extends ApiError | The API returned an error code (e.g. invalid parameter) | | TimeoutError extends ApiError | Request timed out | We are doing our best to provide a reliable service, but sometimes things can go wrong. For this reason, we recommend that you always handle exceptions and provide fallbacks in your application. For example, when requesting recommendations, a fallback could be to display a generic set of items or an error message to the user. ## Integration Example ### 1\. Create a Recombee Account To follow this example, you'll need a Recombee account. If you don't already have one, you can [sign up for free](https://admin.recombee.com/sign-up). If you weren't invited to an existing Organization or Database, Recombee will automatically create one for you during registration. ### 2\. Upload the Catalog The next step is to upload your item catalog to Recombee. You can do this using one of the following methods: * API-based upload: Follow the instructions in our [Managing Item Catalog guide](/getting_started#getting-started-catalog). * Catalog Feed: Set up a feed in the [Admin UI](https://admin.recombee.com/). For this tutorial, we'll use a sample Google Merchant product feed. You can find the sample file at this URL: ``` https://raw.githubusercontent.com/recombee/js-api-client/refs/heads/master/examples/product_feed_sample.xml ``` After adding the feed to the Admin UI and waiting for it to process, you'll be able to see the uploaded items in the Items section of your Database. ### 3\. Integrate Recombee into Your Website Let's assume we want to show recommendations on the product page of item `product-270` to a user with the ID `user-1539`. The following code example uses HTML and vanilla JavaScript to send the Detail View interaction of the product by the user and request 3 related items from the Recombee API: index.html ``` Recombee Integration Example

Related products

``` main.js ``` // A simple function for rendering a box with the recommended product function showProduct(title, description, link, imageLink, price) { return [ `
`, `
`, ` Image of ${title}`, `
`, `
${title}
`, `
Price: $${price}
`, `

${description}

`, ` See Details

`, `
`, `
`, `
`, ].join('\n'); } // Initialize client const client = new recombee.ApiClient( 'js-client-example', 'dXx2Jw4VkkYQP1XU4JwBAqGezs8BNzwhogGIRjDHJi39Yj3i0tWyIZ0IhKKw5Ln7', { region: 'eu-west' }, ); const itemId = 'product-270'; const userId = 'user-1539'; // Send Detail View void client.send(new recombee.AddDetailView(userId, itemId)); try { // Request recommended items const response = await client.send( new recombee.RecommendItemsToItem(itemId, userId, 3, { returnProperties: true, includedProperties: ['title', 'description', 'link', 'image_link', 'price'], filter: "'title' != null AND 'availability' == \"in stock\"", scenario: 'related_items', }), ); // Show recommendations const recomms_html = response.recomms .map((r) => r.values) .map((vals) => showProduct( vals['title'], vals['description'], vals['link'], vals['image_link'], vals['price'], ), ); document.getElementById('relatedProducts').innerHTML = recomms_html.join('\n'); } catch (err) { console.error('Could not load recomms: ', err); } ``` You should see something like this: ![](/img/api_clients/js_example_result.png) Notice how the properties returned by `returnProperties`, in combination with `includedProperties`, were used to show titles, images, descriptions and URLs. ### Identifying Users Using Google Analytics In order to achieve personalization, you need a unique identifier for each user. One of the ways to achieve this can be using Google Analytics. You would need to add the following to the previous example: index.html ``` ``` main.js ``` const client = new recombee.ApiClient(/* ... */); // Optional check: if you want to ensure gtag is defined // (this is often not necessary if you define gtag in HTML as shown) if (typeof gtag !== 'function') { window.dataLayer = window.dataLayer || []; function gtag() { dataLayer.push(arguments); } } // Initialize GA4 gtag('js', new Date()); gtag('config', 'G-XXXXXXXXXX'); // Replace with your GA4 measurement ID gtag('get', 'G-XXXXXXXXXX', 'client_id', async (clientId) => { void client.send(new recombee.AddDetailView(clientId, itemId)); try { const response = await client.send( new recombee.RecommendItemsToUser(clientId, 3, { returnProperties: true, includedProperties: ['title', 'description', 'link', 'image_link', 'price'], filter: "'title' != null AND 'availability' == \"in stock\"", scenario: 'homepage', }), ); const recomms = response.recomms; // ... } catch (error) { // Handle errors } }); ``` This example uses the [Recommend Items to User](/api#recommend-items-to-user) API endpoint. You can use this recommendation type in various places, such as on your homepage. --- # Kotlin API Client > Source: https://docs.recombee.com/kotlin_client > For the complete documentation index, see [llms.txt](/llms.txt). # Kotlin API Client **Table of contents** * [Install](#install) * [Configure](#configure) * [Send Interactions](#send-interactions) * [Get Recommendations](#get-recommendations) * [Personalized Search](#personalized-search) * [Recommend Next Items](#recommend-next-items) * [Batch Requests](#batch-requests) * [Optional Parameters](#optional-parameters) * [Error Handling](#error-handling) This library allows you to request recommendations and send interactions between users and items (such as views, bookmarks, or purchases) to Recombee. It is a thin wrapper around the [Recombee API](/api) and provides a simple way to interact with it. Client-side SDK This SDK is designed for usage in Android applications or other client-side applications (e.g. Compose Multiplatform). For server-side integration with the Recombee API, use our dedicated [Java library](https://github.com/recombee/java-api-client)or other available [server-side SDKs](/api_clients#server-side). For security reasons, it is not possible to change the item catalog, such as the properties of items, using this SDK. To send your Catalog to Recombee, use one of the following methods: * Use one of our server-side SDKs, for example using a script which runs periodically (see [Managing Item Catalog](/getting_started#getting-started-catalog) for more details), * Or set up a [Catalog Feed](/catalog_feeds) in the [Admin UI](https://admin.recombee.com/). [GitHubSee the implementation, contribute, or report issues](https://github.com/Recombee/kotlin-api-client)[API ReferenceList of all available endpoints with examples](/api) ## Install The client is available in the [Maven Central Repository](https://mvnrepository.com/artifact/com.recombee/apiclientkotlin/), which [is included](https://developer.android.com/build/remote-repositories) in new Android projects by default. Adding the client into your project is therefore as simple as adding the dependency into your `build.gradle`: ```kotlindsl dependencies { implementation("com.recombee:apiclientkotlin:6.2.0") } ``` ```versioncatalogkotlindsl --- libs.versions.toml --- [versions] recombee = "6.2.0" [libraries] recombee = { group = "com.recombee", name = "apiclientkotlin", version.ref = "recombee" } --- build.gradle.kts --- dependencies { implementation(libs.recombee) } ``` ```groovydsl dependencies { implementation "com.recombee:apiclientkotlin:6.2.0" } ``` You can then find all the classes and methods in the `com.recombee.apiclientkotlin` package and its subpackages. ## Configure In order to use the API, you will need to create an instance of the `RecombeeClient` class. You will need: * the **ID of your database**, * the **public token**. You can find these in the Admin UI, in [your Database's Settings page](https://admin.recombee.com/go-to-database/settings), under **API ID & Tokens**. Along with this information, you can also find the full code snippet for initializing the client, including the above-mentioned parameters. Ideally, you should only have one instance of the `RecombeeClient` in your application, as it is a lightweight object and can be reused for multiple requests. Tip We published a simple [Android example app](https://github.com/recombee/android-demo) to help you with the integration. Feel free to use it as a reference. ![](/img/api_clients/android_demo.png) You can initialize the client as follows: ``` import com.recombee.apiclientkotlin.RecombeeClient import com.recombee.apiclientkotlin.util.Region // Initialize the API client with the ID of your database and the associated PUBLIC token val client = RecombeeClient( databaseId = "database-id", publicToken = "...db-public-token...", region = Region.UsWest // the region of your database ) ``` You can also set several optional parameters when initializing the client: ``` val client = RecombeeClient( // Required parameters: databaseId = "database-id", publicToken = "...db-public-token...", // Optional parameters: // Use this if you were assigned a custom URI by the Recombee Support team (default: null) baseUri = "custom-uri.recombee.com", // The port to connect to (default: null) port = 443, // Whether to use HTTPS - can be used for debugging (default: true) useHttpsByDefault = true, ) ``` ## Send Interactions After you have initialized the client, you can send interactions between users and items. The individual interactions are classes within the `com.recombee.apiclientkotlin.requests` package. After you create an instance of the interaction, you can send it using one of two methods of the `RecombeeClient` class: * `send` \- for callbacks * `sendAsync` \- for coroutines (must be called from inside a `CoroutineScope`) Each interaction has both mandatory and optional parameters. The most important optional parameter is `recommId` \- the ID of the recommendation to which the interaction belongs. Providing this ID allows you to track successful recommendations. For more information, read about [Reported Metrics](/admin_ui#reported-metrics). For a full list of interactions, along with their parameters, refer to the [API Reference](/api). ``` import com.recombee.apiclientkotlin.requests.* // Either create the interaction first and then send it val bookmark = AddBookmark(userId = "user-13434", itemId = "item-256") client.send(bookmark) // Or send it directly client.send( AddCartAddition( userId = "user-4395", itemId = "item-129", recommId = "23eaa09b-0e24-4487-ba9c-8e255feb01bb", ) ) client.send(AddDetailView(userId = "user-9318", itemId = "item-108")) client.send(AddPurchase(userId = "user-7499", itemId = "item-750")) client.send(AddRating(userId = "user-3967", itemId = "item-365", rating = 0.5)) client.send(SetViewPortion(userId = "user-4289", itemId = "item-487", portion = 0.3)) ``` If you want to send multiple interactions at once, you can use the `Batch` request: ``` import com.recombee.apiclientkotlin.requests.* val batch = Batch(listOf( AddBookmark(userId = "user-13434", itemId = "item-256"), AddCartAddition(userId = "user-4395", itemId = "item-129", cascadeCreate = true), AddDetailView(userId = "user-9318", itemId = "item-108"), )) client.send(batch) ``` You can then use callbacks (or `Result`) to handle any exceptions that may occur. ```callback client.send( AddRating( userId = "user-3967", itemId = "item-365", rating = 0.5, cascadeCreate = true ), { println("Interaction sent successfully") }, { exception: ApiException -> println("Exception: $exception") // use fallback ... } ) ``` ```coroutine val response = client.sendAsync( AddRating( userId = "user-3967", itemId = "item-365", rating = 0.5, cascadeCreate = true ) ) if (response.isFailure) { println("Exception: ${response.exceptionOrNull()}") // use fallback ... } else { println("Interaction sent successfully") } ``` ## Get Recommendations With an initialized client, you can also request recommendations. There are multiple types of recommendations, such as: * [Recommend Items to User](/api#recommend-items-to-user), * [Recommend Items to Item](/api#recommend-items-to-item), * [Recommend Item Segments to User](/api#recommend-item-segments-to-user) (these can be categories, genres, artists, etc.), * or [others](/api#recommendations). Each recommendation request is a class within the `com.recombee.apiclientkotlin.requests` package. After you create an instance of the recommendation request, you can send it using the `send` or `sendAsync` methods of the client (depending on whether you want to use callbacks or coroutines). ```callback val request = RecommendItemsToUser( userId = "user-x", count = 10, scenario = "homepage-for-you" ) client.send(request, { recommendationResponse: RecommendationResponse -> println("recommId: ${recommendationResponse.recommId}") for (recommendedItem in recommendationResponse.recomms) { println("ID: ${recommendedItem.id}") } }, { exception: ApiException -> println("Exception: $exception") // use fallback ... } ) ``` ```coroutine val request = RecommendItemsToUser( userId = "user-x", count = 10, scenario = "homepage-for-you" ) val response = client.sendAsync(request) response.onSuccess { recommendationResponse: RecommendationResponse -> println("recommId: ${recommendationResponse.recommId}") for (recommendedItem in recommendationResponse.recomms) { println("ID: ${recommendedItem.id}") } }.onFailure { exception -> // ApiException println("Exception: $exception") // use fallback ... } ``` For a full list of request parameters and possible responses, visit the [API Reference](/api#recommendations). ### Personalized Search [Personalized full-text search](/api#search-items) is requested in the same way as recommendations: ```callback val searchQuery = " ... search query from search field ...." val request = SearchItems( userId = "user-x", searchQuery = searchQuery, count = 10, scenario = "search", returnProperties = true ) client.send(request, { searchResponse: SearchResponse -> println("recommId: ${searchResponse.recommId}") for (recommendedItem in searchResponse.recomms) { println("ID: ${recommendedItem.id} Values: ${recommendedItem.getValues()}") } }, { exception: ApiException -> println("Exception: $exception") // use fallback ... } ) ``` ```coroutine val searchQuery = " ... search query from search field ...." val request = SearchItems( userId = "user-x", searchQuery = searchQuery, count = 10, scenario = "search", returnProperties = true ) val response = client.sendAsync(request) response.onSuccess { searchResponse: SearchResponse -> println("recommId: ${searchResponse.recommId}") for (recommendedItem in searchResponse.recomms) { println("ID: ${recommendedItem.id} Values: ${recommendedItem.getValues()}") } }.onFailure { exception -> // ApiException println("Exception: $exception") // use fallback ... } ``` ### Recommend Next Items If you are implementing features like infinite scroll or pagination, you can use the `RecommendNextItems` request to load recommendations progressively. This means you can fetch the next set of recommended items without repeating the ones you have already displayed. To use this functionality, you must provide the `recommId` from the initial recommendation request. For more details, see the [Recommend Next Items](/api#recommend-next-items) documentation. ``` var initialRecommId: String? = null // Fetch the initial set of 5 recommendations for user-13434 val initialRecomms = client.sendAsync(RecommendItemsToUser("user-1", 5)) initialRecomms.onSuccess { it -> // Store the recommId to be used by the next request initialRecommId = it.recommId // Display recommendations } // Get the next 3 recommendations as user-13434 scrolls down initialRecommId?.let { recommId -> val nextRecomms = client.sendAsync(RecommendNextItems(recommId, 5)) nextRecomms.onSuccess { TODO() } } ``` ### Batch Requests You may encounter a situation where you display recommendations in multiple places on your website. In such cases, you can use the `Batch` request to send multiple recommendation requests at once. This can help reduce the number of HTTP requests and improve performance. For example, you can request the most popular items, as well as items related to a specific user or item, in a single Batch: ``` val batch = Batch( requests = listOf( RecommendItemsToItem( targetUserId = "user-13434", itemId = "item-356", count = 10, scenario = "because-you-watched", returnProperties = true, includedProperties = listOf("title", "images"), ), RecommendItemsToUser( userId = "user-13434", count = 10, scenario = "new-releases", returnProperties = true, includedProperties = listOf("title", "images"), ), RecommendItemsToUser( userId = "user-13434", count = 10, scenario = "popular", returnProperties = true, includedProperties = listOf("title", "images"), ), ), distinctRecomms = true, ) val result = client.sendAsync(batch) if (result.isFailure) { return listOf() } val data = result.getOrElse { listOf() } val sections: List> = data.map { if (!it.successful) listOf() else { val response = it.getResponse() as RecommendationResponse response.recomms.map { item -> Item( id = item.id, title = item.getValues()["title"] as? String ?: "", images = item.getValues()["images"] as? List ?: listOf(), recommId = response.recommId, ) } } } println("Because You Watched: ${sections[0]}") // Because You Watched: [Item(id=..., title=..., ...), ...] println("New Releases: ${sections[1]}") // New Releases: [Item(id=..., title=..., ...), ...] println("Popular: ${sections[2]}") // Popular: [Item(id=..., title=..., ...), ...] ``` The optional parameter `distinctRecomms` of the `Batch` ensures that the recommended items are not repeated across the responses. You can find more information about Batch requests in the [API Reference](/api#batch). ### Optional Parameters Recommendation requests support various optional parameters to customize their behavior. For a comprehensive list, refer to the [API Reference](/api#recommendations). Below is an example showcasing some commonly used parameters: ``` val request = RecommendItemsToUser( userId = "user-13434", count = 5, // Scenarios help identify the context where recommendations are displayed // and can be customized in the Admin UI at https://admin.recombee.com scenario = "homepage", // Include detailed properties of the recommended items in the response returnProperties = true, // Specify which properties to include (requires returnProperties = true) includedProperties = listOf("title", "img_url", "url", "price"), // Apply a ReQL filter to refine recommendations, // e.g., "Recommend only items with a title that are in stock." filter = "'title' != null AND 'availability' == \"in stock\"" // Note: You can define scenario-specific filters in the Admin UI. ) ``` ## Error Handling The API client throws exceptions when an error occurs. The exceptions are part of the `com.recombee.apiclientkotlin.exceptions` package. The possible exceptions are: | Exception | Cause | | ------------------------------------ | ------------------------------------------------------- | | ApiException | Base class for all exceptions | | ResponseException : ApiException | The API returned an error code (e.g. invalid parameter) | | ApiIOException : ApiException | Request failed (e.g. network issues) | | ApiTimeoutException : ApiIOException | Request timed out | We are doing our best to provide a reliable service, but sometimes things can go wrong. For this reason, we recommend that you always handle exceptions and provide fallbacks in your application. For example, when requesting recommendations, a fallback could be to display a generic set of items or an error message to the user. --- # .NET API Client > Source: https://docs.recombee.com/net_client > For the complete documentation index, see [llms.txt](/llms.txt). # .NET API Client [GitHubInstallation info and more examples](https://github.com/Recombee/net-api-client)[API ReferenceList of all available endpoints with examples](/api) Example .NET ``` using System; using System.Collections.Generic; using System.Linq; using Recombee.ApiClient; using Recombee.ApiClient.ApiRequests; using Recombee.ApiClient.Bindings; using Recombee.ApiClient.Util; public class BasicExample { static int Main(string[] args) { RecombeeClient client = new RecombeeClient("--your-database-id--", "--your-db-private-token--", region: Region.UsWest); try { const int NUM = 100; var userIds = Enumerable.Range(0, NUM).Select(i => String.Format("user-{0}", i)); var itemIds = Enumerable.Range(0, NUM).Select(i => String.Format("item-{0}", i)); // Generate some random purchases of items by users const double PROBABILITY_PURCHASED = 0.1; Random r = new Random(); var purchases = new List(); foreach(var userId in userIds) { purchases.AddRange( itemIds.Where(_ => r.NextDouble() < PROBABILITY_PURCHASED) .Select(itemId => new AddPurchase(userId, itemId, cascadeCreate: true) // Use cascadeCreate parameter to create ) // the yet non-existing users and items ); } Console.WriteLine("Send purchases"); client.Send(new Batch(purchases)); //Use Batch for faster processing of larger data // Recommend 5 items for user 'user-25' RecommendationResponse recommendationResponse = client.Send(new RecommendItemsToUser("user-25", 5)); Console.WriteLine("Recommended items:"); foreach(Recommendation rec in recommendationResponse.Recomms) Console.WriteLine(rec.Id); // User scrolled down - get next 3 recommended items recommendationResponse = client.Send(new RecommendNextItems(recommendationResponse.RecommId, 3)); Console.WriteLine("Next recommended items:"); foreach(Recommendation rec in recommendationResponse.Recomms) Console.WriteLine(rec.Id); } catch(ApiException e) { Console.WriteLine(e.ToString()); // Use fallback } return 0; } } ``` --- # Node.js API Client > Source: https://docs.recombee.com/node_client > For the complete documentation index, see [llms.txt](/llms.txt). # Node.js API Client [GitHubInstallation info and more examples](https://github.com/Recombee/node-api-client)[API ReferenceList of all available endpoints with examples](/api) For client side (browser, mobile apps …) .js library please see the [.js library](/js_client). Example Node.js ``` var recombee = require('recombee-api-client'); var rqs = recombee.requests; var client = new recombee.ApiClient('--your-database-id--', '--your-db-private-token--', { region: 'us-west' }); // Prepare some userIDs and itemIDs const NUM = 100; var userIds = Array.apply(0, Array(NUM)).map((_, i) => { return `user-${i}`; }); var itemIds = Array.apply(0, Array(NUM)).map((_, i) => { return `item-${i}`; }); // Generate some random purchases of items by users const PROBABILITY_PURCHASED = 0.1; var purchases = []; userIds.forEach((userId) => { var purchased = itemIds.filter(() => Math.random() < PROBABILITY_PURCHASED); purchased.forEach((itemId) => { purchases.push(new rqs.AddPurchase(userId, itemId, { 'cascadeCreate': true })) }); }); // Send the data to Recombee, use Batch for faster processing of larger data await client.send(new rqs.Batch(purchases)) try { // Get 5 recommended items for user 'user-25' const response = await client.send(new rqs.RecommendItemsToUser('user-25', 5)); console.log("Recommended items for user-25: %j", response.recomms); // User scrolled down - get next 3 recommended items const nextResponse = await client.send(new rqs.RecommendNextItems(response.recommId, 3)); console.log("Next recommended items for user-25: %j", nextResponse.recomms); } catch (error) { console.error(error); // Use fallback } ``` --- # PHP API Client > Source: https://docs.recombee.com/php_client > For the complete documentation index, see [llms.txt](/llms.txt). # PHP API Client [GitHubInstallation info and more examples](https://github.com/Recombee/php-api-client)[API ReferenceList of all available endpoints with examples](/api) Example PHP ``` use Recombee\RecommApi\Client; use Recombee\RecommApi\Requests as Reqs; use Recombee\RecommApi\Exceptions as Ex; $client = new Client('--your-database-id--', '--your-db-private-token--', ['region' => 'us-west']); const NUM = 100; const PROBABILITY_PURCHASED = 0.1; try { // Generate some random purchases of items by users $purchase_requests = array(); for($i=0; $i < NUM; $i++) { for($j=0; $j < NUM; $j++) { if(mt_rand() / mt_getrandmax() < PROBABILITY_PURCHASED) { $request = new Reqs\AddPurchase("user-{$i}", "item-{$j}", ['cascadeCreate' => true] // Use cascadeCreate to create the // yet non-existing users and items ); array_push($purchase_requests, $request); } } } echo "Send purchases\n"; $res = $client->send(new Reqs\Batch($purchase_requests)); //Use Batch for faster processing of larger data // Get 5 recommendations for user 'user-25' $response = $client->send(new Reqs\RecommendItemsToUser('user-25', 5)); echo 'Recommended items: ' . json_encode($response, JSON_PRETTY_PRINT) . "\n"; // User scrolled down - get next 3 recommended items $response = $client->send(new Reqs\RecommendNextItems($response['recommId'], 3)); echo 'Next recommended items: ' . json_encode($response, JSON_PRETTY_PRINT) . "\n"; } catch(Ex\ApiException $e) { //use fallback } ``` --- # Python API Client > Source: https://docs.recombee.com/python_client > For the complete documentation index, see [llms.txt](/llms.txt). # Python API Client [GitHubInstallation info and more examples](https://github.com/Recombee/python-api-client)[API ReferenceList of all available endpoints with examples](/api) Example Python ``` from recombee_api_client.api_client import RecombeeClient, Region from recombee_api_client.exceptions import APIException from recombee_api_client.api_requests import * import random client = RecombeeClient('--your-database-id--', '--your-db-private-token--', region=Region.US_WEST) #Generate some random purchases of items by users PROBABILITY_PURCHASED = 0.1 NUM = 100 purchase_requests = [] for user_id in ["user-%s" % i for i in range(NUM) ]: for item_id in ["item-%s" % i for i in range(NUM) ]: if random.random() < PROBABILITY_PURCHASED: request = AddPurchase(user_id, item_id, cascade_create=True) purchase_requests.append(request) try: # Send the data to Recombee, use Batch for faster processing of larger data print('Send purchases') client.send(Batch(purchase_requests)) # Get recommendations for user 'user-25' response = client.send(RecommendItemsToUser('user-25', 5)) print("Recommended items: %s" % response) # User scrolled down - get next 3 recommended items response = client.send(RecommendNextItems(response['recommId'], 3)) print("Next recommended items: %s" % response) except APIException as e: print(e) ``` --- # Cart > Source: https://docs.recombee.com/recipes/e-commerce/cart > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Cart ![](/img/recipes/e-commerce/shopping-cart.png) ## Introduction Online shopping carts are critical to e-commerce - a place of high opportunities and also high risks. It is the step of the customer journey where the users often hesitate, and it is important to motivate them not to abandon the cart and complete the purchase. It is at the same time a great place for presenting the users useful accessories to products in the cart, increasing both the user’s satisfaction and the order value. Recombee can help you with these goals by providing personalized recommendations that take into account the products in the cart. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"cart"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/shopping-cart-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[ecommerce:cross-sell](/recommendation_logics#ecommerce-cross-sell)** logic type from the **E-commerce** models This Logic allows for recommendations of products that are compatible with those that the user has already [put into the cart](/api#add-cart-addition). The Logic needs purchase data for returning correct suggestions - therefore if you have a new database and you want to start using this Logic right away, it is good to do an import of the historical purchase data. ![Admin UI - Logic](/img/recipes/e-commerce/shopping-cart-logic.png) ## Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. --- # Category Page > Source: https://docs.recombee.com/recipes/e-commerce/category/reordering-of-category-products > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Show Only Products from the Particular Category (Dynamic)](#show-only-products-from-the-particular-category-dynamic-) * [String Property](#string-property) * [Set of Categories](#set-of-categories) * [Other Filters](#other-filters) * [Requesting Recommendations](#requesting-recommendations) # Category Page ![](/img/recipes/e-commerce/personalized-reordering-of-products.png) ## Introduction Optimize category pages by reordering products according to user preferences for a personalized experience. If you show the category page as a faceted search, read more information in the [Faceted Search](/recipes/e-commerce/search/faceted-search) page. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"category-listing"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/personalized-reordering-of-products-create-scenario.png) There are typically many products in a category and you want to offer the user more products as the user scrolls down. Request the [Recommend Next Items endpoint](/api#recommend-next-items) to load subsequent products of interest. ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[recombee:personal](/recommendation_logics#recombee-personal)** logic type from the **Universal Models** This Logic offers the user products in personalized order. If the user does not have any interactions yet, the products are ordered by global popularity. ![Admin UI - Logic](/img/recipes/e-commerce/personalized-reordering-of-products-logic.png) ## Filters ### Show Only Products from the Particular Category (Dynamic) Based on which category the user enters on the website, only products from the particular category shall be displayed. As the selected category is dynamic, the category filter shall be sent in the [filter parameter](/api#recommend-items-to-user-param-filter) of the [API request](/api#recommend-items-to-user). Based on how you model the category/categories in your catalog, the sent [ReQL expression](/reql) may look like: ##### String Property ReQL ``` 'category' == "" 'category' == "Mobile Phones" # example for Mobile Phones ``` ##### Set of Categories ReQL ``` "" in 'categories' "Mobile Phones" in 'categories' # example for Mobile Phones ``` ### Other Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create an _Infinite Feed_ No-Code Widget using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. In either case, you need to set the `filter` parameter to allow only items from the displayed category in the recommendations. --- # Bestsellers > Source: https://docs.recombee.com/recipes/e-commerce/fully-personalized-homepage/bestsellers > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Bestsellers ![](/img/recipes/e-commerce/bestsellers.png) ## Introduction The "Bestsellers" scenario suggests products that have the highest number of purchases. These recommendations are based on the popularity and widespread demand for these items across the whole user base of your platform. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"bestsellers"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/bestsellers-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[ecommerce:bestseller](/recommendation_logics#ecommerce-bestseller)** logic type from the **E-commerce** models This Logic utilizes a model specifically designed for recommending globally popular and highly purchased items, ensuring effective suggestions based on their widespread demand. ![Admin UI - Logic](/img/recipes/e-commerce/bestsellers-logic.png) ## Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple homepage boxes with a single API request, use the [Batch endpoint](/api#batch) and put the recommendation requests inside it. Set the parameter `distinctRecomms` in order to [deduplicate the items among the boxes](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). --- # Brands For You > Source: https://docs.recombee.com/recipes/e-commerce/fully-personalized-homepage/brands-for-you > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Segmentation Setup](#segmentation-setup) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Requesting Recommendations](#requesting-recommendations) # Brands For You ![](/img/recipes/e-commerce/brands-for-you.png) ## Introduction Get personalized brand recommendations tailored to your unique preferences and interests. Whether you're into fashion, technology, or lifestyle, our recommendation engine is designed to help users discover brands that match their style and needs effectively. ## Segmentation Setup Most of the recommendation rows on the homepage feature products; however, in this case, we want to recommend brands based on the user’s browsing history. In the Recombee Admin UI, navigate to the **[Segmentations](/segmentations)** section and choose **Create**. 1. Choose **Segmentation Type** \- _Property-based_ 2. Pick **Property** from the list that contains the property that determines the brand ![Admin UI - Segmentation Setup](/img/recipes/e-commerce/brands-for-you-segmentation-setup.png) After picking the property, a preview opens up, and you can see the brands and the number of items per brand. ![Admin UI - Segmentation Setup - Preview](/img/recipes/e-commerce/brands-for-you-segmentation-setup-preview.png) Then confirm the settings by hitting the **Create** button. You have now created the Segmentation based on the brand, and you can proceed to recommend the brands (=Segments) to the user. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"brands-for-you"_ 2. Choose **Recommendation type** \- _[Item Segments to User](/api#recommend-item-segments-to-user)_ 3. Continue and choose **Results Segmentation** \- _brands Segmentation_ created in the previous step ![Admin UI - Scenario Setup](/img/recipes/e-commerce/brands-for-you-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[recombee:default](/recommendation_logics#recombee-default)** logic type from the **Universal Models** This particular Logic returns the Segments (=brands) in personalized order to give the user the most suitable brand according to the user’s previous interactions. ![Admin UI - Logic](/img/recipes/e-commerce/brands-for-you-logic.png) ## Requesting Recommendations You shall request the [Recommend Items Segments to User endpoint](/api#recommend-item-segments-to-user) of the Recombee API using an [SDK of your choice](/api_clients). For more information, navigate to the Integration tab of the Scenario in the Admin UI. --- # "For You" Sections > Source: https://docs.recombee.com/recipes/e-commerce/fully-personalized-homepage/for-you-sections > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Boosters](#boosters) * [Requesting Recommendations](#requesting-recommendations) # "For You" Sections ![](/img/recipes/e-commerce/for-you-sections.png) ## Introduction Scenarios such as _"Just For You"_ or _"New Arrivals For You"_ suggest products that align with a user's specific interests, leveraging their past interactions on the site to determine the most relevant recommendations. In case of a new user without any previous recommendations, best-selling and trending products are offered. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"just-for-you"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/for-you-sections-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[ecommerce:homepage](/recommendation_logics#ecommerce-homepage)** logic type from the **E-commerce** models to give a personalized offering for the user The Logic is also motivating the user to proceed with buying products that were of interest during previous visits. ![Admin UI - Logic](/img/recipes/e-commerce/for-you-sections-logic.png) ## Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) Tip: New Arrivals You may want to add an additional **New Arrivals** box to your homepage with a personalized offer of the recently added products. 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter** 2. Find _Recent items_ and click on **+** 3. Specify which **property** in your Items catalog specifies the **date of adding the product into the catalog** 4. Set the **Number of days** for which the new item can be recommended For example, by setting 30 days, each user will get a personalized collection of interesting products that were added during the last month. ![Admin UI - Filter - Recent Items](/img/recipes/e-commerce/filter-recent-items.png) Tip: Category-specific Items You may want to add an additional box to your homepage with a personalized offer of **products from a particular category** (e.g. _“T-shirts you may like”_, _“Posters for You”_, etc.). 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter** 2. **Add one of the following filters** from the library of predefined rules: * _Items from particular category \[string\]_ * _Items from particular category \[set\]_ Used rule depends on whether your products have a single category or multiple categories per product in the catalog. 3. Specify which **property** in your Items catalog specifies the **category** 4. Set the **name of the category** [![Admin UI - Filter - Category-specific Items - ReQL](/img/recipes/e-commerce/filter-category-specific-items.png)](/img/recipes/e-commerce/filter-category-specific-items.png) ## Boosters Tip: Boost Items On Sale You may want to bias the behavior towards a particular business or product goal - for example drive the recommender engine to **push the items that are on sale** more, because you want to completely sell out these products. 1. Navigate to **[Business Rules](/reql#business-rules)** section and **Create Rule** 2. Enter a **Rule name**, such as _"Items On Sale Booster"_ 3. Choose **Rule Type** \- _[Booster](/scenarios#boosters)_ 4. Choose **Entity Type** \- _Items_ 5. Assuming you have an item **property** called _on\_sale_, the ReQL expression can look like this: ``` if 'on_sale' then 2 else 1 ``` [![Admin UI - Booster - Items On Sale](/img/recipes/e-commerce/booster-items-on-sale-reql.png)](/img/recipes/e-commerce/booster-items-on-sale-reql.png) **After creating** the [Booster](/scenarios#boosters), you can apply the rule to your Scenario in the Boosters tab. [![Admin UI - Apply Booster](/img/recipes/e-commerce/booster-items-on-sale-apply.png)](/img/recipes/e-commerce/booster-items-on-sale-apply.png) **Advanced tip**: To easily test how much the items shall be boosted, you can introduce a [Boosting Coefficient Input Value](/scenarios#custom-rules) and use it in the ReQL: ``` if 'on_sale' then $coefficient$ else 1 ``` Then you can set the coefficient directly in the Scenario screen and find the most fitting amount of boosting using the **Preview Results** function. ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple homepage boxes with a single API request, use the [Batch endpoint](/api#batch) and put the recommendation requests inside it. Set the parameter `distinctRecomms` in order to [deduplicate the items among the boxes](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). --- # Personalized Re-ordering of Sections > Source: https://docs.recombee.com/recipes/e-commerce/fully-personalized-homepage/personalized-re-ordering-of-sections-advanced > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Composite Recommendations Overview](#composite-recommendations-overview) * [Segmentation Setup](#segmentation-setup) * [Scenario Setup](#scenario-setup) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Personalized Re-ordering of Sections ![](/img/recipes/e-commerce/personalized-re-ordering-of-sections-advanced.png) ## Introduction Create a truly personalized homepage by selecting the top categories for each user and displaying a dedicated section for each — featuring the most appealing products from those categories, tailored to their preferences. With [Composite Recommendations](/scenarios#composite-recommendations), you can easily personalize both: 1. The **order of homepage sections** (so categories appear in the order each user is most interested in), and 2. The **content inside each section** (so that within each category, the user sees the most relevant products). ## Composite Recommendations Overview **Composite Recommendations** return both a _source entity_ (for example, a [category Segment](/segmentations)) and a list of _results_ (items from that Segment) in a single response. They are requested via the [**Composite Recommendation API endpoint**](/api#composite-recommendation). In our case: * **Source:** ID of the section, e.g., the _category_ (Item Segment) * **Result:** Items (products) for that section [![Category Sections Setup](/img/gui/composite_items_from_category.png)](/img/gui/composite_items_from_category.png) Because the source is personalized (which categories the user likes) and the results are personalized (which products within those categories they like), you get dynamic section ordering and item ordering in one request. ## Segmentation Setup Start by creating a **Segmentation** of your products based on their category. In the Recombee Admin UI, navigate to **[Segmentations](/segmentations)** → **Create**. 1. Choose **Segmentation Type** – _Property-based_. 2. Select the item property (e.g., `category`) that defines the product category. ![Admin UI - Segmentation Setup](/img/recipes/e-commerce/personalized-re-ordering-of-sections-advanced-segmentation-setup.png) Once the property is selected, a preview opens where you can see which categories exist in your catalog and how many products belong to each. ![Admin UI - Segmentation Setup - Preview](/img/recipes/e-commerce/personalized-re-ordering-of-sections-advanced-segmentation-setup-preview.png) ## Scenario Setup Go to **Scenarios** → **Create Scenario**. 1. Choose a **Scenario ID**, e.g. `homepage-sections-and-products`. 2. Set the **Recommendation Type** to **Composite** (see [Composite Recommendations](/scenarios#composite-recommendations)). 3. Then pick one of the [ecommerce:products-from-top-category-for-you](/recommendation_logics#ecommerce-products-from-top-category-for-you) **Template**. ![Admin UI - Scenario Setup](/img/recipes/e-commerce/personalized-reordering-of-sections-create-scenario.png) ## Filters You may want to apply additional filters to ensure only available or visible products are recommended. Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Requesting Recommendations There are two ways to show multiple personalized sections in your application: 1. **Using the API Client** Using an [API Client of your choice](/api_clients), send multiple **[Composite Recommendation requests](/api#composite-recommendation)** within a single **[Batch request](/api#batch)**, with the [distinctRecomms](/api#batch-param-distinctRecomms) parameter set to `true` to deduplicate content across sections. Tip Composite Recommendations automatically ensure distinct _source entities_ (categories), while the `distinctRecomms` flag removes duplicate products between sections. See [this example](/api#composite-recommendation-example-category-sections-with-reordering) for guidance on how to implement this approach in your programming language. Once you receive the response, render each _source_ (category) as a section title and populate it with the corresponding _results_ (products) to create a fully personalized homepage layout. 1. **Using the Widget SDK** For web applications built with HTML, CSS and JavaScript, the [Widget SDKs](/widget-sdks) support Composite Recommendations out of the box. Place one widget per section on your page, each sending its own **[Composite Recommendation request](/api#composite-recommendation)**. Design the section title with the `SourceItemComponent` parameter and the products inside it with `ItemComponent`. Multiple widgets on one page are deduplicated automatically, for products as well as for _source entities_ (categories). For full code examples and in-depth guidance, see the relevant SDK documentation on Composite Recommendations: * [Carousel Widget (JS)](/widget-sdks/carousel-widget-js#composite-recommendations) * [Carousel Widget (React)](/widget-sdks/carousel-widget-react#composite-recommendations) * [Grid Widget (JS)](/widget-sdks/grid-widget-js#composite-recommendations) * [Grid Widget (React)](/widget-sdks/grid-widget-react#composite-recommendations) * [Feed Widget (JS)](/widget-sdks/feed-widget-js#composite-recommendations) * [Feed Widget (React)](/widget-sdks/feed-widget-react#composite-recommendations) --- # Recently Viewed > Source: https://docs.recombee.com/recipes/e-commerce/fully-personalized-homepage/recently-viewed > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Recently Viewed ![](/img/recipes/e-commerce/recently-viewed.png) ## Introduction The "Recently Viewed" scenario suggests products that have been previously viewed by the user, driving the user to ultimately purchase the product. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"recently-viewed"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/recently-viewed-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[recombee:recently-viewed](/recommendation_logics#recombee-recently-viewed)** logic type from the **Universal Models** By adjusting specific parameters, such as `maxAge` and `recencyOrdering`, you can fine-tune the model’s behavior. `maxAge` specifies the time interval in which the user’s Detail Views are taken into account. For example, if you set the parameter to 7 days (it is specified in seconds, thus 7 \* 24 \* 60 \* 60 = 604,800 seconds), the products viewed by the user within the last 7 days will be returned. `recencyOrdering`: By default, the products are returned from the most recently viewed ones, however, you can alter this behavior by setting `recencyOrdering` to _“ascending”_. ![Admin UI - Logic](/img/recipes/e-commerce/recently-viewed-logic.png) ## Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple homepage boxes with a single API request, use the [Batch endpoint](/api#batch) and put the recommendation requests inside it. Set the parameter `distinctRecomms` in order to [deduplicate the items among the boxes](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). --- # Personalized Emailing > Source: https://docs.recombee.com/recipes/e-commerce/personalized-emailing > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Boosters](#boosters) * [Requesting Recommendations](#requesting-recommendations) * [Requesting Dynamic Content from API](#requesting-dynamic-content-from-api) * [Pre-fetching Recommendations](#pre-fetching-recommendations) # Personalized Emailing ![](/img/recipes/e-commerce/personalized-emailing.png) ## Introduction Personalized emailing is essential for e-commerce, ensuring customers receive content that reflects their interests and behaviors, thereby boosting engagement and conversions. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"email"_ or the name of the particular emailing campaign 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/personalized-emailing-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[recombee:emailing](/recommendation_logics#recombee-emailing)** logic type from the **Universal Models** This model is **fine-tuned for periodic** (e.g. daily) personalized emailing campaigns. The `rotationPolicy` parameter specifies how the recommendations for the user change with each subsequent email sent. By default, there is a _smart rotation_ that takes into account the position of recommended items and allows some of the items to re-appear in further e-mails. If you prefer not to repeat a recommended product in the emails ever again, you can set the parameter value to _total_. By default, rotation only takes into account recommendations (e-mails) at most 14 days old. Should a longer time period be needed for your use case, kindly contact [support@recombee.com](mailto:support@recombee.com). ![Admin UI - Logic](/img/recipes/e-commerce/personalized-emailing-logic.png) ## Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) Tip: Personalized Selection from Recently Added Products You may want to create an emailing campaign dedicated to recommending the **newly added products**. 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter** 2. Find _Recent items_ and click on **+** 3. Specify which **property** in your Items catalog specifies the **date of adding the product into the catalog** 4. Set the **Number of days** for which the new item can be recommended For example, by setting 30 days, each user will get a personalized collection of interesting products that were added during the last month. An alternative to this approach would be adding the **Boost recent items booster** instead of a filter - especially if you don’t add new products continuously, so there might not be always a sufficient number of candidates. Tip: Category-specific Items You may want to create an emailing campaign dedicated to products from a **specific category**. 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter** 2. **Add one of the following filters** from the library of predefined rules: * _Items from particular category \[string\]_ * _Items from particular category \[set\]_ Used rule depends on whether your products have a single category or multiple categories per product in the catalog. 3. Specify which **property** in your Items catalog specifies the **category** 4. Set the **name of the category** [![Admin UI - Filter - Category-specific Items - ReQL](/img/recipes/e-commerce/filter-category-specific-items.png)](/img/recipes/e-commerce/filter-category-specific-items.png) ## Boosters Tip: Boost Items On Sale You may want to bias the behavior towards a particular business or product goal - for example drive the recommender engine to **push the items that are on sale** more in the sent emails, because you want to completely sell out these products. 1. Navigate to **[Business Rules](/reql#business-rules)** section and **Create Rule** 2. Enter a **Rule name**, such as _"Items On Sale Booster"_ 3. Choose **Rule Type** \- [Booster](/scenarios#boosters) 4. Choose **Entity Type** \- Items 5. Assuming you have an item **property** called _on\_sale_, the ReQL expression can look like this: ``` if 'on_sale' then 2 else 1 ``` [![Admin UI - Booster - Items On Sale](/img/recipes/e-commerce/booster-items-on-sale-reql.png)](/img/recipes/e-commerce/booster-items-on-sale-reql.png) **After creating** the [Booster](/scenarios#boosters), you can apply the rule to your Scenario in the Boosters tab. [![Admin UI - Apply Booster](/img/recipes/e-commerce/booster-items-on-sale-apply.png)](/img/recipes/e-commerce/booster-items-on-sale-apply.png) **Advanced tip**: To easily test how much the items shall be boosted, you can introduce a [Boosting Coefficient Input Value](/scenarios#custom-rules) and use it in the ReQL: ``` if 'on_sale' then $coefficient$ else 1 ``` Then you can set the coefficient directly in the Scenario screen and find the most fitting amount of boosting using the _Preview Results_ function. ## Requesting Recommendations Choose the way of requesting recommendations compatible with your emailing platform ### Requesting Dynamic Content from API If the emailing platform can fetch the recommendations directly from the Recombee API: 1. Ensure the platform supports the [authentication scheme](/authentication) directly (e.g. in the case of _Customer.io_), or set up a small proxy that authenticates the requests. 2. In case the authentication proxy needs to be set up, please contact [support@recombee.com](mailto:support@recombee.com) for guidance on how your emailing platform can be connected with Recombee. ### Pre-fetching Recommendations If the emailing platform does not support requesting a 3rd party API but supports adding personalized content unique to each user: 1. Request the recommendations for each user who shall get the email using the [Recommend Items to User endpoint](/api#recommend-items-to-user). 2. Upload the recommendations to the emailing platform. 3. Send the emails. You can even request many recommendations at once using the [Batch endpoint](/api#batch). You can contact [support@recombee.com](mailto:support@recombee.com) to get more information on how this procedure shall be implemented in the case of your emailing platform. --- # Alternative Products & Upsell > Source: https://docs.recombee.com/recipes/e-commerce/product-detail/alternative-products-and-upsell > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Boosters](#boosters) * [Requesting Recommendations](#requesting-recommendations) # Alternative Products & Upsell ![](/img/recipes/e-commerce/alternative-products-and-upsell.png) ## Introduction When a customer is interested in a product, it is useful to suggest alternative options they have not considered yet. For example, suggesting similar products of higher quality can increase the likelihood of a purchase and improve customer satisfaction. Recombee addresses this use case by providing personalized recommendations of alternative products, taking into account the customer's browsing and purchase history. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"pdp-similar-products"_ 2. Choose **Recommendation type** \- _[Items to Item](/api#recommend-items-to-item)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/alternative-products-and-upsell-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[ecommerce:similar-products](/recommendation_logics#ecommerce-similar-products)** logic type from the **E-commerce** models This Logic will give you alternatives to the currently displayed item. ![Admin UI - Logic](/img/recipes/e-commerce/alternative-products-and-upsell-logic.png) ## Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Boosters Tip: Upsell Booster The Upsell Booster biases the recommender engine towards items with a **higher price or margin** compared to the item currently being viewed. 1. Navigate to the **[Boosters](/scenarios#boosters)** tab and **Add first booster** 2. Find _Upsell_ and click on **+** 3. Specify which **property** in your Items catalog specifies **price (or margin)** 4. Set the **Boosting coefficient** that defines how much the more expensive items shall be pushed in the recommendations Setting the boost to 1 implies no boost at all, and the higher the coefficient value, the higher the boost. You can use the **Preview Results** function to find the most fitting value of the coefficient. ![Admin UI - Booster](/img/recipes/e-commerce/booster-upsell.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to Item endpoint](/api#recommend-items-to-item) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to Item endpoint](/api#recommend-items-to-item) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. --- # Bought Together & Accessories > Source: https://docs.recombee.com/recipes/e-commerce/product-detail/bought-together-and-accessories > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Bought Together & Accessories ![](/img/recipes/e-commerce/bought-together-and-accessories.png) ## Introduction The "Bought Together" use case leverages past purchasing patterns to offer complementary products, helping you optimize your offerings and save time. By implementing these recommendations, you unlock new opportunities to increase the number of items purchased, subsequently enhancing your revenue potential. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"pdp-bought-together"_ 2. Choose **Recommendation type** \- _[Items to Item](/api#recommend-items-to-item)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/bought-together-and-accessories-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[ecommerce:cross-sell](/recommendation_logics#ecommerce-cross-sell)** logic type from the **E-commerce** models This Logic will give you products that are frequently bought with this product, such as its accessories. The Logic needs purchase data for returning correct suggestions - therefore if you have a new database and you want to start using this Logic right away, it is good to do an import of the historical purchase data. ![Admin UI - Logic](/img/recipes/e-commerce/bought-together-and-accessories-logic.png) ## Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to Item endpoint](/api#recommend-items-to-item) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to Item endpoint](/api#recommend-items-to-item) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. --- # Faceted Search > Source: https://docs.recombee.com/recipes/e-commerce/search/faceted-search > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Facets](#facets) * [Other Filters](#other-filters) * [Requesting Search Results](#requesting-search-results) # Faceted Search ![](/img/recipes/e-commerce/faceted-search.png) ## Introduction Faceted search is a widely used feature in e-commerce websites that enables users to filter products based on various attributes. It is essential for e-commerce websites with a large inventory to allow customers to quickly find products that match their interests/search etc. Personalized search functionalities go beyond just parsing search queries. They also take into account a user's interaction history on the site, fostering a more tailored and intuitive browsing experience. By aligning search results with a user's behavior and preferences, businesses can enhance customer satisfaction, conversion rates, and overall sales. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"faceted-product-search"_ 2. Choose **Recommendation type** \- _[Search Items](/api#search-items)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/faceted-search-create-scenario.png) There are typically many products matching the criteria and you want to offer the user more products as the user scrolls down. Request the [Recommend Next Items endpoint](/api#recommend-next-items) to load subsequent products of interest. ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[search:personalized](/recommendation_logics#search-personalized)** logic type from the **Universal Models** You can adjust how much the results are biased towards the user (as opposed to strictly following the full-text results) by setting the `personalizationImpact` parameter. ![Admin UI - Logic](/img/recipes/e-commerce/faceted-search-logic.png) ## Filters ### Facets The user filters the desired products by various facets such as _price_, _vendor_, _color_, _size_, and many more based on the particular type of products and selected category. You can send the information about the user’s current selection using the [filter parameter](/api#search-items-param-filter) of the [Search Items](/api#search-items) endpoint. Only products satisfying the criteria will be returned. For example, if the user has selected to search only within shoes by Nike that are red and size 42, the filter may look like: ReQL ``` 'category' == "shoes" and 'manufacturer' == "Nike" and 'color' == "red" and "42" in 'available_sizes' ``` If the user then adds a desired price range between 100 and 140 USD, the filter will become: ReQL ``` 'category' == "shoes" and 'manufacturer' == "Nike" and 'color' == "red" and "42" in 'available_sizes' and 100 <= 'price' <= 140 ``` For more detailed information about how to construct the filters, please navigate to the [ReQL documentation](/reql). ### Other Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Requesting Search Results Request the [Search Items endpoint](/api#search-items) of the Recombee API using an [SDK of your choice](/api_clients). Don’t forget to set the [filter parameter](/api#search-items-param-filter) to allow only items that comply with the user’s selected criteria. --- # Quick Search > Source: https://docs.recombee.com/recipes/e-commerce/search/quick-search > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Search Results](#requesting-search-results) # Quick Search ![](/img/recipes/e-commerce/quick-search.png) ## Introduction This use case enables your users to swiftly and effectively search for products that align with their preferences and activity on your platform. It ensures a seamless and efficient search experience tailored to their specific needs and text input. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. Select a distinctive label for your recommendation scenario, such as _"search-products"_ 2. Choose **Recommendation type** \- _[Search Items](/api#search-items)_ ![Admin UI - Scenario Setup](/img/recipes/e-commerce/quick-search-create-scenario.png) The Search Items endpoint performs a full-text search within the products. If you want to show matching categories or vendors besides the product, you can create additional scenarios of type [Search Item Segments](/api#search-item-segments). ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[search:personalized](/recommendation_logics#search-personalized)** logic type from the **Universal Models** You can adjust how much the results are biased towards the user (as opposed to strictly following the full-text results) by setting the `personalizationImpact` parameter. ![Admin UI - Logic](/img/recipes/e-commerce/quick-search-logic.png) ## Filters Available Products (Global Settings) You always want to recommend only the products that are in stock. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such products. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. You can select a **predefined rule from the Recombee Library** to allow only the available products. Depending on how you represent availability in the catalog, it can be **one of the following rules:** * **Not deleted items** \- when you have a _deleted_ property (true/false) * **Available items** \- when you have an _available_ property (true/false) * **Items in stock \[Google Merchant\]** \- when you have a string _available_ property with _"in stock"_ as its value ![Admin UI - Global Settings - Filter](/img/recipes/e-commerce/filter.png) ## Requesting Search Results There are three ways to get search results. 1. **[No-Code Widget](/no-code-widgets)** \- create a [Quick Search No-Code Widget](/no-code-widgets#html-widget-full-text-search) using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the Quick Search SDK for [vanilla JavaScript](/widget-sdks/quick-search-widget-js) or [React](/widget-sdks/quick-search-widget-react) to create a search widget with the design of your choice. 3. **[API SDK](/api_clients)** \- request the [Search Items endpoint](/api#search-items) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. ![Quick Search No-Code Widget](/img/gui/search-widget-sections.png) Quick Search No-Code Widget --- # Cross-Site Recommendations on Article Page > Source: https://docs.recombee.com/recipes/news/article/cross-site-recommendations > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Constraints](#constraints) * [Requesting Recommendations](#requesting-recommendations) # Cross-Site Recommendations on Article Page ![](/img/recipes/news/cross-site-recommendations-on-article-page.png) ## Introduction **Cross-Site Recommendations** enable news platforms operating multiple sites to recommend articles from across their entire network. This helps drive traffic between properties while ensuring that recommendations remain relevant to the user's interests. There are two primary use cases: 1. Recommending articles on **topics related to the current article**, but from different sites. 2. Recommending articles from other sites **based on the user's history** and preferences. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"cross-site-related"_. 2. Choose **Recommendation type** \- _[Items to Item](/api#recommend-items-to-item)_. ![Admin UI - Scenario Setup](/img/recipes/news/cross-site-related-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Select the **[news:related](/recommendation_logics#news-related)** Logic from the **News** model family to recommend articles on topics related to the currently viewed article. * Alternatively, select the **[news:personal](/recommendation_logics#news-personal)** Logic from the same category if you want the recommendations to be primarily based on the user’s reading history and preferences. ![Admin UI - Logic](/img/recipes/news/cross-site-related-logic.png) ## Filters Excluding Articles from the Current Site Since all articles from all sites are stored in a single Recombee database, use the item property that indicates the source site (e.g., `siteId`) to exclude content from the current site. 1. Navigate to the **Business Rules** section and **Create Rule**. 2. In the editor, set the [ReQL](/reql) filter expression: ReQL ``` 'siteId' != context_item["siteId"] ``` The [context\_item](/reql_functions#context-item-function) ReQL function references the currently opened article. 3. Store the rule by clicking _Create Rule_. ![Admin UI - Business Rules](/img/recipes/news/cross-site-related-filter-rule.png) 1. After creating the rule, apply it in the _Filters_ section of the Scenario. ![Admin UI - Scenario Filters](/img/recipes/news/cross-site-related-filters.png) ## Constraints Ensure Diversity Across Sites To showcase the breadth of your network and avoid over-representing any single site, you can apply a [Constraint](/scenarios#constraints) to **limit the number of recommended articles per site**. To set this up: 1. Navigate to the [Constraints](/scenarios#constraints) tab of the Scenario and click **Add Constraint**. 2. Select or create an [Segmentation](/segmentations) that groups articles by site (e.g., using a `siteId` property). 3. Define the **Limit Type**: * **Absolute** to allow a maximum number of articles from a single site (e.g., up to 2). * **Percentage** to ensure no more than a defined share of items come from one site (e.g., max 50%). This setup ensures that the recommendations include content from a variety of sources, reinforcing the value of your full portfolio. ![Admin UI - Constraint](/img/recipes/news/cross-site-constraints.png) ## Requesting Recommendations There are three ways to integrate Cross-Site Recommendations. 1. **[No-Code Widget](/no-code-widgets)** – create a No-Code Widget using the **visual editor in the Admin UI** to embed cross-site recommendations with zero coding. 2. **[Widget SDKs](/widget-sdks)** – use the SDK to display the recommendations as a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid), or [Feed](/widget-sdks#feed). Use the [Recommend Items to User](/api#recommend-items-to-user) or [Recommend Items to Item](/api#recommend-items-to-item) endpoint when initializing the widget. 3. **[API SDK](/api_clients)** – request the appropriate API endpoint using a client SDK of your choice: * **[Recommend Items to Item](/api#recommend-items-to-item)** – for recommendations based on the currently viewed article. * **[Recommend Items to User](/api#recommend-items-to-user)** – for personalized content based on the user's behavior. --- # Read-Next Recommendations > Source: https://docs.recombee.com/recipes/news/article/read-next > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Read-Next Recommendations ![](/img/recipes/news/read-next.png) ## Introduction **Read-Next recommendations** help guide users to their next article after they finish reading one. This feature improves engagement by suggesting relevant content that continues the user’s reading journey. This recipe explains how to set up Read-Next recommendations using Recombee’s **[news:read-next](/recommendation_logics#news-read-next)** Logic, which delivers contextually relevant suggestions based on the currently viewed article. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and select **Create Scenario**. 1. Enter a **Scenario ID**, such as _"read-next"_. 2. Choose **Recommendation type** \- _[Items to Item](/api#recommend-items-to-item)_. ![Admin UI - Scenario Setup](/img/recipes/news/read-next-create-scenario.png) ## Logic The **[Logic](/recommendation_logics)** determines the behavior of the recommendation engine. * Select the **[news:read-next](/recommendation_logics#news-read-next)** logic type from **News** models. This logic recommends relevant articles based on their topic similarity to the currently viewed article and the user's engagement patterns, ensuring the best possible next read. Alternatively, you may choose the [news:related](/recommendation_logics#news-related) Logic if topic similarity is the primary criterion for the section. ![Admin UI - Logic](/img/recipes/news/read-next-logic.png) ## Filters Tip: Recent Articles Filter If you want to recommend only recently published articles, you can configure a filter in the Admin UI: 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter**. 2. Find _Recent items_, and click **+**. 3. Specify the **property** in your item catalog that represents the **publish date**. 4. Define the maximum age of articles (e.g., 30 days). ![Admin UI - Filter - Recent Items](/img/recipes/news/recent-items-filter.png) Tip: Articles From the Same Category You may want to limit the recommended articles to the category of the current article, creating boxes such as _More From Politics_, _More From Sport_, etc. 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter**. 2. From the list, select one of the predefined rules: * **Items from the same category \[string\]** – if each article belongs to a single category. * **Items from the same category \[set\]** – if articles can belong to multiple categories (at least one category must match). 3. Specify which **property** in your item catalog contains the category information. 4. Enter the **name of the category** you want to display. [![Admin UI - Filter - Articles From the Same Category](/img/recipes/news/same-category-filter.png)](/img/recipes/news/same-category-filter.png) ## Requesting Recommendations There are three ways to integrate Read-Next recommendations. 1. **[No-Code Widget](/no-code-widgets)** – create a No-Code Widget using the **visual editor in the Admin UI** to embed Read-Next recommendations without writing code. 2. **[Widget SDKs](/widget-sdks)** – use the SDK to display recommendations as a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid), or [Feed](/widget-sdks#feed). Initialize the widget using the [Recommend Items to Item](/api#recommend-items-to-item) endpoint. 3. **[API & SDK](/api_clients)** * Use the **[Recommend Items to Item](/api#recommend-items-to-item)** endpoint to retrieve relevant articles. * If the Read-Next section functions as an infinite feed of articles, use the **[Recommend Next Items](/api#recommend-next-items)** endpoint to load more articles as the user scrolls. For more details, visit the **Integration** tab in the scenario configuration within the Admin UI. --- # Cross-Site Recommendations on Homepage > Source: https://docs.recombee.com/recipes/news/homepage/cross-site-recommendations > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Constraints](#constraints) * [Requesting Recommendations](#requesting-recommendations) * [Multiple Recommendation Boxes on the Homepage](#multiple-recommendation-boxes-on-the-homepage) # Cross-Site Recommendations on Homepage ![](/img/recipes/news/cross-site-recommendations-on-homepage.png) ## Introduction **Cross-Site Recommendations** allow news platforms that operate multiple sites to suggest personalized content from across their network — directly on the homepage. This helps users discover high-quality articles from sister sites while keeping the recommendations aligned with their interests. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"cross-site-homepage"_. 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_. ![Admin UI - Scenario Setup](/img/recipes/news/cross-site-homepage-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Select the **[news:personal](/recommendation_logics#news-personal)** logic type from the **News** models to deliver personalized recommendations based on each user's behavior and preferences. ![Admin UI - Logic](/img/recipes/news/cross-site-homepage-logic.png) ## Filters Excluding Articles from the Current Site Since all articles from all sites are stored in a single Recombee database, use the item property that indicates the source site (e.g., `siteId`) to exclude content from the current site. To allow deploying this Scenario accross various webistes, this filter should be sent dynamically in the [filter parameter](/api#recommend-items-to-user-param-filter) of the recommendation [API request](/api#recommend-items-to-user), using the current site’s identifier. **Example Filter** ReQL ``` 'siteId' != "" ``` ## Constraints Ensure Diversity Across Sites To showcase the breadth of your network and avoid over-representing any single site, you can apply a [Constraint](/scenarios#constraints) to **limit the number of recommended articles per site**. To set this up: 1. Navigate to the [Constraints](/scenarios#constraints) tab and click **Add Constraint**. 2. Select or create an [Segmentation](/segmentations) that groups articles by site (e.g., using a `siteId` property). 3. Define the **Limit Type**: * **Absolute** to allow a maximum number of articles from a single site (e.g., up to 2). * **Percentage** to ensure no more than a defined share of items come from one site (e.g., max 50%). This setup ensures that the recommendations include content from a variety of sources, reinforcing the value of your full portfolio. ![Admin UI - Constraint](/img/recipes/news/cross-site-constraints.png) ## Requesting Recommendations There are three ways to integrate Cross-Site Recommendations. 1. **[No-Code Widget](/no-code-widgets)** – create a No-Code Widget using the **visual editor in the Admin UI** to embed the cross-site recommendations box without coding. 2. **[Widget SDKs](/widget-sdks)** – use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid), or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** – call the [Recommend Items to User](/api#recommend-items-to-user) endpoint directly using the SDK of your choice to fetch personalized cross-site recommendations. ### Multiple Recommendation Boxes on the Homepage If your homepage includes multiple recommendation sections — such as [personalized category-based sections](/recipes/news/homepage/personalized-sections-with-reordering) or [top stories](/recipes/news/homepage/top-stories) — you typically want to avoid duplication of content among the boxes. To achieve this: * Use a single [Batch request](/api#batch) to send all recommendation requests at once. * Enable the [distinctRecomms parameter](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes) in the batch request to prevent overlapping articles between sections. The [Widget SDKs](/widget-sdks) handle this functionality automatically. --- # Latest News > Source: https://docs.recombee.com/recipes/news/homepage/latest-news > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) * [Multiple Recommendation Boxes on the Homepage](#multiple-recommendation-boxes-on-the-homepage) # Latest News ![](/img/recipes/news/latest-news.png) ## Introduction The **Latest News** section highlights the most recently published articles on your platform. This scenario is purely based on recency — it does not take personalization or topic preferences into account. Use it when you want to surface the newest content for all users, regardless of their history or interests. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and select **Create Scenario**. 1. Enter a **Scenario ID**, such as _"latest-news"_. 2. Choose **Recommendation type** – _[Items to User](/api#recommend-items-to-user)_. ![Admin UI - Scenario Setup](/img/recipes/news/latest-news-create-scenario.png) ## Logic The **[Logic](/recommendation_logics)** determines the behavior of the recommendation engine. * Select the **[news:recent](/recommendation_logics#news-recent)** logic type from the **News** models. This Logic ranks articles purely by their publish time, ensuring that the most recently published content appears first. **The Logic supports the following parameters.** `publishedTimestamp` The property **(required)** in your item catalog that stores the article's publish time (e.g., `publishedAt`). `excludeAlreadyRead` Determines whether to exclude articles the user has already read. This is `true` by default, but you can override it. ![Admin UI - Logic](/img/recipes/news/latest-news-logic.png) ## Filters You can use filters to narrow down the set of articles shown in the Latest News section — for example, to only display news from certain categories. Tip: Category-Specific News You may want to create additional boxes on your homepage showing only the **latest articles from a specific category** — such as _“Latest in Politics”_ or _“Latest in Technology”_. 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter**. 2. **Add one of the following filters** from the library of predefined rules: * **Items from particular category \[string\]** – if articles always belong to a single category * **Items from particular category \[set\]** – if articles can belong to multiple categories 3. Specify which **property** in your item catalog contains the category information. 4. Enter the **Category name** you want to display. [![Admin UI - Filter - Category-specific News](/img/recipes/news/latest-news-filters.png)](/img/recipes/news/latest-news-filters.png) ## Requesting Recommendations There are three ways to retrieve the Latest News recommendations. 1. **[No-Code Widget](/no-code-widgets)** – create a No-Code Widget using the **visual editor in the Admin UI** to embed the Latest News section without writing code. 2. **[Widget SDKs](/widget-sdks)** – use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid), or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User](/api#recommend-items-to-user) endpoint and specify the `latest-news` scenario when initializing the widget. 3. **[API SDK](/api_clients)** – request the [Recommend Items to User](/api#recommend-items-to-user) endpoint of the Recombee API using an SDK of your choice and specify the `latest-news` scenario. ### Multiple Recommendation Boxes on the Homepage If your homepage includes multiple recommendation sections — such as [personalized category-based sections](/recipes/news/homepage/personalized-sections-with-reordering) or [top stories](/recipes/news/homepage/top-stories) — you typically want to avoid duplication of content among the boxes. To achieve this: * Use a single [Batch request](/api#batch) to send all recommendation requests at once. * Enable the [distinctRecomms parameter](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes) in the batch request to prevent overlapping articles between sections. The [Widget SDKs](/widget-sdks) handle this functionality automatically. --- # Personalized Editors’ Picks > Source: https://docs.recombee.com/recipes/news/homepage/personalized-editors-picks > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Requesting Recommendations](#requesting-recommendations) # Personalized Editors’ Picks ![](/img/recipes/news/personalized-editors-picks.png) ## Introduction The **Editors’ Picks** section highlights curated content selected by your editorial team, while still adapting to each reader. This approach combines the **human touch of curation** with the **power of personalization**, making it a great fit for the homepage, category landing pages, or even email campaigns. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and select **Create Scenario**. 1. Enter a **Scenario ID**, such as _"editors-picks"_ 2. Choose **Recommendation type** – _[Items to User](/api#recommend-items-to-user)_ ![Admin UI – Scenario Setup](/img/recipes/news/editors-picks-create-scenario.png) ## Logic The **[Logic](/recommendation_logics)** defines the behavior of the recommendation engine. Select the **[news:editors-picks](/recommendation_logics#news-editors-picks)** Logic from the **News** models to return the articles picked by the editors. The list of articles is provided via the `picks` parameter: the editorial team can either pick the list of items directly in the Recombee Admin UI or if you export the list from a CMS, you can set it [via API](/recommendation_logics#setting-logic-using-api-parameter) when calling the recommendation request. Using the `excludeAlreadyRead` parameter you can either allow or filter out the articles the user has already read. By default, the picked articles are re-ordered per user. You can disable this by setting the `personalizedReordering` parameter to `false`. ![Admin UI - Logic](/img/recipes/news/editors-picks-logic.png) ## Requesting Recommendations There are three ways to retrieve the Editors’ Picks recommendations. 1. **[No-Code Widget](/no-code-widgets)** – create a No-Code Widget using the **visual editor in the Admin UI** to embed the Editors’ Picks section without writing code. 2. **[Widget SDKs](/widget-sdks)** – use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid), or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User](/api#recommend-items-to-user) endpoint and specify the `editors-picks` scenario when initializing the widget. 3. **[API SDK](/api_clients)** – request the [Recommend Items to User](/api#recommend-items-to-user) endpoint of the Recombee API using an SDK of your choice and specify the `editors-picks` scenario. --- # Personalized News Feed > Source: https://docs.recombee.com/recipes/news/homepage/personalized-feed > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [String Property](#string-property) * [Set of Categories](#set-of-categories) * [Boosters](#boosters) * [Constraints](#constraints) * [Requesting Recommendations](#requesting-recommendations) # Personalized News Feed ![](/img/recipes/news/personalized-feed.png) ## Introduction The **Personalized News Feed** is a key feature of many modern news platforms, offering a continuous stream of articles tailored to each user's unique interests and preferences. The feed can serve as the main homepage of the app or website or complement other sections, such as the **[Homepage Top Stories Section](/recipes/news/homepage/top-stories)** or editorial content. This recipe will guide you in setting up a personalized feed that dynamically loads relevant articles as the user scrolls, creating a seamless and engaging reading experience. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and select **Create Scenario**. 1. Enter a **Scenario ID**, such as _"personalized-feed"_. 2. Choose the **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_. ![Admin UI - Scenario Setup](/img/recipes/news/personalized-feed-create-scenario.png) ## Logic The **[Logic](/recommendation_logics)** determines the behavior of the recommendation engine. * Select the **[news:personal](/recommendation_logics#news-personal)** logic type from the **News** models. This logic delivers highly personalized recommendations based on each user's behavior and preferences. ![Admin UI - Logic](/img/recipes/news/personalized-feed-logic.png) ## Filters You can apply [Filters](scenarios#filters) to fine-tune the recommendations in your feed. Below are examples of filters you might find useful. Recent News Filter To ensure the articles in the feed are fresh, you can restrict the recommendations to articles published within a certain timeframe (e.g., the last 3 days): 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter**. 2. Find _Recent items_, and click **+**. 3. Specify the **property** in your item catalog that represents the **publish date**. 4. Define the maximum age of articles (e.g., 3 days). ![Admin UI - Filter - Recent Items](/img/recipes/news/recent-items-filter.png) Excluding Articles From Other Boxes If the homepage includes other content sections that are not powered by Recombee, such as editor-picked articles, and you want to exclude these from the recommended feed, you can do so dynamically using the **[filter parameter](/api#recommend-items-to-user-param-filter)** in the **[API request](/api#recommend-items-to-user)**. For example, if you want to exclude articles with the IDs `article-42`, `article-77`, and `article-92`, you can use the following filter: ReQL ``` 'itemId' not in {"article-42", "article-77", "article-92"} ``` Tip: Category-Specific Feed Personalized feeds can also be applied to category pages. For example, if the user navigates to the "Sports" category, only articles related to sports should be displayed in the feed. Since the selected category is dynamic, you should send the category filter as part of the **[filter parameter](/api#recommend-items-to-user-param-filter)** in the **[API request](/api#recommend-items-to-user)**. Depending on how you model the category/categories in your catalog, the filter (ReQL expression) may look like this: ##### String Property ReQL ``` 'category' == "" 'category' == "sport" ``` ##### Set of Categories ReQL ``` "" in 'categories' "sport" in 'categories' ``` **Alternative Implementation:** As an alternative to using a filter, you can utilize the **[Recommend Items to Item Segment endpoint](/api#recommend-items-to-item-segment)** for a specific category (= **[Item Segment](/segmentations)**). In this case, you don't need to provide a dynamic filter, as it is inferred from the given Item Segment. To load subsequent articles when the user scrolls, use the **[Recommend Next Items endpoint](/api#recommend-next-items)** in the same way as with _Recommend Items to User_. ## Boosters [Boosters](/scenarios#boosters) allow you to influence the recommendation engine to prioritize certain types of content. For example, you can boost promoted content or articles handpicked by editors to give them higher visibility. Tip: Boost Editor's Picks If editors mark certain articles as preferred, and this information is exported to the Items catalog as a property, you can set up a Booster to increase the visibility of these articles. 1. Navigate to the **[Boosters](/scenarios#boosters)** tab and **Add first booster**. 2. Find _Boost editors' picks_ and click **+**. 3. Specify the **property** in your item catalog that identifies **the picked articles** (the property should have a value of _true_ for these articles). 4. Use the _Preview_ tool to adjust the **Boosting coefficient** slider and find the optimal level of boosting for these articles. ![Admin UI - Booster - Editor's Picks](/img/recipes/news/editors-picks-boosters.png) ## Constraints Using **[Constraints](/scenarios#constraints)**, you can enforce rules to maintain a certain level of diversity within the recommended content. For example, you can ensure that the personalized feed includes articles on various topics or categories. Topics Diversity Constraint If you want the personalized feed to always display articles from multiple topics or categories, follow these steps: 1. Navigate to the **[Constraints](/scenarios#constraints)** tab and **Create Constraint**. 2. Select the **[Segmentation](/segmentations)** that represents the topics or categories. If you don't have such Item Segmentation created yet, click the **Create** button and define the Segmentation by selecting the item property that contains the topic/category information. 3. Choose the **Limit Type**: * **Absolute**: Specify a fixed limit (e.g., allow at most 3 articles from a single topic per request). * **Relative**: Specify a percentage limit (e.g., ensure no more than 50% of the recommendations are from one topic). ![Admin UI - Constraints](/img/recipes/news/personalized-feed-constraints.png) ## Requesting Recommendations There are three ways to integrate the Personalized News Feed. 1. **[No-Code Widget](/no-code-widgets)** – create a No-Code Widget using the **visual editor in the Admin UI** to embed an infinite scrolling news feed without writing code. 2. **[Widget SDKs](/widget-sdks#feed)** – use the [Feed](/widget-sdks#feed) component of the Widget SDKs to build a personalized scrolling experience. The widget is initialized using the [Recommend Items to User](/api#recommend-items-to-user) endpoint and automatically handles fetching more articles on scroll / clicking the _Show More_ button. 3. **[API SDK](/api_clients)** – implement the feed manually using the API: * **[Recommend Items to User](/api#recommend-items-to-user)** – retrieves the initial set of articles for the feed. * The response includes a unique `recommId` (e.g., _3f6ad2f2-a3f1-4ba1-a690-f4f01f76d4eb_). * **[Recommend Next Items](/api#recommend-next-items)** – use this endpoint with the `recommId` to load additional articles as the user scrolls. ![Infinite Feed Handling using Recommend Next Items](/img/recipes/news/infinite-feed-next-recomms.png) For more details, visit the **Integration** tab in the scenario configuration within the Admin UI. --- # Personalized Sections With Reordering > Source: https://docs.recombee.com/recipes/news/homepage/personalized-sections-with-reordering > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Composite Recommendations Overview](#composite-recommendations-overview) * [Segmentation Setup](#segmentation-setup) * [Scenario Setup](#scenario-setup) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Personalized Sections With Reordering ![](/img/recipes/news/personalized-sections-with-reordering.png) ## Introduction Modern news homepages often display multiple topical sections (e.g., _World_, _Politics_, _Technology_, _Sports_). You can make these sections fully personalized by determining: 1. The **order of sections** (so categories appear in the order each reader is most interested in), and 2. The **articles inside each section** (so that within each category, the user sees the most relevant content). With [Composite Recommendations](/scenarios#composite-recommendations), both of these steps can be done in one setup — producing a homepage that’s unique for every reader. --- ## Composite Recommendations Overview **Composite Recommendations** return both a _source entity_ (for example, a [category Segment](/segmentations)) and a list of _results_ (articles from that Segment) in a single response. They are requested via the [**Composite Recommendation API endpoint**](/api#composite-recommendation). In our case: * **Source:** ID of the homepage section, e.g., the _category_ (Item Segment) * **Result:** Articles from that category [![Composite Recommendations - News Example](/img/gui/composite_items_from_category.png)](/img/gui/composite_items_from_category.png) Because the source is personalized (which categories the reader cares about) and the results are personalized (which articles within those categories they like), you get dynamic section ordering and personalized content within each section — all in one request. ## Segmentation Setup Start by creating a **Segmentation** based on the item property that represents article categories (e.g., `category` or `categories`). In the Recombee Admin UI, navigate to **[Segmentations](/segmentations)** → **Create**. 1. Choose **Segmentation Type** – _Property-based_. 2. Select the **property** that holds the article’s category information. ![Admin UI - Segmentation Setup](/img/recipes/news/categories-segmentation.png) After picking the property, a preview opens up and you can see what categories exist in your catalog and the number of items per category. If your sections are defined more dynamically (for example, using multiple properties), you can use [Advanced Segmentation options](/segmentations#advanced-creating-segmentations). ## Scenario Setup Go to **Scenarios** → **Create Scenario**. 1. Choose a **Scenario ID**, e.g. `homepage-sections-and-articles`. 2. Set the **Recommendation Type** to **Composite** (see [Composite Recommendations](/scenarios#composite-recommendations)). 3. Then pick one of the **Templates**: * [news:articles-from-top-category-for-you](/recommendation_logics#news-articles-from-top-category-for-you) * [news:articles-from-top-segment-for-you](/recommendation_logics#news-articles-from-top-segment-for-you) depending on how your homepage sections are defined, and create the Scenario. ![Admin UI - Scenario Setup](/img/recipes/news/composite-homepage-sections-articles.png) ## Filters You may want to apply additional filters to ensure only relevant or recent content appears in each section. Tip: Recent Articles Only To ensure relevance, filter for articles published in the last few days: 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter** into the **Result** section. 2. Choose _Recent items_ and click **+**. 3. Specify the **property** that represents the publish date. 4. Define the maximum article age (e.g., 3 days). ![Admin UI - Filter - Recent Articles](/img/recipes/news/recent-items-filter-composite.png) ## Requesting Recommendations There are two ways to show multiple personalized sections in your application: 1. **Using the API Client** Using an [API Client of your choice](/api_clients), send multiple **[Composite Recommendation requests](/api#composite-recommendation)** within a single **[Batch request](/api#batch)**, with the [distinctRecomms](/api#batch-param-distinctRecomms) parameter set to `true` to deduplicate content across sections. Tip Composite Recommendations automatically ensure distinct _source entities_ (categories), while the `distinctRecomms` flag removes duplicate articles between sections. See [this example](/api#composite-recommendation-example-category-sections-with-reordering) for guidance on how to implement this approach in your programming language. Once you receive the response, render each _source_ (category) as a section title and populate it with the corresponding _results_ (articles) to create a fully personalized news homepage layout. 1. **Using the Widget SDK** For web applications built with HTML, CSS and JavaScript, the [Widget SDKs](/widget-sdks) support Composite Recommendations out of the box. Place one widget per section on your page, each sending its own **[Composite Recommendation request](/api#composite-recommendation)**. Design the section title with the `SourceItemComponent` parameter and the articles inside it with `ItemComponent`. Multiple widgets on one page are deduplicated automatically, for articles as well as for _source entities_ (categories). For full code examples and in-depth guidance, see the relevant SDK documentation on Composite Recommendations: * [Carousel Widget (JS)](/widget-sdks/carousel-widget-js#composite-recommendations) * [Carousel Widget (React)](/widget-sdks/carousel-widget-react#composite-recommendations) * [Grid Widget (JS)](/widget-sdks/grid-widget-js#composite-recommendations) * [Grid Widget (React)](/widget-sdks/grid-widget-react#composite-recommendations) * [Feed Widget (JS)](/widget-sdks/feed-widget-js#composite-recommendations) * [Feed Widget (React)](/widget-sdks/feed-widget-react#composite-recommendations) --- # Top Stories > Source: https://docs.recombee.com/recipes/news/homepage/top-stories > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Boosters](#boosters) * [Requesting Recommendations](#requesting-recommendations) * [Multiple Recommendation Boxes on the Homepage](#multiple-recommendation-boxes-on-the-homepage) # Top Stories ![](/img/recipes/news/top-stories.png) ## Introduction The **Top Stories** section is a key feature in most news platforms, designed to spotlight the most significant, trending, and engaging stories of the day. This recipe will guide you in setting up a Top Stories scenario that blends up-to-date news articles, personalized recommendations based on user behavior, and editorial curation. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and select **Create Scenario**. 1. Enter a **Scenario ID**, such as _"top-stories"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/news/top-stories-create-scenario.png) ## Logic The **[Logic](/recommendation_logics)** determines the behavior of the recommendation engine. * Select the **[news:daily-news](/recommendation_logics#news-daily-news)** logic type from the **News** models. This Logic prioritizes delivering top daily stories tailored to your audience. You can configure the following parameters to refine the recommendations. `editorsPicks` An optional list of editor-selected stories that will be prepended before algorithmically recommended content. This list can be managed: * Directly in the Recombee Admin UI. * Dynamically via the [API parameter](/recommendation_logics#recommendation-logics-set-via-api) in the recommendation request, enabling integration with an external CMS. The `publishedTimestamp` specifies the property in your item catalog that stores the article's publication timestamp. This ensures that the model can prioritize fresh articles. ![Admin UI - Logic](/img/recipes/news/top-stories-logic.png) ## Filters Tip: Recent Articles Filter By default, the Logic accounts for article freshness and recommends trending or breaking content. However, to enforce a strict limit (e.g., excluding articles older than 24 hours), you can configure a filter in the Admin UI. 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter**. 2. Find _Recent items_, and click **+**. 3. Specify the **property** in your item catalog that represents the **publish date**. 4. Define the maximum age of articles (e.g. 1 day). ![Admin UI - Filter - Recent Items](/img/recipes/news/recent-items-filter.png) ## Boosters **[Boosters](/scenarios#boosters)** allow you to influence the recommendation engine to prioritize certain types of content. For example, you can boost promoted content or articles handpicked by editors to give them higher visibility. Tip: Boost Editor's Picks If editors mark certain articles as preferred, and this information is exported to the Items catalog as a property, you can set up a Booster to increase the visibility of these articles. 1. Navigate to the **[Boosters](/scenarios#boosters)** tab and **Add first booster**. 2. Find _Boost editors' picks_ and click **+**. 3. Specify the **property** in your item catalog that identifies **the picked articles** (the property should have a value of _true_ for these articles). 4. Use the _Preview_ tool to adjust the **Boosting coefficient** slider and find the optimal level of boosting for these articles. ![Admin UI - Booster - Editor's Picks](/img/recipes/news/editors-picks-boosters.png) ## Requesting Recommendations There are three ways to retrieve recommendations. 1. **[No-Code Widget](/no-code-widgets)** – create a No-Code Widget using the **visual editor in the Admin UI** to embed recommendations without coding. 2. **[Widget SDKs](/widget-sdks)** – use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid), or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User](/api#recommend-items-to-user) endpoint when initializing the widget. 3. **[API SDK](/api_clients)** – request the [Recommend Items to User](/api#recommend-items-to-user) endpoint of the Recombee API using an SDK of your choice. For further details, visit the **Integration** tab in the scenario configuration within the Admin UI. ### Multiple Recommendation Boxes on the Homepage If your homepage includes multiple recommendation sections — such as [personalized category-based sections](/recipes/news/homepage/personalized-sections-with-reordering) or [cross-site recommendations](/recipes/news/homepage/cross-site-recommendations) — you typically want to avoid duplication of content among the boxes. To achieve this: * Use a single [Batch request](/api#batch) to send all recommendation requests at once. * Enable the [distinctRecomms parameter](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes) in the batch request to prevent overlapping articles between sections. The [Widget SDKs](/widget-sdks) handle this functionality automatically. --- # Personalized Emailing > Source: https://docs.recombee.com/recipes/news/personalized-emailing > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) * [Requesting Dynamic Content from API](#requesting-dynamic-content-from-api) * [Pre-fetching Recommendations](#pre-fetching-recommendations) # Personalized Emailing ![](/img/recipes/news/personalized-emailing.png) ## Introduction Deliver engaging and relevant newsletters with personalized news content for every reader. The [news:emailing](/recommendation_logics#news-emailing) Logic is tailored specifically for **periodic email campaigns** — such as daily or weekly digests. It combines the user’s interests with essential unread content, helping them stay informed without missing out on important headlines. Whether you're sending editorial roundups, topic-specific campaigns, or broad-reaching digests, this Logic ensures each email remains fresh, relevant, and highly personalized. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"emailing"_ or a campaign-specific ID (e.g., _"weekly-digest"_). 2. Choose **Recommendation type** – _[Items to User](/api#recommend-items-to-user)_. ![Admin UI - Scenario Setup](/img/recipes/news/emailing-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Select the **[news:emailing](/recommendation_logics#news-emailing)** logic type from the **News** models. This Logic is designed to generate personalized selections of articles specifically for email newsletters. ![Admin UI - Logic](/img/recipes/news/emailing-logic.png) It automatically blends: * **Personalized recommendations** based on the user’s reading behavior and interests. * **Key unread articles**, ensuring that important stories — which the user hasn't seen yet — are not missed. This makes it ideal for newsletters where both **engagement and awareness** matter. ## Filters Filter on Recent Articles To ensure that your email only includes **fresh news**, apply the _Recent items_ predefined filter: 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter**. 2. Find _Recent items_ and click **+**. 3. Choose the **property** in your catalog that stores **publish time** (e.g., `publishedAt`). 4. Set the maximum age of articles depending on your campaign frequency: * **1 day** for daily emails * **7 days** for weekly newsletters * Or another interval that fits your content cycle [![Admin UI - Filter - Recent Articles](/img/recipes/news/recent-items-filter.png)](/img/recipes/news/recent-items-filter.png) Tip: Category-Specific Campaigns To focus an email on a specific topic (e.g., _Politics_, _Tech_, _Sports_): 1. Navigate to the **[Filters](/scenarios#filters)** tab and **Add first filter**. 2. **Add one of the following filters** from the library of predefined rules: * **Items from particular category \[string\]** – if articles always belong to a single category * **Items from particular category \[set\]** – if articles can belong to multiple categories 3. Choose the **property** used in your catalog for topics or categories (e.g., `category`, `topics`) 4. Enter the **Category name** you want to display. [![Admin UI - Filter - Category-specific News](/img/recipes/news/emailing-filters.png)](/img/recipes/news/emailing-filters.png) ## Requesting Recommendations Choose the way of requesting recommendations compatible with your emailing platform ### Requesting Dynamic Content from API If the emailing platform can fetch the recommendations directly from the Recombee API: 1. Ensure the platform supports the [authentication scheme](/authentication) directly (e.g. in the case of _Customer.io_), or set up a small proxy that authenticates the requests. 2. In case the authentication proxy needs to be set up, please contact [support@recombee.com](mailto:support@recombee.com) for guidance on how your emailing platform can be connected with Recombee. ### Pre-fetching Recommendations If the emailing platform does not support requesting a 3rd party API but supports adding personalized content unique to each user: 1. Request the recommendations for each user who shall get the email using the [Recommend Items to User endpoint](/api#recommend-items-to-user). 2. Upload the recommendations to the emailing platform. 3. Send the emails. You can request many recommendations at once using the [Batch endpoint](/api#batch). You can contact [support@recombee.com](mailto:support@recombee.com) to get more information on how this procedure shall be implemented in the case of your emailing platform. --- # Search Articles > Source: https://docs.recombee.com/recipes/news/search-articles > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Requesting Search Results](#requesting-search-results) # Search Articles ![](/img/recipes/news/search-articles.png) ## Introduction For news and publishing sites, search quality depends on more than matching the query. A reader searching for _"elections"_, _"climate"_, or _"football"_ often expects recent articles, currently popular stories, and content that fits their reading habits. Recombee’s personalized news search combines the search query with article freshness, trendingness, and user preferences to create a more engaging discovery experience. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"search"_ 2. Choose **Recommendation type** \- _[Search Items](/api#search-items)_ ![Admin UI - Scenario Setup](/img/recipes/news/search-articles-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[news:search](/recommendation_logics#news-search)** logic type from the **News** models to get smart full-text search optimized for searching news articles. This Logic lets you balance multiple ranking signals: **Freshness Impact** * `freshnessWeight` controls how much recently published articles are prioritized. * `freshnessDateProperty` specifies the item property that stores the article publication date. For news sites, we recommend setting `freshnessDateProperty` to the property that contains the article publication date, such as `publishedAt` or `datePublished`. **Trendingness Impact** * `trendingnessWeight` controls how much currently trending articles affect the ranking. * `trendingnessPeriod` defines the time window used to calculate trendingness. **Personalization Impact** * `personalizationWeight` controls how much the results are personalized for the individual reader. **Other Parameters** * `allowEmptyQueryFallback` controls what happens when the search query is empty. When enabled, Recombee can return personalized recommendations instead of an empty result list. ![Admin UI - Logic](/img/recipes/news/search-articles-logic.png) ## Requesting Search Results There are three ways to get search results. 1. **[No-Code Widget](/no-code-widgets)** \- create a [Quick Search No-Code Widget](/no-code-widgets#html-widget-full-text-search) using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the Quick Search SDK for [vanilla JavaScript](/widget-sdks/quick-search-widget-js) or [React](/widget-sdks/quick-search-widget-react) to create a search widget with the design of your choice. 3. **[API SDK](/api_clients)** \- request the [Search Items endpoint](/api#search-items) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. ![Quick Search No-Code Widget](/img/recipes/news/search-articles-no-code-widget.png) Quick Search No-Code Widget --- # More Like This > Source: https://docs.recombee.com/recipes/video/asset-detail-and-player/more-like-this > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # More Like This ![](/img/recipes/video/more-like-this.png) ## Introduction As a user, you'll appreciate the "More like this" section when exploring video details, as it conveniently displays titles similar to your current selection. This makes it super easy for you to discover new videos that align with your tastes. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"similar-movies"_ 2. Choose **Recommendation type** \- _[Items to Item](/api#recommend-items-to-item)_ (as the recommendations will be based mainly on the currently viewed movie or series) ![Admin UI - Scenario Setup](/img/recipes/video/more-like-this-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[video:more-like-this](/recommendation_logics#video-more-like-this)** logic type from the **Video** models Based on the `assetType` parameter you can choose what type of assets will be returned (e.g. movies, series, episodes, or movies and episodes, etc.). Using the `excludeAlreadyWatched` parameter you can either allow or filter out the titles the user has already watched. ![Admin UI - Logic](/img/recipes/video/more-like-this-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI.** 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to Item endpoint](/api#recommend-items-to-item) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to Item endpoint](/api#recommend-items-to-item) of the Recombee API using an SDK of your choice. For more information navigate to the Integration tab of the Scenario in the Admin UI. --- # Watch Next > Source: https://docs.recombee.com/recipes/video/asset-detail-and-player/watch-next > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Watch Next ![](/img/recipes/video/watch-next.png) ## Introduction This use-case is designed to keep your users immersed in the ultimate binge-watching zone, through seamless transitions from one captivating title to the next. Your users will be able to explore and discover new titles that speak to their interests, resulting in satisfied customers. The "Watch Next" scenario is dedicated to delivering personalized recommendations to each user, showcasing titles related to the one the user just watched. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"watch-next"_ 2. Choose **Recommendation type** \- _[Items to Item](/api#recommend-items-to-item)_ (as the recommendations will be based mainly on the movie or episode that has been just watched) ![Admin UI - Scenario Setup](/img/recipes/video/watch-next-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[video:watch-next](/recommendation_logics#video-watch-next)** logic type from the **Video** models which is optimized for the end-of-playback recommendations Based on the `assetType` parameter you can choose what type of assets will be returned (e.g. movies, series, episodes, or movies and episodes, etc.). Using the `excludeAlreadyWatched` parameter you can either allow or filter out the titles the user has already watched. ![Admin UI - Logic](/img/recipes/video/watch-next-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI.** 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to Item endpoint](/api#recommend-items-to-item) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to Item endpoint](/api#recommend-items-to-item) of the Recombee API using an SDK of your choice. For more information navigate to the Integration tab of the Scenario in the Admin UI. --- # Short Videos Feed > Source: https://docs.recombee.com/recipes/video/feed/swiping-feed > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Sending Interactions](#sending-interactions) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Content Freshness](#content-freshness) * [Optimization Weights](#optimization-weights) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Short Videos Feed ![](/img/recipes/video/short-videos-feed.png) ## Introduction A short videos feed (TikTok / Instagram Reels / YouTube Shorts–style) is a continuously personalized stream of bite-sized videos, where each item is selected and ranked in real time to match the user’s immediate interests and engagement patterns. The feed is consumed one video at a time, with each next recommendation optimized for relevance and engagement. ## Sending Interactions To achieve high-quality real-time personalization, it is essential to continuously send user interactions as they consume the feed. * Send [View Portions](/api#set-view-portion) for consumed content, with the [autoPresented parameter](/api#set-view-portion-param-autoPresented) set to `true` and [timeSpent](/api#set-view-portion-param-timeSpent) specified. * Interactions should be sent periodically (e.g., every few seconds) * For short videos, the `portion` parameter can be set to `0` at the start of playback and to `1` afterwards * Send likes and dislikes as +1 / -1 [Ratings](/api#add-rating) These signals allow Recombee to quickly adapt the feed to the user’s current preferences. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"short-videos-feed"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/video/short-videos-feed-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the [**recombee:swiping-feed**](/recommendation_logics#recombee-swiping-feed) Logic type from the **Default** models This Logic is designed for infinite swiping feed experiences, where users continuously browse short-form content and can express feedback through likes or dislikes. ### Content Freshness The Logic can prioritize newer content using the following parameter: * `creationTimestamp` \- property representing the creation time of an item, allowing the Logic to evaluate and boost more recent content ### Optimization Weights Recommendations are optimized in real time based on a configurable combination of user engagement signals, such as likes, number of viewed items, purchases, and time spent watching content. You can control the importance of these signals using the following parameters: * `timeSpentWeight` \- weight controlling the importance of [time spent](/api#set-view-portion-param-timeSpent) watching content * `likeWeight` \- weight controlling the importance of user likes, sent as positive [Ratings](/api#add-rating) * `itemsShownWeight` \- weight controlling the importance of maximizing the number of items consumed by the user * `purchaseWeight` \- weight controlling the importance of maximizing the number of [Purchases](/api#add-purchase) (of e.g., premium gated content) ![Admin UI - Logic](/img/recipes/video/short-videos-feed-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** * create an _Infinite Feed_ No-Code Widget using the visual editor in the Admin UI. 2. **[Widget SDKs](/widget-sdks)** * use the SDK for a [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. * use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** * request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. * as the user continues browsing, use [Recommend Next Items](/api#recommend-next-items) to retrieve the next batch of content For more information navigate to the Integration tab of the Scenario in the Admin UI. --- # Actors For You > Source: https://docs.recombee.com/recipes/video/fully-personalized-homepage/actors-for-you > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Segmentation Setup](#segmentation-setup) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Actors For You ![](/img/recipes/video/actors-for-you.png) ## Introduction Leverage the influence of favorite actors on viewing choices. This scenario adds a personalized touch to your video recommendations by featuring actors your users love the most, as determined by their viewing history. ## Segmentation Setup Most of the recommendation rows on the homepage feature videos, however, in this case, we want to recommend actors that the user shall like based on the user’s watching history. In the Recombee Admin UI, navigate to the **[Segmentations](/segmentations)** section and choose **Create**. 1. Choose **Segmentation Type** \- _Property-based_ 2. Pick **Property** from the list that contains the property that contains the list of actors per movie or episode ![Admin UI - Segmentation Setup](/img/recipes/video/actors-for-you-segmentation-setup.png) After picking the property, a preview opens up and you can see the actors and the number of assets in which they star. ![Admin UI - Segmentation Setup - Preview](/img/recipes/video/actors-for-you-segmentation-setup-preview.png) Then confirm the settings by hitting the **Create** button. You have now created the Segmentation based on the actors, and you can proceed to recommend the actors (=Segments) to the user. Similarly, you can create a Segmentation based e.g. on the director. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"actors-for-you"_ 2. Choose **Recommendation type** \- _[Item Segments to User](/api#recommend-item-segments-to-user)_ 3. Continue and choose **Results Segmentation** \- _actors Segmentation_ created in the previous step ![Admin UI - Scenario Setup](/img/recipes/video/actors-for-you-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[recombee:default](/recommendation_logics#recombee-default)** logic type from the **Universal Models** This particular Logic returns the Segments (=actors) in personalized order to recommend the user interesting actors according to the user’s previous interactions. ![Admin UI - Logic](/img/recipes/video/actors-for-you-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Recommendations You shall request the [Recommend Items Segments to User endpoint](/api#recommend-item-segments-to-user) of the Recombee API using an [SDK of your choice](/api_clients). For more information navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple rows with a single API request, use the [Batch endpoint](/api#batch) and put the recommendation requests inside it. Set the parameter `distinctRecomms` in order to [deduplicate the assets among the rows](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). --- # Because You Watched > Source: https://docs.recombee.com/recipes/video/fully-personalized-homepage/because-you-watched > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Composite Recommendations Overview](#composite-recommendations-overview) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Because You Watched ![](/img/recipes/video/because-you-watched.png) ## Introduction The **Because You Watched** scenario ensures your users receive recommendations based on their recent watches. By analyzing their viewing history, we present a carefully curated list of videos that share thematic elements with what your users enjoyed before. With [Composite Recommendations](/scenarios#composite-recommendations), you can return both: 1. The **source item** (the video the user recently watched), and 2. The **recommended items** (similar titles or related content) — all in a single API response. ## Composite Recommendations Overview **Composite Recommendations** combine multiple recommendation steps into one response. They are requested via the [**Composite Recommendation API endpoint**](/api#composite-recommendation). In this use case: * **Source:** The video the user watched (an _Item_) * **Result:** Related videos the user is likely to enjoy next [![Because You Watched Composite Recommendation Example](/img/gui/composite_because_you_watched.png)](/img/gui/composite_because_you_watched.png) This setup ensures contextual recommendations that feel natural and personalized — “because you watched _X_, you might also like _Y_.” --- ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, e.g. `because-you-watched`. 2. Set the **Recommendation Type** to **Composite** (see [Composite Recommendations](/scenarios#composite-recommendations)). 3. Select the **Template:** [video:because-you-watched](/recommendation_logics#video-because-you-watched). ![Admin UI - Composite Scenario Setup](/img/recipes/video/because-you-watched-create-scenario.png) ## Logic Within the [video:because-you-watched](/recommendation_logics#video-because-you-watched) Logic, you can customize the returned assets in the **Result** section using parameters such as: * `assetType` – to specify which types of videos to include (e.g., _movies_, _series_, _episodes_). * `excludeAlreadyWatched` – to filter out content the user has already seen. ![Admin UI - Logic](/img/recipes/video/because-you-watched-logic-result.png) You can also configure how the watched asset is selected in the **Source** section using: * `maxDaysAgo` – to specify the maximum number of days since the user watched a video for it to be considered for the “Because” selection. * `minWatchedPercentage` – to define the minimum portion of a video that must be watched (based on the _View Portion_ interaction) for it to be considered watched by the user. ![Admin UI - Logic](/img/recipes/video/because-you-watched-logic-source.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Recommendations There are two ways to show multiple personalized rows in your application: 1. **Using the API Client** Using an [API Client of your choice](/api_clients), you can retrieve _Because You Watched_ recommendations via the **[Composite Recommendation API endpoint](/api#composite-recommendation)**. For more information navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple rows with a single API request, use the [Batch endpoint](/api#batch) and put recommendation requests for all rows inside it. Set the parameter `distinctRecomms` in order to [deduplicate the assets among the rows](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). 1. **Using the Widget SDK** For web applications built with HTML, CSS and JavaScript, the [Widget SDKs](/widget-sdks) support Composite Recommendations out of the box. Place a widget on your page, with `createRequest` returning a **[Composite Recommendation request](/api#composite-recommendation)**. Design the row title with the `SourceItemComponent` parameter and the videos inside it with `ItemComponent`. In order to request content for multiple rows, simply place multiple widgets on the page. These will get deduplicated automatically, for the recommended videos as well as for the _source items_ (the watched videos). For full code examples and in-depth guidance, see the relevant SDK documentation on Composite Recommendations: * [Carousel Widget (JS)](/widget-sdks/carousel-widget-js#composite-recommendations) * [Carousel Widget (React)](/widget-sdks/carousel-widget-react#composite-recommendations) * [Grid Widget (JS)](/widget-sdks/grid-widget-js#composite-recommendations) * [Grid Widget (React)](/widget-sdks/grid-widget-react#composite-recommendations) * [Feed Widget (JS)](/widget-sdks/feed-widget-js#composite-recommendations) * [Feed Widget (React)](/widget-sdks/feed-widget-react#composite-recommendations) --- # Continue Watching > Source: https://docs.recombee.com/recipes/video/fully-personalized-homepage/continue-watching > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Continue Watching ![](/img/recipes/video/continue-watching.png) ## Introduction The "Continue Watching" use case is designed to address a common user scenario – interruptions in their viewing experience. Users may encounter interruptions due to various factors such as time constraints or shifting priorities. This use case allows users to easily pick up where they left off in their content journey, making consuming content more smooth and enjoyable. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"continue-watching"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ (as we want to show the partially watched content of a particular user) ![Admin UI - Scenario Setup](/img/recipes/video/continue-watching-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[video:continue-watching](/recommendation_logics#video-continue-watching)** logic type from the **Video** models By the `watchingStartedPercentage` and `watchingCompletedPercentage` parameters, you can specify what content shall be considered as partially watched. Based on the `assetType` parameter you can also choose what type of content will be considered (e.g. movies, series, episodes, or movies and episodes, etc.) - the default is `movies+episodes`. ![Admin UI - Logic](/img/recipes/video/continue-watching-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI.** 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. For more information navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple rows with a single API request, use the [Batch endpoint](/api#batch) and put the recommendation requests inside it. Set the parameter `distinctRecomms` in order to [deduplicate the assets among the rows](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). --- # Editors’ Picks For You > Source: https://docs.recombee.com/recipes/video/fully-personalized-homepage/editors-picks-for-you > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Editors’ Picks For You ![](/img/recipes/video/editors-picks-for-you.png) ## Introduction Recombee enhances your editorial capabilities by enabling you to tailor your selections to showcase the most relevant titles to your audience. Show your users content that has been carefully selected by the editorial team, with the option to personalize the ordering of these videos for each user. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"editors-picks"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ (as we want to reorder the content picked by editors based on the user’s watching history) ![Admin UI - Scenario Setup](/img/recipes/video/editors-picks-for-you-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[video:editorial-picks](/recommendation_logics#video-editorial-picks)** logic type from the **Video** models to return the assets picked by the editors The list of picked assets is provided via the `picks` parameter: the editorial team can either pick the list of items directly in the Recombee Admin UI or if you export the list from a CMS, you can set it [via API](/recommendation_logics#setting-logic-using-api-parameter) when calling the recommendation request. To reorder the picks based on the user’s history, set the `personalizedReordering` parameter to `true`. Using the `excludeAlreadyWatched` parameter you can either allow or filter out the titles the user has already watched. ![Admin UI - Logic](/img/recipes/video/editors-picks-for-you-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI.** 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. For more information navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple rows with a single API request, use the [Batch endpoint](/api#batch) and put the recommendation requests inside it. Set the parameter `distinctRecomms` in order to [deduplicate the assets among the rows](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). --- # Personalized Re-ordering of Rows > Source: https://docs.recombee.com/recipes/video/fully-personalized-homepage/personalized-re-ordering-of-rows-advanced > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Composite Recommendations Overview](#composite-recommendations-overview) * [Segmentation Setup](#segmentation-setup) * [Scenario Setup](#scenario-setup) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) # Personalized Re-ordering of Rows ![](/img/recipes/video/personalized-re-ordering-of-rows-advanced.png) ## Introduction It is usually the cornerstone of the OTT platform homepage to show the picks from various (micro) genres. You can make these rows truly personalized: Pick the top genres for the particular user, and also show the most appealing assets inside these rows. The same approach is besides the homepage often also used in the category pages, such as Movies or Series. With [Composite Recommendations](/scenarios#composite-recommendations), you can easily personalize both: 1. The **order of those rows** (so genres appear in the order each user is most interested in), and 2. The **content inside each row** (so that within each genre, the user sees the most relevant items). ## Composite Recommendations Overview **Composite Recommendations** return both a _source entity_ (for example, a [genre Segment](/segmentations)) and a list of _results_ (items from that Segment) in a single response. They are requested via the [**Composite Recommendation API endpoint**](/api#composite-recommendation). In our case: * **Source:** ID of the row, e.g. the _genre_ (Item Segment) * **Result:** Items (videos) for that row [![Genre Rows Setup](/img/gui/composite_videos_to_genre.png)](/img/gui/composite_videos_to_genre.png) Because the source is personalized (which genre the user likes), and the result is personalized (which items within that genre they like), you get dynamic row ordering and item ordering in one request. ## Segmentation Setup First, in the Admin UI you create a **Segmentation** of your catalog items by genre. 1. Navigate to **Segmentations** → **Create**. 2. Set _Segmentation Type_ to _Property-based_. 3. Select the item property (e.g., `genre`) which defines the genre classification. ![Admin UI - Segmentation Setup](/img/recipes/video/genre-rows-with-personalized-order-advanced-segmentation-setup.png) After picking the property, a preview opens up and you can see what genres exist in your catalog and the number of items per genre. ![Admin UI - Segmentation Setup - Preview](/img/recipes/video/genre-rows-with-personalized-order-advanced-segmentation-setup-preview.png) ## Scenario Setup Go to **Scenarios** → **Create Scenario**. 1. Choose a **Scenario ID**, e.g. `homepage-rows-and-videos`. 2. Set the **Recommendation Type** to **Composite** (see [Composite Recommendations](/scenarios#composite-recommendations)). 3. Then pick one of the **Templates**: * [video:videos-from-top-genre-for-you](/recommendation_logics#video-videos-from-top-genre-for-you) * [video:videos-from-top-segment-for-you](/recommendation_logics#video-videos-from-top-segment-for-you) depending on the nature of your rows and create the Scenario. ![Admin UI - Scenario Setup](/img/recipes/video/composite-hp-rows-videos.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Recommendations There are two ways to show multiple personalized rows in your application: 1. **Using the API Client** Using an [API Client of your choice](/api_clients), send multiple **[Composite Recommendation requests](/api#composite-recommendation)** within a single **[Batch request](/api#batch)**, with the [distinctRecomms](/api#batch-param-distinctRecomms) parameter set to `true` to deduplicate content across rows. Tip Composite Recommendations automatically ensure distinct _source entities_ (genres), while the `distinctRecomms` flag removes duplicate videos between rows. See [this example](/api#composite-recommendation-example-category-sections-with-reordering) for guidance on how to implement this approach in your programming language. Once you receive the response, render each _source_ (genre) as a row title and populate it with the corresponding _results_ (videos) to create a fully personalized homepage layout. 1. **Using the Widget SDK** For web applications built with HTML, CSS and JavaScript, the [Widget SDKs](/widget-sdks) support Composite Recommendations out of the box. Place one widget per row on your page, each sending its own **[Composite Recommendation request](/api#composite-recommendation)**. Design the row title with the `SourceItemComponent` parameter and the videos inside it with `ItemComponent`. Multiple widgets on one page are deduplicated automatically, for videos as well as for _source entities_ (genres). For full code examples and in-depth guidance, see the relevant SDK documentation on Composite Recommendations: * [Carousel Widget (JS)](/widget-sdks/carousel-widget-js#composite-recommendations) * [Carousel Widget (React)](/widget-sdks/carousel-widget-react#composite-recommendations) * [Grid Widget (JS)](/widget-sdks/grid-widget-js#composite-recommendations) * [Grid Widget (React)](/widget-sdks/grid-widget-react#composite-recommendations) * [Feed Widget (JS)](/widget-sdks/feed-widget-js#composite-recommendations) * [Feed Widget (React)](/widget-sdks/feed-widget-react#composite-recommendations) --- # Popular & Trending > Source: https://docs.recombee.com/recipes/video/fully-personalized-homepage/popular-and-trending > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Boosters](#boosters) * [Constraints](#constraints) * [Diversify the Genres of Recommended Assets](#diversify-the-genres-of-recommended-assets) * [Requesting Recommendations](#requesting-recommendations) # Popular & Trending ![](/img/recipes/video/popular-and-trending.png) ## Introduction This scenario brings your users the hottest and most trending videos in real-time. From viral hits to rising stars, your users can immerse themselves in a dynamic selection that reflects the pulse of the video community. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"popular-movies-and-series"_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/video/popular-and-trending-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[video:popular](/recommendation_logics#video-popular)** logic type from the **Video** models to get the popular assets among the users The `timePeriod` specifies the time period in which the the popularity is measured. Therefore you can have e.g. _Popular This Month_ by setting the parameter to 30 days, or get recently trending content by setting the parameter to 7 days. More advanced use cases such as _Popular in Your Country_ can be achieved by setting the `userSegmentFilter` parameter, which specifies which users will be considered when computing the popularity. The parameter accepts a ReQL filter on top of the user properties - only the users that pass the filter will considered. Assuming that the users have a property called country and you want to recommend assets popular in the particular user’s country, the parameter shall be set to `‘country’ == context_user[“country”]`. The `assetType` parameter specifies what type of assets will be returned (e.g. movies, series, episodes, movies and episodes, etc.). ![Admin UI - Logic](/img/recipes/video/popular-and-trending-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Boosters Boost Content Picked by the Editorial Team You may want to boost the assets the editorial team picked as preferred. If you export this flag from your CMS as a **boolean property,** you can apply the _Boost editors' picks_ predefined rule in the **Boosters** tab of the **Scenario**. [![Admin UI - Booster - Boost editors' picks](/img/recipes/video/booster-editor-picks.png)](/img/recipes/video/booster-editor-picks.png) You can find the appropriate level of boosting using the **Preview.** [![Admin UI - Booster - Boost editors' picks - Preview](/img/recipes/video/booster-editor-picks-preview.png)](/img/recipes/video/booster-editor-picks-preview.png) ## Constraints ### Diversify the Genres of Recommended Assets You may want to show the user popular content from various genres, preventing the situation when all the content is from the same category, and may not attract the user. In order to do this, navigate to the [Constraints](/scenarios#constraints) tab of the Scenario, and add a new Constraint. The Constraint will be based on an Item [Segmentation](/segmentations) that splits the items by their genre. If you already have such Segmentation and you can pick it from the list, otherwise, you can create a new Segmentation based on the property that specifies the genre of the assets. Now you can specify the limit and allow e.g. up to 3 assets from a single genre, or up to 50% (with `Limit` type set to percentage) of the recommended items in the row to be of a single genre. ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI.** 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. For more information navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple rows with a single API request, use the [Batch endpoint](/api#batch) and put the recommendation requests inside it. Set the parameter `distinctRecomms` in order to [deduplicate the assets among the rows](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). --- # “Recommended For You” Rows > Source: https://docs.recombee.com/recipes/video/fully-personalized-homepage/recommended-for-you-rows > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Boosters](#boosters) * [Requesting Recommendations](#requesting-recommendations) # “Recommended For You” Rows ![](/img/recipes/video/recommended-for-you-rows.png) ## Introduction With a particular emphasis on customizable filters, our advanced recommendation algorithms curate rows on your viewers' homepage that align precisely with their unique preferences. They can enjoy a homepage that truly reflects their taste, ensuring each video suggestion is a perfect match. You can add a "For You" row, along with other personalized rows such as a "New Releases For You", a row with content from user's country or area, and much more thanks to our flexible [filters](#filters). ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**. The Scenario ID depends on what content will be shown in the particular box (what Filter will be applied), so it can be e.g. _top-picks-for-you_, _local-content-for-you_, or _new-releases-for-you_ 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ (as we want to personalize the content based on the user’s watching history) ![Admin UI - Scenario Setup](/img/recipes/video/recommended-for-you-rows-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[video:personal](/recommendation_logics#video-personal)** logic type from the **Video** models to recommend assets based on the user’s watching history Based on the `assetType` parameter you can choose what type of assets will be returned (e.g. movies, series, episodes, or movies and episodes, etc.). Using the `excludeAlreadyWatched` parameter you can either allow or filter out the titles the user has already watched. ![Admin UI - Logic](/img/recipes/video/recommended-for-you-rows-logic.png) ## Filters New Releases You may want to create a **Latest Releases For You** row and show only assets added in e.g. the last two weeks. 1. Navigate to **[Filters](/scenarios#filters)** tab and **Add first filter** 2. Find _Recent items_ and click on **+** 3. Specify which **property** in your Items catalog specifies the **publish date** 4. Enter maximal age in days ![Admin UI - Filter - Recent Items](/img/recipes/video/filter-recent-items.png) Local Content You may want to create a **Local Content For You** row and show only the content specific to the user’s country, state, city, etc. 1. Navigate to **[Business Rules](/reql#business-rules)** section and **Create Rule** 2. Enter a **Rule name**, such as _"User Local Content"_ 3. Choose **Rule Type** \- _Filter_ 4. Choose **Entity Type** \- _Items_ 5. Assuming the user has a _country_ user **property** and the assets have a _countries_ item **property**, that contains the countries to which the asset is local, the ReQL expression can look like this: ``` context_user["country"] in 'countries' ``` [![Admin UI - Filter - User Local Content - ReQL](/img/recipes/video/filter-user-local-content-reql.png)](/img/recipes/video/filter-user-local-content-reql.png) **After creating** the [Filter](/scenarios#filters), you can apply the rule to your Scenario in the Filters tab. [![Admin UI - Filter - User Local Content](/img/recipes/video/filter-user-local-content.png)](/img/recipes/video/filter-user-local-content.png) If the locations of the user and the videos are specified by latitude and longitude, you can use the [Geographical ReQL functions](/reql_functions#geographical-functions), such as [earth\_distance](/reql_functions#earth-distance). Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Boosters Boost Content Picked by the Editorial Team You may want to boost the assets the editorial team picked as preferred. If you export this flag from your CMS as a **boolean property,** you can apply the _Boost editors' picks_ predefined rule in the **Boosters** tab of the **Scenario**. [![Admin UI - Booster - Boost editors' picks](/img/recipes/video/booster-editor-picks.png)](/img/recipes/video/booster-editor-picks.png) You can find the appropriate level of boosting using the **Preview.** [![Admin UI - Booster - Boost editors' picks - Preview](/img/recipes/video/booster-editor-picks-preview.png)](/img/recipes/video/booster-editor-picks-preview.png) ## Requesting Recommendations There are three ways to get recommendations. 1. **[No-Code Widget](/no-code-widgets)** \- create a No-Code Widget using the **visual editor in the Admin UI.** 2. **[Widget SDKs](/widget-sdks)** \- use the SDK for a [Carousel](/widget-sdks#carousel), [Grid](/widget-sdks#grid) or [Feed](/widget-sdks#feed) to display the recommendations in the design of your choice. Use the [Recommend Items to User endpoint](/api#recommend-items-to-user) when initializing the widget. 3. **[API SDK](/api_clients)** \- request the [Recommend Items to User endpoint](/api#recommend-items-to-user) of the Recombee API using an SDK of your choice. For more information navigate to the Integration tab of the Scenario in the Admin UI. In order to request content for multiple rows with a single API request, use the [Batch endpoint](/api#batch) and put the recommendation requests inside it. Set the parameter `distinctRecomms` in order to [deduplicate the assets among the rows](/api#batch-example-using-distinctrecomms-parameter-to-deduplicate-results-in-multiple-boxes). --- # Personalized Emailing > Source: https://docs.recombee.com/recipes/video/personalized-emailing > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Recommendations](#requesting-recommendations) * [Requesting Dynamic Content from API](#requesting-dynamic-content-from-api) * [Pre-fetching Recommendations](#pre-fetching-recommendations) # Personalized Emailing ![](/img/recipes/video/personalized-emailing.png) ## Introduction Send personalized emails that perfectly align with your users' individual taste. Whether they are seeking thrilling adventures, heartfelt dramas, or mind-bending mysteries, our personalized emails will keep them up to date with the latest and greatest titles, catering to their unique preferences. Enhance the quality of your users' time on the platform by providing them with content recommendations tailored to their recent views and tastes. This powerful functionality allows you to recommend new releases, remind users of new episodes, and offer a range of other personalized suggestions. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"email"_ or the name of the particular emailing campaign 2. Choose **Recommendation type** \- _[Items to User](/api#recommend-items-to-user)_ ![Admin UI - Scenario Setup](/img/recipes/video/personalized-emailing-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[video:emailing](/recommendation_logics#video-emailing)** logic type from the **Video** models This model is **fine-tuned for periodic** (e.g. daily) personalized emailing campaigns. With the `rotationPolicy` parameter, you can control how the recommendations for the user change with each subsequent email sent. By default, there is a smart rotation that takes into account the position of recommended items and allows some of the items to re-appear in further e-mails. If you prefer not to repeat already recommended videos in the emails ever again, you can set the parameter to value `total`. By default, rotation only takes into account recommendations (e-mails) at most 14 days old. Should a longer time period be needed for your use case, kindly contact [support@recombee.com](mailto:support@recombee.com). `assetType` parameter specifies what type of assets will be returned (e.g. movies, series, episodes, movies and episodes, etc.). ![Admin UI - Logic](/img/recipes/video/personalized-emailing-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) Tip: Personalized selection from the recently added videos You may want to give the users personalized offering of the recently added titles. For example, by setting **30 days**, each user will get a personalized collection of interesting videos that were added during the last month. 1. Navigate to **[Filters](/scenarios#filters)** tab and **Add first filter** 2. Find _Recent items_ and click on **+** 3. Specify which **property** in your Items catalog specifies the **publish date** 4. Enter maximal age in days ![Admin UI - Filter - Recent Items](/img/recipes/video/filter-recent-items.png) An alternative to this approach would be adding the **Boost recent items** booster instead of a filter - especially if you don’t add new videos continuously, so there might not be always a sufficient number of candidates. ## Requesting Recommendations Choose the way of requesting recommendations compatible with your emailing platform ### Requesting Dynamic Content from API If the emailing platform can fetch the recommendations directly from the Recombee API: 1. Ensure the platform supports the [authentication scheme](/authentication) directly (e.g. in the case of _Customer.io_), or set up a small proxy that authenticates the requests. 2. In case the authentication proxy needs to be set up, please contact [support@recombee.com](mailto:support@recombee.com) for guidance on how your emailing platform can be connected with Recombee. ### Pre-fetching Recommendations If the emailing platform does not support requesting a 3rd party API but supports adding personalized content unique to each user: 1. Request the recommendations for each user who shall get the email using the [Recommend Items to User endpoint](/api#recommend-items-to-user). 2. Upload the recommendations to the emailing platform. 3. Send the emails. You can even request many recommendations at once using the [Batch endpoint](/api#batch). You can contact [support@recombee.com](mailto:support@recombee.com) to get more information on how this procedure shall be implemented in the case of your emailing platform. --- # Search Movies/Series > Source: https://docs.recombee.com/recipes/video/search-movies-and-series > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Introduction](#introduction) * [Scenario Setup](#scenario-setup) * [Logic](#logic) * [Filters](#filters) * [Requesting Search Results](#requesting-search-results) # Search Movies/Series ![](/img/recipes/video/search-movies-and-series.png) ## Introduction Say goodbye to endless scrolling and time-consuming searches. With our full-text search functionality, desired titles are just a few keystrokes away. Our search feature ensures that you can locate the content you're looking for quickly and effortlessly. Personalized search functionalities go beyond parsing search queries. They take a user's interaction history on the site, fostering a more tailored and intuitive browsing experience. By aligning search results with a user's behavior, businesses can enhance user engagement and other key metrics. ## Scenario Setup In the Recombee Admin UI, navigate to the **[Scenarios](/scenarios)** section and choose **Create Scenario**. 1. Enter a **Scenario ID**, such as _"search"_ 2. Choose **Recommendation type** \- _[Search Items](/api#search-items)_ ![Admin UI - Scenario Setup](/img/recipes/video/search-movies-and-series-create-scenario.png) ## Logic The [Logic](/recommendation_logics) defines the behavior of the recommendation engine. * Choose the **[video:search](/recommendation_logics#video-search)** logic type from the **Video** models to get personalized full-text search optimized for searching videos You can adjust how much the results are biased towards the user (as opposed to strictly following the full-text results) by setting the `personalizationImpact` parameter. Based on the `assetType` parameter you can choose what type of assets will be returned (e.g. movies, series, episodes, or movies and episodes, etc.). ![Admin UI - Logic](/img/recipes/video/search-movies-and-series-logic.png) ## Filters Available Assets (Global Settings) You always want to recommend only movies, series, and episodes that are currently available to watch for your users. Therefore you need to apply a [**Filter**](/scenarios#filters) rule to allow only such assets. As it would be tedious and prone to error to add this rule to all the Scenarios, this rule shall be added to the [**Global Settings**](/scenarios#global-settings), so it is always applied everywhere. **The particular filter depends on how you specify such assets in your catalog:** * If you have a **boolean property** that marks the asset as available you can use the predefined _Available items \[boolean\]_ rule. * If you have a **timestamp property** that specifies when the asset is published (becomes available) you can use the predefined _Published items rule_. * Or if you have a **licensing window (start date, end date)** you can use the predefined _Items within their licensing window_ rule. * In every other case, you can create a [**custom filter rule**](/reql) to allow only the available assets according to your own logic. ![Admin UI - Global Settings - Filter](/img/recipes/video/filter.png) ## Requesting Search Results There are three ways to get search results. 1. **[No-Code Widget](/no-code-widgets)** \- create a [Quick Search No-Code Widget](/no-code-widgets#html-widget-full-text-search) using the **visual editor in the Admin UI**. 2. **[Widget SDKs](/widget-sdks)** \- use the Quick Search SDK for [vanilla JavaScript](/widget-sdks/quick-search-widget-js) or [React](/widget-sdks/quick-search-widget-react) to create a search widget with the design of your choice. 3. **[API SDK](/api_clients)** \- request the [Search Items endpoint](/api#search-items) of the Recombee API using an SDK of your choice. For more information, navigate to the Integration tab of the Scenario in the Admin UI. ![Quick Search No-Code Widget](/img/gui/search-widget-sections-video.png) Quick Search No-Code Widget --- # Regions > Source: https://docs.recombee.com/regions > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Available Regions](#available-regions) # Regions Recombee maintains multiple server clusters around the world in order to provide the service with minimal network latency. You can pick the one that is the closest to you on creating a Database in [Recombee Admin UI](/admin_ui). ## Available Regions ### US (West Coast) ID: `us-west` Server-side Base URL: `rapi-us-west.recombee.com` Client-side Base URL: `client-rapi-us-west.recombee.com` ### Canada (East Coast) ID: `ca-east` Server-side Base URL: `rapi-ca-east.recombee.com` Client-side Base URL: `client-rapi-ca-east.recombee.com` ### Europe ID: `eu-west` Server-side Base URL: `rapi-eu-west.recombee.com` Client-side Base URL: `client-rapi-eu-west.recombee.com` ### Australia ID: `ap-se` Server-side Base URL: `rapi-ap-se.recombee.com` Client-side Base URL: `client-rapi-ap-se.recombee.com` You can set the region when initializing the [SDK Client](/api_clients). Please check the documentation of your chosen SDK for details. --- # Ruby API Client > Source: https://docs.recombee.com/ruby_client > For the complete documentation index, see [llms.txt](/llms.txt). # Ruby API Client [GitHubInstallation info and more examples](https://github.com/Recombee/ruby-api-client)[API ReferenceList of all available endpoints with examples](/api) Example Ruby ``` require 'recombee_api_client' include RecombeeApiClient client = RecombeeClient.new('--your-database-id--', '--your-db-private-token--', {:region => 'us-west'}) # Generate some random purchases of items by users NUM = 100 PROBABILITY_PURCHASED = 0.1 users = (1..NUM).map { |i| "user-#{i}" } items = (1..NUM).map { |i| "item-#{i}" } purchases = [] users.each do |user_id| purchased = items.select { |_| rand(0.0..1.0) < PROBABILITY_PURCHASED } purchased.each { |item_id| purchases.push( AddPurchase.new(user_id, item_id,'cascadeCreate' => true) # Use cascadeCreate to create the # yet non-existing users and items )} end begin # Send the data to Recombee, use Batch for faster processing of larger data client.send(Batch.new(purchases)) # Get recommendations for user 'user-25' response = client.send(RecommendItemsToUser.new('user-25', 5)) puts "Recommended items for user-25: #{response}" # User scrolled down - get next 3 recommended items response = client.send(RecommendNextItems.new(response['recommId'], 3)) puts "Next recommended items for user-25: #{response}" rescue APIError => e puts e # Use fallback end ``` --- # Shoptet Integration > Source: https://docs.recombee.com/shoptet_integration > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [Steps](#steps) * [Catalog Feed](#catalog-feed) * [Creating Scenario](#creating-scenario) * [Interaction Tracking](#interaction-tracking) * [Creating a No-Code Widget](#creating-a-no-code-widget) * [Widget in Banner](#widget-in-banner) * [Placing a Widget Using CSS](#id1) * [Placing a Widget on a Specific Page](#placing-a-widget-on-a-specific-page) # Shoptet Integration Recombee can be used on any e-commerce site made with [Shoptet](https://shoptet.cz/). ![](/img/headings/shoptet.png) * Real-time recommendations. * 100+ algorithms. * Fully customizable business rules. ## Steps The integration process consists of multiple steps. This manual assumes usage of Shoptet themes, but even if your e-shop is tailor-made, you will only need to change some names and everything will work as expected. First of all, you need to create your [Recombee account](https://admin.recombee.com/sign-up)with a 30-day free trial. Following steps: * Uploading your catalog feed with items * Creating a scenario in your Recombee Admin UI * Starting a tracking module for customer interactions * Creating a No-Code Widget * Placing the Widget on the Shoptet page ### Catalog Feed Catalog feed gives Recombee access to your items and their properties (such as price, availability, etc.). * In your Shoptet Admin console go to **Propojení/XML feedy**. * Copy URL address of _Heureka.cz - Rozšířený feed_. * In the section **Zabezpečení**, make sure you allow access from any IP address: * Uncheck _Zakázat přístup z IP adres, které nejsou uvedené na globálním whitelistu_ * Login to your [Recombee Admin UI](https://admin.recombee.com/). * Go to **Catalog feed** on the left menu in section **Integration**. * Click on _Create feed_. * Select _Heureka feed_. * Paste in the URL address from Shoptet from the previous steps. * Save Feed. * After a few minutes, you should see a log with numbers of successfully uploaded items. * Continue by creating a scenario, which is an application of recommendation. ### Creating Scenario The scenario defines the way you want to show items to your customers. * Read our detailed documentation on [how to make a scenario](/scenarios). * Proceed to Interaction tracking of your customers. ### Interaction Tracking Interactions represent the behavior of your customers, their preferences, and their taste. By sending us their interactions, Recombee can match what they would like to buy next. * **Detail view** * Detail view is an action of a customer viewing a specific product site and reading details such as price, brand, color, etc. * **Cart addition** * Interaction of customer putting an item to cart. * **Purchase** * Interaction of customer buying one or more products. **Getting interactions** To track your customers in real-time, you need to install the Recombee tracking module on your page. First, download the module [here](/files/shoptet/tracking_module.js) and save it as _tracking\_module.js_. * In your Recombee Admin UI in **General** go to section _Settings_. * Find _API tokens_ and copy your _Public Token_. * Open _tracking\_module.js_ in the text editor of your choice (for example, **Notepad** or **Atom**, don't use MS Word). * Paste your _Public Token_ between quotes on the first line and end the line with a semicolon (;). * On the next line write the _name of your database_ between quotes and end the line with a semicolon (;). It should look like this: JS ``` const publicToken = 'fFDj0Zkaz3036zLxmJWyy1jtbdvrgP4vL5vMHOklvMULjuD88qlPNk6Trv1ZlLYz'; const dbName = 'yourDatabaseName'; ``` * Save the file. * On your Shoptet Admin page go to **Vzhled a obsah**, section_Správce souborů_. * Create a folder _js_. * Open folder _js_. * Upload the file _tracking\_module.js_. * Save and exit. * On your Shoptet Admin page, go to **Vzhled a obsah**, section_Editor_ and menu _HTML kód_. * In the first text box _Záhlaví (před koncovým tagem HEAD)_ paste this code: HTML ``` ``` * In the second text box _Zápatí (před koncovým tagem BODY)_ paste this code: HTML ``` ``` * Save and exit. Your interactions should be working. Check it in your Recombee Admin UI and proceed to widget creation - a place on your site for recommendations. ### Creating a No-Code Widget You can create a No-Code Widget in our Admin UI or make one on your own. To make your No-Code Widget in the Admin UI, follow the steps at [No-Code Widget](/getting_started#getting-started-recomms-widget). Once your No-Code Widget is created: * Copy the generated HTML code as shown in the picture below. [![Embed Code](/img/shoptet/widget_code_selection.jpg)](/img/shoptet/widget_code_selection.jpg) * Open the text editor of your choice (for example, **Notepad** or**Atom**, don't use MS Word). * Paste the copied HTML code. * Save the file with the .js suffix. For example, save it as_widget.js_ ### Widget in Banner To show your No-Code Widget with recommendations on the site, you need to place it in a Shoptet banner or follow the steps in the following section [Placing a widget using CSS](/shoptet_integration#id1). To place an No-Code Widget in a Shoptet banner: * Open your Shoptet admin page. * Go to **Vzhled a obsah** and select section **Bannery**. * Click on an empty banner, for example, _Banner č. 3_. * Change the type of banner in _Typ banneru_ to _Textový banner_. * Check the _Zobrazit banner_ checkbox. * Check both _Desktop_ and _Mobile_. * Insert whole code from the file you created in the previous step (_widget.js_) to the box _Text nastavení._ * Save. * Using the Shoptet Admin page, select the location of the banner with your No-Code Widget. ### Placing a Widget Using CSS You can place an No-Code Widget anywhere on the site with our new feature[Position of the widget](/no-code-widgets#html-integration-positioning-of-the-widget). **Element anchor** First, you need to select an element on a specific page that will be used as an anchor. You can do it by opening the developer mode of the page and identifying the element selector. To learn more about element identifiers [click here.](https://www.w3schools.com/jquery/jquery_selectors.asp) * Open your widget file (_widget.js_) in the text editor of your choice (for example, **Notepad** or **Atom**, don't use MS Word). * Find the line which starts: JS ``` recombeeIntegration({ "type": "InitializeRecommendationWidget", "rootElementId": "widget-root-3a6f7234-1811-4b60-aa28-1cacf99d0666", "widgetId": "3a6f7234-1811-4b60-aa28-1cacf99d0666", "appendToElementSelector": ""}); ``` * Notice the last line. Put your element selector there. * Examples of use with element selector `div#description` to place No-Code Widget : * **insertBeforeElementSelector**: The widget will be inserted before the first element matching this selector: JS ``` "insertBeforeElementSelector": "div#description" ``` * **insertAfterElementSelector**: The widget will be inserted after the first element matching this selector. JS ``` "insertAfterElementSelector": "div#description" ``` * **prependToElementSelector**: The widget will be inserted as the first child of the first element matching this selector. JS ``` "prependToElementSelector": "div#description" ``` * **appendToElementSelector**: The widget will be inserted as the last child of the first element matching this selector. JS ``` "appendToElementSelector": "div#description" ``` * Save the file and exit. **JavaScript Shoptet Integration** * On your Shoptet Admin page go to **Vzhled a obsah**, section_Správce souborů_. * If not yet created, create a folder _js_. * Open folder _js_. * Upload your widget text file _widget.js_. * On your Shoptet Admin page, go to **Vzhled a obsah**, section_Editor_ and menu _HTML kód_. * In the second text box _Zápatí (před koncovým tagem BODY)_ paste this code at the end: HTML ``` ``` * Save and exit. If you want to add more widgets, upload the text file of widgets and add the same code as in the step above with the changed name _widget.js_ to the name of your file. ### Placing a Widget on a Specific Page Some pages can have specific widgets - for example, a page with the cart or product detail page. To do it, nest the widget code in `if condition`with a page keyword. Shoptet naming conventions give keywords for some specific pages: | Keyword | Page | | ------------- | ------------------------------ | | homepage | Homepage | | thankYou | Page after successful order | | productDetail | Page with details of a product | | cart | Page with cart content | To position your widget on this site (e.g. `cart`): * On your Shoptet Admin page go to **Vzhled a obsah**, section_Správce souborů_. * Download your widget file from folder _js_. * Open the widget file in the text editor of your choice (for example,**Notepad** or **Atom**, don't use MS Word). * Add the if condition`if (dataLayer[0].shoptet.pageType === 'cart') {` at the first line. * Add ending bracket `}` at the last line of your file. * Save the file. * On your Shoptet Admin page go to **Vzhled a obsah**, section_Správce souborů_. * Upload the file. * Save and exit. Example of widget visible only in the cart. JS ``` if(dataLayer[0].shoptet.pageType === 'cart') { window.recombeeIntegration = window.recombeeIntegration || function() { (recombeeIntegration.q = recombeeIntegration.q || []) .push(arguments); }; recombeeIntegration.l = +new Date(); recombeeIntegration ({ "type": "SetDefaults", "publicToken": "mFDjOZkaz3036zLxmJWyy1jtbdvrgP4vL5vMHOkWvMULguDS7q1PNkRTrvrZ1LYz", "databaseId" : "medium-mockup-prod", "rapiHostname": "client-rapi.recombee.com:443" }); recombeeIntegration({ "type": "InitializeRecommendationWidget", "rootElementId": "widget-root-dab4bb53-0584-4b49-984f-1f5b2f4354a2", "widgetId": "dab4bb53-0584-4b49-984f-1f5b2f4354a2", "appendToElementSelector": "div.content-inner", }); } ``` --- # Swift API Client > Source: https://docs.recombee.com/swift_client > For the complete documentation index, see [llms.txt](/llms.txt). # Swift API Client **Table of contents** * [Install](#install) * [Configure](#configure) * [Send Interactions](#send-interactions) * [Get Recommendations](#get-recommendations) * [Personalized Search](#personalized-search) * [Recommend Next Items](#recommend-next-items) * [Optional Parameters](#optional-parameters) * [Batch Requests](#batch-requests) * [Error Handling](#error-handling) * [Example](#example) This library allows you to request recommendations and send interactions between users and items (such as views, bookmarks, or purchases) to Recombee. It is a thin wrapper around the [Recombee API](/api) and provides a simple way to interact with it. Client-side SDK This SDK is designed for use in iOS or macOS applications. For security reasons, it is not possible to change the item catalog, such as the properties of items, using this SDK. To send your Catalog to Recombee, use one of the following methods: * Use one of our server-side SDKs, for example using a script which runs periodically (see [Managing Item Catalog](/getting_started#getting-started-catalog) for more details), * Or set up a [Catalog Feed](/catalog_feeds) in the [Admin UI](https://admin.recombee.com/). [GitHubSee the implementation, contribute, or report issues](https://github.com/Recombee/swift-api-client)[API ReferenceList of all available endpoints with examples](/api) ## Install Add the dependency to your Xcode project using **Swift Package Manager**: 1. In Xcode, go to `File → Add Packages`. 2. Enter the repository URL: `https://github.com/recombee/swift-api-client`. 3. Choose the latest version and confirm. Alternatively, in `Package.swift`: ``` .package(url: "https://github.com/recombee/swift-api-client", from: "6.2.0") ``` Then add the following to your target dependencies: ``` .target( name: "MyApp", dependencies: ["RecombeeClient"] ) ``` ## Configure In order to use the API, you will need to create an instance of the `RecombeeClient` class. You will need: * the **ID of your database**, * the **public token**. You can find these in the Admin UI, in [your Database's Settings page](https://admin.recombee.com/go-to-database/settings), under **API ID & Tokens**. Along with this information, you can also find a complete code snippet for initializing the client. Ideally, you should only create **one instance** of `RecombeeClient` in your application. It is a lightweight object and can be reused for multiple requests. Tip We published a simple [iOS example app](https://github.com/recombee/ios-demo) to help you with the integration. Feel free to use it as a reference. ![](/img/api_clients/ios_demo.png) You can initialize the client as follows: ``` import RecombeeClient // Initialize the API client with the ID of your database and the associated public token let client = RecombeeClient( databaseId: "database-id", publicToken: "...db-public-token...", region: .euWest // the region of your database ) ``` You can also configure optional parameters when initializing the client: ``` let client = RecombeeClient( databaseId: "database-id", publicToken: "...db-public-token...", region: .euWest // the region of your database // Optional parameters: // Use this if you were assigned a custom URI by the Recombee Support team (default: nil) baseUri: "custom-uri.recombee.com", // The port to connect to (default: nil) port: 443, // Whether to use HTTPS - can be disabled for debugging (default: true) useHttpsByDefault: true ) ``` ## Send Interactions After you have initialized the client, you can send interactions between users and items. The individual interactions are types conforming to the `Request` protocol in the Recombee Swift SDK. You create an instance of the interaction and send it using the `send` method of the `RecombeeClient` class. Alternatively, when you don't need to process the response, you can use the `sendDetached` method instead, which sends a request to the Recombee API in a detached task with default priority. ``` // Either create the interaction first and then send it let bookmark = AddBookmark(userId: "user-13434", itemId: "item-256") try await client.send(bookmark) // Or send it directly try await client.send( AddCartAddition( userId: "user-4395", itemId: "item-129", recommId: "23eaa09b-0e24-4487-ba9c-8e255feb01bb" ) ) try await client.send(AddDetailView(userId: "user-9318", itemId: "item-108")) try await client.send(AddPurchase(userId: "user-7499", itemId: "item-750")) client.sendDetached(AddRating(userId: "user-3967", itemId: "item-365", rating: 0.5)) client.sendDetached(SetViewPortion(userId: "user-4289", itemId: "item-487", portion: 0.3)) ``` Each interaction has both mandatory and optional parameters. The most important optional parameter is `recommId` — if the interaction is based on a previous recommendation, it is the ID of the recommendation request that returned the item. Providing this ID allows you to track successful recommendations. For more information, read about [Reported Metrics](/admin_ui#reported-metrics). For a full list of interactions and their parameters, refer to the [API Reference](/api). You can also send multiple interactions at once using the `Batch` request: ``` let batch = Batch(requests: [ AddBookmark(userId: "user-13434", itemId: "item-256"), AddCartAddition(userId: "user-4395", itemId: "item-129", cascadeCreate: true), AddDetailView(userId: "user-9318", itemId: "item-108") ]) let responses = try await client.send(batch) ``` To handle errors gracefully, use `do-catch` blocks: ``` do { try await client.send( AddRating( userId: "user-3967", itemId: "item-365", rating: 0.5, cascadeCreate: true ) ) print("Interaction sent successfully") } catch let error as ClientError { print("ClientError: \(error.localizedDescription)") } catch { print("Unexpected error: \(error.localizedDescription)") } ``` ## Get Recommendations With an initialized client, you can also request recommendations. There are multiple types of recommendations, such as: * [Recommend Items to User](/api#recommend-items-to-user), * [Recommend Items to Item](/api#recommend-items-to-item), * [Recommend Item Segments to User](/api#recommend-item-segments-to-user) (these can be categories, genres, artists, etc.), * or [others](/api#recommendations). Each recommendation request is a struct within the `RecombeeClient` module and is sent using the `send` method. ``` let client = RecombeeClient( databaseId: "your-database-id", publicToken: "your-public-token", region: .usWest ) do { let request = RecommendItemsToUser( userId: "user-x", count: 10, scenario: "homepage-for-you" ) let response = try await client.send(request) print("recommId: \(response.recommId)") for item in response.recomms { print("ID: \(item.id)") } } catch { print("Error: \(error)") // Provide fallback... } ``` For a full list of request parameters and possible responses, visit the [API Reference](/api#recommendations). ### Personalized Search [Personalized full-text search](/api#search-items) is requested in the same way as recommendations: ``` let request = SearchItems( userId: "user-x", searchQuery: "headphones", count: 10, scenario: "search", returnProperties: true ) do { let response = try await client.send(request) print("recommId: \(response.recommId)") for item in response.recomms { print("ID: \(item.id), Values: \(item.values ?? [:])") } } catch { print("Search error: \(error)") } ``` ### Recommend Next Items If you are implementing features like infinite scroll or pagination, you can use the `RecommendNextItems` request to load recommendations progressively. This means you can fetch the next set of recommended items without repeating the ones you have already displayed. To use this functionality, you must provide the `recommId` from the initial recommendation request. For more details, see the [Recommend Next Items](/api#recommend-next-items) documentation. ``` // Fetch initial recommendations let initial = try await client.send( RecommendItemsToUser(userId: "user-1", count: 5) ) let recommId = initial.recommId // Later (e.g. when scrolling) let next = try await client.send( RecommendNextItems(recommId: recommId, count: 5) ) for item in next.recomms { print("Next: \(item.id)") } ``` ### Optional Parameters Recommendation requests support various optional parameters to customize their behavior. For a comprehensive list, refer to the [API Reference](/api#recommendations). Below is an example showcasing some commonly used parameters: ``` let request = RecommendItemsToUser( userId: "user-13434", count: 5, // Scenarios help identify the context where recommendations are displayed // and can be customized in the Admin UI at https://admin.recombee.com scenario: "homepage", // Include detailed properties of the recommended items in the response returnProperties: true, // Specify which properties to include (requires returnProperties = true) includedProperties: ["title", "img_url", "url", "price"], // Apply a ReQL filter to refine recommendations, // e.g., "Recommend only items with a title that are in stock." filter: "'category' == \"chairs\" and 'price' < 200" // Note: You can define scenario-specific filters in the Admin UI. // The filter defined here is combined with the Admin UI filter using logical AND. ) ``` ### Batch Requests You may encounter a situation where you display recommendations in multiple places in your app. In such cases, you can use the `Batch` request to send multiple recommendation requests at once. This can help reduce the number of HTTP requests and improve performance. For example, you can request the most popular items, as well as items related to a specific user or item, in a single `Batch`: ``` /// A basic representation of a recommended item. struct Item { let id: String let title: String let images: [String] let recommId: String } let batch = Batch( requests: [ RecommendItemsToItem( itemId: "item-356", targetUserId: "user-13434", count: 3, scenario: "because-you-watched", returnProperties: true, includedProperties: ["title", "images"] ), RecommendItemsToUser( userId: "user-13434", count: 3, scenario: "new-releases", returnProperties: true, includedProperties: ["title", "images"] ), RecommendItemsToUser( userId: "user-13434", count: 3, scenario: "popular", returnProperties: true, includedProperties: ["title", "images"] ) ], distinctRecomms: true ) do { let responses = try await client.send(batch) let sections: [[Item]] = responses.map { wrapper in if let response = try? wrapper.response?.decode(as: RecommendationResponse.self) { return response.recomms.map { item in Item( id: item.id, title: item.values?["title"] as? String ?? "", images: item.values?["images"] as? [String] ?? [], recommId: response.recommId ) } } else { return [] } } print("Because You Watched: \(sections[0])") print("New Releases: \(sections[1])") print("Popular: \(sections[2])") } catch { print("Batch request failed: \(error)") } ``` The optional parameter `distinctRecomms` of the `Batch` ensures that the recommended items are not repeated across the responses. You can find more information about Batch requests in the [API Reference](/api#batch). ## Error Handling The API client throws errors of type `ClientError` when an operation fails. Each case of this enum represents a different failure scenario that may occur while communicating with the Recombee API. These errors are part of the `RecombeeClient` SDK and can be used in Swift's `do-catch` error handling blocks. | Error | Cause | | ------------------------- | ------------------------------------------------------------------------------------ | | ClientError.timeout | The request exceeded the configured timeout interval. | | ClientError.responseError | The API returned a non-success HTTP status code (e.g. 400, 500). | | ClientError.networkError | A network-related issue occurred, such as a connection failure. | | ClientError.decodingError | The response could not be decoded, possibly due to mismatched types or invalid data. | | ClientError.unknownError | An unspecified or unrecognized error occurred. | ### Example ``` do { let response = try await client.send(RecommendItemsToUser(userId: "user-1", count: 5)) print("Recommended items: \(response.recomms.map(\.id))") } catch let error as ClientError { print("ClientError: \(error.errorDescription ?? "Unknown error")") } catch { print("Unexpected error: \(error.localizedDescription)") } ``` We are doing our best to provide a reliable service, but sometimes things can go wrong. For this reason, we recommend that you always handle exceptions and provide fallbacks in your application. For example, when requesting recommendations, a fallback could be to display a generic set of items or an error message to the user. --- # Date and Time Specifiers > Source: https://docs.recombee.com/time_specifiers > For the complete documentation index, see [llms.txt](/llms.txt). # Date and Time Specifiers | Specifier | Replaced by | Example | | --------- | ---------------------------------------------------------------------- | ----------- | | %a | Abbreviated weekday name \* | Thu | | %A | Full weekday name \* | Thursday | | %b | Abbreviated month name \* | Aug | | %B | Full month name \* | August | | %c | Date and time representation \* | Thu Aug 23 | | %C | Year divided by 100 and truncated to integer (00-99) | 20 | | %d | Day of the month, zero-padded (01-31) | 23 | | %D | Short MM/DD/YY date, equivalent to %m/%d/%y | 08/23/01 | | %e | Day of the month, space-padded ( 1-31) | 23 | | %F | Short YYYY-MM-DD date, equivalent to %Y-%m-%d | 2001-08-23 | | %g | Week-based year, last two digits (00-99) | 1 | | %G | Week-based year | 2001 | | %h | Abbreviated month name \* (same as %b) | Aug | | %H | Hour in 24h format (00-23) | 14 | | %I | Hour in 12h format (01-12) | 2 | | %j | Day of the year (001-366) | 235 | | %m | Month as a decimal number (01-12) | 8 | | %M | Minute (00-59) | 55 | | %n | New-line character (‘n’) | | | %p | AM or PM designation | PM | | %r | 12-hour clock time \* | 02:55:02 pm | | %R | 24-hour HH:MM time, equivalent to %H:%M | 14:55 | | %S | Second (00-61) | 2 | | %t | Horizontal-tab character (‘t’) | | | %T | ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S | 14:55:02 | | %u | ISO 8601 weekday as number with Monday as 1 (1-7) | 4 | | %U | Week number with the first Sunday as the first day of week one (00-53) | 33 | | %V | ISO 8601 week number (00-53) | 34 | | %w | Weekday as a decimal number with Sunday as 0 (0-6) | 4 | | %W | Week number with the first Monday as the first day of week one (00-53) | 34 | | %x | Date representation \* | 08/23/01 | | %X | Time representation \* | 14:55:02 | | %y | Year, last two digits (00-99) | 1 | | %Y | Year | 2001 | | %z | ISO 8601 offset from UTC in timezone (1 minute=1, 1 hour=100) | 100 | | %Z | Timezone name or abbreviation | CDT | | %% | A % sign | % | Adopted from . --- # Carousel Widget (JS) > Source: https://docs.recombee.com/widget-sdks/carousel-widget-js > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [ Installation ](#install) * [ Client Initialization ](#client-initialization) * [ Providing User ID ](#providing-user-id) * [ Basic Example ](#basic-example) * [ Custom CSS ](#custom-css) * [ Custom Templates ](#custom-templates) * [ Overriding Base Classes ](#overriding-base-classes) * [ Composite Recommendations ](#composite-recommendations) * [API Reference](#api) * [CarouselWidget](#api/CarouselWidget) * [CarouselWidgetOptions](#api/CarouselWidgetOptions) * [DefaultItem](#api/DefaultItem) * [DefaultItemProps](#api/DefaultItemProps) * [ItemImage](#api/ItemImage) * [ItemImageProps](#api/ItemImageProps) * [addRecommIdQueryParam](#api/addRecommIdQueryParam) * [Recommendation](#api/Recommendation) * [CreateRequestFunction](#api/CreateRequestFunction) * [FetchContentOptions](#api/FetchContentOptions) * [CarouselWidgetProps](#api/CarouselWidgetProps) * [CarouselWidgetState](#api/CarouselWidgetState) * [DefaultCarousel](#api/DefaultCarousel) * [DefaultCarouselProps](#api/DefaultCarouselProps) * [DefaultCarouselArrow](#api/DefaultCarouselArrow) * [CarouselArrowProps](#api/CarouselArrowProps) # Carousel Widget (JS) > A Vanilla JS widget that displays a horizontal scroll of recommended items, designed to increase engagement through visually appealing item rotation. Use this library when you want to display a widget without using a transpiler like Babel and without using JSX. This library exports a `htm` HTML factory to assemble custom elements of the widget. This widget library is version 0.2.19 and the API can change. Please specify exact version when installing. ## Installation Install `@recombee/carousel-widget-js@0.2.19` and `recombee-js-api-client`packages using your preferred NPM package manager. This example is using`pnpm`. ``` pnpm add @recombee/carousel-widget-js@0.2.19 recombee-js-api-client ``` Always remember to apply the default CSS file distributed alongside the widget library, as shown in the examples. ## Client Initialization The widget loads recommendation data using [Recombee API Client](/js_client). Here is how to initialize the client with necessary configuration for a specific database: ``` import { } from "recombee-js-api-client"; const = "[database-id]"; const = "[database-public-token]"; const = "[database-region]"; export const = new (, , { : , }); ``` The Database Public Token can be found in the Admin UI[Database Settings Page](https://admin.recombee.com/go-to-database/settings). The widget also needs to be provided a `createRequest` function, which instantiates a client request class to define which data to pull from the database. Use Scenario ID which can be found on Admin GUI[Database Scenarios Page](https://admin.recombee.com/go-to-database/scenarios). Please ensure that you provide the user ID (typically obtained from your existing user tracking system), along with other relevant parameters - such as an item ID or [Item Segment](/segmentations) ID - depending on the specific type of recommendation request. See the[Providing User ID](#providing-user-id) section for details on how to obtain user ID in specific cases. ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; const : = ({ }) => { const = "recommend-items-to-user"; return new (userId, , { : , : true, : true, }); }; ``` ### Providing User ID Each visitor of your website should be identified by a user identificator (`userId`) to correlate user activity and deliver best possible recommendation performance. The `userId` should preferrably originate from your user's account details when the user is authenticated or as some session-persistent random ID when they are anonymous. The SDK provides utility which generates random user id and saves it to a cookie to cover the latter case: ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; import { } from "@recombee/carousel-widget-react"; let : string | undefined; if (authenticatedUserId) { = authenticatedUserId; } else { = .(); } const : = ({ }) => { const = "recommend-items-to-user"; return new (, , { : , : true, : true, }); }; ``` ## Basic Example The widget in this example uses the [DefaultItem](#api/DefaultItem) component to render each recommendation in a consistent layout. The resulting widget is inserted into the element specified by the`container` field. Values of the recommended items - such as title, image URL, or link URL - are obtained from the API response and accessed via `props.result?.values`. Ensure that [returnProperties: true](/api#recommend-items-to-user-param-returnProperties) is set in the request, and optionally use[includedProperties](/api#recommend-items-to-user-param-includedProperties)to control which item properties are returned. ``` import { , , , , , } from "@recombee/carousel-widget-js"; import "@recombee/carousel-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "gap-4 p-6", : "min-w-[240px] min-h-[260px]", : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, }); ``` The [addRecommIdQueryParam](#api/addRecommIdQueryParam) utility function is used to append the recommendation ID to the item's URL as the `recombee_recomm_id` query parameter. This enables you to [report successful (clicked) recommendations back to Recombee](/admin_ui#reported-metrics) for improved tracking and performance optimization. ## Custom CSS Recombee Widgets are designed to be styling-agnostic. You can fully customize their appearance using your own CSS by passing class names through customization properties. In these docs examples, we use utility classes from [Tailwind CSS](https://tailwindcss.com/) for styling. Class names for internal elements and custom components are passed as props and applied by the widget during rendering. The default structure of the_Basic Example_ widget is illustrated below (pseudo-code): ```
... more items ...
``` This is handy to understand how to customize the widget to full potential. ### Setting own classes ``` import { , , , , , } from "@recombee/carousel-widget-js"; import "@recombee/carousel-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "overflow-hidden rounded-lg border-[#ededed] bg-white text-[#282b30] dark:border-none dark:bg-transparent dark:text-white", : "gap-4 p-6", : "min-w-[240px] min-h-[260px]", : () => `<${} classNameDisableBase className="border-b border-slate-600" contentWrapperClassName="text-center" href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, }); ``` ## Custom Templates Recombee Widgets support full customization of internal components such as the appearance of the recommended items. You can provide your own components via props like [ItemComponent](#api/ItemComponent) to control the structure, styling, and behavior of the widget. This flexibility allows you to adapt the widget's appearance and functionality to match your design and user experience requirements. ### Custom Item ``` import { , , } from "@recombee/carousel-widget-js"; import "@recombee/carousel-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "gap-4 p-6", : "min-h-[290px] w-[200px]", : () => `
<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />${.?.?.["genres"]?.includes("drama") && `
Drama
`}${.?.?.["genres"]?.includes( "science_fiction", ) && `
Sci-Fi
`}
${`${.?.?.genres?.join(", ")}`}
${`${.?.?.title}`}
${`${.?.?.year}`}
`, }); ``` ### Custom Arrows ``` import { , , , , , } from "@recombee/carousel-widget-js"; import "@recombee/carousel-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "gap-4 p-6", : "min-h-[400px] w-[400px]", : () => { if (. === "left" && ...) { return ``; } if (. === "right" && ...) { return ``; } }, : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, }); ``` ### Full Customization ``` import { , , , , , } from "@recombee/carousel-widget-js"; import "@recombee/carousel-widget-js/dist/styles.css"; function (: any) { const = `w-full rounded-lg border border-[#ededed] py-2 px-3 text-center text-[14px]/[1.43] font-medium text-[#80868f]`; return ` `, }); ``` ## Overriding Base Classes Some base styles are always applied to ensure the widget maintains the structural shape of a carousel. However, these can be disabled or overridden if needed. Use the[CarouselWidgetProps.classNameDisableDefault](#api/CarouselWidgetProps.classNameDisableDefault) and related options to opt out of default styling. ``` import { , , , , , } from "@recombee/carousel-widget-js"; import "@recombee/carousel-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : true, : "rb:no-scrollbar flex min-h-[420px] snap-x snap-mandatory content-stretch gap-1 overflow-x-auto p-6", : true, : "min-h-[260px] flex min-w-full flex-grow basis-full snap-center", : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, }); ``` ## Composite Recommendations ``` const : = ({ }) => { return new ("top-from-genre-for-you", , { : { : true, }, }); }; import { , , , , , } from "@recombee/carousel-widget-js"; import "@recombee/carousel-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "gap-4 p-6", : "min-w-[240px] min-h-[260px]", : ({ }) => { return ? `

Because you like ${?.}

` : null; }, : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, }); ``` ## API Reference const ### CarouselWidget Carousel Widget initialization function type ### CarouselWidgetOptions Carousel Widget configuration options. #### Properties ##### container string CSS Selector to target the element where the widget should be inserted. --- ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : ({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }, }); ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### initialItemsCount number | undefined Number of items to load immediately. Adjust to have more items loaded ahead of user scrolling. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### SourceItemComponent ((props: { state: CarouselWidgetState; source?: Recommendation | null | undefined; }) => ReactNode) | undefined A component rendering a source recommended item when using Composite Scenario. --- ##### ItemComponent (props: { state: CarouselWidgetState; result?: Recommendation | undefined; }) => ReactNode A component rendering a single recommended item. --- ##### ArrowComponent ((props: CarouselArrowProps) => ReactNode) | undefined A component rendering either left or right carousel arrow --- ##### CarouselComponent ((props: DefaultCarouselProps) => ReactNode) | undefined Component responsible for rendering the widget markup. Example in which the passed component wraps the default carousel component with additional custom HTML. ``` import React from "react"; import { , , , } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : () => { return `

Recommended

<${} ...${} />
`; }, }); ``` This property also allows to fully cutomize the carousel HTML in extreme cases. ``` import React from "react"; import { , } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : () => { return `
// Use carouselProps.state.items array to loop over items
`; }, }); ``` --- const ### DefaultItem Default Item component provided for basic usage. interface ### DefaultItemProps Recommended item component properties. #### Properties ##### className string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableBase boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### imageWrapperClassName string | undefined Custom classes of item image wrapper element. See[Custom CSS](#custom-css). --- ##### imageWrapperClassNameDisableBase boolean | undefined Disables default classes of item image wrapper element. There are some default class names with essential styles applied to the item image wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentWrapperClassName string | undefined Custom classes of item content element. See[Custom CSS](#custom-css). --- ##### result Recommendation | undefined A single item recommedation. --- ##### href string | null | undefined Item link URL. --- ##### image ReactNode Item Image element. --- ##### labelContent ReactNode Item content above title. Sets the entire content of an item aside from an image. --- ##### labelContentWrapperClassName string | undefined Custom classes of label content wrapper element. See[Custom CSS](#custom-css). --- ##### labelContentWrapperClassNameDisableBase boolean | undefined Disables default classes of label content wrapper element. There are some default class names with essential styles applied to the label content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### title ReactNode Item title. --- ##### titleWrapperClassName string | undefined Custom classes of title wrapper element. See[Custom CSS](#custom-css). --- ##### titleWrapperClassNameDisableBase boolean | undefined Disables default classes of title wrapper element. There are some default class names with essential styles applied to the title wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### highlightedContent ReactNode Item content under title. Sets the entire content of an item aside from an image. --- ##### highlightedContentWrapperClassName string | undefined Custom classes of highlighted content wrapper element. See[Custom CSS](#custom-css). --- ##### highlightedContentWrapperClassNameDisableBase boolean | undefined Disables default classes of highlighted content wrapper element. There are some default class names with essential styles applied to the highlighted content wrapper element. This setting disables them as an escape hatch for customization. See[Custom CSS](#custom-css). --- ##### bottomContent ReactNode Any custom content to display at the bottom of the item. --- const ### ItemImage Item image component type ### ItemImageProps Item Image properties #### Properties ##### src string | null | undefined Image URL --- ##### missingImageSrc string | undefined URL of an image to display when the main image could not be loaded. --- ##### className string | undefined Image wrapper class name --- ##### imgClassName string | undefined Image class name --- ##### width number | undefined Image width in pixels --- ##### height number | undefined Image height in pixels --- ##### verticalAlignment "top" | "center" | "bottom" | undefined Image vertical alignment --- ##### horizontalAlignment "center" | "left" | "right" | undefined Image horizontal alignment --- ##### fittingAlgorithm "cover" | "scale\_down" | undefined Image fitting algorithm --- function ### addRecommIdQueryParam Utility function to append `recombee_recomm_id` parameter to an url string. For usage in widget template to construct item link URL. type ### Recommendation Single recommendation item #### Properties ##### id string Item ID --- ##### values { \[key: string\]: any; } | undefined Item properties --- type ### CreateRequestFunction Factory for creating Recombee API Request to load data into a Widget. type ### FetchContentOptions CreateRequestFunction parameter #### Properties ##### count number Number of items to fetch for the widget. Pass it to the appropriate Request constructor. --- type ### CarouselWidgetProps Carousel Widget React Component configuration properties #### Properties ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : ({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }, }); ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### initialItemsCount number | undefined Number of items to load immediately. Adjust to have more items loaded ahead of user scrolling. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### SourceItemComponent ((props: { state: CarouselWidgetState; source?: Recommendation | null | undefined; }) => ReactNode) | undefined A component rendering a source recommended item when using Composite Scenario. --- ##### ItemComponent (props: { state: CarouselWidgetState; result?: Recommendation | undefined; }) => ReactNode A component rendering a single recommended item. --- ##### ArrowComponent ((props: CarouselArrowProps) => ReactNode) | undefined A component rendering either left or right carousel arrow --- ##### CarouselComponent ((props: DefaultCarouselProps) => ReactNode) | undefined Component responsible for rendering the widget markup. Example in which the passed component wraps the default carousel component with additional custom HTML. ``` import React from "react"; import { , , , } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : () => { return `

Recommended

<${} ...${} />
`; }, }); ``` This property also allows to fully cutomize the carousel HTML in extreme cases. ``` import React from "react"; import { , } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : () => { return `
// Use carouselProps.state.items array to loop over items
`; }, }); ``` --- class ### CarouselWidgetState Exposes internal state data of the widget to be used in customizable components #### Properties ##### wrapperRef ObservableRef React ref necessary to control the carousel wrapper element. See[Customization Example](#api/CarouselWidgetProps.CarouselComponent). --- ##### contentRef ObservableRef React ref necessary to control the carousel content element. See[Customization Example](#api/CarouselWidgetProps.CarouselComponent). --- ##### items { key: string; entity: Recommendation; }\[\] Array of items to show in the carousel. --- ##### sourceItem Recommendation | null | undefined Array of items to show in the carousel. --- ##### recommId string | undefined Id of recommendation response from which the items originated. --- ##### leftArrow ArrowState Current state of left Carousel arrow --- ##### rightArrow ArrowState Current state of right Carousel arrow --- const ### DefaultCarousel Default visual component used to render carousel container interface ### DefaultCarouselProps Carousel Properties #### Properties ##### state CarouselWidgetState Carousel state. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### SourceItemComponent ((props: { state: CarouselWidgetState; source?: Recommendation | null | undefined; }) => ElementType) | undefined A component rendering a source recommended item when using Composite Scenario. --- ##### ItemComponent (props: { state: CarouselWidgetState; result?: Recommendation | undefined; }) => ElementType A component rendering a single recommended item. --- ##### ArrowComponent ((props: CarouselArrowProps) => ElementType) | undefined A component rendering either left or right carousel arrow --- const ### DefaultCarouselArrow Default Carousel arrow component type ### CarouselArrowProps Carousel Arrow configuration options #### Properties ##### arrowDirection "left" | "right" The direction of an arrow to render. --- ##### state CarouselWidgetState Carousel state. --- --- # Carousel Widget (React) > Source: https://docs.recombee.com/widget-sdks/carousel-widget-react > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [ Installation ](#install) * [ Client Initialization ](#client-initialization) * [ Providing User ID ](#providing-user-id) * [ Basic Example ](#basic-example) * [ Custom CSS ](#custom-css) * [ Custom Templates ](#custom-templates) * [ Custom Item ](#custom-item) * [ Custom Arrows ](#custom-arrows) * [ Full Customization ](#full-customization) * [ Overriding Base Classes ](#overriding-base-classes) * [ Composite Recommendations ](#composite-recommendations) * [API Reference](#api) * [CarouselWidget](#api/CarouselWidget) * [CarouselWidgetProps](#api/CarouselWidgetProps) * [CarouselWidgetState](#api/CarouselWidgetState) * [DefaultItem](#api/DefaultItem) * [DefaultItemProps](#api/DefaultItemProps) * [ItemImage](#api/ItemImage) * [ItemImageProps](#api/ItemImageProps) * [Recommendation](#api/Recommendation) * [addRecommIdQueryParam](#api/addRecommIdQueryParam) * [DefaultCarousel](#api/DefaultCarousel) * [DefaultCarouselProps](#api/DefaultCarouselProps) * [DefaultCarouselArrow](#api/DefaultCarouselArrow) * [CarouselArrowProps](#api/CarouselArrowProps) * [CreateRequestFunction](#api/CreateRequestFunction) * [FetchContentOptions](#api/FetchContentOptions) # Carousel Widget (React) > A React component widget that displays a horizontal scroll of recommended items, designed to increase engagement through visually appealing item rotation. Use this library when you want to render a widget and you are using React and JSX in your project. This widget library is version 0.2.17 and the API can change. Please specify exact version when installing. ## Installation Install `@recombee/carousel-widget-react@0.2.17` and `recombee-js-api-client`packages using your preferred NPM package manager. This example is using`pnpm`. ``` pnpm add @recombee/carousel-widget-react@0.2.17 recombee-js-api-client ``` Always remember to apply the default CSS file distributed alongside the widget library, as shown in the examples. ## Client Initialization The widget loads recommendation data using [Recombee API Client](/js_client). Here is how to initialize the client with necessary configuration for a specific database: ``` import { } from "recombee-js-api-client"; const = "[database-id]"; const = "[database-public-token]"; const = "[database-region]"; export const = new (, , { : , }); ``` The Database Public Token can be found in the Admin UI[Database Settings Page](https://admin.recombee.com/go-to-database/settings). The widget also needs to be provided a `createRequest` function, which instantiates a client request class to define which data to pull from the database. Use Scenario ID which can be found on Admin GUI[Database Scenarios Page](https://admin.recombee.com/go-to-database/scenarios). Please ensure that you provide the user ID (typically obtained from your existing user tracking system), along with other relevant parameters - such as an item ID or [Item Segment](/segmentations) ID - depending on the specific type of recommendation request. See the[Providing User ID](#providing-user-id) section for details on how to obtain user ID in specific cases. ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; const : = ({ }) => { const = "recommend-items-to-user"; return new (userId, , { : , : true, : true, }); }; ``` ### Providing User ID Each visitor of your website should be identified by a user identificator (`userId`) to correlate user activity and deliver best possible recommendation performance. The `userId` should preferrably originate from your user's account details when the user is authenticated or as some session-persistent random ID when they are anonymous. The SDK provides utility which generates random user id and saves it to a cookie to cover the latter case: ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; import { } from "@recombee/carousel-widget-react"; let : string | undefined; if (authenticatedUserId) { = authenticatedUserId; } else { = .(); } const : = ({ }) => { const = "recommend-items-to-user"; return new (, , { : , : true, : true, }); }; ``` ## Basic Example The widget in this example uses the [DefaultItem](#api/DefaultItem) component to render each recommendation in a consistent layout. The resulting widget is inserted into the element specified by the`container` field. Values of the recommended items - such as title, image URL, or link URL - are obtained from the API response and accessed via `props.result?.values`. Ensure that [returnProperties: true](/api#recommend-items-to-user-param-returnProperties) is set in the request, and optionally use[includedProperties](/api#recommend-items-to-user-param-includedProperties)to control which item properties are returned. ``` import { , , , , } from "@recombee/carousel-widget-react"; import "@recombee/carousel-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="gap-4 p-6" ="min-w-[240px] min-h-[260px]" ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} /> ); }; ``` The [addRecommIdQueryParam](#api/addRecommIdQueryParam) utility function is used to append the recommendation ID to the item's URL as the `recombee_recomm_id` query parameter. This enables you to [report successful (clicked) recommendations back to Recombee](/admin_ui#reported-metrics) for improved tracking and performance optimization. ## Custom CSS Recombee Widgets are designed to be styling-agnostic. You can fully customize their appearance using your own CSS by passing class names through customization properties. In these docs examples, we use utility classes from [Tailwind CSS](https://tailwindcss.com/) for styling. Class names for internal elements and custom components are passed as props and applied by the widget during rendering. The default structure of the_Basic Example_ widget is illustrated below (pseudo-code): ```
... more items ...
``` This is handy to understand how to customize the widget to full potential. ### Setting own classes ``` import { , , , , } from "@recombee/carousel-widget-react"; import "@recombee/carousel-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="overflow-hidden rounded-lg border-[#ededed] bg-white text-[#282b30] dark:border-none dark:bg-transparent dark:text-white" ="gap-4 p-6" ="min-w-[240px] min-h-[260px]" ={() => ( < ="border-b border-slate-600" ="text-center" ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} /> ); }; ``` ## Custom Templates Recombee Widgets support full customization of internal components such as the appearance of the recommended items. You can provide your own components via props like [ItemComponent](#api/ItemComponent) to control the structure, styling, and behavior of the widget. This flexibility allows you to adapt the widget's appearance and functionality to match your design and user experience requirements. ### Custom Item ``` import { , } from "@recombee/carousel-widget-react"; import "@recombee/carousel-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="gap-4 p-6" ="min-h-[290px] w-[200px]" ={() => ( < ="overflow-hidden rounded-lg border-[#ededed] bg-white text-[#282b30] dark:border-none dark:bg-transparent dark:text-white"> < ="relative overflow-hidden bg-cover bg-no-repeat"> < ={`${.?.?.images?.[0]}`} ={600} ={400} /> {.?.?.["genres"]?.includes("drama") && ( < ="absolute top-3 left-3 bg-[#3f91ff] px-2 text-xs/[1.67] font-semibold text-white"> Drama )} {.?.?.["genres"]?.includes("science_fiction") && ( < ="absolute top-3 left-3 bg-[#36c696] px-2 text-xs/[1.67] font-semibold text-white"> Sci-Fi )} < ="p-3"> < ="mb-1 line-clamp-4 overflow-hidden text-[14px]/[1.43] text-nowrap text-ellipsis text-[#80868f]"> {`${.?.?.genres?.join(", ")}`} < ="text-md mb-1 overflow-hidden text-nowrap text-ellipsis"> {`${.?.?.title}`} < ="line-clamp-4 pb-3 text-base text-[#3f91ff]"> {`${.?.?.year}`} < ="w-full rounded-lg border border-[#ededed] py-2 text-center text-[14px]/[1.43] font-medium text-[#80868f]"> Play )} /> ); }; ``` ### Custom Arrows ``` import { , , , , } from "@recombee/carousel-widget-react"; import "@recombee/carousel-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="gap-4 p-6" ="min-h-[400px] w-[400px]" ={() => { if ( . === "left" && ... ) { return ( < ="absolute top-1/2 left-4 -translate-y-6 rounded-lg rounded-sm border border-[#ededed] bg-white px-3 py-2 text-center text-[14px]/[1.43] font-medium text-[#80868f]" ="button" ={...} > prev ); } if ( . === "right" && ... ) { return ( < ="absolute top-1/2 right-4 -translate-y-6 rounded-lg rounded-sm border border-[#ededed] bg-white px-3 py-2 text-center text-[14px]/[1.43] font-medium text-[#80868f]" ="button" ={...} > next ); } }} ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} /> ); }; ``` ### Full Customization ``` import { , , , , } from "@recombee/carousel-widget-react"; import "@recombee/carousel-widget-react/dist/styles.css"; export default () => ( < ={} ={} ={() => null} ={() => ( < ="p-4"> < {...} ="gap-1" ="min-h-[240px] w-[200px]" /> < ="flex justify-end gap-2 pt-4"> < ="flex gap-2"> < ={!...} ={...} > PREV < ={!...} ={...} > NEXT )} ={() => ( < ="overflow-hidden rounded-lg border-[#ededed] bg-white text-[#282b30] dark:border-none dark:bg-transparent dark:text-white"> < ="relative overflow-hidden bg-cover bg-no-repeat"> < ={`${.?.?.images?.[0]}`} ={600} ={400} /> {.?.?.["genres"]?.includes("drama") && ( < ="absolute top-3 left-3 bg-[#3f91ff] px-2 text-xs/[1.67] font-semibold text-white"> Drama )} {.?.?.["genres"]?.includes("science_fiction") && ( < ="absolute top-3 left-3 bg-[#36c696] px-2 text-xs/[1.67] font-semibold text-white"> Sci-Fi )} < ="p-3"> < ="mb-1 line-clamp-4 overflow-hidden text-[14px]/[1.43] text-nowrap text-ellipsis text-[#80868f]"> {`${.?.?.genres?.join(", ")}`} < ="text-md mb-1 overflow-hidden text-nowrap text-ellipsis"> {`${.?.?.title}`} < ="line-clamp-4 pb-3 text-base text-[#3f91ff]"> {`${.?.?.year}`} < ="w-full rounded-lg border border-[#ededed] py-2 text-center text-[14px]/[1.43] font-medium text-[#80868f]"> Play )} /> ); function (: any) { const = `w-full rounded-lg border border-[#ededed] py-2 px-3 text-center text-[14px]/[1.43] font-medium text-[#80868f]`; return ( < ={(, { "opacity-50": .disabled, })} {...} /> ); } ``` ## Overriding Base Classes Some base styles are always applied to ensure the widget maintains the structural shape of a carousel. However, these can be disabled or overridden if needed. Use the[CarouselWidgetProps.classNameDisableDefault](#api/CarouselWidgetProps.classNameDisableDefault) and related options to opt out of default styling. ``` import { , , , , } from "@recombee/carousel-widget-react"; import "@recombee/carousel-widget-react/dist/styles.css"; export default () => { return ( < ="flex justify-center"> < ="w-[40%]"> < ={} ={} ="rb:no-scrollbar flex min-h-[420px] snap-x snap-mandatory content-stretch gap-1 overflow-x-auto p-6" ="min-h-[260px] flex min-w-full flex-grow basis-full snap-center" ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} /> ); }; ``` ## Composite Recommendations Widget SDKs can also be used to render [Composite Recommendations](/scenarios#composite-recommendations). A common use case is displaying [dynamic category- or genre-based rails](/scenarios#fully-personalized-homepage) on the homepage, as well as scenarios such as [Because You Watched](/scenarios#because-you-watched-movie-). The CompositeRecommendation request is called from within the[createRequest](/widget-sdks/carousel-widget-react#api/CarouselWidgetProps.createRequest)function. To render the header (for example, the user’s favorite category or the title of the watched movie), implement the[SourceItemComponent](/widget-sdks/carousel-widget-react#api/CarouselWidgetProps.SourceItemComponent). ``` const : = ({ }) => { return new ("top-from-genre-for-you", , { : { : true }, }); }; import { , , , , } from "@recombee/carousel-widget-react"; import "@recombee/carousel-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="gap-4 p-6" ="min-w-[240px] min-h-[260px]" ={({ }) => { return ? ( < ="px-6"> < ="mt-5 mb-0">Because you like {?.} ) : null; }} ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} /> ); }; ``` ## API Reference const ### CarouselWidget Carousel widget React Component. See [CarouselWidgetProps](#api/CarouselWidgetProps) for configuration options. type ### CarouselWidgetProps Carousel Widget React Component configuration properties #### Properties ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-react"; < // ...ommited code... ={({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }} />; ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### initialItemsCount number | undefined Number of items to load immediately. Adjust to have more items loaded ahead of user scrolling. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### SourceItemComponent ((props: { state: CarouselWidgetState; source?: Recommendation | null | undefined; }) => ReactNode) | undefined A component rendering a source recommended item when using Composite Scenario. --- ##### ItemComponent (props: { state: CarouselWidgetState; result?: Recommendation | undefined; }) => ReactNode A component rendering a single recommended item. --- ##### ArrowComponent ((props: CarouselArrowProps) => ReactNode) | undefined A component rendering either left or right carousel arrow --- ##### CarouselComponent ((props: DefaultCarouselProps) => ReactNode) | undefined Component responsible for rendering the widget markup. Example in which the passed component wraps the default carousel component with additional custom HTML. ``` import React from "react"; import { , , } from "@recombee/carousel-widget-react"; < // ...ommited code... ={() => { return ( <> <>Recommended < {...} /> ); }} />; ``` This property also allows to fully cutomize the carousel HTML in extreme cases. ``` import React from "react"; import { } from "@recombee/carousel-widget-react"; < // ...ommited code... ={() => { return ( < ={...}> <>Recommended < ={...}> // Use carouselProps.state.items array to loop over items ); }} />; ``` --- class ### CarouselWidgetState Exposes internal state data of the widget to be used in customizable components #### Properties ##### wrapperRef ObservableRef React ref necessary to control the carousel wrapper element. See[Customization Example](#api/CarouselWidgetProps.CarouselComponent). --- ##### contentRef ObservableRef React ref necessary to control the carousel content element. See[Customization Example](#api/CarouselWidgetProps.CarouselComponent). --- ##### items { key: string; entity: Recommendation; }\[\] Array of items to show in the carousel. --- ##### sourceItem Recommendation | null | undefined Array of items to show in the carousel. --- ##### recommId string | undefined Id of recommendation response from which the items originated. --- ##### leftArrow ArrowState Current state of left Carousel arrow --- ##### rightArrow ArrowState Current state of right Carousel arrow --- const ### DefaultItem Default Item component provided for basic usage. interface ### DefaultItemProps Recommended item component properties. #### Properties ##### className string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableBase boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### imageWrapperClassName string | undefined Custom classes of item image wrapper element. See[Custom CSS](#custom-css). --- ##### imageWrapperClassNameDisableBase boolean | undefined Disables default classes of item image wrapper element. There are some default class names with essential styles applied to the item image wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentWrapperClassName string | undefined Custom classes of item content element. See[Custom CSS](#custom-css). --- ##### result Recommendation | undefined A single item recommedation. --- ##### href string | null | undefined Item link URL. --- ##### image ReactNode Item Image element. --- ##### labelContent ReactNode Item content above title. Sets the entire content of an item aside from an image. --- ##### labelContentWrapperClassName string | undefined Custom classes of label content wrapper element. See[Custom CSS](#custom-css). --- ##### labelContentWrapperClassNameDisableBase boolean | undefined Disables default classes of label content wrapper element. There are some default class names with essential styles applied to the label content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### title ReactNode Item title. --- ##### titleWrapperClassName string | undefined Custom classes of title wrapper element. See[Custom CSS](#custom-css). --- ##### titleWrapperClassNameDisableBase boolean | undefined Disables default classes of title wrapper element. There are some default class names with essential styles applied to the title wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### highlightedContent ReactNode Item content under title. Sets the entire content of an item aside from an image. --- ##### highlightedContentWrapperClassName string | undefined Custom classes of highlighted content wrapper element. See[Custom CSS](#custom-css). --- ##### highlightedContentWrapperClassNameDisableBase boolean | undefined Disables default classes of highlighted content wrapper element. There are some default class names with essential styles applied to the highlighted content wrapper element. This setting disables them as an escape hatch for customization. See[Custom CSS](#custom-css). --- ##### bottomContent ReactNode Any custom content to display at the bottom of the item. --- const ### ItemImage Item image component type ### ItemImageProps Item Image properties #### Properties ##### src string | null | undefined Image URL --- ##### missingImageSrc string | undefined URL of an image to display when the main image could not be loaded. --- ##### className string | undefined Image wrapper class name --- ##### imgClassName string | undefined Image class name --- ##### width number | undefined Image width in pixels --- ##### height number | undefined Image height in pixels --- ##### verticalAlignment "top" | "center" | "bottom" | undefined Image vertical alignment --- ##### horizontalAlignment "center" | "left" | "right" | undefined Image horizontal alignment --- ##### fittingAlgorithm "cover" | "scale\_down" | undefined Image fitting algorithm --- type ### Recommendation Single recommendation item #### Properties ##### id string Item ID --- ##### values { \[key: string\]: any; } | undefined Item properties --- function ### addRecommIdQueryParam Utility function to append `recombee_recomm_id` parameter to an url string. For usage in widget template to construct item link URL. const ### DefaultCarousel Default visual component used to render carousel container interface ### DefaultCarouselProps Carousel Properties #### Properties ##### state CarouselWidgetState Carousel state. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### SourceItemComponent ((props: { state: CarouselWidgetState; source?: Recommendation | null | undefined; }) => ElementType) | undefined A component rendering a source recommended item when using Composite Scenario. --- ##### ItemComponent (props: { state: CarouselWidgetState; result?: Recommendation | undefined; }) => ElementType A component rendering a single recommended item. --- ##### ArrowComponent ((props: CarouselArrowProps) => ElementType) | undefined A component rendering either left or right carousel arrow --- const ### DefaultCarouselArrow Default Carousel arrow component type ### CarouselArrowProps Carousel Arrow configuration options #### Properties ##### arrowDirection "left" | "right" The direction of an arrow to render. --- ##### state CarouselWidgetState Carousel state. --- type ### CreateRequestFunction Factory for creating Recombee API Request to load data into a Widget. type ### FetchContentOptions CreateRequestFunction parameter #### Properties ##### count number Number of items to fetch for the widget. Pass it to the appropriate Request constructor. --- --- # Feed Widget (JS) > Source: https://docs.recombee.com/widget-sdks/feed-widget-js > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [ Installation ](#install) * [ Client Initialization ](#client-initialization) * [ Providing User ID ](#providing-user-id) * [ Basic Example ](#basic-example) * [ Custom CSS ](#custom-css) * [ Custom Templates ](#custom-templates) * [ Overriding Base Classes ](#overriding-base-classes) * [ Composite Recommendations ](#composite-recommendations) * [API Reference](#api) * [FeedWidget](#api/FeedWidget) * [FeedWidgetOptions](#api/FeedWidgetOptions) * [FeedWidgetProps](#api/FeedWidgetProps) * [FeedWidgetState](#api/FeedWidgetState) * [DefaultItem](#api/DefaultItem) * [DefaultItemProps](#api/DefaultItemProps) * [ItemImage](#api/ItemImage) * [ItemImageProps](#api/ItemImageProps) * [Recommendation](#api/Recommendation) * [addRecommIdQueryParam](#api/addRecommIdQueryParam) * [CreateRequestFunction](#api/CreateRequestFunction) * [FetchContentOptions](#api/FetchContentOptions) # Feed Widget (JS) > A Vanilla JS widget that creates a personalized, scrollable feed of item recommendations, designed for continuous content discovery. Use this library when you want to display a widget without using a transpiler like Babel and without using JSX. This library exports a `htm` HTML factory to assemble custom elements of the widget. This widget library is version 0.2.17 and the API can change. Please specify exact version when installing. ## Installation Install `@recombee/feed-widget-js@0.2.17` and `recombee-js-api-client`packages using your preferred NPM package manager. This example is using`pnpm`. ``` pnpm add @recombee/feed-widget-js@0.2.17 recombee-js-api-client ``` Always remember to apply the default CSS file distributed alongside the widget library, as shown in the examples. ## Client Initialization The widget loads recommendation data using [Recombee API Client](/js_client). Here is how to initialize the client with necessary configuration for a specific database: ``` import { } from "recombee-js-api-client"; const = "[database-id]"; const = "[database-public-token]"; const = "[database-region]"; export const = new (, , { : , }); ``` The Database Public Token can be found in the Admin UI[Database Settings Page](https://admin.recombee.com/go-to-database/settings). The widget also needs to be provided a `createRequest` function, which instantiates a client request class to define which data to pull from the database. Use Scenario ID which can be found on Admin GUI[Database Scenarios Page](https://admin.recombee.com/go-to-database/scenarios). Please ensure that you provide the user ID (typically obtained from your existing user tracking system), along with other relevant parameters - such as an item ID or [Item Segment](/segmentations) ID - depending on the specific type of recommendation request. See the[Providing User ID](#providing-user-id) section for details on how to obtain user ID in specific cases. ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; const : = ({ }) => { const = "recommend-items-to-user"; return new (userId, , { : , : true, : true, }); }; ``` ### Providing User ID Each visitor of your website should be identified by a user identificator (`userId`) to correlate user activity and deliver best possible recommendation performance. The `userId` should preferrably originate from your user's account details when the user is authenticated or as some session-persistent random ID when they are anonymous. The SDK provides utility which generates random user id and saves it to a cookie to cover the latter case: ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; import { } from "@recombee/carousel-widget-react"; let : string | undefined; if (authenticatedUserId) { = authenticatedUserId; } else { = .(); } const : = ({ }) => { const = "recommend-items-to-user"; return new (, , { : , : true, : true, }); }; ``` ## Basic Example The widget in this example uses the [DefaultItem](#api/DefaultItem) component to render each recommendation in a consistent layout. The resulting widget is inserted into the element specified by the`container` field. Values of the recommended items - such as title, image URL, or link URL - are obtained from the API response and accessed via `props.result?.values`. Ensure that [returnProperties: true](/api#recommend-items-to-user-param-returnProperties) is set in the request, and optionally use[includedProperties](/api#recommend-items-to-user-param-includedProperties)to control which item properties are returned. ``` import { , , , , , } from "@recombee/feed-widget-js"; import "@recombee/feed-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "click", : 1, : 2, : "min-h-[260px]", : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, : () => `
`, }); ``` ## Custom CSS Recombee Widgets are designed to be styling-agnostic. You can fully customize their appearance using your own CSS by passing class names through customization properties. In these docs examples, we use utility classes from [Tailwind CSS](https://tailwindcss.com/) for styling. Class names for internal elements and custom components are passed as props and applied by the widget during rendering. The default structure of the_Basic Example_ widget is illustrated below (pseudo-code): ```
... more items ...
``` This is especially handy for understanding how to customize the widget to its full potential. ### Setting own classes ``` import { , , , , , } from "@recombee/feed-widget-js"; import "@recombee/feed-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "click", : "grid-cols-[repeat(auto-fill,minmax(200px,1fr))] p-3 gap-2 overflow-hidden text-[#282b30] rounded-lg bg-white border border-[#ededed] dark:border-none dark:bg-transparent dark:text-white", : "min-h-[260px]", : () => `<${} className="border-b border-slate-600" contentWrapperClassName="text-center" href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, : () => `
`, }); ``` ## Custom Templates Recombee Widgets support full customization of internal components such as the appearance of the recommended items. You can provide your own components via props like [ItemComponent](#api/ItemComponent) to control the structure, styling, and behavior of the widget. This flexibility allows you to adapt the widget's appearance and functionality to match your design and user experience requirements. ### Custom Item ``` import { , , } from "@recombee/feed-widget-js"; import "@recombee/feed-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "click", : "min-h-[310px]", : () => `
<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />${.?.?.["genres"]?.includes("drama") && `
Drama
`}${.?.?.["genres"]?.includes( "science_fiction", ) && `
Sci-Fi
`}
${`${.?.?.genres?.join(", ")}`}
${`${.?.?.title}`}
${`${.?.?.year}`}
`, : () => `
`, }); ``` ## Overriding Base Classes Some base styles are always applied to ensure the widget maintains the structural shape of a feed. However, these can be disabled or overridden if needed. Use the[FeedWidgetProps.classNameDisableDefault](#api/FeedWidgetProps.classNameDisableDefault) and related options to opt out of default styling. ``` import { , , , , , } from "@recombee/feed-widget-js"; import "@recombee/feed-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "click", : 2, : "min-h-[260px]", : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, : () => `
`, }); ``` ## Composite Recommendations ``` const : = ({ }) => { return new ("top-from-genre-for-you", , { : { : true, }, }); }; import { , , , , , } from "@recombee/feed-widget-js"; import "@recombee/feed-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "click", : 1, : 2, : "min-h-[260px]", : ({ }) => { return ? `

Because you like ${?.}

` : null; }, : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, : () => `
`, }); ``` ## API Reference const ### FeedWidget Feed widget initialization function. See [FeedWidgetOptions](#api/FeedWidgetOptions) type ### FeedWidgetOptions Configuration options of Feed widget #### Properties ##### container string CSS Selector to target the element where the widget should be inserted. --- ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : ({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }, }); ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### initialRowsCount number | undefined Number of rows to load initially. --- ##### loadMoreRowsCount number | undefined Number of rows to load on "load more" trigger invocation. --- ##### loadMoreTrigger "scroll" | "click" --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | "layout" | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### ItemComponent FC<{ state: FeedWidgetState; result: Recommendation; }> A component rendering a single recommended item. --- ##### LoadMoreTriggerComponent FC<{ state: FeedWidgetState; }> | (FC<{ state: FeedWidgetState; }> & FC<{ state: FeedWidgetState; }>) | undefined --- ##### SourceItemComponent FC<{ state: FeedWidgetState; source?: Recommendation | null | undefined; }> | undefined A component rendering a source recommended item when using Composite Scenario. --- type ### FeedWidgetProps Configuration options for the Feed widget. #### Properties ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : ({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }, }); ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### initialRowsCount number | undefined Number of rows to load initially. --- ##### loadMoreRowsCount number | undefined Number of rows to load on "load more" trigger invocation. --- ##### loadMoreTrigger "scroll" | "click" --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | "layout" | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### ItemComponent FC<{ state: FeedWidgetState; result: Recommendation; }> A component rendering a single recommended item. --- ##### LoadMoreTriggerComponent FC<{ state: FeedWidgetState; }> | (FC<{ state: FeedWidgetState; }> & FC<{ state: FeedWidgetState; }>) | undefined --- ##### SourceItemComponent FC<{ state: FeedWidgetState; source?: Recommendation | null | undefined; }> | undefined A component rendering a source recommended item when using Composite Scenario. --- class ### FeedWidgetState A Class exposing Feed internal state to be used for customization. #### Properties ##### sourceItem Recommendation | null | undefined Array of items to show in the carousel. --- ##### items ({ type: "ENTITY"; key: string; entity: Recommendation; } | { type: "PLACEHOLDER"; key: string; })\[\] Array of items to show in the feed --- ##### recommId string | undefined Id of recommendation response from which the items originated. --- ##### handleTriggerClick () => void Handles clicking on a trigger to load more feed items by a configured increment --- const ### DefaultItem Default Item component provided for basic usage. interface ### DefaultItemProps Recommended item component properties. #### Properties ##### className string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableBase boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### imageWrapperClassName string | undefined Custom classes of item image wrapper element. See[Custom CSS](#custom-css). --- ##### imageWrapperClassNameDisableBase boolean | undefined Disables default classes of item image wrapper element. There are some default class names with essential styles applied to the item image wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentWrapperClassName string | undefined Custom classes of item content element. See[Custom CSS](#custom-css). --- ##### result Recommendation | undefined A single item recommedation. --- ##### href string | null | undefined Item link URL. --- ##### image ReactNode Item Image element. --- ##### labelContent ReactNode Item content above title. Sets the entire content of an item aside from an image. --- ##### labelContentWrapperClassName string | undefined Custom classes of label content wrapper element. See[Custom CSS](#custom-css). --- ##### labelContentWrapperClassNameDisableBase boolean | undefined Disables default classes of label content wrapper element. There are some default class names with essential styles applied to the label content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### title ReactNode Item title. --- ##### titleWrapperClassName string | undefined Custom classes of title wrapper element. See[Custom CSS](#custom-css). --- ##### titleWrapperClassNameDisableBase boolean | undefined Disables default classes of title wrapper element. There are some default class names with essential styles applied to the title wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### highlightedContent ReactNode Item content under title. Sets the entire content of an item aside from an image. --- ##### highlightedContentWrapperClassName string | undefined Custom classes of highlighted content wrapper element. See[Custom CSS](#custom-css). --- ##### highlightedContentWrapperClassNameDisableBase boolean | undefined Disables default classes of highlighted content wrapper element. There are some default class names with essential styles applied to the highlighted content wrapper element. This setting disables them as an escape hatch for customization. See[Custom CSS](#custom-css). --- ##### bottomContent ReactNode Any custom content to display at the bottom of the item. --- const ### ItemImage Item image component type ### ItemImageProps Item Image properties #### Properties ##### src string | null | undefined Image URL --- ##### missingImageSrc string | undefined URL of an image to display when the main image could not be loaded. --- ##### className string | undefined Image wrapper class name --- ##### imgClassName string | undefined Image class name --- ##### width number | undefined Image width in pixels --- ##### height number | undefined Image height in pixels --- ##### verticalAlignment "top" | "center" | "bottom" | undefined Image vertical alignment --- ##### horizontalAlignment "center" | "left" | "right" | undefined Image horizontal alignment --- ##### fittingAlgorithm "cover" | "scale\_down" | undefined Image fitting algorithm --- type ### Recommendation Single recommendation item #### Properties ##### id string Item ID --- ##### values { \[key: string\]: any; } | undefined Item properties --- function ### addRecommIdQueryParam Utility function to append `recombee_recomm_id` parameter to an url string. For usage in widget template to construct item link URL. type ### CreateRequestFunction Factory for creating Recombee API Request to load data into a Widget. type ### FetchContentOptions CreateRequestFunction parameter #### Properties ##### count number Number of items to fetch for the widget. Pass it to the appropriate Request constructor. --- --- # Feed Widget (React) > Source: https://docs.recombee.com/widget-sdks/feed-widget-react > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [ Installation ](#install) * [ Client Initialization ](#client-initialization) * [ Providing User ID ](#providing-user-id) * [ Basic Example ](#basic-example) * [ Custom CSS ](#custom-css) * [ Custom Templates ](#custom-templates) * [ Overriding Base Classes ](#overriding-base-classes) * [ Composite Recommendations ](#composite-recommendations) * [API Reference](#api) * [FeedWidget](#api/FeedWidget) * [FeedWidgetProps](#api/FeedWidgetProps) * [FeedWidgetState](#api/FeedWidgetState) * [DefaultItem](#api/DefaultItem) * [DefaultItemProps](#api/DefaultItemProps) * [ItemImage](#api/ItemImage) * [ItemImageProps](#api/ItemImageProps) * [Recommendation](#api/Recommendation) * [addRecommIdQueryParam](#api/addRecommIdQueryParam) * [CreateRequestFunction](#api/CreateRequestFunction) * [FetchContentOptions](#api/FetchContentOptions) # Feed Widget (React) > A React component widget that creates a personalized, scrollable feed of item recommendations, designed for continuous content discovery. Use this library when you want to render a widget and you are using React and JSX in your project. This widget library is version 0.2.15 and the API can change. Please specify exact version when installing. ## Installation Install `@recombee/feed-widget-react@0.2.15` and `recombee-js-api-client`packages using your preferred NPM package manager. This example is using`pnpm`. ``` pnpm add @recombee/feed-widget-react@0.2.15 recombee-js-api-client ``` Always remember to apply the default CSS file distributed alongside the widget library, as shown in the examples. ## Client Initialization The widget loads recommendation data using [Recombee API Client](/js_client). Here is how to initialize the client with necessary configuration for a specific database: ``` import { } from "recombee-js-api-client"; const = "[database-id]"; const = "[database-public-token]"; const = "[database-region]"; export const = new (, , { : , }); ``` The Database Public Token can be found in the Admin UI[Database Settings Page](https://admin.recombee.com/go-to-database/settings). The widget also needs to be provided a `createRequest` function, which instantiates a client request class to define which data to pull from the database. Use Scenario ID which can be found on Admin GUI[Database Scenarios Page](https://admin.recombee.com/go-to-database/scenarios). Please ensure that you provide the user ID (typically obtained from your existing user tracking system), along with other relevant parameters - such as an item ID or [Item Segment](/segmentations) ID - depending on the specific type of recommendation request. See the[Providing User ID](#providing-user-id) section for details on how to obtain user ID in specific cases. ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; const : = ({ }) => { const = "recommend-items-to-user"; return new (userId, , { : , : true, : true, }); }; ``` ### Providing User ID Each visitor of your website should be identified by a user identificator (`userId`) to correlate user activity and deliver best possible recommendation performance. The `userId` should preferrably originate from your user's account details when the user is authenticated or as some session-persistent random ID when they are anonymous. The SDK provides utility which generates random user id and saves it to a cookie to cover the latter case: ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; import { } from "@recombee/carousel-widget-react"; let : string | undefined; if (authenticatedUserId) { = authenticatedUserId; } else { = .(); } const : = ({ }) => { const = "recommend-items-to-user"; return new (, , { : , : true, : true, }); }; ``` ## Basic Example The widget in this example uses the [DefaultItem](#api/DefaultItem) component to render each recommendation in a consistent layout. The resulting widget is inserted into the element specified by the`container` field. Values of the recommended items - such as title, image URL, or link URL - are obtained from the API response and accessed via `props.result?.values`. Ensure that [returnProperties: true](/api#recommend-items-to-user-param-returnProperties) is set in the request, and optionally use[includedProperties](/api#recommend-items-to-user-param-includedProperties)to control which item properties are returned. ``` import { , , , , } from "@recombee/feed-widget-react"; import "@recombee/feed-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="click" ={1} ={2} ="min-h-[260px]" ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} ={() => ( < ="flex justify-center p-2"> < ="me-2 mb-2 rounded-lg bg-[#3f91ff] px-5 py-2.5 text-sm font-medium text-white focus:ring-4 focus:ring-blue-300 focus:outline-hidden" ={..} > More )} /> ); }; ``` ## Custom CSS Recombee Widgets are designed to be styling-agnostic. You can fully customize their appearance using your own CSS by passing class names through customization properties. In these docs examples, we use utility classes from [Tailwind CSS](https://tailwindcss.com/) for styling. Class names for internal elements and custom components are passed as props and applied by the widget during rendering. The default structure of the_Basic Example_ widget is illustrated below (pseudo-code): ```
... more items ...
``` This is especially handy for understanding how to customize the widget to its full potential. ### Setting own classes ``` import { , , , , } from "@recombee/feed-widget-react"; import "@recombee/feed-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="click" ="grid-cols-[repeat(auto-fill,minmax(200px,1fr))] p-3 gap-2 overflow-hidden text-[#282b30] rounded-lg bg-white border border-[#ededed] dark:border-none dark:bg-transparent dark:text-white" ="min-h-[260px]" ={() => ( < ="border-b border-slate-600" ="text-center" ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} ={() => ( < ="flex justify-center p-2"> < ="me-2 mb-2 rounded-lg bg-[#3f91ff] px-5 py-2.5 text-sm font-medium text-white focus:ring-4 focus:ring-blue-300 focus:outline-hidden" ={..} > More )} /> ); }; ``` ## Custom Templates Recombee Widgets support full customization of internal components such as the appearance of the recommended items. You can provide your own components via props like [ItemComponent](#api/ItemComponent) to control the structure, styling, and behavior of the widget. This flexibility allows you to adapt the widget's appearance and functionality to match your design and user experience requirements. ### Custom Item ``` import { , } from "@recombee/feed-widget-react"; import "@recombee/feed-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="click" ="min-h-[310px]" ={() => ( < ="overflow-hidden rounded-lg border-[#ededed] bg-white text-[#282b30] dark:border-none dark:bg-transparent dark:text-white"> < ="relative overflow-hidden bg-cover bg-no-repeat"> < ={`${.?.?.images?.[0]}`} ={600} ={400} /> {.?.?.["genres"]?.includes("drama") && ( < ="absolute top-3 left-3 bg-[#3f91ff] px-2 text-xs/[1.67] font-semibold text-white"> Drama )} {.?.?.["genres"]?.includes("science_fiction") && ( < ="absolute top-3 left-3 bg-[#36c696] px-2 text-xs/[1.67] font-semibold text-white"> Sci-Fi )} < ="p-3"> < ="mb-1 line-clamp-4 overflow-hidden text-[14px]/[1.43] text-nowrap text-ellipsis text-[#80868f]"> {`${.?.?.genres?.join(", ")}`} < ="text-md mb-1 overflow-hidden text-nowrap text-ellipsis"> {`${.?.?.title}`} < ="line-clamp-4 pb-3 text-base text-[#3f91ff]"> {`${.?.?.year}`} < ="w-full rounded-lg border border-[#ededed] py-2 text-center text-[14px]/[1.43] font-medium text-[#80868f]"> Play )} ={() => ( < ="flex justify-center p-2"> < ="me-2 mb-2 rounded-lg bg-[#3f91ff] px-5 py-2.5 text-sm font-medium text-white focus:ring-4 focus:ring-blue-300 focus:outline-hidden" ={..} > More )} /> ); }; ``` ## Overriding Base Classes Some base styles are always applied to ensure the widget maintains the structural shape of a feed. However, these can be disabled or overridden if needed. Use the[FeedWidgetProps.classNameDisableDefault](#api/FeedWidgetProps.classNameDisableDefault) and related options to opt out of default styling. ``` import { , , , , } from "@recombee/feed-widget-react"; import "@recombee/feed-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="click" ={2} ="min-h-[260px]" ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} ={() => ( < ="flex justify-center p-2"> < ="me-2 mb-2 rounded-lg bg-[#3f91ff] px-5 py-2.5 text-sm font-medium text-white focus:ring-4 focus:ring-blue-300 focus:outline-hidden" ={..} > More )} /> ); }; ``` ## Composite Recommendations Widget SDKs can also be used to render [Composite Recommendations](/scenarios#composite-recommendations). A common use case is displaying [dynamic category- or genre-based rails](/scenarios#fully-personalized-homepage) on the homepage, as well as scenarios such as [Because You Watched](/scenarios#because-you-watched-movie-). The CompositeRecommendation request is called from within the[createRequest](/widget-sdks/carousel-widget-react#api/CarouselWidgetProps.createRequest)function. To render the header (for example, the user’s favorite category or the title of the watched movie), implement the[SourceItemComponent](/widget-sdks/carousel-widget-react#api/CarouselWidgetProps.SourceItemComponent). ``` const : = ({ }) => { return new ("top-from-genre-for-you", , { : { : true }, }); }; import { , , , , } from "@recombee/feed-widget-react"; import "@recombee/feed-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="click" ={1} ={2} ="min-h-[260px]" ={({ }) => { return ? ( < ="my-5">Because you like {?.} ) : null; }} ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} ={() => ( < ="flex justify-center p-2"> < ="me-2 mb-2 rounded-lg bg-[#3f91ff] px-5 py-2.5 text-sm font-medium text-white focus:ring-4 focus:ring-blue-300 focus:outline-hidden" ={..} > More )} /> ); }; ``` ## API Reference const ### FeedWidget Feed widget component. See [FeedWidgetProps](#api/FeedWidgetProps) for configuration options. type ### FeedWidgetProps Configuration options for the Feed widget. #### Properties ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-react"; < // ...ommited code... ={({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }} />; ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### initialRowsCount number | undefined Number of rows to load initially. --- ##### loadMoreRowsCount number | undefined Number of rows to load on "load more" trigger invocation. --- ##### loadMoreTrigger "scroll" | "click" --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | "layout" | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### ItemComponent FC<{ state: FeedWidgetState; result: Recommendation; }> A component rendering a single recommended item. --- ##### LoadMoreTriggerComponent FC<{ state: FeedWidgetState; }> | (FC<{ state: FeedWidgetState; }> & FC<{ state: FeedWidgetState; }>) | undefined --- ##### SourceItemComponent FC<{ state: FeedWidgetState; source?: Recommendation | null | undefined; }> | undefined A component rendering a source recommended item when using Composite Scenario. --- class ### FeedWidgetState A Class exposing Feed internal state to be used for customization. #### Properties ##### sourceItem Recommendation | null | undefined Array of items to show in the carousel. --- ##### items ({ type: "ENTITY"; key: string; entity: Recommendation; } | { type: "PLACEHOLDER"; key: string; })\[\] Array of items to show in the feed --- ##### recommId string | undefined Id of recommendation response from which the items originated. --- ##### handleTriggerClick () => void Handles clicking on a trigger to load more feed items by a configured increment --- const ### DefaultItem Default Item component provided for basic usage. interface ### DefaultItemProps Recommended item component properties. #### Properties ##### className string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableBase boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### imageWrapperClassName string | undefined Custom classes of item image wrapper element. See[Custom CSS](#custom-css). --- ##### imageWrapperClassNameDisableBase boolean | undefined Disables default classes of item image wrapper element. There are some default class names with essential styles applied to the item image wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentWrapperClassName string | undefined Custom classes of item content element. See[Custom CSS](#custom-css). --- ##### result Recommendation | undefined A single item recommedation. --- ##### href string | null | undefined Item link URL. --- ##### image ReactNode Item Image element. --- ##### labelContent ReactNode Item content above title. Sets the entire content of an item aside from an image. --- ##### labelContentWrapperClassName string | undefined Custom classes of label content wrapper element. See[Custom CSS](#custom-css). --- ##### labelContentWrapperClassNameDisableBase boolean | undefined Disables default classes of label content wrapper element. There are some default class names with essential styles applied to the label content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### title ReactNode Item title. --- ##### titleWrapperClassName string | undefined Custom classes of title wrapper element. See[Custom CSS](#custom-css). --- ##### titleWrapperClassNameDisableBase boolean | undefined Disables default classes of title wrapper element. There are some default class names with essential styles applied to the title wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### highlightedContent ReactNode Item content under title. Sets the entire content of an item aside from an image. --- ##### highlightedContentWrapperClassName string | undefined Custom classes of highlighted content wrapper element. See[Custom CSS](#custom-css). --- ##### highlightedContentWrapperClassNameDisableBase boolean | undefined Disables default classes of highlighted content wrapper element. There are some default class names with essential styles applied to the highlighted content wrapper element. This setting disables them as an escape hatch for customization. See[Custom CSS](#custom-css). --- ##### bottomContent ReactNode Any custom content to display at the bottom of the item. --- const ### ItemImage Item image component type ### ItemImageProps Item Image properties #### Properties ##### src string | null | undefined Image URL --- ##### missingImageSrc string | undefined URL of an image to display when the main image could not be loaded. --- ##### className string | undefined Image wrapper class name --- ##### imgClassName string | undefined Image class name --- ##### width number | undefined Image width in pixels --- ##### height number | undefined Image height in pixels --- ##### verticalAlignment "top" | "center" | "bottom" | undefined Image vertical alignment --- ##### horizontalAlignment "center" | "left" | "right" | undefined Image horizontal alignment --- ##### fittingAlgorithm "cover" | "scale\_down" | undefined Image fitting algorithm --- type ### Recommendation Single recommendation item #### Properties ##### id string Item ID --- ##### values { \[key: string\]: any; } | undefined Item properties --- function ### addRecommIdQueryParam Utility function to append `recombee_recomm_id` parameter to an url string. For usage in widget template to construct item link URL. type ### CreateRequestFunction Factory for creating Recombee API Request to load data into a Widget. type ### FetchContentOptions CreateRequestFunction parameter #### Properties ##### count number Number of items to fetch for the widget. Pass it to the appropriate Request constructor. --- --- # Grid Widget (JS) > Source: https://docs.recombee.com/widget-sdks/grid-widget-js > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [ Installation ](#install) * [ Client Initialization ](#client-initialization) * [ Providing User ID ](#providing-user-id) * [ Basic Example ](#basic-example) * [ Custom CSS ](#custom-css) * [ Custom Templates ](#custom-templates) * [ Composite Recommendations ](#composite-recommendations) * [API Reference](#api) * [GridWidget](#api/GridWidget) * [GridWidgetOptions](#api/GridWidgetOptions) * [GridWidgetProps](#api/GridWidgetProps) * [GridWidgetState](#api/GridWidgetState) * [DefaultItem](#api/DefaultItem) * [DefaultItemProps](#api/DefaultItemProps) * [ItemImage](#api/ItemImage) * [ItemImageProps](#api/ItemImageProps) * [Recommendation](#api/Recommendation) * [addRecommIdQueryParam](#api/addRecommIdQueryParam) * [CreateRequestFunction](#api/CreateRequestFunction) * [FetchContentOptions](#api/FetchContentOptions) # Grid Widget (JS) > A Vanilla JS widget that renders a grid of recommended items, optimized for high-density product presentation. Use this library when you want to display a widget without using a transpiler like Babel and without using JSX. This library exports a `htm` HTML factory to assemble custom elements of the widget. This widget library is version 0.2.17 and the API can change. Please specify exact version when installing. ## Installation Install `@recombee/grid-widget-js@0.2.17` and `recombee-js-api-client`packages using your preferred NPM package manager. This example is using`pnpm`. ``` pnpm add @recombee/grid-widget-js@0.2.17 recombee-js-api-client ``` Always remember to apply the default CSS file distributed alongside the widget library, as shown in the examples. ## Client Initialization The widget loads recommendation data using [Recombee API Client](/js_client). Here is how to initialize the client with necessary configuration for a specific database: ``` import { } from "recombee-js-api-client"; const = "[database-id]"; const = "[database-public-token]"; const = "[database-region]"; export const = new (, , { : , }); ``` The Database Public Token can be found in the Admin UI[Database Settings Page](https://admin.recombee.com/go-to-database/settings). The widget also needs to be provided a `createRequest` function, which instantiates a client request class to define which data to pull from the database. Use Scenario ID which can be found on Admin GUI[Database Scenarios Page](https://admin.recombee.com/go-to-database/scenarios). Please ensure that you provide the user ID (typically obtained from your existing user tracking system), along with other relevant parameters - such as an item ID or [Item Segment](/segmentations) ID - depending on the specific type of recommendation request. See the[Providing User ID](#providing-user-id) section for details on how to obtain user ID in specific cases. ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; const : = ({ }) => { const = "recommend-items-to-user"; return new (userId, , { : , : true, : true, }); }; ``` ### Providing User ID Each visitor of your website should be identified by a user identificator (`userId`) to correlate user activity and deliver best possible recommendation performance. The `userId` should preferrably originate from your user's account details when the user is authenticated or as some session-persistent random ID when they are anonymous. The SDK provides utility which generates random user id and saves it to a cookie to cover the latter case: ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; import { } from "@recombee/carousel-widget-react"; let : string | undefined; if (authenticatedUserId) { = authenticatedUserId; } else { = .(); } const : = ({ }) => { const = "recommend-items-to-user"; return new (, , { : , : true, : true, }); }; ``` ## Basic Example The widget in this example uses the [DefaultItem](#api/DefaultItem) component to render each recommendation in a consistent layout. The resulting widget is inserted into the element specified by the`container` field. Values of the recommended items - such as title, image URL, or link URL - are obtained from the API response and accessed via `props.result?.values`. Ensure that [returnProperties: true](/api#recommend-items-to-user-param-returnProperties) is set in the request, and optionally use[includedProperties](/api#recommend-items-to-user-param-includedProperties)to control which item properties are returned. Number of items loaded to grid widget is governed by CSS Grid styling which must be provided. See the example code where the grid is defined using utility classes provided by TailwindCSS. ``` import { , , , , , } from "@recombee/grid-widget-js"; import "@recombee/grid-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "grid-cols-[repeat(1,1fr)] grid-rows-[repeat(4,1fr)] gap-2 @lg:grid-cols-[repeat(2,1fr)] @lg:grid-rows-[repeat(3,1fr)] @xl:grid-cols-[repeat(4,1fr)] @xl:grid-rows-[repeat(2,1fr)]", : "min-h-[260px]", : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, }); ``` ## Custom CSS Recombee Widgets are designed to be styling-agnostic. You can fully customize their appearance using your own CSS by passing class names through customization properties. In these docs examples, we use utility classes from [Tailwind CSS](https://tailwindcss.com/) for styling. Class names for internal elements and custom components are passed as props and applied by the widget during rendering. The default structure of the_Basic Example_ widget is illustrated below (pseudo-code): ```
... more items ...
``` This is especially handy for understanding how to customize the widget to its full potential. ### Setting own classes ``` import { , , , , , } from "@recombee/grid-widget-js"; import "@recombee/grid-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "rb:overflow-hidden rb:text-[#282b30] rb:rounded-lg rb:bg-white rb:border rb:border-[#ededed] rb:dark:border-none rb:dark:bg-transparent rb:dark:text-white", : "grid-cols-[repeat(4,1fr)] grid-rows-[repeat(1,1fr)] gap-2 p-1", : "min-h-[260px]", : () => `<${} className="border-b border-slate-600" contentWrapperClassName="text-center" href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, }); ``` ## Custom Templates Recombee Widgets support full customization of internal components such as the appearance of the recommended items. You can provide your own components via props like [ItemComponent](#api/ItemComponent) to control the structure, styling, and behavior of the widget. This flexibility allows you to adapt the widget's appearance and functionality to match your design and user experience requirements. ### Custom Item ``` import { , , } from "@recombee/grid-widget-js"; import "@recombee/grid-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : "min-h-[310px]", : () => `
<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />${.?.?.["genres"]?.includes("drama") && `
Drama
`}${.?.?.["genres"]?.includes( "science_fiction", ) && `
Sci-Fi
`}
${`${.?.?.genres?.join(", ")}`}
${`${.?.?.title}`}
${`${.?.?.year}`}
`, }); ``` ## Composite Recommendations ``` import { , , , , , } from "@recombee/grid-widget-js"; import "@recombee/grid-widget-js/dist/styles.css"; const : = ({ }) => { return new ("top-from-genre-for-you", , { : { : true, }, }); }; ({ : "#widget-root", : , : , : "composite", : "min-h-[310px]", : ({ }) => { return ? `

Because you like ${?.}

` : null; }, : () => `<${} href=${( .?.?.link, .., )} image=${`<${} src=${`${.?.?.images?.[0]}`} width=${600} height=${400} />`} labelContent=${`${.?.?.genres?.join(", ")}`} title=${`${.?.?.title}`} highlightedContent=${`${.?.?.year}`} />`, }); ``` ## API Reference const ### GridWidget Grid widget type ### GridWidgetOptions Grid widget options #### Properties ##### container string CSS Selector to target the element where the widget should be inserted. --- ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : ({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }, }); ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | "layout" | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### ItemComponent FC<{ state: GridWidgetState; result: Recommendation; }> A component rendering a single recommended item. --- ##### SourceItemComponent FC<{ state: GridWidgetState; source?: Recommendation | null | undefined; }> | undefined A component rendering a source recommended item when using Composite Scenario. --- type ### GridWidgetProps Grid Widget component configuration options #### Properties ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : ({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }, }); ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | "layout" | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### ItemComponent FC<{ state: GridWidgetState; result: Recommendation; }> A component rendering a single recommended item. --- ##### SourceItemComponent FC<{ state: GridWidgetState; source?: Recommendation | null | undefined; }> | undefined A component rendering a source recommended item when using Composite Scenario. --- class ### GridWidgetState Class exposing internal state of the grid #### Properties ##### sourceItem Recommendation | null | undefined Array of items to show in the carousel. --- ##### items ({ type: "ENTITY"; key: string; entity: Recommendation; } | { type: "PLACEHOLDER"; key: string; })\[\] Recommended items to display --- ##### recommId string | undefined Id of recommendation response from which the items originated. --- const ### DefaultItem Default Item component provided for basic usage. interface ### DefaultItemProps Recommended item component properties. #### Properties ##### className string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableBase boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### imageWrapperClassName string | undefined Custom classes of item image wrapper element. See[Custom CSS](#custom-css). --- ##### imageWrapperClassNameDisableBase boolean | undefined Disables default classes of item image wrapper element. There are some default class names with essential styles applied to the item image wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentWrapperClassName string | undefined Custom classes of item content element. See[Custom CSS](#custom-css). --- ##### result Recommendation | undefined A single item recommedation. --- ##### href string | null | undefined Item link URL. --- ##### image ReactNode Item Image element. --- ##### labelContent ReactNode Item content above title. Sets the entire content of an item aside from an image. --- ##### labelContentWrapperClassName string | undefined Custom classes of label content wrapper element. See[Custom CSS](#custom-css). --- ##### labelContentWrapperClassNameDisableBase boolean | undefined Disables default classes of label content wrapper element. There are some default class names with essential styles applied to the label content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### title ReactNode Item title. --- ##### titleWrapperClassName string | undefined Custom classes of title wrapper element. See[Custom CSS](#custom-css). --- ##### titleWrapperClassNameDisableBase boolean | undefined Disables default classes of title wrapper element. There are some default class names with essential styles applied to the title wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### highlightedContent ReactNode Item content under title. Sets the entire content of an item aside from an image. --- ##### highlightedContentWrapperClassName string | undefined Custom classes of highlighted content wrapper element. See[Custom CSS](#custom-css). --- ##### highlightedContentWrapperClassNameDisableBase boolean | undefined Disables default classes of highlighted content wrapper element. There are some default class names with essential styles applied to the highlighted content wrapper element. This setting disables them as an escape hatch for customization. See[Custom CSS](#custom-css). --- ##### bottomContent ReactNode Any custom content to display at the bottom of the item. --- const ### ItemImage Item image component type ### ItemImageProps Item Image properties #### Properties ##### src string | null | undefined Image URL --- ##### missingImageSrc string | undefined URL of an image to display when the main image could not be loaded. --- ##### className string | undefined Image wrapper class name --- ##### imgClassName string | undefined Image class name --- ##### width number | undefined Image width in pixels --- ##### height number | undefined Image height in pixels --- ##### verticalAlignment "top" | "center" | "bottom" | undefined Image vertical alignment --- ##### horizontalAlignment "center" | "left" | "right" | undefined Image horizontal alignment --- ##### fittingAlgorithm "cover" | "scale\_down" | undefined Image fitting algorithm --- type ### Recommendation Single recommendation item #### Properties ##### id string Item ID --- ##### values { \[key: string\]: any; } | undefined Item properties --- function ### addRecommIdQueryParam Utility function to append `recombee_recomm_id` parameter to an url string. For usage in widget template to construct item link URL. type ### CreateRequestFunction Factory for creating Recombee API Request to load data into a Widget. type ### FetchContentOptions CreateRequestFunction parameter #### Properties ##### count number Number of items to fetch for the widget. Pass it to the appropriate Request constructor. --- --- # Grid Widget (React) > Source: https://docs.recombee.com/widget-sdks/grid-widget-react > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [ Installation ](#install) * [ Client Initialization ](#client-initialization) * [ Providing User ID ](#providing-user-id) * [ Basic Example ](#basic-example) * [ Custom CSS ](#custom-css) * [ Custom Templates ](#custom-templates) * [ Composite Recommendations ](#composite-recommendations) * [API Reference](#api) * [GridWidget](#api/GridWidget) * [GridWidgetProps](#api/GridWidgetProps) * [GridWidgetState](#api/GridWidgetState) * [DefaultItem](#api/DefaultItem) * [DefaultItemProps](#api/DefaultItemProps) * [ItemImage](#api/ItemImage) * [ItemImageProps](#api/ItemImageProps) * [Recommendation](#api/Recommendation) * [addRecommIdQueryParam](#api/addRecommIdQueryParam) * [CreateRequestFunction](#api/CreateRequestFunction) * [FetchContentOptions](#api/FetchContentOptions) # Grid Widget (React) > A React component widget that renders a grid of recommended items, optimized for high-density product presentation. Use this library when you want to render a widget and you are using React and JSX in your project. This widget library is version 0.2.15 and the API can change. Please specify exact version when installing. ## Installation Install `@recombee/grid-widget-react@0.2.15` and `recombee-js-api-client`packages using your preferred NPM package manager. This example is using`pnpm`. ``` pnpm add @recombee/grid-widget-react@0.2.15 recombee-js-api-client ``` Always remember to apply the default CSS file distributed alongside the widget library, as shown in the examples. ## Client Initialization The widget loads recommendation data using [Recombee API Client](/js_client). Here is how to initialize the client with necessary configuration for a specific database: ``` import { } from "recombee-js-api-client"; const = "[database-id]"; const = "[database-public-token]"; const = "[database-region]"; export const = new (, , { : , }); ``` The Database Public Token can be found in the Admin UI[Database Settings Page](https://admin.recombee.com/go-to-database/settings). The widget also needs to be provided a `createRequest` function, which instantiates a client request class to define which data to pull from the database. Use Scenario ID which can be found on Admin GUI[Database Scenarios Page](https://admin.recombee.com/go-to-database/scenarios). Please ensure that you provide the user ID (typically obtained from your existing user tracking system), along with other relevant parameters - such as an item ID or [Item Segment](/segmentations) ID - depending on the specific type of recommendation request. See the[Providing User ID](#providing-user-id) section for details on how to obtain user ID in specific cases. ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; const : = ({ }) => { const = "recommend-items-to-user"; return new (userId, , { : , : true, : true, }); }; ``` ### Providing User ID Each visitor of your website should be identified by a user identificator (`userId`) to correlate user activity and deliver best possible recommendation performance. The `userId` should preferrably originate from your user's account details when the user is authenticated or as some session-persistent random ID when they are anonymous. The SDK provides utility which generates random user id and saves it to a cookie to cover the latter case: ``` import { type } from "@recombee/carousel-widget-react"; import { } from "recombee-js-api-client"; import { } from "@recombee/carousel-widget-react"; let : string | undefined; if (authenticatedUserId) { = authenticatedUserId; } else { = .(); } const : = ({ }) => { const = "recommend-items-to-user"; return new (, , { : , : true, : true, }); }; ``` ## Basic Example The widget in this example uses the [DefaultItem](#api/DefaultItem) component to render each recommendation in a consistent layout. The resulting widget is inserted into the element specified by the`container` field. Values of the recommended items - such as title, image URL, or link URL - are obtained from the API response and accessed via `props.result?.values`. Ensure that [returnProperties: true](/api#recommend-items-to-user-param-returnProperties) is set in the request, and optionally use[includedProperties](/api#recommend-items-to-user-param-includedProperties)to control which item properties are returned. Number of items loaded to grid widget is governed by CSS Grid styling which must be provided. See the example code where the grid is defined using utility classes provided by TailwindCSS. ``` import { , , , , } from "@recombee/grid-widget-react"; import "@recombee/grid-widget-react/dist/styles.css"; export default () => { return ( < ="@container"> < ={} ={} ="grid-cols-[repeat(1,1fr)] grid-rows-[repeat(4,1fr)] gap-2 @lg:grid-cols-[repeat(2,1fr)] @lg:grid-rows-[repeat(3,1fr)] @xl:grid-cols-[repeat(4,1fr)] @xl:grid-rows-[repeat(2,1fr)]" ="min-h-[260px]" ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} /> ); }; ``` ## Custom CSS Recombee Widgets are designed to be styling-agnostic. You can fully customize their appearance using your own CSS by passing class names through customization properties. In these docs examples, we use utility classes from [Tailwind CSS](https://tailwindcss.com/) for styling. Class names for internal elements and custom components are passed as props and applied by the widget during rendering. The default structure of the_Basic Example_ widget is illustrated below (pseudo-code): ```
... more items ...
``` This is especially handy for understanding how to customize the widget to its full potential. ### Setting own classes ``` import { , , , , } from "@recombee/grid-widget-react"; import "@recombee/grid-widget-react/dist/styles.css"; export default () => { return ( < ="@container"> < ={} ={} ="rb:overflow-hidden rb:text-[#282b30] rb:rounded-lg rb:bg-white rb:border rb:border-[#ededed] rb:dark:border-none rb:dark:bg-transparent rb:dark:text-white" ="grid-cols-[repeat(4,1fr)] grid-rows-[repeat(1,1fr)] gap-2 p-1" ="min-h-[260px]" ={() => ( < ="border-b border-slate-600" ="text-center" ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} /> ); }; ``` ## Custom Templates Recombee Widgets support full customization of internal components such as the appearance of the recommended items. You can provide your own components via props like [ItemComponent](#api/ItemComponent) to control the structure, styling, and behavior of the widget. This flexibility allows you to adapt the widget's appearance and functionality to match your design and user experience requirements. ### Custom Item ``` import { , } from "@recombee/grid-widget-react"; import "@recombee/grid-widget-react/dist/styles.css"; export default () => { return ( < ={} ={} ="min-h-[310px]" ={() => ( < ="overflow-hidden rounded-lg border-[#ededed] bg-white text-[#282b30] dark:border-none dark:bg-transparent dark:text-white"> < ="relative overflow-hidden bg-cover bg-no-repeat"> < ={`${.?.?.images?.[0]}`} ={600} ={400} /> {.?.?.["genres"]?.includes("drama") && ( < ="absolute top-3 left-3 bg-[#3f91ff] px-2 text-xs/[1.67] font-semibold text-white"> Drama )} {.?.?.["genres"]?.includes("science_fiction") && ( < ="absolute top-3 left-3 bg-[#36c696] px-2 text-xs/[1.67] font-semibold text-white"> Sci-Fi )} < ="p-3"> < ="mb-1 line-clamp-4 overflow-hidden text-[14px]/[1.43] text-nowrap text-ellipsis text-[#80868f]"> {`${.?.?.genres?.join(", ")}`} < ="text-md mb-1 overflow-hidden text-nowrap text-ellipsis"> {`${.?.?.title}`} < ="line-clamp-4 pb-3 text-base text-[#3f91ff]"> {`${.?.?.year}`} < ="w-full rounded-lg border border-[#ededed] py-2 text-center text-[14px]/[1.43] font-medium text-[#80868f]"> Play )} /> ); }; ``` ## Composite Recommendations Widget SDKs can also be used to render [Composite Recommendations](/scenarios#composite-recommendations). A common use case is displaying [dynamic category- or genre-based rails](/scenarios#fully-personalized-homepage) on the homepage, as well as scenarios such as [Because You Watched](/scenarios#because-you-watched-movie-). The CompositeRecommendation request is called from within the[createRequest](/widget-sdks/carousel-widget-react#api/CarouselWidgetProps.createRequest)function. To render the header (for example, the user’s favorite category or the title of the watched movie), implement the[SourceItemComponent](/widget-sdks/carousel-widget-react#api/CarouselWidgetProps.SourceItemComponent). ``` import { , , , , } from "@recombee/grid-widget-react"; import "@recombee/grid-widget-react/dist/styles.css"; const : = ({ }) => { return new ("top-from-genre-for-you", , { : { : true }, }); }; export default () => { return ( < ={} ={} ="composite" ="min-h-[310px]" ={({ }) => { return ? ( < ="my-5">Because you like {?.} ) : null; }} ={() => ( < ={( .?.?.link, .., )} ={ < ={`${.?.?.images?.[0]}`} ={600} ={400} /> } ={`${.?.?.genres?.join(", ")}`} ={`${.?.?.title}`} ={`${.?.?.year}`} /> )} /> ); }; ``` ## API Reference const ### GridWidget Grid Widget component type ### GridWidgetProps Grid Widget component configuration options #### Properties ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest CreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-react"; < // ...ommited code... ={({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }} />; ``` --- ##### deduplicationPartitionKey string | undefined A string key specifying a group of widgets, in which recommendation results will be deduplicated. By default, all widgets belong to a single group so all results from the same database are deduplicated. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableDefault boolean | undefined Disables default classes of widget wrapper element. There are some default class names with essential styles applied to the widget wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentClassName string | undefined Custom classes of content wrapper element. See[Custom CSS](#custom-css). --- ##### contentClassNameDisableDefault boolean | "layout" | undefined Disables default classes of content wrapper element. There are some default class names with essential styles applied to the content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### itemWrapperClassName string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### itemWrapperClassNameDisableDefault boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### ItemComponent FC<{ state: GridWidgetState; result: Recommendation; }> A component rendering a single recommended item. --- ##### SourceItemComponent FC<{ state: GridWidgetState; source?: Recommendation | null | undefined; }> | undefined A component rendering a source recommended item when using Composite Scenario. --- class ### GridWidgetState Class exposing internal state of the grid #### Properties ##### sourceItem Recommendation | null | undefined Array of items to show in the carousel. --- ##### items ({ type: "ENTITY"; key: string; entity: Recommendation; } | { type: "PLACEHOLDER"; key: string; })\[\] Recommended items to display --- ##### recommId string | undefined Id of recommendation response from which the items originated. --- const ### DefaultItem Default Item component provided for basic usage. interface ### DefaultItemProps Recommended item component properties. #### Properties ##### className string | undefined Custom classes of item wrapper element. See[Custom CSS](#custom-css). --- ##### classNameDisableBase boolean | undefined Disables default classes of item wrapper element. There are some default class names with essential styles applied to the item wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### imageWrapperClassName string | undefined Custom classes of item image wrapper element. See[Custom CSS](#custom-css). --- ##### imageWrapperClassNameDisableBase boolean | undefined Disables default classes of item image wrapper element. There are some default class names with essential styles applied to the item image wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### contentWrapperClassName string | undefined Custom classes of item content element. See[Custom CSS](#custom-css). --- ##### result Recommendation | undefined A single item recommedation. --- ##### href string | null | undefined Item link URL. --- ##### image ReactNode Item Image element. --- ##### labelContent ReactNode Item content above title. Sets the entire content of an item aside from an image. --- ##### labelContentWrapperClassName string | undefined Custom classes of label content wrapper element. See[Custom CSS](#custom-css). --- ##### labelContentWrapperClassNameDisableBase boolean | undefined Disables default classes of label content wrapper element. There are some default class names with essential styles applied to the label content wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### title ReactNode Item title. --- ##### titleWrapperClassName string | undefined Custom classes of title wrapper element. See[Custom CSS](#custom-css). --- ##### titleWrapperClassNameDisableBase boolean | undefined Disables default classes of title wrapper element. There are some default class names with essential styles applied to the title wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### highlightedContent ReactNode Item content under title. Sets the entire content of an item aside from an image. --- ##### highlightedContentWrapperClassName string | undefined Custom classes of highlighted content wrapper element. See[Custom CSS](#custom-css). --- ##### highlightedContentWrapperClassNameDisableBase boolean | undefined Disables default classes of highlighted content wrapper element. There are some default class names with essential styles applied to the highlighted content wrapper element. This setting disables them as an escape hatch for customization. See[Custom CSS](#custom-css). --- ##### bottomContent ReactNode Any custom content to display at the bottom of the item. --- const ### ItemImage Item image component type ### ItemImageProps Item Image properties #### Properties ##### src string | null | undefined Image URL --- ##### missingImageSrc string | undefined URL of an image to display when the main image could not be loaded. --- ##### className string | undefined Image wrapper class name --- ##### imgClassName string | undefined Image class name --- ##### width number | undefined Image width in pixels --- ##### height number | undefined Image height in pixels --- ##### verticalAlignment "top" | "center" | "bottom" | undefined Image vertical alignment --- ##### horizontalAlignment "center" | "left" | "right" | undefined Image horizontal alignment --- ##### fittingAlgorithm "cover" | "scale\_down" | undefined Image fitting algorithm --- type ### Recommendation Single recommendation item #### Properties ##### id string Item ID --- ##### values { \[key: string\]: any; } | undefined Item properties --- function ### addRecommIdQueryParam Utility function to append `recombee_recomm_id` parameter to an url string. For usage in widget template to construct item link URL. type ### CreateRequestFunction Factory for creating Recombee API Request to load data into a Widget. type ### FetchContentOptions CreateRequestFunction parameter #### Properties ##### count number Number of items to fetch for the widget. Pass it to the appropriate Request constructor. --- --- # Quick Search Widget (JS) > Source: https://docs.recombee.com/widget-sdks/quick-search-widget-js > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [ Installation ](#install) * [ Client Initialization ](#client-initialization) * [ Providing User ID ](#providing-user-id) * [ Basic Example ](#basic-example) * [ Custom Template ](#custom-template) * [ Multi-Type Search Results ](#multi-type-search-results) * [API Reference](#api) * [QuickSearchWidget](#api/QuickSearchWidget) * [QuickSearchWidgetOptions](#api/QuickSearchWidgetOptions) * [QuickSearchWidgetProps](#api/QuickSearchWidgetProps) * [QuickSearchWidgetState](#api/QuickSearchWidgetState) * [ItemImage](#api/ItemImage) * [ItemImageProps](#api/ItemImageProps) * [addRecommIdQueryParam](#api/addRecommIdQueryParam) # Quick Search Widget (JS) > A Vanilla JS widget that enables users to perform real-time product searches with instant results, enhancing product discoverability and conversion. Use this library when you want to display a widget without using a transpiler like Babel and without using JSX. This library exports a `htm` HTML factory to assemble custom elements of the widget. This widget library is version 0.2.16 and the API can change. Please specify exact version when installing. ## Installation Install `@recombee/quick-search-widget-js@0.2.16` and`recombee-js-api-client` packages using your preferred NPM package manager. This example is using `pnpm`. ``` pnpm add @recombee/quick-search-widget-js@0.2.16 recombee-js-api-client ``` Always remember to apply the default CSS file distributed alongside the widget library, as shown in the examples. ## Client Initialization The widget loads recommendation data using [Recombee API Client](/js_client). Here is how to initialize the client with necessary configuration for a specific database: ``` import { } from "recombee-js-api-client"; const = "[database-id]"; const = "[database-public-token]"; const = "[database-region]"; export const = new (, , { : , }); ``` The Database Public Token can be found in the Admin UI[Database Settings Page](https://admin.recombee.com/go-to-database/settings). The widget also needs to be provided a `createRequest` function, which instantiates a client request class to define which data to pull from the database. Use Scenario ID which can be found on Admin GUI[Database Scenarios Page](https://admin.recombee.com/go-to-database/scenarios). Quick Search widget requires the `createRequest` function to return a Batch Request. For a basic case of single search request, always wrap it in a batch. ``` import { type } from "@recombee/quick-search-widget-react"; import { , , } from "recombee-js-api-client"; const : = ({ }) => { return new ( [ new (userId, , 5, { : "search-items", : true, : true, }), new (userId, , 5, { : "search-categories", : true, }), ], { : true, }, ); }; ``` ### Providing User ID Each visitor of your website should be identified by a user identificator (`userId`) to correlate user activity and deliver best possible recommendation performance. The `userId` should preferrably originate from your user's account details when the user is authenticated or as some session-persistent random ID when they are anonymous. The SDK provides utility which generates random user id and saves it to a cookie to cover the latter case: ``` import { type } from "@recombee/quick-search-widget-react"; import { , , } from "recombee-js-api-client"; import { } from "@recombee/carousel-widget-react"; let : string | undefined; if (authenticatedUserId) { = authenticatedUserId; } else { = .(); } const : = ({ }) => { return new ( [ new (, , 5, { : "search-items", : true, : true, }), new (, , 5, { : "search-categories", : true, }), ], { : true, }, ); }; ``` ## Basic Example The widget in this example uses the [DefaultItem](#api/DefaultItem) component to render each recommendation in a consistent layout. The resulting widget is inserted into the element specified by the`container` field. Values of the recommended items - such as title, image URL, or link URL - are obtained from the API response and accessed via `props.result?.values`. Ensure that [returnProperties: true](/api#recommend-items-to-user-param-returnProperties) is set in the request, and optionally use[includedProperties](/api#recommend-items-to-user-param-includedProperties)to control which item properties are returned. ``` import { , , , , , , , , } from "@recombee/quick-search-widget-js"; import "@recombee/quick-search-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : 3, : "(min-width: 1000px)", : "lg:w-[var(--qs-input-width)] lg:flex lg:justify-center", : () => `
<${} state=${.} inputProps=${{ : `Search for "table"...`, }} />
`, : () => ``, : () => `
${!.. && `
<${} state=${.} inputProps=${{ : `Search for "table"...`, }} />
`}
Results
${. .(0) .( () => `<${} key=${.} href=${( .?., ., )} image=${`<${} className="size-16 overflow-hidden rounded-lg" src=${`${.?.}`} width=${600} height=${400} />`} primaryContent=${.?.} secondaryContent=${.?.} highlightedContent=${`USD ${.?.}`} ...${.} />`, )}
`, }); ``` ## Custom Template You can customize the appearance and behavior of the Quick Search Widget by overriding its individual components: * [DropdownComponent](#api/DropdownComponent) – Renders the dropdown containing search results. * [InputComponent](#api/InputComponent) – Handles the search input field where users type their queries. * [TriggerComponent](#api/TriggerComponent) – Controls how the widget is opened on mobile devices. The example also demonstrates how to make the search form submittable to a dedicated results page using a `submit` button. ``` import { , , , , , , , } from "@recombee/quick-search-widget-js"; import "@recombee/quick-search-widget-js/dist/styles.css"; ({ : "#widget-root", : , : , : 3, : 1000, : "(min-width: 1000px)", : () => `
<${} />
${.. && `<${} className="rb:absolute rb:top-2.25 rb:right-2.25 rb:h-5 rb:w-5" />`}
`, : () => ``, : () => `
${!.. && `
`, }); ``` ## Multi-Type Search Results You can use the Quick Search Widget to display multiple types of results. For example, showing not only items but also categories or brands using the[Search Item Segments](/api#search-item-segments) requests. All search requests are sent together in a single [Batch](/api#batch)request. ``` import { , , , , , , , , } from "@recombee/quick-search-widget-js"; import "@recombee/quick-search-widget-js/dist/styles.css"; const : = ({ }) => { return new ( [ new ("userId", , 5, { : "search", : true, : true, }), new ("userId", , 5, { : "search-brands", : true, }), ], { : true, }, ); }; ({ : "#widget-root", : , : , : 3, : 0, : "(min-width: 1000px)", : "lg:w-[var(--qs-input-width)] lg:flex lg:justify-center", : () => `
<${} state=${.} inputProps=${{ : `Search for "table"...`, }} />
`, : () => ``, : () => `
${!.. && `
<${} state=${.} inputProps=${{ : `Search for "table"...`, }} />
`}
Segments
${..(1).( () => `
${.}
`, )}
Results
${. .(0) .( () => `<${} key=${.} href=${( .?., ., )} image=${`<${} className="size-16 overflow-hidden rounded-lg" src=${`${.?.}`} width=${600} height=${400} />`} primaryContent=${.?.} secondaryContent=${.?.} highlightedContent=${`USD ${.?.}`} ...${.} />`, )}
`, }); ``` ## API Reference const ### QuickSearchWidget Quick Search widget type ### QuickSearchWidgetOptions Quick Search widget options #### Properties ##### container string CSS Selector to target the element where the widget should be inserted. --- ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest QuickSearchCreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : ({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }, }); ``` --- ##### initialQuery string | undefined String to be prefilled into the search input --- ##### minSearchCharactersCount number Minimum length of search query for search request to be sent. --- ##### typingDebounceDuration number | undefined Maximum duration between keystrokes in milliseconds before search request is made. --- ##### primaryResultsIndex number | undefined Index of request in a batch from which the results are considered to be navigable by arrow keys. --- ##### InputComponent FC Component responsible for rendering the widget input. --- ##### TriggerComponent FC Component responsible for rendering the widget trigger on mobile devices. --- ##### DropdownComponent FC Component responsible for rendering the widget dropdown. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### popoverClassName string | undefined Custom classes of popover wrapper element. See[Custom CSS](#custom-css). --- ##### popoverClassNameDisableDefault boolean | undefined Disables default classes of popover wrapper element. There are some default class names with essential styles applied to the popover wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### desktopMediaQuery string CSS media query specifing when the widget should behave as displayed on desktop. By default, widget behaves as mobile-first, filling entire device screen with results dropdown. --- type ### QuickSearchWidgetProps Quick Search component configuration options #### Properties ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest QuickSearchCreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-js"; ({ // ...ommited code... : ({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }, }); ``` --- ##### initialQuery string | undefined String to be prefilled into the search input --- ##### minSearchCharactersCount number Minimum length of search query for search request to be sent. --- ##### typingDebounceDuration number | undefined Maximum duration between keystrokes in milliseconds before search request is made. --- ##### primaryResultsIndex number | undefined Index of request in a batch from which the results are considered to be navigable by arrow keys. --- ##### InputComponent FC Component responsible for rendering the widget input. --- ##### TriggerComponent FC Component responsible for rendering the widget trigger on mobile devices. --- ##### DropdownComponent FC Component responsible for rendering the widget dropdown. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### popoverClassName string | undefined Custom classes of popover wrapper element. See[Custom CSS](#custom-css). --- ##### popoverClassNameDisableDefault boolean | undefined Disables default classes of popover wrapper element. There are some default class names with essential styles applied to the popover wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### desktopMediaQuery string CSS media query specifing when the widget should behave as displayed on desktop. By default, widget behaves as mobile-first, filling entire device screen with results dropdown. --- class ### QuickSearchWidgetState Class exposing quick search widget state for use in custom templates #### Properties ##### isDesktop boolean Indicates that the widget is displayed on desktop device. --- ##### reset () => void Resets the widget to its initial state --- ##### inputProps { value: string; onChange: (event: ChangeEvent) => void; onKeyDown: (event: KeyboardEvent) => void; onClick: () => void; ref: (element: HTMLElement | null) => void; } Properties to be passed to a input component. --- ##### triggerProps { ref: (element: HTMLElement | null) => void; onClick: () => void; } Properties to be passed to the trigger button of a mobile widget. --- ##### closeButtonProps { type: "button"; onClick: () => void; onTouchEnd: () => void; } Properties to be passed to the close button of a mobile dropdown. --- ##### items (index: number) => { key: string; id: string; recommId: string; values: { \[key: string\]: any; }; metadata: {} | undefined; itemProps: { tabIndex: number; "data-search-result-id"?: string | undefined; onKeyDown: (event: KeyboardEvent) => void; }; }\[\] Getter for current results of the request batch. The `index` parameter indicates an index of results in the Batch Request for which to return items. --- ##### isExpanded boolean Boolean flag indicating that the widget dropdown is open. --- ##### isLoading boolean Boolean flag indicating that a request for new results is in flight. --- const ### ItemImage Item image component type ### ItemImageProps Item Image properties #### Properties ##### src string | null | undefined Image URL --- ##### missingImageSrc string | undefined URL of an image to display when the main image could not be loaded. --- ##### className string | undefined Image wrapper class name --- ##### imgClassName string | undefined Image class name --- ##### width number | undefined Image width in pixels --- ##### height number | undefined Image height in pixels --- ##### verticalAlignment "top" | "center" | "bottom" | undefined Image vertical alignment --- ##### horizontalAlignment "center" | "left" | "right" | undefined Image horizontal alignment --- ##### fittingAlgorithm "cover" | "scale\_down" | undefined Image fitting algorithm --- function ### addRecommIdQueryParam Utility function to append `recombee_recomm_id` parameter to an url string. For usage in widget template to construct item link URL. --- # Quick Search Widget (React) > Source: https://docs.recombee.com/widget-sdks/quick-search-widget-react > For the complete documentation index, see [llms.txt](/llms.txt). **Table of contents** * [ Installation ](#install) * [ Client Initialization ](#client-initialization) * [ Providing User ID ](#providing-user-id) * [ Basic Example ](#basic-example) * [ Custom Template ](#custom-template) * [ Multi-Type Search Results ](#multi-type-search-results) * [API Reference](#api) * [QuickSearchWidget](#api/QuickSearchWidget) * [QuickSearchWidgetProps](#api/QuickSearchWidgetProps) * [QuickSearchWidgetState](#api/QuickSearchWidgetState) * [ItemImage](#api/ItemImage) * [ItemImageProps](#api/ItemImageProps) * [addRecommIdQueryParam](#api/addRecommIdQueryParam) # Quick Search Widget (React) > A React component widget that enables users to perform real-time product searches with instant results, enhancing product discoverability and conversion. Use this library when you want to render a widget and you are using React and JSX in your project. This widget library is version 0.2.15 and the API can change. Please specify exact version when installing. ## Installation Install `@recombee/quick-search-widget-react@0.2.15` and`recombee-js-api-client` packages using your preferred NPM package manager. This example is using `pnpm`. ``` pnpm add @recombee/quick-search-widget-react@0.2.15 recombee-js-api-client ``` Always remember to apply the default CSS file distributed alongside the widget library, as shown in the examples. ## Client Initialization The widget loads recommendation data using [Recombee API Client](/js_client). Here is how to initialize the client with necessary configuration for a specific database: ``` import { } from "recombee-js-api-client"; const = "[database-id]"; const = "[database-public-token]"; const = "[database-region]"; export const = new (, , { : , }); ``` The Database Public Token can be found in the Admin UI[Database Settings Page](https://admin.recombee.com/go-to-database/settings). The widget also needs to be provided a `createRequest` function, which instantiates a client request class to define which data to pull from the database. Use Scenario ID which can be found on Admin GUI[Database Scenarios Page](https://admin.recombee.com/go-to-database/scenarios). Quick Search widget requires the `createRequest` function to return a Batch Request. For a basic case of single search request, always wrap it in a batch. ``` import { type } from "@recombee/quick-search-widget-react"; import { , , } from "recombee-js-api-client"; const : = ({ }) => { return new ( [ new (userId, , 5, { : "search-items", : true, : true, }), new (userId, , 5, { : "search-categories", : true, }), ], { : true, }, ); }; ``` ### Providing User ID Each visitor of your website should be identified by a user identificator (`userId`) to correlate user activity and deliver best possible recommendation performance. The `userId` should preferrably originate from your user's account details when the user is authenticated or as some session-persistent random ID when they are anonymous. The SDK provides utility which generates random user id and saves it to a cookie to cover the latter case: ``` import { type } from "@recombee/quick-search-widget-react"; import { , , } from "recombee-js-api-client"; import { } from "@recombee/carousel-widget-react"; let : string | undefined; if (authenticatedUserId) { = authenticatedUserId; } else { = .(); } const : = ({ }) => { return new ( [ new (, , 5, { : "search-items", : true, : true, }), new (, , 5, { : "search-categories", : true, }), ], { : true, }, ); }; ``` ## Basic Example The widget in this example uses the [DefaultItem](#api/DefaultItem) component to render each recommendation in a consistent layout. The resulting widget is inserted into the element specified by the`container` field. Values of the recommended items - such as title, image URL, or link URL - are obtained from the API response and accessed via `props.result?.values`. Ensure that [returnProperties: true](/api#recommend-items-to-user-param-returnProperties) is set in the request, and optionally use[includedProperties](/api#recommend-items-to-user-param-includedProperties)to control which item properties are returned. ``` import { , , , , , , , } from "@recombee/quick-search-widget-react"; import "@recombee/quick-search-widget-react/dist/styles.css"; export default () => { return ( < ="flex justify-center p-12"> < ="@container-normal"> < ={} ={} ={3} ="(min-width: 1000px)" ="lg:w-[var(--qs-input-width)] lg:flex lg:justify-center" ={() => ( < ="flex w-[400px] text-[#374040]"> < ={.} ={{ : `Search for "table"...` }} /> )} ={() => ( < {.....} ="flex size-[38px] items-center justify-center rounded-sm bg-[#3bc4a1] text-white" > < /> )} ={() => ( < ="mt-1 flex h-full max-h-full min-h-0 flex-col rounded-sm bg-white text-[#374040] shadow-2xl lg:h-auto lg:max-w-[900px] lg:min-w-[600px]"> {!.. && ( < ="flex items-center gap-2 p-2"> < ="flex-grow"> < ={.} ={{ : `Search for "table"...` }} /> < {.....} ="flex size-[38px] items-center justify-center" > < /> )} < ="flex min-h-0 flex-grow flex-col"> < ="px-4 py-4 pb-2 text-sm font-semibold text-[#3f91ff]"> Results < ="overflow-auto p-2"> {..(0).(() => ( < ={.} ={( .?., ., )} ={ < ="size-16 overflow-hidden rounded-lg" ={`${.?.}`} ={600} ={400} /> } ={.?.} ={.?.} ={`USD ${.?.}`} {....} /> ))} )} /> ); }; ``` ## Custom Template You can customize the appearance and behavior of the Quick Search Widget by overriding its individual components: * [DropdownComponent](#api/DropdownComponent) – Renders the dropdown containing search results. * [InputComponent](#api/InputComponent) – Handles the search input field where users type their queries. * [TriggerComponent](#api/TriggerComponent) – Controls how the widget is opened on mobile devices. The example also demonstrates how to make the search form submittable to a dedicated results page using a `submit` button. ``` import { , , , , , , } from "@recombee/quick-search-widget-react"; import "@recombee/quick-search-widget-react/dist/styles.css"; export default () => { return ( < ="flex justify-center p-12"> < ="@container-normal"> < ={} ={} ={3} ={1000} ="(min-width: 1000px)" ={() => ( < ="GET" ="https://example.com/search" ="_blank" ="flex w-[400px] gap-2 text-[#374040]" > < ="relative flex flex-grow overflow-hidden rounded-lg border border-[#d9dbdb]"> < ="absolute flex size-[38px] items-center justify-center text-[#737979]"> < /> < ="q" ="text" ="block h-[39px] w-full indent-[38px] outline-hidden" ={`Search for "table"...`} {.....} /> {.. && ( < ="rb:absolute rb:top-2.25 rb:right-2.25 rb:h-5 rb:w-5" /> )} < ="submit" ="rounded-lg bg-[#3f91ff] px-5 py-2.5 text-sm font-medium text-white focus:ring-4 focus:ring-blue-300 focus:outline-hidden" > Search )} ={() => ( < {.....} ="flex size-[38px] items-center justify-center rounded-sm bg-[#3bc4a1] text-white" > < /> )} ={() => ( < ="mt-1 flex h-full max-h-full min-h-0 flex-col rounded-sm bg-white text-[#374040] shadow-2xl lg:h-auto lg:max-w-[900px] lg:min-w-[600px]"> {!.. && ( < ="flex items-center gap-2 p-2"> < ="flex-grow"> < ="relative flex flex-grow overflow-hidden rounded-lg border border-[#d9dbdb]"> < ="flex size-[42px] items-center justify-center text-[#737979]"> < /> < ="text" ="block w-full outline-hidden" ="Search in docs..." {.....} /> {.. && ( < ="absolute top-2.5 right-2.5 h-5 w-5 animate-spin rounded-full border-2 border-dashed border-current text-[#d9dbdb] [--animate-spin:spin_3s_linear_infinite]" /> )} < {.....} ="flex size-[38px] items-center justify-center" > < /> )} < ="flex min-h-0 flex-grow flex-col"> < ="px-4 py-4 pb-2 text-sm font-semibold text-[#3f91ff]"> Results < ="overflow-auto p-2"> {..(0).(() => ( < ={.} ={( .?., ., )} {....} ="flex items-center gap-4 rounded-sm p-2 outline-hidden hover:bg-[#f7f7f7] focus:bg-[#f7f7f7]" > <> < ="size-16 overflow-hidden rounded-lg" ={`${.?.}`} ={600} ={400} /> < ="rb:flex-grow"> < ="rb:font-semibold rb:text-nowrap rb:text-ellipsis rb:overflow-hidden"> {.?.} < ="rb:text-[#737979] rb:text-nowrap rb:text-ellipsis rb:overflow-hidden"> {.?.} < ="rb:font-bold rb:text-[#3f91ff] rb:text-nowrap rb:text-ellipsis rb:overflow-hidden">{`USD ${.?.}`} ))} )} /> ); }; ``` ## Multi-Type Search Results You can use the Quick Search Widget to display multiple types of results. For example, showing not only items but also categories or brands using the[Search Item Segments](/api#search-item-segments) requests. All search requests are sent together in a single [Batch](/api#batch)request. ``` import { , , , , , , , } from "@recombee/quick-search-widget-react"; import "@recombee/quick-search-widget-react/dist/styles.css"; const : = ({ }) => { return new ( [ new ("userId", , 5, { : "search", : true, : true, }), new ("userId", , 5, { : "search-brands", : true, }), ], { : true, }, ); }; export default () => { return ( < ="flex justify-center p-12"> < ="@container-normal"> < ={} ={} ={3} ={0} ="(min-width: 1000px)" ="lg:w-[var(--qs-input-width)] lg:flex lg:justify-center" ={() => ( < ="flex w-[400px] text-[#374040]"> < ={.} ={{ : `Search for "table"...` }} /> )} ={() => ( < {.....} ="flex size-[38px] items-center justify-center rounded-sm bg-[#3bc4a1] text-white" > < /> )} ={() => ( < ="mt-1 flex h-full max-h-full min-h-0 flex-col rounded-sm bg-white text-[#374040] shadow-2xl lg:h-auto lg:max-w-[900px] lg:min-w-[600px]"> {!.. && ( < ="flex items-center gap-2 p-2"> < ="flex-grow"> < ={.} ={{ : `Search for "table"...` }} /> < {.....} ="flex size-[38px] items-center justify-center" > < /> )} < ="flex"> < ="flex min-h-0 flex-col"> < ="px-4 py-4 pb-2 text-sm font-semibold text-[#3f91ff]"> Segments < ="overflow-auto p-2"> {..(1).(() => ( < ={.} ={( .?., ., )} {....} ="flex items-center gap-2 rounded-sm p-2 text-nowrap outline-hidden hover:bg-[#f7f7f7] focus:bg-[#f7f7f7]" > < ="flex-grow"> < ="font-semibold">{.} ))} < ="flex min-h-0 min-w-0 flex-grow flex-col"> < ="px-4 py-4 pb-2 text-sm font-semibold text-[#3f91ff]"> Results < ="overflow-y-auto p-2"> {..(0).(() => ( < ={.} ={( .?., ., )} ={ < ="size-16 overflow-hidden rounded-lg" ={`${.?.}`} ={600} ={400} /> } ={.?.} ={.?.} ={`USD ${.?.}`} {....} /> ))} )} /> ); }; ``` ## API Reference const ### QuickSearchWidget Quick Search widget component type ### QuickSearchWidgetProps Quick Search component configuration options #### Properties ##### apiClient ApiClient Instance of Recombee JS API Client. See[Example](#client-initialization). --- ##### createRequest QuickSearchCreateRequestFunction Request factory function. See[Quick Example](#client-initialization) or visit[API Reference](/api) for overview of available requests. --- ##### onRecommResponse WidgetRecommResponseCallback | undefined Callback function allowing to intercept and inspect recommendation request+response made by widget. ``` import React from "react"; import { } from "@recombee/carousel-widget-react"; < // ...ommited code... ={({ , }) => { // use data from request and response for any purpose, i.e. internal tracking }} />; ``` --- ##### initialQuery string | undefined String to be prefilled into the search input --- ##### minSearchCharactersCount number Minimum length of search query for search request to be sent. --- ##### typingDebounceDuration number | undefined Maximum duration between keystrokes in milliseconds before search request is made. --- ##### primaryResultsIndex number | undefined Index of request in a batch from which the results are considered to be navigable by arrow keys. --- ##### InputComponent FC Component responsible for rendering the widget input. --- ##### TriggerComponent FC Component responsible for rendering the widget trigger on mobile devices. --- ##### DropdownComponent FC Component responsible for rendering the widget dropdown. --- ##### className string | undefined Custom classes of widget wrapper element. See[Custom CSS](#custom-css). --- ##### popoverClassName string | undefined Custom classes of popover wrapper element. See[Custom CSS](#custom-css). --- ##### popoverClassNameDisableDefault boolean | undefined Disables default classes of popover wrapper element. There are some default class names with essential styles applied to the popover wrapper element. This setting disables them as an escape hatch for customization. See [Custom CSS](#custom-css). --- ##### desktopMediaQuery string CSS media query specifing when the widget should behave as displayed on desktop. By default, widget behaves as mobile-first, filling entire device screen with results dropdown. --- class ### QuickSearchWidgetState Class exposing quick search widget state for use in custom templates #### Properties ##### isDesktop boolean Indicates that the widget is displayed on desktop device. --- ##### reset () => void Resets the widget to its initial state --- ##### inputProps { value: string; onChange: (event: ChangeEvent) => void; onKeyDown: (event: KeyboardEvent) => void; onClick: () => void; ref: (element: HTMLElement | null) => void; } Properties to be passed to a input component. --- ##### triggerProps { ref: (element: HTMLElement | null) => void; onClick: () => void; } Properties to be passed to the trigger button of a mobile widget. --- ##### closeButtonProps { type: "button"; onClick: () => void; onTouchEnd: () => void; } Properties to be passed to the close button of a mobile dropdown. --- ##### items (index: number) => { key: string; id: string; recommId: string; values: { \[key: string\]: any; }; metadata: {} | undefined; itemProps: { tabIndex: number; "data-search-result-id"?: string | undefined; onKeyDown: (event: KeyboardEvent) => void; }; }\[\] Getter for current results of the request batch. The `index` parameter indicates an index of results in the Batch Request for which to return items. --- ##### isExpanded boolean Boolean flag indicating that the widget dropdown is open. --- ##### isLoading boolean Boolean flag indicating that a request for new results is in flight. --- const ### ItemImage Item image component type ### ItemImageProps Item Image properties #### Properties ##### src string | null | undefined Image URL --- ##### missingImageSrc string | undefined URL of an image to display when the main image could not be loaded. --- ##### className string | undefined Image wrapper class name --- ##### imgClassName string | undefined Image class name --- ##### width number | undefined Image width in pixels --- ##### height number | undefined Image height in pixels --- ##### verticalAlignment "top" | "center" | "bottom" | undefined Image vertical alignment --- ##### horizontalAlignment "center" | "left" | "right" | undefined Image horizontal alignment --- ##### fittingAlgorithm "cover" | "scale\_down" | undefined Image fitting algorithm --- function ### addRecommIdQueryParam Utility function to append `recombee_recomm_id` parameter to an url string. For usage in widget template to construct item link URL.