Skip to content

Commit 785b3cf

Browse files
committed
Release: v6.0.0
- Added support for the new Composite Recommendation endpoint - Added new parameter `autoPresented` for Detail View and View Portion interactions - Added new parameter `timeSpent` for View Portion interactions - Added support for `reqlExpressions` on recommended items
1 parent 879536d commit 785b3cf

20 files changed

+1163
-151
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ https://github.com/recombee/swift-api-client
4646
Alternatively, in `Package.swift`:
4747

4848
```swift
49-
.package(url: "https://github.com/recombee/swift-api-client", from: "5.0.2")
49+
.package(url: "https://github.com/recombee/swift-api-client", from: "6.0.0")
5050
```
5151

5252
Then add to your target dependencies:
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
This file is auto-generated
3+
*/
4+
5+
/// CompositeRecommendationResponse Binding
6+
public struct CompositeRecommendationResponse: RecombeeBinding, Encodable {
7+
public typealias CodingKeys = CompositeRecommendationResponseCodingKeys
8+
9+
/// Id of the composite recommendation request
10+
public let recommId: String
11+
12+
/// Parameters of the source stage
13+
public let source: Recommendation
14+
15+
/// Obtained recommendations
16+
public let recomms: [Recommendation]
17+
18+
/// How many times *Recommend Next Items* have been called for this `recommId`
19+
public var numberNextRecommsCalls: Int?
20+
21+
/// Coding keys for decoding/encoding
22+
public enum CompositeRecommendationResponseCodingKeys: String, CodingKey {
23+
case recommId
24+
case source
25+
case recomms
26+
case numberNextRecommsCalls
27+
}
28+
29+
/// Initializes CompositeRecommendationResponse Binding
30+
/// - Parameters:
31+
/// - recommId: Id of the composite recommendation request
32+
/// - source: Parameters of the source stage
33+
/// - recomms: Obtained recommendations
34+
/// - numberNextRecommsCalls: How many times *Recommend Next Items* have been called for this `recommId`
35+
public init(recommId: String, source: Recommendation, recomms: [Recommendation], numberNextRecommsCalls: Int? = nil) {
36+
self.recommId = recommId
37+
self.source = source
38+
self.recomms = recomms
39+
self.numberNextRecommsCalls = numberNextRecommsCalls
40+
}
41+
42+
/// Initializes a new `CompositeRecommendationResponse` from a decoder
43+
public init(from decoder: Decoder) throws {
44+
let container = try decoder.container(keyedBy: CodingKeys.self)
45+
46+
recommId = try Self.decodeMandatorySimpleField(container, forKey: .recommId)
47+
source = try Self.decodeMandatorySimpleField(container, forKey: .source)
48+
recomms = try Self.decodeMandatorySimpleField(container, forKey: .recomms)
49+
numberNextRecommsCalls = Self.decodeSimpleField(container, forKey: .numberNextRecommsCalls)
50+
}
51+
}

Sources/RecombeeClient/Bindings/CompositeRecommendationStageParameters.swift

Lines changed: 382 additions & 0 deletions
Large diffs are not rendered by default.

Sources/RecombeeClient/Bindings/Logic.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ public struct Logic: RecombeeBinding, Encodable {
77
public typealias CodingKeys = LogicCodingKeys
88

99
/// Name of the logic that should be used
10-
public let name: String
10+
public var name: String?
1111

1212
/// Parameters passed to the logic
1313
public var settings: JSONDictionary?
@@ -22,7 +22,7 @@ public struct Logic: RecombeeBinding, Encodable {
2222
/// - Parameters:
2323
/// - name: Name of the logic that should be used
2424
/// - settings: Parameters passed to the logic
25-
public init(name: String, settings: JSONDictionary? = nil) {
25+
public init(name: String? = nil, settings: JSONDictionary? = nil) {
2626
self.name = name
2727
self.settings = settings
2828
}
@@ -31,7 +31,7 @@ public struct Logic: RecombeeBinding, Encodable {
3131
public init(from decoder: Decoder) throws {
3232
let container = try decoder.container(keyedBy: CodingKeys.self)
3333

34-
name = try Self.decodeMandatorySimpleField(container, forKey: .name)
34+
name = Self.decodeSimpleField(container, forKey: .name)
3535
settings = Self.decodeJSONField(container, forKey: .settings)
3636
}
3737
}

Sources/RecombeeClient/Bindings/Recommendation.swift

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,29 @@ public struct Recommendation: RecombeeBinding, Encodable {
1212
/// Property values of the recommended item
1313
public var values: JSONDictionary?
1414

15+
/// Dictionary of evaluated ReQL expressions specified in the request and calculated for the recommended item.
16+
/// The keys are the names of the ReQL expressions, and the values are the results of the evaluations.
17+
18+
public var reqlEvaluations: JSONDictionary?
19+
1520
/// Coding keys for decoding/encoding
1621
public enum RecommendationCodingKeys: String, CodingKey {
1722
case id
1823
case values
24+
case reqlEvaluations
1925
}
2026

2127
/// Initializes Recommendation Binding
2228
/// - Parameters:
2329
/// - id: Id of the recommended item
2430
/// - values: Property values of the recommended item
25-
public init(id: String, values: JSONDictionary? = nil) {
31+
/// - reqlEvaluations: Dictionary of evaluated ReQL expressions specified in the request and calculated for the recommended item.
32+
/// The keys are the names of the ReQL expressions, and the values are the results of the evaluations.
33+
34+
public init(id: String, values: JSONDictionary? = nil, reqlEvaluations: JSONDictionary? = nil) {
2635
self.id = id
2736
self.values = values
37+
self.reqlEvaluations = reqlEvaluations
2838
}
2939

3040
/// Initializes a new `Recommendation` from a decoder
@@ -33,5 +43,6 @@ public struct Recommendation: RecombeeBinding, Encodable {
3343

3444
id = try Self.decodeMandatorySimpleField(container, forKey: .id)
3545
values = Self.decodeJSONField(container, forKey: .values)
46+
reqlEvaluations = Self.decodeJSONField(container, forKey: .reqlEvaluations)
3647
}
3748
}

Sources/RecombeeClient/Requests/AddDetailView.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ public struct AddDetailView: Request {
2929
/// A dictionary of additional data for the interaction.
3030
public var additionalData: JSONDictionary? = nil
3131

32+
/// 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`.
33+
public var autoPresented: Bool? = nil
34+
3235
/// Initializes AddDetailView request
3336
/// - Parameters:
3437
/// - userId: User who viewed the item
@@ -38,14 +41,16 @@ public struct AddDetailView: Request {
3841
/// - cascadeCreate: Sets whether the given user/item should be created if not present in the database.
3942
/// - recommId: If this detail view is based on a recommendation request, `recommId` is the id of the clicked recommendation.
4043
/// - additionalData: A dictionary of additional data for the interaction.
41-
public init(userId: String, itemId: String, timestamp: Date? = nil, duration: Int? = nil, cascadeCreate: Bool? = true, recommId: String? = nil, additionalData: JSONDictionary? = nil) {
44+
/// - autoPresented: 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`.
45+
public init(userId: String, itemId: String, timestamp: Date? = nil, duration: Int? = nil, cascadeCreate: Bool? = true, recommId: String? = nil, additionalData: JSONDictionary? = nil, autoPresented: Bool? = nil) {
4246
self.userId = userId
4347
self.itemId = itemId
4448
self.timestamp = timestamp
4549
self.duration = duration
4650
self.cascadeCreate = cascadeCreate
4751
self.recommId = recommId
4852
self.additionalData = additionalData
53+
self.autoPresented = autoPresented
4954
}
5055

5156
/// The API path for the request
@@ -92,6 +97,10 @@ public struct AddDetailView: Request {
9297
body["additionalData"] = additionalData
9398
}
9499

100+
if let autoPresented = autoPresented {
101+
body["autoPresented"] = autoPresented
102+
}
103+
95104
return body
96105
}
97106
}
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/*
2+
This file is auto-generated
3+
*/
4+
5+
import Foundation
6+
7+
/// Composite Recommendation returns both a *source entity* (e.g., an Item or [Item Segment](https://docs.recombee.com/segmentations.html)) and a list of related recommendations in a single response.
8+
/// It is ideal for use cases such as personalized homepage sections (*Articles from <category>*), *Because You Watched <movie>*, or *Artists Related to Your Favorite Artist <artist>*.
9+
/// See detailed **examples and configuration guidance** in the [Composite Scenarios documentation](https://docs.recombee.com/scenarios#composite-recommendations).
10+
/// **Structure**
11+
/// The endpoint operates in two stages:
12+
/// 1. Recommends the *source* (e.g., an Item Segment or item) to the user.
13+
/// 2. Recommends *results* (items or Item Segments) related to that *source*.
14+
/// For example, *Articles from <category>* can be decomposed into:
15+
/// - [Recommend Item Segments To User](https://docs.recombee.com/api#recommend-item-segments-to-user) to find the category.
16+
/// - [Recommend Items To Item Segment](https://docs.recombee.com/api#recommend-items-to-item-segment) to recommend articles from that category.
17+
/// 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.
18+
/// Each *Composite Recommendation* counts as a single recommendation API request for billing.
19+
/// **Stage-specific Parameters**
20+
/// 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).
21+
/// In the example above:
22+
/// - `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`).
23+
/// - `resultSettings` may include any parameter valid for [Recommend Items To Item Segment](https://docs.recombee.com/api#recommend-items-to-item-segment).
24+
/// See [this example](https://docs.recombee.com/api#composite-recommendation-example-setting-parameters-for-individual-stages) for more details.
25+
public struct CompositeRecommendation: Request {
26+
public typealias Response = CompositeRecommendationResponse
27+
28+
/// Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing".
29+
/// 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.
30+
/// 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.
31+
32+
public let scenario: String
33+
34+
/// Number of items to be recommended (N for the top-N recommendation).
35+
36+
public let count: Int
37+
38+
/// ID of the item for which the recommendations are to be generated.
39+
40+
public var itemId: String? = nil
41+
42+
/// ID of the user for which the recommendations are to be generated.
43+
44+
public var userId: String? = nil
45+
46+
/// Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case.
47+
/// See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details.
48+
/// The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users.
49+
/// Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com).
50+
51+
public var logic: Logic? = nil
52+
53+
/// ID of the segment from `contextSegmentationId` for which the recommendations are to be generated.
54+
55+
public var segmentId: String? = nil
56+
57+
/// 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.
58+
59+
public var cascadeCreate: Bool? = true
60+
61+
/// Parameters applied for recommending the *Source* stage. The accepted parameters correspond with the recommendation sub-endpoint used to recommend the *Source*.
62+
63+
public var sourceSettings: CompositeRecommendationStageParameters? = nil
64+
65+
/// Parameters applied for recommending the *Result* stage. The accepted parameters correspond with the recommendation sub-endpoint used to recommend the *Result*.
66+
67+
public var resultSettings: CompositeRecommendationStageParameters? = nil
68+
69+
/// Dictionary of custom options.
70+
71+
public var expertSettings: JSONDictionary? = nil
72+
73+
/// Initializes CompositeRecommendation request
74+
/// - Parameters:
75+
/// - scenario: Scenario defines a particular application of recommendations. It can be, for example, "homepage", "cart", or "emailing".
76+
/// 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.
77+
/// 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.
78+
/// - count: Number of items to be recommended (N for the top-N recommendation).
79+
/// - itemId: ID of the item for which the recommendations are to be generated.
80+
/// - userId: ID of the user for which the recommendations are to be generated.
81+
/// - logic: Logic specifies the particular behavior of the recommendation models. You can pick tailored logic for your domain and use case.
82+
/// See [this section](https://docs.recombee.com/recommendation_logics) for a list of available logics and other details.
83+
/// The difference between `logic` and `scenario` is that `logic` specifies mainly behavior, while `scenario` specifies the place where recommendations are shown to the users.
84+
/// Logic can also be set to a [scenario](https://docs.recombee.com/scenarios) in the [Admin UI](https://admin.recombee.com).
85+
/// - segmentId: ID of the segment from `contextSegmentationId` for which the recommendations are to be generated.
86+
/// - cascadeCreate: 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.
87+
/// - sourceSettings: Parameters applied for recommending the *Source* stage. The accepted parameters correspond with the recommendation sub-endpoint used to recommend the *Source*.
88+
/// - resultSettings: Parameters applied for recommending the *Result* stage. The accepted parameters correspond with the recommendation sub-endpoint used to recommend the *Result*.
89+
/// - expertSettings: Dictionary of custom options.
90+
91+
public init(scenario: String, count: Int, itemId: String? = nil, userId: String? = nil, logic: Logic? = nil, segmentId: String? = nil, cascadeCreate: Bool? = true, sourceSettings: CompositeRecommendationStageParameters? = nil, resultSettings: CompositeRecommendationStageParameters? = nil, expertSettings: JSONDictionary? = nil) {
92+
self.scenario = scenario
93+
self.count = count
94+
self.itemId = itemId
95+
self.userId = userId
96+
self.logic = logic
97+
self.segmentId = segmentId
98+
self.cascadeCreate = cascadeCreate
99+
self.sourceSettings = sourceSettings
100+
self.resultSettings = resultSettings
101+
self.expertSettings = expertSettings
102+
}
103+
104+
/// The API path for the request
105+
public var path: String { "/recomms/composite/" }
106+
107+
/// The HTTP method used to send the request
108+
public var method: HTTPMethod { .POST }
109+
110+
/// Timeout interval in seconds.
111+
public var timeout: TimeInterval = 3.0
112+
113+
/// Whether to enforce HTTPS for this request.
114+
public var ensureHttps: Bool { false }
115+
116+
/// Query parameters to be included in the URL
117+
public var queryParameters: [String: Any]? {
118+
return [:]
119+
}
120+
121+
/// The body of the request as a dictionary
122+
public var bodyParameters: [String: Any]? {
123+
var body: [String: Any] = [
124+
"scenario": scenario,
125+
"count": count,
126+
]
127+
128+
if let itemId = itemId {
129+
body["itemId"] = itemId
130+
}
131+
132+
if let userId = userId {
133+
body["userId"] = userId
134+
}
135+
136+
if let logic = logic {
137+
body["logic"] = logic
138+
}
139+
140+
if let segmentId = segmentId {
141+
body["segmentId"] = segmentId
142+
}
143+
144+
if let cascadeCreate = cascadeCreate {
145+
body["cascadeCreate"] = cascadeCreate
146+
}
147+
148+
if let sourceSettings = sourceSettings {
149+
body["sourceSettings"] = sourceSettings
150+
}
151+
152+
if let resultSettings = resultSettings {
153+
body["resultSettings"] = resultSettings
154+
}
155+
156+
if let expertSettings = expertSettings {
157+
body["expertSettings"] = expertSettings
158+
}
159+
160+
return body
161+
}
162+
}

Sources/RecombeeClient/Requests/MergeUsers.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import Foundation
66

77
/// 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.
88
/// 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**.
9+
/// By default, the *Merge Users* request is only available from server-side integrations for security reasons, to prevent potential abuse.
10+
/// 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.
911
public struct MergeUsers: Request {
1012
public typealias Response = StringResponseBinding
1113

0 commit comments

Comments
 (0)