Upsells — Reference
The Upsells surface is the suggestion plane for SGEN commerce. It owns the rules that surface a related, complementary, or higher-tier product alongside what the shopper is already viewing or has already added to the cart — the merchandising shelf on product pages, the recommendation strip in the cart drawer, the one-click add at checkout, and the cross-sell email after order completion.
This page is a reference for platform engineers and integrators who need to understand the surface before extending it, scripting against it, or scoping a recommendation model. Customer-facing how-tos live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
Overview
Upsells lives under the Commerce module in SG-Admin. The module renders three primary views — the rule list, the rule create / edit form (with trigger source, candidate selection, and placement target), and the performance view that reports impressions, click-throughs, and attributed revenue per rule — and exposes a small set of write operations for create, edit, pause, resume, reorder, archive, and add or remove exclusions.
The module is paired by convention: one half renders the views and prepares the rule and performance data, the other half handles writes and returns AJAX responses. Engineers reading the SG-Admin source will see this split across two controller files; the reference below describes the combined surface as it appears to a calling integration.
Upsells are distinct from Bundles. A bundle ships several products as one line in the cart; an upsell adds a separate line that the shopper can decline. Both surfaces participate in the merchandising pipeline, but the entry points and the cart shape differ. Bundle records live under the adjacent Bundles surface; this page covers suggestion-rule definitions only.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Commerce → Upsells
- URL prefix:
/sg-admin/upsells/ - View templates:
application/views/Admin/Commerce/Upsells/
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Commerce → Upsells [ + Add rule ] │├──────────────────────────────────────────────────────────────────────┤│ Name Placement Trigger Status ││ ──────────────────── ──────────── ─────────────── ──────────────││ Cable for laptop product page cat: laptops active ││ Warranty on TVs cart drawer cat: tvs active ││ Premium upgrade checkout tier: standard active ││ Branded mug product page sku: mug-001 active ││ Filters subscription post-purchase order: any paused ││ ││ Impressions (30d): 48,210 · Click-through: 8.4% · Attributed: $14,820 ││ [ Edit ] [ Pause ] [ Reorder ] [ Exclusions ] [ Archive ] │└──────────────────────────────────────────────────────────────────────┘Actions
The Upsells surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List upsell rules
Returns the rule set paginated, with name, placement target (product page / cart drawer / checkout / post-purchase email), trigger summary, candidate selection summary, status (active, paused, scheduled, expired, archived), and a performance flag (impressions, click-through rate, attributed revenue over the last 30 days). Supports filter by placement, by status, by trigger product, and by candidate product.
View upsell rule
Returns the full record for a single rule — name, trigger source (which product or category the shopper is viewing or buying), candidate selection (which products are eligible to be suggested), placement target, render template, priority within its placement, schedule window, exclusion list, and the performance ledger with one entry per impression and per click. The performance ledger is paginated and summarized at the top.
Create upsell rule
Opens an empty rule form. Required fields at minimum: name, trigger source, candidate selection method, placement target. Optional fields cover render template override, priority slot, schedule window, exclusion list, and per-shopper frequency cap. On submit, the surface validates the trigger and candidate references against the catalog, persists the record, and returns the new identifier.
Edit upsell rule
Loads an existing record into the same form shape used for create, pre-populated. Submit replaces the stored rule with the posted values; fields left blank do not clear server-side values (the form is partial-update by default). Edits to an active rule take effect on the next placement evaluation — already-rendered pages retain their previously chosen candidates until the next page load.
Pause and resume
Toggles the rule between active and paused without altering its definition. Paused rules are excluded from placement evaluation but retain their performance history and remain queryable. Resume restores the rule to active without resetting frequency caps.
Reorder priority within a placement
Each placement target evaluates its eligible rules in priority order. Reorder rewrites the priority slot for a given rule, shifting the rest of the list within that placement to accommodate. Priority matters because each placement typically renders a small number of suggestion cards — usually three to six — and lower-priority rules may not appear when higher-priority rules saturate the slot count.
Add and remove exclusions
The exclusion list keeps a rule from firing for specific products, categories, or customer segments. Adding an exclusion appends a row; removing detaches a row. Exclusions are evaluated alongside trigger matching — a rule that would otherwise match is suppressed when any exclusion row applies.
Archive rule
Marks the rule inactive without removing it from the database. Archived rules disappear from the default list view but remain queryable via the archived filter. Their performance ledger entries remain attached for attribution reporting; the rule itself is excluded from placement evaluation.
View performance
Returns the per-impression and per-click ledger for a single rule. Each entry records the shopper session, the trigger context (page or cart state), the candidate product shown, the timestamp, and the outcome (impression-only, clicked, added-to-cart, purchased). Used for attribution reporting and for diagnosing rules that under-perform their cohort.
Engineering note. The performance ledger is append-only. Attribution joins back to the order ledger are computed at read time rather than written into the ledger itself, so changes to the attribution window in Settings reshape historical reports without rewriting rows.
Data model
An upsell-rule record carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. Stable across edits. |
name | string | Operator-facing label. Not unique. |
placement | enum | product_page, cart_drawer, checkout, post_purchase_email. |
trigger_kind | enum | product, category, tier, cart_state. |
trigger_selector | json | References interpreted against the catalog or cart shape. |
candidate_kind | enum | static_list, category_pick, related_by_attribute, manual. |
candidate_selector | json | References that resolve at render time to a candidate product set. |
priority | integer | Slot within the placement. Lower runs first. |
frequency_cap | integer | Optional max impressions per shopper per window. |
frequency_window | enum | session, day, week, lifetime. |
status | enum | active, paused, scheduled, expired, archived. |
starts_at | timestamp | Optional schedule start. |
ends_at | timestamp | Optional schedule end. |
render_template | string | Optional override for the suggestion card template. |
created_at | timestamp | Set on create, immutable. |
updated_at | timestamp | Touched on any edit. |
rule_id, exclusion_kind (product / category / segment), exclusion_selector. Multiple rows are evaluated as logical-OR — any matching exclusion suppresses the rule.Performance ledger entry: rule_id, session_id, trigger_context, candidate_product_id, event_kind (impression / click / add_to_cart / purchase), event_at. Conversion attribution joins ledger rows to the order ledger on session and timestamp window.
Candidate semantics: static_list selects a fixed product set declared in the rule. category_pick selects N products from a category at render time, typically by best-seller or stock-available order. related_by_attribute selects products sharing one or more catalog attributes (color, material, size class). manual selects from an operator-curated list ranked by drag-to-reorder.
SHOPPER CONTEXT placement = product_page · viewing = laptop-15│▼┌───────────────────────────────────────────────┐│ Upsell engine ││ ││ for each rule where placement matches: ││ ▶ trigger selector matches context? ││ ▶ schedule window OK? ││ ▶ frequency cap not yet reached? ││ ▶ no exclusion row applies? ││ ││ if YES → resolve candidate selector ││ → filter out already-in-cart items ││ → filter out the trigger item itself ││ → emit (rule, candidate) pair ││ if placement slot saturated → stop ││ else → continue to next rule by priority │└───────────────────────┬───────────────────────┘│▼SUGGESTION CARDS│▼performance ledger writes(impression + click + cart-add + purchase)Permissions
Access to the Upsells surface is gated at two layers.
Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Upsells surface.
Layer 2 — per-action capability. Within SG-Admin, each Upsells action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List rules | ✔ | ✔ | ✔ |
| View rule | ✔ | ✔ | ✔ |
| View performance | ✔ | ✔ | ✔ |
| Create rule | ✔ | ✔ | — |
| Edit rule | ✔ | ✔ | — |
| Pause / resume | ✔ | ✔ | — |
| Reorder priority | ✔ | — | — |
| Adjust frequency cap | ✔ | — | — |
| Add / remove exclusions | ✔ | ✔ | — |
| Archive rule | ✔ | — | — |
| Restore archived rule | ✔ | — | — |
Self-protection rules. A rule cannot be deleted while its performance ledger references an open attribution window — the surface returns a structured rejection until the window closes. Trigger and candidate selectors are validated against the live catalog; references to archived products are rejected at write time, and references to products that become archived after the rule is saved are filtered out at render time. The placement target cannot be changed on a rule with non-empty performance history; create a fresh rule instead.
Audit. Every write — create, edit, pause, resume, reorder, exclusion change, archive, restore — emits an Activity Log entry. The log records the acting operator, the rule identifier, and the change shape (field-level diff for edits). Render events write to the performance ledger; the two records are correlated by rule identifier and timestamp.
REQUEST│▼┌───────────────────────────┐│ Admin gate │ unauth → reject│ (every /sg-admin/* call) │└─────────────┬─────────────┘│ authed▼┌───────────────────────────┐│ Capability check │ role lacks cap → reject│ (per-action) │ (custom roles override defaults)└─────────────┬─────────────┘│ allowed▼┌───────────────────────────┐│ Self-protection rules │ open-attribution delete /│ │ archived-product reference /│ │ placement-change-with-history → reject└─────────────┬─────────────┘│ passes▼action executes│▼Activity Log + performance ledgerRelated references
- Bundles — Reference. Bundles may appear as upsell candidates. The upsell engine references the bundle's catalog identifier and renders the bundle card as a single suggestion.
- Products — Reference. Owns the catalog identifiers, categories, and attributes used by trigger and candidate selectors. Archived products are filtered out at render time.
- Discounts — Reference. Upsell-accepted lines participate in discount evaluation like any other cart line. There is no built-in "upsell discount" — to incentivize the suggestion, pair the rule with a discount rule scoped to the candidate product.
- Price Lists — Reference. Upsell candidates quote at price-list-resolved prices, not at catalog base prices. Customer-group pricing applies to the suggestion card.
- Orders — Reference. Records the suggestion-attribution flag on lines that originated from an upsell click. Attribution joins are computed at read time against the performance ledger.
- Customers — Reference. Customer-segment exclusions and customer-tier triggers reference the segment definitions documented here.
- Settings — Reference. Owns the placement-slot counts (how many suggestions to render per placement), the attribution-window default, and the rule grammar registration for trigger and candidate selectors. Changes there reshape the Upsells evaluation behavior.
- Email — Reference. The post-purchase email placement hands a candidate selection to the transactional-email pipeline. Template rendering and delivery happen in the Email surface; the upsell rule only supplies the candidates.
/docs/upsells.