Skip to content

Commit 9b6cfdf

Browse files
jamesandersenJames Andersen
authored andcommitted
feat: address PR review — extend Cart, tighten schema constraints, add privacy note
- Extend attribution to Cart in addition to Checkout (following discount pattern) - Add minProperties: 1 on dedup_keys to prevent empty objects - Constrain custom values to string/number/boolean with maxProperties: 20 - Strengthen platform field from SHOULD to MUST match agent profile URL - Add Privacy Note section to docs
1 parent bd739fb commit 9b6cfdf

2 files changed

Lines changed: 63 additions & 11 deletions

File tree

docs/specification/attribution.md

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ via URL parameters on their landing page. This extension preserves that data.
3535

3636
**Dependencies:**
3737

38-
- Checkout Capability
38+
- Cart Capability or Checkout Capability
3939

4040
## Discovery
4141

@@ -47,6 +47,12 @@ Businesses advertise attribution support in their profile:
4747
"version": "{{ ucp_version }}",
4848
"capabilities": {
4949
"dev.ucp.shopping.attribution": [
50+
{
51+
"version": "{{ ucp_version }}",
52+
"extends": "dev.ucp.shopping.cart",
53+
"spec": "https://ucp.dev/{{ ucp_version }}/specification/attribution",
54+
"schema": "https://ucp.dev/{{ ucp_version }}/schemas/shopping/attribution.json"
55+
},
5056
{
5157
"version": "{{ ucp_version }}",
5258
"extends": "dev.ucp.shopping.checkout",
@@ -61,33 +67,34 @@ Businesses advertise attribution support in their profile:
6167

6268
## Schema Composition
6369

64-
The attribution extension extends the **checkout object** directly:
70+
The attribution extension extends both **cart** and **checkout** objects:
6571

66-
- **Base schema extended**: `checkout.json`
67-
- **Path**: `checkout.attribution`
72+
- **Base schemas extended**: `cart.json`, `checkout.json`
73+
- **Path**: `cart.attribution`, `checkout.attribution`
6874
- **Schema reference**: `attribution.json`
6975

70-
The `attribution` property is composed onto the checkout object via `allOf`,
76+
The `attribution` property is composed onto each object via `allOf`,
7177
following the same extension pattern as `fulfillment.json` and `discount.json`.
7278

7379
## Schema Definition
7480

7581
### Attribution Payload
7682

7783
The `attribution` object contains referral context from the platform that drove
78-
the checkout:
84+
the cart or checkout:
7985

8086
| Field | Type | Required | Description |
8187
|---------------|--------|----------|------------------------------------------------------------------------------------------------------|
8288
| `platform` | string | Yes | Referring platform identifier using reverse domain naming (e.g., `com.google`, `com.meta`) |
8389
| `dedup_keys` | object | No | Deduplication keys for reconciling with the merchant's server-side reporting |
8490
| `utm` | object | No | Standard UTM parameters for web analytics compatibility |
85-
| `custom` | object | No | Platform-specific key-value pairs routed by the merchant based on the `platform` field |
91+
| `custom` | object | No | Platform-specific key-value pairs routed by the merchant based on the `platform` field. Values MUST be string, number, or boolean. Maximum 20 properties. |
8692

8793
### Deduplication Keys
8894

8995
The `dedup_keys` object prevents double-counting when both the referring
90-
platform and the merchant report the same transaction independently:
96+
platform and the merchant report the same transaction independently. If
97+
present, at least one key MUST be provided:
9198

9299
| Field | Type | Description |
93100
|--------------|--------|----------------------------------------------------------------------------------------|
@@ -118,6 +125,25 @@ The `attribution` property supports the following operations:
118125
| `update` | `optional` | Platform MAY update attribution |
119126
| `complete` | `optional` | Platform MAY include attribution on complete |
120127

128+
## Privacy Note
129+
130+
This extension replaces attribution and conversion signals that traditionally
131+
flow from the referring platform to the business via the merchant's website.
132+
When a purchase occurs through an agentic flow, the website is bypassed and
133+
these signals would otherwise be lost. While the fields primarily carry
134+
marketing and campaign metadata, some values — such as click identifiers and
135+
session identifiers in `dedup_keys` or `custom` — may be considered advertising
136+
data subject to user consent under applicable privacy regulations.
137+
138+
Implementations **MUST**:
139+
140+
- Only use attribution data for the purposes of conversion measurement,
141+
reporting, and attribution
142+
- **NOT** transmit personally identifiable information (e.g., email addresses,
143+
phone numbers, names) through any field in this extension
144+
- Comply with applicable consent requirements for advertising and marketing
145+
data in the jurisdictions where they operate
146+
121147
## Usage Examples
122148

123149
### Google (Google Ads / Gemini)

source/schemas/shopping/attribution.json

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@
33
"$id": "https://ucp.dev/schemas/shopping/attribution.json",
44
"name": "dev.ucp.shopping.attribution",
55
"title": "Attribution Extension",
6-
"description": "Extends Checkout with attribution support, enabling referring platforms to pass attribution data and deduplication keys through agentic checkout flows.",
6+
"description": "Extends Cart and Checkout with attribution support, enabling referring platforms to pass attribution data and deduplication keys through agentic checkout flows.",
77
"$defs": {
88
"attribution_payload": {
99
"type": "object",
1010
"required": ["platform"],
1111
"properties": {
1212
"platform": {
1313
"$ref": "types/reverse_domain_name.json",
14-
"description": "Referring platform identifier (reverse domain naming). SHOULD correspond to the domain of the platform's UCP-Agent profile URL.",
14+
"description": "Referring platform identifier (reverse domain naming). MUST correspond to the domain of the platform's UCP-Agent profile URL.",
1515
"examples": ["com.google", "com.meta", "com.tiktok", "com.openai"]
1616
},
1717
"dedup_keys": {
1818
"type": "object",
1919
"description": "Deduplication keys for reconciling this event with the merchant's own server-side reporting. Without these, the same transaction may be counted twice in analytics and reporting platforms.",
20+
"minProperties": 1,
2021
"properties": {
2122
"event_id": { "type": "string", "description": "Shared dedup key. The merchant includes this same event_id when reporting the event via their server-side integration (e.g., CAPI, Enhanced Conversions, Events API) to prevent double-counting." },
2223
"session_id": { "type": "string", "description": "Platform session identifier for cross-event correlation (e.g., fbp, ga_session_id)." }
@@ -37,10 +38,35 @@
3738
"custom": {
3839
"type": "object",
3940
"description": "Platform-specific key-value pairs not covered by the structured fields above. Merchants pass these through to their analytics integrations based on the platform field.",
40-
"additionalProperties": true
41+
"additionalProperties": {
42+
"type": ["string", "number", "boolean"]
43+
},
44+
"maxProperties": 20
4145
}
4246
}
4347
},
48+
"dev.ucp.shopping.cart": {
49+
"title": "Cart with Attribution",
50+
"description": "Cart extended with referral attribution.",
51+
"allOf": [
52+
{
53+
"$ref": "cart.json"
54+
},
55+
{
56+
"type": "object",
57+
"properties": {
58+
"attribution": {
59+
"$ref": "#/$defs/attribution_payload",
60+
"description": "Referral attribution data from the platform that drove the cart.",
61+
"ucp_request": {
62+
"create": "optional",
63+
"update": "optional"
64+
}
65+
}
66+
}
67+
}
68+
]
69+
},
4470
"dev.ucp.shopping.checkout": {
4571
"title": "Checkout with Attribution",
4672
"description": "Checkout extended with referral attribution.",

0 commit comments

Comments
 (0)