← Files WixARCHIVED FILE
skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md
25.8 KB · Oct 3, 2026 · 06:02 UTC
---
name: "Recommend: eCommerce Strategy"
description: Unified eCommerce recommendation skill — analyzes site data across ALL domains (discounts, shipping, and future domains) and generates up to 5 actionable recommendations. Single entry point for any "help my business" request. Tracking is built-in.
layer: R
references:
- name: "API: Recommendation Tracking"
path: ecommerce/api-recommendation-tracking.md
load: false
- name: "Goal: Increase AOV"
path: ecommerce/goal-increase-aov.md
load: false
- name: "Goal: Clear Inventory"
path: ecommerce/goal-clear-inventory.md
load: false
- name: "Goal: Seasonal Revenue"
path: ecommerce/goal-seasonal-revenue.md
load: false
- name: "Goal: Drive Cross-Sells"
path: ecommerce/goal-drive-cross-sells.md
load: false
- name: "Goal: Reduce Cart Abandonment"
path: ecommerce/goal-reduce-cart-abandonment.md
load: false
- name: "Setup: Coupons"
path: ecommerce/setup-coupons.md
load: false
---
# Recommend: eCommerce Strategy
>
> **After classifying domains in Step 4b**, load the matching goal skill with `ReadFullDocsArticle`:
> - **SEASONAL** → [Goal: Seasonal Revenue](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-seasonal-revenue)
> - **UPSELL_BOOST** / **SHIPPING** → [Goal: Increase AOV](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-increase-aov) (includes both discount and shipping flows)
> - **STOCK_MOVER** → [Goal: Clear Inventory](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-clear-inventory)
> - **BUNDLE_AND_SAVE** → [Goal: Drive Cross-Sells](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-drive-cross-sells)
> - **ABANDONED_CART** → [Goal: Reduce Cart Abandonment](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-reduce-cart-abandonment)
>
> **If COUPON mechanism in Step 4c**, load:
> - [Setup: Coupons](https://dev.wix.com/docs/api-reference/business-solutions/coupons)
## EXECUTION RULES — READ BEFORE ANYTHING ELSE
**You are an operator, not a consultant.** When this recipe is activated:
1. **Do NOT ask clarifying questions — start executing immediately from Step 1.** The merchant's request contains enough information. The analysis steps will determine which domains and strategies apply.
2. **Do NOT produce recommendations before calling the mandatory APIs.** If you skip the API calls and generate advice from assumptions, your output is wrong — even if it sounds reasonable.
3. **Execute every step in order.** Do not skip steps. Do not merge steps. Do not answer "in the meantime."
4. **Use ONLY data returned by API calls.** Never substitute reasoning, general knowledge, or doc summaries for live data. Every number you cite in `reasoning` MUST come directly from an API response — do NOT assume, infer, or fabricate data.
5. **If a call fails or is blocked, report the exact blocker.** Do not work around it with assumptions.
6. **All API calls use `CallWixSiteAPI`.** The internal tool names (getSiteData, getCatalogAnalytics, etc.) are NOT directly callable.
7. **Generate recommendations across ALL relevant domains** — not just discounts. Consider shipping, discounts, and any other domain that the data supports.
---
## Step 1: Resolve the target site
**MANDATORY — do this first.**
If you don't already have a `siteId`, call `ListWixSites` to find it.
If the merchant mentioned a site name, match it. If only one site exists, auto-select it. Store the `siteId` — every subsequent API call requires it.
**Do not proceed without a siteId.**
---
## Step 2: Load recommendation history (Tracking)
**MANDATORY — do NOT skip unless the user said `SKIP_TRACKING` or "don't track".**
Query the tracking database for existing recommendations on this site:
```
CallWixSiteAPI(
url: "https://manage.wix.com/_api/agentic-recommendations/v1/agentic-recommendations/query",
method: "POST",
body: { "query": { "filter": {}, "cursorPaging": { "limit": 50 } } }
)
```
**Use the returned history to inform your analysis:**
| State | How to use it |
|---|---|
| `PROPOSED` | Don't re-propose — ask about the pending one |
| `DONE` | Don't re-propose — consider complementary recommendations |
| `REJECTED` | Do NOT re-propose. If `rejectionPermanent` is true, never suggest this action type again |
| `FAILED` | Offer to retry or suggest alternative |
| `EXPIRED` | Can re-propose if still relevant with fresh data |
If the query returns empty results or fails, continue — this is a fresh session.
---
## Step 3: Gather site data
**MANDATORY API CALL — do not skip.**
```
CallWixSiteAPI(
url: "https://www.wix.com/wix-profile-client/v4/profile/metasite",
method: "POST",
body: {
"fields": [
"language",
"merchant_business_country",
"suggested_main_industry",
"suggested_sub_industry",
"last_30_days_distinct_visitors",
"last_30_days_orders_count",
"online_gpv_last_30_days",
"payment_currency"
]
}
)
```
**Available fields:**
| Field ID | Type | Description | Used for |
|---|---|---|---|
| `language` | STRING | Wix site language code | Locale-aware recommendations |
| `merchant_business_country` | STRING | Merchant's business country (ISO alpha-2) | Holiday detection, region analysis, shipping |
| `suggested_main_industry` | STRING | Dominant industry in last 30 days (user growth model) | Domain classification, goal selection |
| `suggested_sub_industry` | STRING | Dominant sub-industry in last 30 days | Domain classification |
| `last_30_days_distinct_visitors` | LONG | Distinct visitors in last 30 days (incl. app sessions) | Traffic-based thresholds |
| `last_30_days_orders_count` | LONG | Order count in last 30 days | AOV calculation, goal selection |
| `online_gpv_last_30_days` | LONG | Online Gross Payment Volume in last 30 days (site currency units) | Revenue analysis, AOV calculation |
| `payment_currency` | STRING | Store payment currency code (ISO-4217) | Discount/shipping amount formatting |
**Response shape** — each field is a nested object; missing fields = no data for this site:
```json
{
"metaSiteId": "<msid>",
"fields": {
"language": { "aSingleValue": { "aString": "en-US" } },
"merchant_business_country": { "aSingleValue": { "aString": "US" } },
"payment_currency": { "aSingleValue": { "aString": "USD" } },
"last_30_days_orders_count": { "aSingleValue": { "aLong": "2141" } },
"online_gpv_last_30_days": { "aSingleValue": { "aLong": "526550" } }
}
}
```
Extracting values:
- String: `fields.<name>.aSingleValue.aString`
- Number: `fields.<name>.aSingleValue.aLong` — **returned as a JSON string, parse to int before arithmetic**
**Derived value:** `aov = parseInt(online_gpv_last_30_days) / parseInt(last_30_days_orders_count)` — in `payment_currency` units
**Currency rule:** All monetary values (`online_gpv_last_30_days`, `aov`, discount thresholds, shipping amounts) are in the site's `payment_currency`. Never assume USD. Always display and compute amounts using `payment_currency`.
**STOP if `merchant_business_country`, `suggested_main_industry`, or `online_gpv_last_30_days` are missing or null.** Report: "Cannot generate recommendations — missing required site data: {fields}."
---
## Step 3b: Validate the request
Check if the merchant's request includes anything unsupported. **Reject** these:
| Unsupported request | Response |
|---|---|
| Buy one get one (BOGO) | Explain: not supported by Discount Rules API |
| Fixed-price bundles ("3 for $100") | Explain: requires custom pricing logic |
| Unrelated to eCommerce | Decline politely |
If valid, continue.
---
## Step 4: Identify applicable domains
Based on the merchant's request AND the site data, determine which domains to analyze. **Multiple domains can be active simultaneously.**
| Domain | When to activate | Data signals |
|---|---|---|
| **DISCOUNTS** | Merchant mentions sales, promotions, revenue, AOV, clearance, holidays, coupons. **Also activate if no specific domain is mentioned** (default). | Always — site data contains discount metrics |
| **SHIPPING** | Merchant mentions shipping, delivery, checkout conversion, cart abandonment. **Also activate proactively** if site data suggests shipping issues. | High visitors + low orders may indicate shipping friction |
| **ABANDONED_CART** | Activate proactively if site data shows abandoned carts with no active recovery automation. No merchant trigger needed — detect from data. | `currentDiscounts` empty or no cart recovery automation visible |
**Priority rule**: If the merchant mentions a specific holiday/event/date, the DISCOUNTS domain MUST use the **SEASONAL** strategy — even if other signals like "boost sales" or "increase revenue" could match other goals. Holidays are time-sensitive and take priority over general intent.
**If the request is generic** (e.g., "boost my sales", "help my business"), **activate ALL domains**. The best recommendations will come from analyzing every angle.
**If the request targets a specific domain** (e.g., "give me a coupon", "fix my shipping rates", "set up a gift card"), **activate ONLY that domain**. Do not generate cross-domain recommendations — focus all 5 recommendation slots on the requested domain. The merchant asked for something specific; respect that focus.
---
## Step 4b: Load domain-specific goal skills
**MANDATORY — load the matching goal skill(s) now using `ReadFullDocsArticle`.** These contain detailed strategy logic, KPIs, margin tiers, campaign window calculations, and guardrails that you MUST follow.
**For DISCOUNTS domain — classify the discount goal and load it:**
| Discount goal | Trigger | Load this skill |
|---|---|---|
| SEASONAL | Holiday/event/date mentioned | [Goal: Seasonal Revenue](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-seasonal-revenue) |
| UPSELL_BOOST | "increase AOV", "spend more", "upsell" | [Goal: Increase AOV](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-increase-aov) |
| STOCK_MOVER | "clear inventory", "overstock", "clearance" | [Goal: Clear Inventory](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-clear-inventory) |
| BUNDLE_AND_SAVE | "bundle", "cross-sell", "buy together" | [Goal: Drive Cross-Sells](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-drive-cross-sells) |
| Generic (no clear goal) | "boost sales", ambiguous | Default to SEASONAL if holiday nearby, else UPSELL_BOOST |
**For SHIPPING domain — load the same goal as discounts.** Shipping flows (free shipping threshold, rate optimization) serve the same business goals as discount flows. Load the matching discount goal above — it now includes shipping flow references.
**For ABANDONED_CART domain — load the cart abandonment goal:**
[Goal: Reduce Cart Abandonment](https://dev.wix.com/docs/api-reference/business-solutions/e-commerce/skills/goal-reduce-cart-abandonment)
**The goal skill will instruct you to load flow and guardrail skills** — follow those instructions. This chain provides the detailed execution logic you need for high-quality recommendations.
**Do NOT skip this step.** The goal/flow/guardrail skills contain critical constraints (margin tiers, campaign windows, conflict checks) that prevent bad recommendations.
---
## Step 4c: Determine mechanism — Automatic Discount or Coupon
**Only for DISCOUNTS domain. Skip if DISCOUNTS is not active.**
| Merchant says | Mechanism |
|---|---|
| "sale", "promotion", "discount for everyone" | **AUTOMATIC** |
| "coupon", "code", "promo code", "voucher" | **COUPON** |
| "discount for subscribers", "influencer code" | **COUPON** |
| Unclear | **Ask the merchant** |
**If unclear, ask:** "Would you like this to apply automatically to everyone, or as a coupon code?"
**If COUPON is selected**, load the coupon setup reference with `ReadFullDocsArticle`:
[Setup: Coupons](https://dev.wix.com/docs/api-reference/business-solutions/coupons)
---
## Step 5: Analyze catalog
**Permission**: `ecom:discounts_recommendations:v1:recommendation:build_recommendation`
Call both APIs concurrently:
### Call 1: GetCatalogAnalytics
```
CallWixSiteAPI(
url: "https://manage.wix.com/recommendations/v1/recommendations/get-catalog-analytics-tool",
method: "POST",
body: {
"aggregates": <see table below>,
"minMarginPct": 0.15
}
)
```
Valid `aggregates` values: `op` ∈ `count|sum|avg|min|max|stddev|quantiles` · `field` ∈ `quantity|price|cost|profit|profitMargin|ordersCount` · `q` required only for `quantiles` (array of 0.0–1.0, max 20)
**Aggregates by goal:**
| Goal | `aggregates` array |
|---|---|
| UPSELL_BOOST | `[{"op":"count","field":"price"}, {"op":"quantiles","field":"price","q":[0.5,0.75,0.9]}, {"op":"avg","field":"profitMargin"}]` |
| BUNDLE_AND_SAVE | `[{"op":"min","field":"price"}, {"op":"max","field":"price"}, {"op":"avg","field":"profitMargin"}, {"op":"count","field":"price"}]` |
| STOCK_MOVER | `[{"op":"sum","field":"quantity"}, {"op":"sum","field":"ordersCount"}, {"op":"avg","field":"profitMargin"}]` |
| SEASONAL | `[{"op":"sum","field":"ordersCount"}, {"op":"quantiles","field":"price","q":[0.5,0.9]}, {"op":"avg","field":"profitMargin"}]` |
| SHIPPING | `[{"op":"count","field":"price"}, {"op":"quantiles","field":"price","q":[0.5,0.75]}, {"op":"avg","field":"profitMargin"}]` |
**Response shape:**
```json
{
"categoryGroups": [
{
"categoryName": "Electronics",
"fields": {
"count()": 45,
"quantiles([0.5,0.75,0.9],price)": [
{ "quantile": 0.5, "value": 89.99 },
{ "quantile": 0.75, "value": 149.99 }
],
"avg(profitMargin)": 0.42
}
},
{ "categoryName": "All Products", "fields": { "count()": 120, "avg(profitMargin)": 0.35 } }
]
}
```
**Important**: Use "All Products" only for overall catalog stats. Exclude it from category-level analysis.
### Call 2: GetProductCatalogData
```
CallWixSiteAPI(
url: "https://manage.wix.com/recommendations/v1/recommendations/get-product-catalog-data-tool",
method: "POST",
body: {
"businessGoal": "<goal from Step 4>",
"minMarginPct": 0.15,
"catalogLimit": 30,
"query": "<keywords from merchant request, or empty string>",
"categoryNames": <category names if mentioned, or empty array>
}
)
```
**Sort order applied server-side by `businessGoal`:**
| Goal | Sort order |
|---|---|
| UPSELL_BOOST | price DESC, ordersCount DESC |
| BUNDLE_AND_SAVE | price DESC, ordersCount DESC |
| STOCK_MOVER | quantity DESC, ordersCount ASC |
| SEASONAL / SHIPPING | ordersCount DESC |
**Response shape:**
```json
{
"items": [
{
"id": "product-uuid",
"name": "Premium Headphones",
"quantity": 85,
"price": 149.99,
"profit": 67.50,
"profitMargin": 0.45,
"ordersCount": 23
}
]
}
```
`price` and `profit` are in `payment_currency` units. `id` is the product UUID — use for `productIds` in rules.
### Step 5b: Convert category names to GUIDs (if using CATEGORY scope)
**MANDATORY before outputting any categoryIds.** Never output category names as IDs.
**Send only categories you plan to target — max 10 per call.**
```
CallWixSiteAPI(
url: "https://manage.wix.com/recommendations/v1/recommendations/get-category-ids-tool",
method: "POST",
body: { "categoryNames": ["<top category 1>", "<top category 2>"] }
)
```
**Response:** `{ "categoryIds": ["a1b2c3d4-...", "b2c3d4e5-..."] }`
If `categoryIds` is empty: category doesn't exist — fall back to SITE scope and tell the merchant: "Could not resolve category '{name}', using site-wide scope instead."
### Failure handling
- Both calls fail: Fall back to SITE scope using only site profile data.
- One fails: Use whichever succeeded.
---
## Step 6: Generate recommendations across ALL active domains
**Only now — after data gathering — generate recommendations.**
Maximum **5 recommendations total** across all domains. Each recommendation includes its `domain` field.
### Discount recommendations (if DISCOUNTS domain active)
Use site data + catalog data to generate discount recommendations. Each should use a **different strategy**:
| Strategy | When to use | Key parameters |
|---|---|---|
| SEASONAL | Holiday/event within 30 days | Time-bounded, site-wide or category scope |
| UPSELL_BOOST | AOV data available | minSubTotal above current AOV |
| STOCK_MOVER | Products with high stock + low orders | Deeper discounts on slow movers |
| BUNDLE_AND_SAVE | Many low-priced items | minItemQuantity conditions |
**Scope selection** (in order of preference):
1. **CATEGORY** (preferred): High-opportunity category from analytics. Must have GUID from GetCategoryIds.
2. **ITEMS** (specific): Individual products from catalog data. Max 5 product IDs.
3. **SITE** (fallback): When no clear category/product opportunity.
**Performance signals:**
| What you observe in the data | What to recommend |
|---|---|
| High visitors, low ordersCount | Site-wide discount to convert traffic |
| High AOV, few items per order | BUNDLE_AND_SAVE |
| Products with high stock + low orders | STOCK_MOVER |
| Holiday within 30 days | SEASONAL |
**Discount constraints:**
- Discount must not exceed `discountMargin` from site data (unless merchant overrides)
- Round percentages to 5/10/15/20/25% unless merchant specified exact value
- All categoryIds must be GUIDs from GetCategoryIds
- All productIds must be from GetProductCatalogData
- Mechanism must be AUTOMATIC or COUPON per Step 4c
### Shipping recommendations (if SHIPPING domain active)
Analyze the site's shipping configuration using the rules below. All shipping recommendations use `domain: "shipping"`.
**Externally managed regions:** Regions where `deliveryCarriers[].appId` matches an external carrier (e.g., Shippo) — exclude from ALL analysis. Do not recommend changes to these.
**Shipping analysis rules — evaluate each and recommend where data supports:**
| Rule | Finding | Recommendation |
|---|---|---|
| **Coverage** | Active region with zero shipping options | CRITICAL — `create_shipping_option` for that region |
| **Coverage** | Domestic country not covered by any region | CRITICAL — `activate_region` or create domestic region |
| **Coverage** | Inactive regions with shipping options | `activate_region` or clean up orphaned options |
| **Free Shipping** | No free shipping option anywhere | `create_shipping_option` with AOV-calibrated threshold (1.2-1.5x AOV) |
| **Free Shipping** | Free shipping threshold > 2x AOV | Lower threshold — too high for most customers |
| **Rates** | Flat rate > 15% of AOV | Reduce rate or add conditional tiering — sticker shock risk |
| **Rates** | All flat rates, no conditional pricing | Add threshold-based tiers for better conversion |
| **Rates** | Per-item pricing enabled | Review — usually causes unexpectedly high totals |
| **Carrier** | No backup rate on carrier regions | `enable_backup_rate` as fallback |
| **Options** | Too many options per region (> 5) | Consolidate — choice paralysis reduces conversion |
| **Options** | Only 1 option per region | Add at least one alternative (e.g., express tier) |
**Shipping action types:** `create_shipping_option`, `update_shipping_option`, `enable_backup_rate`, `activate_region`.
**Priority order:** CRITICAL blockers (no options, no coverage) → Conversion-linked (no free shipping, high rates) → Revenue opportunities (international, tiered pricing) → Configuration improvements (consolidate, add estimates).
### Abandoned cart recommendations (if ABANDONED_CART domain active)
Detect if the merchant has significant cart abandonment without active recovery. All abandoned cart recommendations use `domain: "abandoned_cart_recovery"`.
**Eligibility gate (BOTH conditions required):**
1. Cart abandonment recovery automation is **NOT active** on the site
2. Estimated missing sales >= $200 over the last 30 days
**If either condition fails, do NOT generate abandoned cart recommendations.**
**Urgency thresholds based on missing sales (USD, last 30 days):**
| Missing sales | Urgency |
|---|---|
| >= $1,000 | HIGH |
| $200 — $999 | MEDIUM |
| < $200 | Do not recommend |
**Action type:** `activate_abandoned_cart_recovery`
**Params must include:** `automation_key` ("wix_e_commerce-cart_abandonment"), `missing_sales_usd` (integer, rounded), `abandoned_cart_count` (integer), `window_days` (always 30).
**Title pattern:** "Recover $[missing_sales_usd] in abandoned carts"
**Reasoning MUST cite:** automation is inactive, exact cart count, exact missing sales USD, 30-day window, and why the urgency level was chosen.
### Cross-domain balance
- If request is generic, aim for recommendations from **multiple domains** (e.g., 2-3 discount + 1-2 shipping + abandoned cart if eligible)
- If request targets a specific domain, focus all slots on that domain
- Rank by business impact: CRITICAL blockers first, then conversion-linked, then revenue opportunities
---
## Step 7: Validate before returning
1. **Conflict check**: Do existing active discounts/coupons overlap with your recommendation scope? Warn about stacking.
2. **Margin check**: Discounts within `discountMargin` cap.
3. **No duplicates**: Each recommendation targets a different scope/action combination.
4. **No contradictions**: Don't recommend opposite actions in the same domain.
5. **Strategy diversity**: Discount recommendations use different strategies where possible.
6. **Mechanism match**: Discount mechanism matches Step 4c determination.
7. **ID validity**: All categoryIds are GUIDs from GetCategoryIds. All productIds are from GetProductCatalogData.
8. **Rounding**: Discount percentages round to 5/10/15/20/25% unless merchant specified exact value.
9. **Data-backed**: Every recommendation must reference specific data from API responses.
10. **Domain labeled**: Every recommendation has the correct `domain` field.
---
## Step 8: Persist recommendations to database (Tracking)
**MANDATORY — do NOT skip unless the user said `SKIP_TRACKING`.**
Call `BatchCreate` to persist ALL recommendations as PROPOSED:
```
CallWixSiteAPI(
url: "https://manage.wix.com/_api/agentic-recommendations/v1/agentic-recommendations/batch-create",
method: "POST",
body: {
"agenticRecommendations": [
{
"title": "<recommendation title>",
"reasoning": "<recommendation reasoning>",
"domain": "<discounts|shipping|abandoned_cart_recovery>",
"urgency": "<CRITICAL|HIGH|MEDIUM|LOW>",
"advice": {
"action": "<action type>",
"params": <params object>,
"successCriteria": "<how to verify success>"
}
}
],
"conversationId": "<conversationId>"
}
)
```
**Save the `id` and `revision` from each result.** Include them in the output.
If BatchCreate fails, report the error and include recommendations without tracking IDs.
---
## Output format
```json
{
"recommendations": [
{
"id": "<tracking-id from BatchCreate, or omit if tracking failed>",
"revision": "<revision from BatchCreate>",
"title": "Memorial Weekend Flash Sale — 15% Off Orders Over $250",
"reasoning": "AOV is $242 (online_gpv_last_30_days / last_30_days_orders_count). merchant_business_country is US, Memorial Day is within 7 days. Setting $250 threshold nudges carts above AOV while staying within 25% discount cap.",
"domain": "discounts",
"urgency": "HIGH",
"advice": {
"action": "apply_discount",
"params": {
"mechanism": "AUTOMATIC",
"scope": "SITE",
"categoryIds": [],
"productIds": [],
"name": "Memorial Weekend Sale",
"why": "Your AOV is $242. A 15% discount on orders over $250 encourages adding one more item.",
"discountType": "PERCENTAGE",
"discount": 15,
"code": "",
"usageLimit": 0,
"limitPerCustomer": 0,
"conditions": {
"minItemQuantity": 0,
"minSubTotal": 250,
"startDate": "2026-05-23",
"endDate": "2026-05-26"
}
},
"success_criteria": "15% discount applied site-wide for orders above $250 during Memorial Weekend"
}
}
]
}
```
### Field rules
| Field | Rule |
|---|---|
| `id` | GUID from tracking BatchCreate response (omit if tracking skipped/failed) |
| `title` | Short, actionable. Max 200 chars. Always English. |
| `reasoning` | **Must reference which API call returned the data.** Always English. |
| `domain` | `"discounts"`, `"shipping"`, or `"abandoned_cart_recovery"` (future: `"gift_cards"`, `"taxes"`) |
| `urgency` | `CRITICAL`, `HIGH`, `MEDIUM`, or `LOW` |
| `mechanism` | `AUTOMATIC` or `COUPON`. From Step 4c. Only for discounts domain. |
| `name` | Marketing headline, 2-5 words. Translate to site `language` if not English. |
| `why` | 1-2 sentences with specific data points from API responses. Translate to site `language`. |
| `code` | Only for COUPON mechanism. Memorable code, max 20 chars (e.g., "SAVE15"). |
| `scope` + IDs | For discounts: SITE = both empty, CATEGORY = categoryIds only (max 3), ITEMS = productIds only (max 5). |
| `success_criteria` | How to verify the recommendation was applied correctly |
### Valid action types by domain
| Domain | Action types |
|---|---|
| discounts | `apply_discount` |
| shipping | `create_shipping_option`, `update_shipping_option`, `enable_backup_rate`, `activate_region` |
| abandoned_cart_recovery | `activate_abandoned_cart_recovery` |
---
## Constraints
- Maximum 5 recommendations total across all domains
- Each discount recommendation must use a different strategy
- All data must come from API responses — no assumptions
- Respect discountMargin cap unless merchant overrides
- All IDs must be GUIDs from API responses
- Catalog queries limited to 30 items
- Every recommendation MUST be persisted via tracking before presenting (unless SKIP_TRACKING)
- Recommendations should span multiple domains when the request is generic
- Never recommend changes to externally managed (Shippo) shipping regions
SHA-256: ff862d8b093bb83b1d082be25c54a18d039f4e3187788fd7464cade0d0c02173