diff --git a/.changeset/add-device-platform-exclude.md b/.changeset/add-device-platform-exclude.md new file mode 100644 index 0000000000..0fc66c5c74 --- /dev/null +++ b/.changeset/add-device-platform-exclude.md @@ -0,0 +1,5 @@ +--- +"adcontextprotocol": minor +--- + +Add `targeting.device_platform_exclude` as the typed operating-system exclusion companion to `device_platform`, with exclude-wins and reject-rather-than-drop semantics. diff --git a/docs/media-buy/advanced-topics/targeting.mdx b/docs/media-buy/advanced-topics/targeting.mdx index 407f0efbf4..51a4274c39 100644 --- a/docs/media-buy/advanced-topics/targeting.mdx +++ b/docs/media-buy/advanced-topics/targeting.mdx @@ -485,10 +485,13 @@ Use for **technical requirements**: ```json { "$schema": "/schemas/core/targeting.json", - "device_platform": ["ios", "android"] + "device_platform": ["ios", "android"], + "device_platform_exclude": ["fire_os"] } ``` +Use `device_platform_exclude` when a campaign supports most platforms with a small deny-list. Exclusion wins if a value appears in both arrays. Device-platform inclusion and exclusion support are implied by `media_buy`; a seller that cannot enforce a requested platform constraint must reject it rather than broaden delivery. + **Available platforms** (defined in [`device-platform.json`](https://adcontextprotocol.org/schemas/v3/enums/device-platform.json), based on Sec-CH-UA-Platform standard extended for CTV): - Browser: `ios`, `android`, `windows`, `macos`, `linux`, `chromeos` - CTV: `tvos`, `tizen`, `webos`, `fire_os`, `roku_os` @@ -831,6 +834,14 @@ For products where inventory and audience planning are inseparable, such as line - **Use cases**: App install campaigns (iOS-only app), CTV-specific campaigns - **Values**: `ios`, `android`, `windows`, `macos`, `linux`, `chromeos`, `tvos`, `tizen`, `webos`, `fire_os`, `roku_os` +### device_platform_exclude +- **Description**: Exclude specific operating-system platforms from delivery +- **Format**: Array of device platform identifiers +- **Examples**: `["fire_os"]`, `["tvos", "roku_os"]` +- **Use cases**: Exclude platforms incompatible with an app, landing experience, or creative runtime +- **Conflict rule**: Exclusion wins when a platform is present in both `device_platform` and `device_platform_exclude` +- **Note**: Support is implied by `media_buy`; sellers reject constraints they cannot enforce + ### device_type - **Description**: Restrict to specific device form factors - **Format**: Array of device type identifiers diff --git a/docs/protocol/get_adcp_capabilities.mdx b/docs/protocol/get_adcp_capabilities.mdx index ecf8de5734..95fb0b447b 100644 --- a/docs/protocol/get_adcp_capabilities.mdx +++ b/docs/protocol/get_adcp_capabilities.mdx @@ -244,7 +244,7 @@ The following fields have been removed from the capabilities response: - `features.content_standards` — Replaced by `media_buy.content_standards` object. Presence of the object indicates support. - `features.audience_targeting` — Replaced by `media_buy.audience_targeting` object. Presence of the object indicates support. - `features.conversion_tracking` — Replaced by `media_buy.conversion_tracking` object. Presence of the object indicates support. -- `execution.targeting.device_platform`, `device_type` — Implied by `media_buy` support. +- `execution.targeting.device_platform`, `device_platform_exclude`, `device_type`, `device_type_exclude` — Implied by `media_buy` support. - `execution.targeting.audience_include`, `audience_exclude` — Implied by `audience_targeting` object presence. - `execution.trusted_match.supported` — Object presence indicates support. - `brand.identity` — Implied by `brand` in `supported_protocols`. `get_brand_identity` is always available. diff --git a/static/schemas/source/core/targeting.json b/static/schemas/source/core/targeting.json index 2d1bb5edc0..172f216a6a 100644 --- a/static/schemas/source/core/targeting.json +++ b/static/schemas/source/core/targeting.json @@ -210,6 +210,14 @@ }, "minItems": 1 }, + "device_platform_exclude": { + "type": "array", + "description": "Exclude specific operating-system platforms from delivery. Uses the same canonical device-platform vocabulary as device_platform. Exclusion wins when a platform appears in both include and exclude arrays. Support is implied by media_buy support; sellers MUST reject an exclusion they cannot enforce rather than silently dropping it.", + "items": { + "$ref": "/schemas/enums/device-platform.json" + }, + "minItems": 1 + }, "device_type": { "type": "array", "description": "Restrict to specific device form factors. Use for campaigns targeting hardware categories rather than operating systems (e.g., mobile-only promotions, CTV campaigns).", diff --git a/tests/device-platform-exclude.test.cjs b/tests/device-platform-exclude.test.cjs new file mode 100644 index 0000000000..055166f396 --- /dev/null +++ b/tests/device-platform-exclude.test.cjs @@ -0,0 +1,25 @@ +const assert = require('node:assert/strict'); +const fs = require('node:fs'); +const path = require('node:path'); +const { describe, it } = require('node:test'); + +const targeting = JSON.parse(fs.readFileSync( + path.join(__dirname, '..', 'static', 'schemas', 'source', 'core', 'targeting.json'), + 'utf8', +)); + +describe('device_platform_exclude targeting overlay', () => { + it('uses the canonical device-platform enum with a non-empty array', () => { + const field = targeting.properties.device_platform_exclude; + assert.equal(field.type, 'array'); + assert.equal(field.minItems, 1); + assert.equal(field.items.$ref, '/schemas/enums/device-platform.json'); + }); + + it('pins exclude-wins and reject-rather-than-drop semantics', () => { + const description = targeting.properties.device_platform_exclude.description; + assert.match(description, /Exclusion wins/); + assert.match(description, /MUST reject/); + assert.match(description, /silently dropping/); + }); +});