Skip to content

Enhancement Proposal: Ancillaries Extension #188

@alldentobias

Description

@alldentobias

Summary

This proposal introduces an Ancillaries Extension for the Shopping Checkout capability, enabling businesses to offer additional products, services, and insurance tied to line items in a checkout. The extension provides a standardized way for platforms to present upsells, cross-sells, protection plans, and required additions (like recycling fees) while maintaining a clean separation from core checkout fields.

The extension supports suggested ancillaries (offered by the business), applied ancillaries (added to the checkout), buyer input collection (e.g., time slot selection), and mutually exclusive alternatives (e.g., warranty tiers).

Motivation

E-commerce checkouts commonly need to offer ancillary items beyond the primary cart contents—protection plans, installation services, complementary accessories, and legally required fees. Currently, there is no standardized way in UCP to:

  1. Suggest related products/services tied to specific line items
  2. Present mutually exclusive options (e.g., "Basic" vs "Premium" warranty)
  3. Collect required buyer input before adding an ancillary (e.g., installation scheduling)
  4. Distinguish between buyer-selected and automatically applied ancillaries

This creates implementation fragmentation and inconsistent buyer experiences across platforms.

Goals

  • Enable businesses to suggest ancillaries related to specific line items or the overall checkout
  • Support categorization (product, service, insurance) for appropriate UI rendering
  • Handle ancillaries requiring buyer input (time slot selection, text input)
  • Group mutually exclusive alternatives via group_id
  • Support automatic ancillaries for legal requirements and promotional additions
  • Maintain applied ancillary metadata to enable UI features like "You selected X, alternatives were Y, Z"

Non-Goals

  • Subscription/recurring billing management (complex, separate proposal needed)
  • Inventory management for ancillary items
  • Dynamic pricing rules or discount calculations for ancillaries
  • Multi-quantity input handling (e.g., "select 3 accessories")

Detailed Design

Capability

{
  "capabilities": [{
    "name": "dev.ucp.shopping.checkout",
    "version": "2026-01-11",
    "extensions": [{
      "name": "dev.ucp.shopping.ancillaries",
      "version": "2026-02-17",
      "spec": "https://ucp.dev/extensions/ancillaries/spec.json",
      "schema": "https://ucp.dev/extensions/ancillaries/schema.json"
    }]
  }]
}

Schema

Request (adding ancillaries)

{
  "ancillaries": {
    "items": [
      {
        "item": { "id": "string (SKU)" },
        "for": "string (line item ID, optional)",
        "quantity": "integer",
        "input": {
          "type": "string (text | selection)",
          "value": "string (option ID or free text)"
        }
      }
    ]
  }
}

Response (suggestions and applied)

{
  "ancillaries": {
    "title": "string (optional header)",
    "suggested": [
      {
        "item": {
          "id": "string",
          "title": "string",
          "price": "integer (minor units)",
          "image_url": "string (optional)"
        },
        "type": "complementary | suggested | required",
        "category": "product | service | insurance",
        "for": "string (line item ID, optional)",
        "group_id": "string (optional, for mutually exclusive options)",
        "description": "string (optional)",
        "original_price": "integer (optional, for discounted items)",
        "requires_input": "boolean",
        "input_schema": {
          "type": "string (text | selection)",
          "label": "string",
          "description": "string (optional)",
          "required": "boolean",
          "options": [
            { "id": "string", "label": "string" }
          ],
          "constraints": {
            "max_length": "integer (for text type)"
          }
        },
        "terms_url": "string (URI, optional)"
      }
    ],
    "applied": [
      {
        "id": "string (line item ID)",
        "for": "string (optional)",
        "type": "complementary | suggested | required",
        "category": "product | service | insurance",
        "group_id": "string (optional)",
        "description": "string",
        "terms_url": "string (optional)",
        "automatic": "boolean",
        "reason_code": "legal_requirement | promotional_gift | bundle_component | loyalty_benefit",
        "input": {
          "type": "string",
          "value": "string"
        }
      }
    ]
  }
}

Full Example (Insurance Suggestions)

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "id": "sku_smartphone_256", "title": "Smartphone 256GB", "price": 99900 },
      "quantity": 1
    }
  ],
  "ancillaries": {
    "title": "Protect your new device",
    "suggested": [
      {
        "item": { "id": "sku_protection_2yr", "title": "2-Year Protection Plan", "price": 19900 },
        "type": "complementary",
        "category": "insurance",
        "for": "li_1",
        "group_id": "insurance_phone",
        "description": "Covers accidental damage, battery service, and 24/7 support",
        "terms_url": "https://example.com/protection-plan/terms"
      },
      {
        "item": { "id": "sku_protection_theft", "title": "2-Year Plan with Theft Coverage", "price": 26900 },
        "type": "complementary",
        "category": "insurance",
        "for": "li_1",
        "group_id": "insurance_phone",
        "description": "Full protection plus theft and loss coverage",
        "terms_url": "https://example.com/protection-plan-theft/terms"
      }
    ]
  }
}

Example (Service with Input)

{
  "ancillaries": {
    "suggested": [
      {
        "item": { "id": "sku_tv_install", "title": "Professional TV Installation", "price": 14900 },
        "type": "complementary",
        "category": "service",
        "for": "li_1",
        "description": "Expert wall mounting and setup included",
        "requires_input": true,
        "input_schema": {
          "type": "selection",
          "label": "Select installation date and time",
          "required": true,
          "options": [
            { "id": "slot_1", "label": "Tuesday, Feb 18 - 9:00 AM to 11:00 AM" },
            { "id": "slot_2", "label": "Tuesday, Feb 18 - 2:00 PM to 4:00 PM" }
          ]
        }
      }
    ]
  }
}

Example Request (Adding Service with Input)

{
  "ancillaries": {
    "items": [
      {
        "item": { "id": "sku_tv_install" },
        "for": "li_1",
        "quantity": 1,
        "input": { "type": "selection", "value": "slot_2" }
      }
    ]
  }
}

Example (Automatic Ancillary)

{
  "ancillaries": {
    "applied": [
      {
        "id": "li_2",
        "for": "li_1",
        "type": "required",
        "category": "service",
        "description": "Electronics Recycling Fee (required by state law)",
        "automatic": true,
        "reason_code": "legal_requirement"
      }
    ]
  }
}

Behavioral Changes

  1. Applied ancillaries appear both in ancillaries.applied[] (with relational context) and line_items[] (as purchasable items)
  2. Automatic ancillaries (legal requirements, promotional gifts) cannot be removed by platforms
  3. Rejected ancillary additions are communicated via the existing messages[] array with specific codes

Risks and Mitigations

Backward Compatibility: This is an additive extension. Existing checkouts without ancillaries continue to work unchanged. Platforms can adopt incrementally.

Complexity: The extension introduces several new concepts (input schemas, group_id, automatic ancillaries). Mitigation: Comprehensive documentation with examples for each use case.

Performance: Additional data in responses. Mitigation: All fields are optional; businesses only include what's relevant.

Security: terms_url accepts external URLs. Mitigation: Platforms should validate/sanitize URLs before rendering.

Test Plan

Unit Tests:

  • Schema validation for all defined types
  • Input schema constraint validation (max_length for text)
  • Required field enforcement

Integration Tests:

  • Adding ancillaries with and without input
  • Mutually exclusive selection (only one from group_id)
  • Automatic ancillary behavior (cannot remove)
  • Rejection message handling

End-to-End Tests:

  • Full flow: view suggestions → select with input → submit → verify applied
  • Insurance tier selection flow
  • Service scheduling flow

Graduation Criteria

Working Draft → Candidate:

  • Schema merged and documented (with Working Draft disclaimer)
  • Unit and integration tests are passing
  • Initial documentation is written
  • TC majority vote to advance

Candidate → Stable:

  • At least 2 platform implementations providing feedback
  • Adoption feedback has been collected and addressed
  • Full documentation and migration guides are published
  • TC majority vote to advance

Implementation History

  • [2026-02-11]: Proposal submitted.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions