Skip to content

[Proposal]: Structured product attributes via schema.org PropertyValue #400

@sakinaroufid

Description

@sakinaroufid

Summary

Add an optional attributes array on Product and Variant for measurable facts like battery life, display size, weight, and storage. Each entry has a required name and value, plus optional numeric_value and unit. Same inline shape as the existing Variant.barcodes. About 30 lines of schema across two files. Additive: no new endpoints, transports, or request parameters.

The shape matches schema.org PropertyValue, which is what most catalog teams already publish via JSON-LD on their product pages. For them, adoption is mostly piping existing data into UCP catalog responses.

Motivation

An agent gets the query "phone with at least 20 hours of battery, under $800." The catalog response usually contains the answer but it's stuck in prose: "all-day battery", "lightweight at 1.2 kg".

tags doesn't carry units. metadata accepts anything, but every merchant picks a different shape, which is the same fragmentation problem as parsing prose.

attributes gives a structured place for measurable facts. numeric_value lets agents filter without parsing display strings.

This isn't a vendor-specific use case. Every catalog has the same gap, and a vendor-namespaced version would be the same field with a different prefix, which doesn't help the cross-merchant comparison problem.

Goals

  • Get measurable attributes out of prose into structured form on Product and Variant.
  • Expose a typed numeric field so agents can filter without LLM extraction.
  • Stay additive. No breaking changes, no new endpoints, no new transports.

Non-Goals

  • Defining a UCP-canonical vocabulary of attribute names. Names follow merchant convention and schema.org practice. Vertical extensions can standardize identifiers later.
  • Server-side filtering. Filtering happens agent-side over the catalog response.
  • Localization of attribute names. Display strings come from the rendering layer.
  • Range expressions. v1 is single values. Range siblings can land later.
  • Categorical attributes (color, fit, material). Those go in tags or product options.

Detailed Design

Schema

"attributes": {
  "type": "array",
  "description": "Structured product attributes for measurable facts (battery life, display size, weight). Use `tags` for categorical labels and `metadata` for business-specific data. Same shape as schema.org `PropertyValue`.",
  "items": {
    "type": "object",
    "required": ["name", "value"],
    "properties": {
      "name": {
        "type": "string",
        "description": "Human-readable attribute name (e.g. `Battery life`, `Display`, `Weight`). Same as schema.org `PropertyValue.name`."
      },
      "value": {
        "type": "string",
        "description": "Display value. Same as schema.org `PropertyValue.value`. Can be a number, range, or domain notation."
      },
      "numeric_value": {
        "type": "number",
        "description": "Optional comparable numeric form of `value`. Businesses SHOULD populate this when the attribute is a single measurement so agents can filter without parsing the display string."
      },
      "unit": {
        "type": "string",
        "description": "Optional unit of measurement (e.g. `hours`, `kg`, `inches`, `GB`). Open vocabulary; clients MUST tolerate unknown values."
      }
    }
  }
}

Same field on Variant. Inline structured array, no new schema files. Same pattern as Variant.barcodes.

Placement

Attributes constant across all variants go on Product (display size, refresh rate). Attributes that vary by variant go on Variant (storage, weight by size). Clients read whichever level is populated. If both are populated, variant wins.

Cross-capability impact

attributes lives on the existing Product and Variant schemas. It propagates wherever those types appear today, which includes catalog responses and Variant references in cart and order line items. No transport bindings, request shapes, or other capabilities change.

Worked example

{
  "id": "prod_aurora_phone",
  "title": "Aurora Phone",
  "description": { "plain": "Flagship phone with all-day battery." },
  "price_range": {
    "min": { "amount": 79900, "currency": "USD" },
    "max": { "amount": 89900, "currency": "USD" }
  },
  "attributes": [
    { "name": "Battery life", "value": "22", "numeric_value": 22, "unit": "hours" },
    { "name": "Display",      "value": "6.1", "numeric_value": 6.1, "unit": "inches" }
  ],
  "variants": [
    {
      "id": "var_aurora_128",
      "title": "128 GB",
      "description": { "plain": "Aurora Phone, 128 GB storage." },
      "price": { "amount": 79900, "currency": "USD" },
      "attributes": [
        { "name": "Storage", "value": "128", "numeric_value": 128, "unit": "GB" }
      ]
    },
    {
      "id": "var_aurora_256",
      "title": "256 GB",
      "description": { "plain": "Aurora Phone, 256 GB storage." },
      "price": { "amount": 89900, "currency": "USD" },
      "attributes": [
        { "name": "Storage", "value": "256", "numeric_value": 256, "unit": "GB" }
      ]
    }
  ]
}

Risks and Mitigations

Backward compatibility. Additive on Product and Variant. Existing producers keep working. Existing consumers ignore the new field. Same profile as adding any optional field.

Vocabulary fragmentation. Open name vocabulary means catalog teams pick inconsistent names early. Cross-merchant filtering should lean on numeric_value plus unit (both bounded enough to compare meaningfully) rather than exact name matching. The schema.org PropertyValue ecosystem has converging conventions for names over time.

Adoption gap. No required population. Useful when populated, harmless when absent, same as tags and barcodes.

Codegen. Same shape as Variant.barcodes. No new pattern.

Security and performance. No new attack surface, no new request paths, payload growth bounded. Negligible.

Test Plan

Schema validation: required name and value enforced, missing fields rejected, entries with and without each optional field validate. Existing fixtures without attributes validate unchanged.

Sample fixture in the conformance suite: a phone product with populated attributes on both product and variant levels.

Pydantic models in python_sdk regenerate cleanly.

Graduation Criteria

Working Draft to Candidate:

  • Schema merged with Working Draft disclaimer.
  • Catalog spec doc gains an Attributes section with placement guidance and the worked example.
  • Pydantic models regenerated in python_sdk.
  • At least one merchant prototype publishing attributes.
  • TC majority vote.

Candidate to Stable:

  • Adoption from at least two independent merchant deployments.
  • Documentation finalized.
  • TC majority vote.

Implementation History

  • [2026-04-30]: Proposal submitted.

Metadata

Metadata

Assignees

No one assigned

    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