Recommendations Customization
Overview
Luigi’s Box Recommendations Customizations API allows you to manually override the automated recommendation algorithms. You can promote specific items (upsell), enforce brand consistency, or curate seasonal collections by "pinning" items to specific positions in the result set.
To use this feature, a recommender must be initialized. See Recommender API for more details.
Important We strongly recommend using the Luigi's Box App UI instead of this API. Manage customizations easily at https://app.luigisbox.com/sites/{TRACKER_ID}/setup/recommendations_customization. It allows you to customize the recommendations with no programming effort.
Core Concepts
To effectively use this API, you must understand the relationship between the following components:
- Customization (Scope): This represents the Context or the Trigger. It defines when a set of rules should apply. For example, "Only apply these rules when the user is looking at a Fender Guitar" or "Apply these rules to the Basket page."
- Pin: This represents the Action or the Result. It defines what items should appear. For example, "Show this specific guitar strap in position 1."
- Target: The specific rule used to trigger the Customization (e.g., a specific Item ID or a Category).
graph TD
Tracker[Tracker / Store] --> Model[Recommender Model e.g. Basket]
Model --> Cust1[Customization 1: Target Item A]
Model --> Cust2[Customization 2: Target Brand Nike]
Cust1 --> Pin1[Pin: Show Item X at Pos 1]
Cust1 --> Pin2[Pin: Show Item Y at Pos 2]
Cust2 --> Pin3[Pin: Show Item Z at Pos 1]
style Tracker fill:#f9f,stroke:#333,stroke-width:2px
style Model fill:#bbf,stroke:#333,stroke-width:2px
style Cust1 fill:#dfd,stroke:#333,stroke-width:2px
style Cust2 fill:#dfd,stroke:#333,stroke-width:2px
1. Defining the Scope (The "When")
Every customization is attached to a specific Recommender Model (e.g., basket, product_detail). Within that model, you can define Target Types to control specificity.
Scope Priority
When a recommendation request matches multiple customizations, the Priority determines which one wins:
- Item Target (Highest): Matches a specific Item ID (e.g., "User is viewing Product A").
- Criteria Target: Matches item attributes (e.g., "User is viewing any item where Brand is Nike").
- All (Lowest): Applies globally to the model (e.g., "Always apply on the Homepage").
The Customization Object
The Customization Object (often referred to as the "Scope") is the parent container. It holds the target definition and the list of pins.
| Field | Type | Required | Description |
id |
UUID | Read-only | Unique identifier. |
model |
String | Yes | Recommender model name (e.g., basket). |
target_type |
String | Yes |
item, criteria, or all. |
target_identity |
String | Cond. | The item ID (ID) if target_type is item. |
target_criteria |
Object | Cond. | The Criteria Object if target_type is criteria. |
tags |
Array | No | List of organizational tags. |
pin_definitions |
Array | Yes | List of Pin Objects. |
creator |
String | Read-only | User who created the customization. |
Examples
Target: Item
{
"id": "199620b4-...",
"model": "basket",
"target_type": "item",
"target_identity": "/p/123",
"tags": ["guitar"],
"pin_definitions": [ ... ]
}
Target: Criteria
{
"id": "199620b4-...",
"model": "basket",
"target_type": "criteria",
"target_criteria": {
"attribute": "brand",
"operator": "in",
"values": ["Fender"]
},
"pin_definitions": [ ... ]
}
Target: All
{
"id": "199620b4-...",
"model": "basket",
"target_type": "all",
"pin_definitions": [ ... ]
}
2. Defining the Pins (The "What")
Once a Customization is triggered, the Pins determine which items are injected into the results.
Pin Types
- Item Pin: Injects a specific product ID.
- Criteria Pin: Injects items that match specific metadata (e.g., "Any item that is Red"). Note: This is computationally expensive.
Pin Behavior and Positioning
- Regular (position: N): Forces the item into the Nth slot (1-based index).
- Global (position: -1): Attempts to pin the item in every position (usually used with Criteria pins to flood results).
- Block (position: 0): Acts as a Blacklist. Prevents the defined item or criteria from appearing in the recommendations.
The Pin Object
| Field | Type | Required | Description |
position |
Integer | Yes | 1-based index. Use -1 for Global, 0 for Block. |
pin_type |
String | Yes |
item or criteria. |
pin_identity |
String | Cond. | Item ID if pin_type is item. |
pin_criteria |
Object | Cond. | Criteria Object if pin_type is criteria. |
active_from |
Date | No | ISO 8601 Start date. |
active_to |
Date | No | ISO 8601 End date. |
is_block_pin |
Boolean | No | If true, excludes matching items. |
Examples
Pin Type: Item
{
"position": 1,
"pin_type": "item",
"pin_identity": "/p/234",
"active_from": "2025-01-22T08:49:58Z",
"is_block_pin": false
}
Pin Type: Criteria
{
"position": 4,
"pin_type": "criteria",
"pin_criteria": {
"attribute": "color",
"operator": "in",
"values": ["red"]
}
}
3. Resolving Collisions
Because multiple customizations can target the same context, conflicts can occur. The system resolves them using a Priority Selection & Shifting strategy.
flowchart TD
Start{Conflict Detected?}
Start -- No --> Apply[Apply Pin normally]
Start -- Yes --> Type{Collision Type}
Type -- Same Position --> Select[Select Pins with Highest Priority]
Select --> Order[Order by Recency]
Order --> Return[Return Selected & Shift Downstream Pins]
Type -- Duplicate Item --> LocCheck{Same Scope?}
LocCheck -- Yes --> MinPos[Use Minimum Position]
LocCheck -- No --> HighScope[Use Pin from Higher Priority Scope]
Type -- Block vs Regular --> BlockScope{Regular Pin Scope Priority > Block Scope Priority?}
BlockScope -- Yes --> RegularWins[Regular Pin Overrides Block]
BlockScope -- No --> BlockWins[Item is Blocked & Removed]
Scenario A: Collision on Position
Situation:
- Pins A & B (High Priority, e.g., Item Scope) want Position 2.
- Pin C (Low Priority, e.g., Criteria Scope) also wants Position 2.
- Pin X (Any Priority) wants Position 3.
Resolution:
- Select Winner: The system selects only the pins with the highest priority (Pins A & B). Pin C is ignored completely because it lost the priority battle for Position 2.
- Order Winners: A and B are ordered by recency (e.g., input order).
- Shift Downstream: Because A and B now occupy Position 2 and 3, the original Pin X (which wanted Position 3) is pushed down to Position 4.
Result:
- Pos 2: Pin A
- Pos 3: Pin B
- Pos 4: Pin X (Shifted)
- (Pin C is discarded).
Scenario B: Duplicates
Situation: The same item is pinned in multiple places.
Resolution:
- Same Scope: The item appears at the minimum (lowest number) position defined.
- Different Scopes: The pin from the highest priority scope is respected.
Scenario C: Block vs. Regular
Situation: One rule says "Show Item A", another says "Block Item A".
Resolution: The Regular pin overrides the Block pin only if its scope has a higher priority. Otherwise, the Block pin wins, and the item is completely excluded from the recommendation results.
4. Advanced Logic: The Criteria Object
The Criteria Object allows defining complex rules using logic (and, or, not) and attribute comparisons. It is used in target_criteria (Customization) and pin_criteria (Pin).
Structure
The top level must be a Logical operator or an Attribute condition.
1. Logical Criteria
Combines multiple criteria using boolean logic.
| Field | Type | Description |
operator |
String |
and, or, not (unary). |
criteria |
Array | List of nested criteria objects. |
Example:
{
"operator": "or",
"criteria": [
{
"attribute": "color",
"operator": "in",
"values": ["red", "black"]
},
{
"operator": "and",
"criteria": [
{
"attribute": "gender",
"operator": "in",
"values": ["woman", "unisex"]
},
{
"attribute": "size",
"operator": "lte",
"values": [38]
}
]
}
]
}
2. Attribute Criteria
Basic criteria comparing item attributes to static values.
| Field | Description |
attribute |
The name of the attribute (e.g., brand). |
operator |
Comparison operation. |
values |
List of values to match against. |
condition |
Optional dynamic condition (see below). |
transformation |
Optional value transformation (see below). |
Supported Operators:
| Type | Operators |
| Text/Boolean |
in, not_in, all_of, exists, not_exists
|
| Numeric/Date |
lt, lte, gt, gte
|
Example:
{
"attribute": "color",
"operator": "in",
"values": ["red", "black"]
}
3. Type Criteria
Matches specific item types (product, variant, query, category, article).
| Field | Description |
operator |
in, not_in
|
values |
List of types (e.g., ["product", "variant"]). |
condition |
Optional dynamic condition. |
Criteria Condition (Dynamic)
Allows comparing an attribute against a value derived from the current context (e.g., "Recommend items with the same brand as the current item").
| Field | Description |
left_attribute |
Attribute name to use for validation. |
left_value |
Placeholder referencing which part of the attribute to use (e.g., @same). |
operator |
Supported operators: in, not_in, all_of, exists, not_exists (text/boolean); lt, lte, gt, gte, between, eq, neq (numeric/date). |
right_values |
Values to match against the left side. |
transformation |
Optional value transformation (see below). |
Supported left_value placeholders:
-
@same: Exact value of the attribute. -
@same_first,@same_last: First or last value of a list. -
@same_second,@same_third: Second or third value of a list. -
@same_first_two,@same_first_three: First two or three values of a list. -
@same_second_and_later,@same_third_and_later: All values from the second or third onward. -
@same_but_last: All values except the last. -
*_main_only: Suffix to target only the first list in multidimensional attributes (e.g.,@same_first_main_only).
Example:
{
"left_attribute": "_category",
"left_value": "@same",
"operator": "in",
"right_values": ["Shoes"]
}
Transformations
Transforms the value before comparison.
| Field | Type | Required | Description |
function |
String | ✓ | The operation to perform (e.g., +, *). |
value |
Number | The argument for the function (e.g., 42, -0.8). |
Supported Functions:
-
Numeric:
-
+: Add thevalueto the original number. -
*: Multiply the original number by thevalue.
-
-
Date:
-
+: Addvalue(in days) to the original date.
-
-
Text/Array:
-
length: Count the characters or array items. (Novaluerequired). Example:
-
{
"function": "+",
"value": -5
}