Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/assignment-tracker-no-slot-claim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"adcontextprotocol": minor
---

Assignment trackers: tracker-slot limits apply only when the effective format declares at least one tracker slot (a `pixel_tracker` slot or a canonical `impression_tracker`, `click_tracker`, or `viewability_tracker` slot). A format that declares none, such as canonical `image`, makes no slot-limit claim, so a seller does not reject an assignment tracker for lack of a slot; it still fires every accepted tracker or rejects the assignment. Trackers match slots by event (`impression_tracker` takes `impression`, `click_tracker` takes `click`, `viewability_tracker` takes the `viewable_*` events and `audible_video_complete`, any other `pixel_tracker` slot takes any event), and the same rules govern trackers a `replace` transfers (#8713).
11 changes: 10 additions & 1 deletion docs/creative/task-reference/sync_creatives.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,16 @@ Each entry contains `event` and `url`, with `custom_event_name` required and non

The seller MUST fire every accepted assignment tracker at its declared event or reject the assignment through existing assignment errors. This includes unknown custom events and events that cannot fire on the assigned format; silent no-op behavior is not permitted. Where a `tracker_execution_contract` applies, match assignment entries as `pixel_tracker` with `method: "img"` and the entry's event/custom name, respecting its execution actor and firing paths. An unlisted selector in a complete contract rejects the assignment; an undeclared selector does not waive the fire-or-reject requirement. The capability alone does not promise that every format accepts every event.

Assignment trackers and the creative's own trackers count together against the effective format's tracker-slot limits, including canonical `params.slots[].max` and legacy repeatable-group `max_count`. Each assignment tracker consumes one occurrence in one compatible declared tracker slot; existing creative assets retain their slot occupancy. Sellers MAY choose any allocation that satisfies every slot's asset type, event role, and count constraints, but MUST NOT pool capacity from incompatible slots or move creative assets to make room. If no valid allocation exists, the seller MUST reject the assignment rather than dropping trackers or modifying the creative. Each supplied occurrence fires once per logical event; identical URLs are not deduplicated, including when the same URL also appears in a creative asset.
Assignment trackers and the creative's own trackers count together against the effective format's tracker-slot limits, including canonical `params.slots[].max` and legacy repeatable-group `max_count`. A tracker slot is a declared slot with `asset_type: "pixel_tracker"`, or one whose `asset_group_id` is a canonical tracker slot (`impression_tracker`, `click_tracker`, `viewability_tracker`). Each assignment tracker consumes one occurrence in one compatible tracker slot; existing creative assets retain their slot occupancy. A tracker is compatible by event:

- `impression_tracker` takes `impression`;
- `click_tracker` takes `click`;
- `viewability_tracker` takes the `viewable_*` events and `audible_video_complete`;
- any other `pixel_tracker` slot takes any event.

Sellers MAY choose any allocation that satisfies every slot's event and count constraints, but MUST NOT pool capacity from incompatible slots or move creative assets to make room. If no valid allocation exists, the seller MUST reject the assignment rather than dropping trackers or modifying the creative.

These limits apply only when the effective format declares at least one tracker slot. A format that declares none, such as the canonical `image` format, whose tracking model fires trackers through macros, makes no slot-limit claim: the seller does not reject an assignment tracker for lack of a slot. The fire-or-reject rule above still applies, so the seller MUST fire every accepted tracker at its declared event or reject the assignment, for example for an event the format cannot fire. The same rules govern trackers that a [`replace`](#replacing-a-creative-on-a-package) transfers, counted alongside the replacement creative's own trackers. Each supplied occurrence fires once per logical event; identical URLs are not deduplicated, including when the same URL also appears in a creative asset.

Tracker URLs use the existing [macro-bearing URL rules](/docs/creative/universal-macros#template-syntax) without declarations, including 3.x compatibility behavior. Declarations on creative assets do not transfer to these URLs. Neither URL syntax nor assignment tracker support guarantees resolution of any particular macro; check the seller's macro resolution capabilities. Buyers can put their own known buy/package values directly in the URL, avoiding a dependency on seller ID substitution. Readback preserves the accepted templates.

Expand Down
2 changes: 1 addition & 1 deletion docs/creative/tracker-execution-contracts.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Neither promise implies the other. A seller can resolve `{CACHEBUSTER}` without

This 3.2 surface covers only first-class `pixel_tracker`, `vast_tracker`, and `daast_tracker` manifest assets. It does not inspect trackers embedded in fetched VAST/DAAST documents, wrappers, JavaScript responses, or generic URL assets. Runtime preview observation is a separate, later capability; the production commitment does not depend on it.

In AdCP 3.3, capability-gated [assignment trackers](/docs/creative/task-reference/sync_creatives#assignment-trackers) are also checked against the effective package contract as `pixel_tracker` with `method: "img"` and their event/custom name. They fire alongside the creative's trackers and count against the same format tracker-slot limits. An unlisted selector in a complete contract rejects the assignment. Even without a declared selector, an accepted assignment tracker MUST fire at its event or the seller MUST reject the assignment; unknown custom events cannot silently no-op.
In AdCP 3.3, capability-gated [assignment trackers](/docs/creative/task-reference/sync_creatives#assignment-trackers) are also checked against the effective package contract as `pixel_tracker` with `method: "img"` and their event/custom name. They fire alongside the creative's trackers and count against the same format tracker-slot limits where the format declares tracker slots; a format that declares none makes no slot-limit claim (see [assignment trackers](/docs/creative/task-reference/sync_creatives#assignment-trackers)). An unlisted selector in a complete contract rejects the assignment. Even without a declared selector, an accepted assignment tracker MUST fire at its event or the seller MUST reject the assignment; unknown custom events cannot silently no-op.

## Product-format authority

Expand Down
2 changes: 1 addition & 1 deletion docs/protocol/get_adcp_capabilities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1524,7 +1524,7 @@ Creative protocol capabilities. Only present if `creative` is in `supported_prot
| `has_creative_library` | boolean | When `true`, the agent exposes reusable [`sync_creatives`](/docs/creative/task-reference/sync_creatives) and `list_creatives` library operations. |
| `supports_provenance` | boolean | Added in 3.3; defaults to `false`. Opts in to product provenance policy enforcement and trusted-verifier handling on `sync_creatives`. A creative library alone does not imply support. Sellers that omit this flag or set it to `false` skip the provenance storyboards. Any provenance policy a seller publishes still applies. |
| `stable_creative_ids` | boolean | When `true`, every creative that entered the library outside [`sync_creatives`](/docs/creative/task-reference/sync_creatives#seller-assigned-creative-ids) gets a seller-assigned `creative_id` that stays the same for the creative's lifetime, is unique within the account, and never reuses a buyer's ID, and `delete_missing` never archives those creatives. Lets a buyer that connects to an advertiser with existing creatives reference them reliably. Requires `has_creative_library: true`. When `false` or absent, sellers SHOULD follow the same rules but buyers MUST NOT rely on them. |
| `supports_assignment_trackers` | boolean | Added in 3.3; defaults to `false`. When `true`, accepts assignment-scoped `trackers` in create/update media buy and sync assignment requests, fires them alongside the creative's own trackers or rejects the assignment, enforces shared format tracker-slot limits, and returns the assignment tracker list in readback. Requires `has_creative_library: true`. When `false` or absent, buyers MUST NOT send the field and the agent MUST reject it with [`UNSUPPORTED_FEATURE`](/docs/building/verification/compliance-catalog#error-code-unsupported-feature). Independent of landing-page override support. See [assignment trackers](/docs/creative/task-reference/sync_creatives#assignment-trackers). |
| `supports_assignment_trackers` | boolean | Added in 3.3; defaults to `false`. When `true`, accepts assignment-scoped `trackers` in create/update media buy and sync assignment requests, fires them alongside the creative's own trackers or rejects the assignment, enforces shared format tracker-slot limits where the format declares tracker slots, and returns the assignment tracker list in readback. Requires `has_creative_library: true`. When `false` or absent, buyers MUST NOT send the field and the agent MUST reject it with [`UNSUPPORTED_FEATURE`](/docs/building/verification/compliance-catalog#error-code-unsupported-feature). Independent of landing-page override support. See [assignment trackers](/docs/creative/task-reference/sync_creatives#assignment-trackers). |
| `supports_revisions` | boolean | When `true`, the library accepts buyer-authored immutable `revision_id` values and preserves them through sync echo, current readback, review attribution, and revision-homogeneous delivery rows. Requires `has_creative_library: true`. Does not imply revision history, rollback, or staged activation. |
| `supports_assignment_landing_page` | boolean | Added in 3.3; defaults to `false`. When `true`, accepts assignment-scoped `landing_page_url` in create/update media buy and sync assignment requests, serves the override or rejects the assignment, and reports the effective destination in assignment readback. Requires `has_creative_library: true`. When `false` or absent, buyers MUST NOT send the field and the agent MUST reject it with [`UNSUPPORTED_FEATURE`](/docs/building/verification/compliance-catalog#error-code-unsupported-feature). See [assignment landing pages](/docs/creative/task-reference/sync_creatives#assignment-landing-pages). |
| `live_updates` | object | Experimental; added in 3.3. Which kinds of change (`click_through`, `trackers`, `asset_content`, `format`) the agent applies in place to a live creative under the same `creative_id`, and how the creative serves while each is decided: `uninterrupted`, `staged` (the prior version serves until the change is approved; `on_rejection` is `keeps_prior` or `stops`), or `paused_for_review`. A floor: listed kinds are accepted on every live creative in the listed mode or a less disruptive one. Optional `max_propagation_seconds` bounds how long a prior version may still serve after a change applies. A declaring agent refuses other changes with [`CREATIVE_LIVE_UPDATE_UNSUPPORTED`](/docs/building/verification/compliance-catalog#error-code-creative-live-update-unsupported) and answers the exact outcome of one change on a [`sync_creatives` `dry_run`](/docs/creative/task-reference/sync_creatives#live-creative-updates). Requires `has_creative_library: true`. See [Live creative updates](/docs/creative/task-reference/sync_creatives#live-creative-updates). |
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/migration/3-2-to-3-3.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ Optional. `list_creatives` may return `seller_revision` on each creative: a sell

### Assignment landing pages and trackers

A seller that declares `creative.supports_assignment_landing_page: true` (requires a creative library) accepts `landing_page_url` on a package creative assignment, `sync_creatives` `assignments[]`, and `assign` operations. The override changes the destination for one creative on one package without changing the library creative or its approval; the seller serves it everywhere it applies or rejects the assignment, and returns the actual destination from `list_creatives` and `get_media_buys`. Agents without the capability reject the field with `UNSUPPORTED_FEATURE`. Likewise, a seller that declares `creative.supports_assignment_trackers: true` accepts assignment-scoped measurement `trackers`, fires them alongside the creative's own without changing its revision or approval, enforces the format's tracker-slot limits, and returns the assignment-only list from `list_creatives` and `get_media_buys` (#8220). See [Assignment landing pages](/docs/creative/task-reference/sync_creatives#assignment-landing-pages).
A seller that declares `creative.supports_assignment_landing_page: true` (requires a creative library) accepts `landing_page_url` on a package creative assignment, `sync_creatives` `assignments[]`, and `assign` operations. The override changes the destination for one creative on one package without changing the library creative or its approval; the seller serves it everywhere it applies or rejects the assignment, and returns the actual destination from `list_creatives` and `get_media_buys`. Agents without the capability reject the field with `UNSUPPORTED_FEATURE`. Likewise, a seller that declares `creative.supports_assignment_trackers: true` accepts assignment-scoped measurement `trackers`, fires them alongside the creative's own without changing its revision or approval, enforces the format's tracker-slot limits where the format declares tracker slots (a format that declares none makes no slot-limit claim, #8713), and returns the assignment-only list from `list_creatives` and `get_media_buys` (#8220). See [Assignment landing pages](/docs/creative/task-reference/sync_creatives#assignment-landing-pages).

### Hosted video and audio playback trackers

Expand Down
2 changes: 1 addition & 1 deletion static/schemas/source/core/creative-assignment.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"type": "array",
"items": { "$ref": "/schemas/core/assignment-tracker.json" },
"minItems": 1,
"description": "Additional measurement trackers for this creative on this package only, fired alongside the creative's own trackers without changing the library creative, its revision, or its approval. Requires creative.supports_assignment_trackers: true; buyers MUST NOT send this field otherwise and unsupported agents MUST reject it with UNSUPPORTED_FEATURE. The seller MUST fire every accepted tracker at its declared event or reject the assignment through existing assignment errors; trackers MUST NOT be silently dropped. Creative and assignment trackers together count against the effective format's tracker-slot limits, including canonical params.slots[].max and legacy repeatable-group max_count. Each assignment tracker consumes one compatible slot occurrence without moving creative assets; reject if no allocation satisfies each slot's type, event role, and count constraints. Each accepted occurrence fires once per logical event; identical URLs are not deduplicated. A supplied list replaces the prior assignment tracker list. Omission from a complete package creative_assignments replacement clears the assignment trackers; omitting the entire replacement array leaves assignments unchanged. Empty arrays and null are not accepted.",
"description": "Additional measurement trackers for this creative on this package only, fired alongside the creative's own trackers without changing the library creative, its revision, or its approval. Requires creative.supports_assignment_trackers: true; buyers MUST NOT send this field otherwise and unsupported agents MUST reject it with UNSUPPORTED_FEATURE. The seller MUST fire every accepted tracker at its declared event or reject the assignment through existing assignment errors; trackers MUST NOT be silently dropped. Creative and assignment trackers together count against the effective format's tracker-slot limits, including canonical params.slots[].max and legacy repeatable-group max_count. Each assignment tracker consumes one compatible tracker-slot occurrence without moving creative assets (impression_tracker takes impression, click_tracker takes click, viewability_tracker takes viewable_* and audible_video_complete, any other pixel_tracker slot takes any event); reject if no allocation satisfies each slot's event and count constraints. These limits apply only when the effective format declares at least one tracker slot: a format that declares none makes no slot-limit claim, and the seller still fires every accepted tracker or rejects the assignment. Each accepted occurrence fires once per logical event; identical URLs are not deduplicated. A supplied list replaces the prior assignment tracker list. Omission from a complete package creative_assignments replacement clears the assignment trackers; omitting the entire replacement array leaves assignments unchanged. Empty arrays and null are not accepted.",
"x-added-in": "3.3.0"
},
"landing_page_url": {
Expand Down
Loading
Loading