Skip to content

feat: add attribution extension for checkout sessions#295

Open
jamesandersen wants to merge 2 commits intoUniversal-Commerce-Protocol:mainfrom
jamesandersen:feat/attribution-extension
Open

feat: add attribution extension for checkout sessions#295
jamesandersen wants to merge 2 commits intoUniversal-Commerce-Protocol:mainfrom
jamesandersen:feat/attribution-extension

Conversation

@jamesandersen
Copy link
Copy Markdown

Enhancement Proposal: Attribution Extension

Summary

An optional attribution extension for UCP checkout sessions that enables referring platforms to pass attribution data and deduplication keys through agentic checkout flows — preserving the merchant's analytics and ROI measurement capabilities that are otherwise lost when the checkout bypasses the merchant's website.

Motivation

When a user discovers a product through any external channel — a paid ad, an organic recommendation, an influencer link, or an AI agent's suggestion — and completes a purchase via an agentic commerce protocol, the merchant loses the attribution data they normally receive. In the traditional web flow, this data arrives via URL parameters on the merchant's landing page (e.g., utm_source, utm_campaign, platform-specific click IDs like gclid, fbclid, ttclid). With agentic checkout, the user never visits the landing page, so these parameters are never set.

This creates two critical problems for merchants:

  1. Merchants lose channel attribution and ROI visibility — Without campaign and channel identifiers flowing through to the conversion event, merchants cannot attribute sales to the channels that drove them. This breaks the analytics pipelines that merchants rely on to measure channel performance, optimize budgets, and evaluate return on spend. Tools like Google Analytics, Northbeam, and Triple Whale all depend on UTM parameters and click IDs arriving with the transaction to build attribution models. When these signals are missing, the merchant's analytics show agentic purchases as "direct" or "unattributed" traffic.

  2. Conversion reporting double-counts transactions — When a purchase completes through an agentic flow, both the referring platform and the merchant's existing server-side integration (e.g., Meta Conversions API, Google Enhanced Conversions, TikTok Events API) may report the same transaction independently. Without a shared deduplication key, the same conversion is counted twice — inflating metrics and corrupting automated bidding data.

This affects every platform that refers users to merchant products through agentic checkout — including Google, Meta, TikTok, Snap, Pinterest, OpenAI/ChatGPT, and others.

Goals

  • Enable referring platforms to pass structured attribution data (UTM parameters, platform-specific identifiers) through agentic checkout to the merchant
  • Provide deduplication keys so merchants can reconcile agentic transactions with their existing server-side reporting
  • Preserve compatibility with existing merchant analytics tools (Google Analytics, Northbeam, Triple Whale, etc.)
  • Support any referring platform — not limited to a specific platform or channel type

Non-Goals

  • Multi-touch attribution modeling — this is the merchant's domain, handled by their analytics tools downstream
  • Prescribing how merchants should process or store attribution data
  • Defining platform-specific deduplication protocols — each platform has its own model (Google uses gclid + order_id, Meta/TikTok use event_id, etc.)
  • Content creator attribution (covered by Issue #185)
  • Agent discovery telemetry (covered by Issue #180)

Related Work

Proposal Focus Relationship
Issue #180 — Attribution Signals Agent discovery context (how/why product recommended) Complementary — #180 is about the agent's reasoning; this is about the referral channel data
Issue #185 — Content Citation Content creator attribution (reviews/guides influence) Complementary — focuses on content influence tracking
PR #10 — Affiliate Attribution Affiliate tracking (stalled) Overlapping — this proposal is broader, covering all referral platforms not just affiliates

Neither #180 nor #185 addresses the use case where the platform that referred a user to a product needs to pass attribution data through the checkout flow to the merchant.

Detailed Design

Extension Schema

The extension follows the same composition pattern as fulfillment.json and discount.json: defines the extended checkout in $defs["dev.ucp.shopping.checkout"] using allOf to compose onto checkout.json, with ucp_request annotations specifying per-operation behavior.

Attribution Payload:

Field Type Required Description
platform string Yes Referring platform identifier (reverse domain naming). SHOULD correspond to the domain of the platform's UCP-Agent profile URL.
dedup_keys object No Deduplication keys for reconciling with the merchant's server-side reporting
utm object No Standard UTM parameters for web analytics compatibility
custom object No Platform-specific key-value pairs routed by the merchant based on the platform field

Dedup Keys:

Field Type Description
event_id string Shared dedup key for reconciling with the merchant's server-side reporting
session_id string Platform session identifier for cross-event correlation (e.g., fbp, ga_session_id)

UTM Parameters: utm_source, utm_medium, utm_campaign, utm_content, utm_term, utm_id

Request Behavior:

Operation Behavior
create optional
update optional
complete optional

Usage Examples

Google (Google Ads / Gemini) — A user discovers a product through a Google Shopping ad and completes the purchase via agentic checkout:

{
  "attribution": {
    "platform": "com.google",
    "dedup_keys": {
      "session_id": "GA1.2.1234567890.1710300000"
    },
    "utm": {
      "utm_source": "google",
      "utm_medium": "cpc",
      "utm_campaign": "spring_collection_2026",
      "utm_content": "60123456789",
      "utm_id": "18234567890"
    },
    "custom": {
      "click_id": "EAIaIQobChMI8bXe7...",
      "ad_group_id": "142345678901",
      "placement": "Google_Shopping",
      "gbraid": "WVLA4QjBkaJkZW..."
    }
  }
}

Meta — A user discovers a product through Meta's platform and their AI agent completes the purchase:

{
  "attribution": {
    "platform": "com.meta",
    "dedup_keys": {
      "event_id": "evt_abc123def456",
      "session_id": "fb.1.1710300000000.1234567890"
    },
    "utm": {
      "utm_source": "meta",
      "utm_medium": "paid_social",
      "utm_campaign": "spring_sale_2026",
      "utm_content": "6861203971771",
      "utm_id": "6861196821371"
    },
    "custom": {
      "click_id": "IwY2xjawOR56Fle...",
      "placement": "Meta_AI"
    }
  }
}

TikTok — A user discovers a product via TikTok and completes the purchase through an agentic flow:

{
  "attribution": {
    "platform": "com.tiktok",
    "dedup_keys": {
      "event_id": "evt_tt_xyz789abc012"
    },
    "utm": {
      "utm_source": "tiktok",
      "utm_medium": "paid_social",
      "utm_campaign": "spring_launch_2026"
    },
    "custom": {
      "click_id": "E.C.P.abcdef123456..."
    }
  }
}

OpenAI (ChatGPT Shopping) — Even without a traditional campaign, the platform provides attribution context:

{
  "attribution": {
    "platform": "com.openai",
    "dedup_keys": {
      "event_id": "evt_oai_def456ghi789"
    },
    "utm": {
      "utm_source": "chatgpt",
      "utm_medium": "agentic",
      "utm_campaign": "shopping_recommendations"
    }
  }
}

Design Rationale

  1. Follows UCP extension pattern — uses allOf composition onto checkout.json with ucp_request annotations, matching fulfillment.json and discount.json. Capability declarations (platform_schema, business_schema) follow the same pattern as fulfillment.json.
  2. Separate from signals — UCP's signals property carries environment data for authorization and abuse prevention. Attribution serves a different purpose: marketing analytics context. Mixing them would conflate security/risk data with marketing data.
  3. Single attribution object — Each platform provides one attribution payload per checkout. Multi-touch attribution across platforms is the merchant's domain.
  4. UTM as the universal attribution layer — UTM parameters are the universal language of web analytics that merchants already know how to process.
  5. Dedup keys as first-class concept — Different platforms use different dedup models. The dedup_keys object accommodates all models with optional fields.
  6. Platform-namespaced — Reverse domain naming provides a clean discriminator. The platform value SHOULD correspond to the domain of the platform's UCP-Agent profile URL, linking attribution identity to protocol identity without coupling to UCP-specific constructs.
  7. Custom field for platform-specific data — Platform-specific identifiers go in custom, keeping the core schema minimal and universal.

Risks and Mitigations

Risk Mitigation
Privacy concerns about passing tracking data Attribution data flows from the referring platform (which already has it) to the merchant (who would have received it via URL params in the web flow). No new data is created.
Schema bloat from platform-specific fields Core schema covers only universal fields (UTM, dedup keys). All platform-specific identifiers go in custom.
Inconsistent dedup models across platforms dedup_keys fields are all optional. Each platform populates only the fields relevant to its dedup model.
Overlap with existing proposals (#180, #185, PR #10) Complementary to #180 and #185 (different data, different use case). PR #10 is stalled and narrower in scope.

Test Plan

  • JSON Schema validation: validate all usage examples against the schema
  • Round-trip test: create checkout with attribution, verify it persists through update and complete operations
  • Missing fields: verify checkout succeeds when attribution is omitted entirely (optional extension)
  • Platform routing: verify merchants can discriminate by platform field and route to correct analytics integration

Graduation Criteria

  • Schema merged into UCP source
  • Specification documentation complete
  • 2+ independent implementations (per UCP Enhancement Proposal process)
  • TC majority vote for Candidate status

Code Changes

New Files:

  • source/schemas/shopping/attribution.json — Extension schema with $defs containing attribution_payload and dev.ucp.shopping.checkout composition
  • docs/specification/attribution.md — Extension documentation

Modified Files:

  • mkdocs.yml — Added attribution extension to nav and llmstxt sections
  • .cspell/custom-words.txt — Added attribution-related terms

Note: No modifications to checkout.json are required. UCP extensions compose onto checkout via allOf in the extension schema (same pattern as fulfillment.json, discount.json).

Discussion Points

  • custom field constraints: The current schema defines custom as an open object (additionalProperties: true) with no constraints on value types or size. The ACP Affiliate Attribution RFC applies constraints to its equivalent metadata field: keys MUST be strings; values MUST be strings, numbers, or booleans; arrays and nested objects are NOT permitted; implementations MAY enforce limits (e.g., ≤ 20 keys, ≤ 4KB total). Adopting similar constraints would provide cross-protocol consistency.

References


Type of change

  • New feature (non-breaking change which adds functionality)
  • Documentation update

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings

Enable referring platforms to pass attribution data (UTM parameters,
deduplication keys, platform-specific identifiers) through agentic
checkout flows. Preserves merchant analytics and ROI measurement
capabilities that are otherwise lost when checkout bypasses the
merchant's website.
@jamesandersen jamesandersen force-pushed the feat/attribution-extension branch from c3072a5 to bd739fb Compare March 23, 2026 23:40
@igrigorik igrigorik added the TC review Ready for TC review label Mar 30, 2026
}
}
},
"dev.ucp.shopping.checkout": {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should attribution extension be applied to Cart as well, in addition to Checkout? Please see discounts extension as an example where it can extend both cart and checkout. In future, it could extend other events as well, but for now maybe starting with Cart and Checkout is a good idea. What do you think?

"dedup_keys": {
"type": "object",
"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.",
"properties": {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both event_id and session_id are optional, making an empty dedup_keys: {} schema-valid and semantically meaningless. Should we add "minProperties": 1 to prevent this?

If dedup_keys is there, we should have alteast 1 additional property.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense - updated

"custom": {
"type": "object",
"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.",
"additionalProperties": true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you flagged this as a discussion point, I think it is a good idea to add some constraints e.g

"additionalProperties": {
    "type": ["string", "number", "boolean"]
  },
 "maxProperties": 50

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even 50 feels pretty generous so just added this but set maxProperties to 20 as a start

The merchant passes `event_id` and `fbp` (from `session_id`) to their
Conversions API integration. The shared `event_id` prevents duplicate event
counting between the platform's first-party event and the merchant's server-side
event.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a callout for privacy:
e.g something like -

Privacy Note:

Platforms and Businesses implementing this extension SHOULD ensure that the transmission of attribution data complies with applicable privacy laws and the user's consent preferences. Data passed via the utm, dedup_keys, or custom fields should only be used for the purposes of attribution and conversion reporting as authorized by the user.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good callout ... let me think about this a bit - the data flowing through here is ideally unrelated to the user (e.g. not derived from the user or user identifiable) but rather a flow between the agent and the business to replace data that normally flows via the website.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright added some language to reinforce the privacy posture of this extension ... definitely open to more tweaks on the language but was trying to find something striking a reasonable balance of firmness without being anchored or implying any specific jurisdictions/ regulations / privacy policy / terms of service etc.

"properties": {
"platform": {
"$ref": "types/reverse_domain_name.json",
"description": "Referring platform identifier (reverse domain naming). SHOULD correspond to the domain of the platform's UCP-Agent profile URL.",
Copy link
Copy Markdown
Contributor

@amithanda amithanda Apr 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about using MUST for better security? With SHOULD it is possible that a platform could pass com.google attribution while being a different platform entirely.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, good call; updated.

…d 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
@jamesandersen jamesandersen force-pushed the feat/attribution-extension branch from c4b2cf1 to 9b6cfdf Compare April 1, 2026 06:43
@amithanda
Copy link
Copy Markdown
Contributor

amithanda commented Apr 3, 2026

Thanks @jamesandersen for quick iteration on the PR, it is looking quite good. We had an internal review on this and there are some interesting questions that we identified. We will add those shortly to the PR and we can do another pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

TC review Ready for TC review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants