Signal Definition

A signal definition is one entry in a data provider's published adagents.json signals[]: AdCP 3.1.13 gives it 31 fields, seven of identity and shape, three of them required (id, name, value_type), and 24 optional provenance and consent disclosures.

A signal definition is the authoritative record of one targeting signal, published by the domain that owns the data. AdCP 3.1.13 puts 31 properties on the object and requires three: id, pattern ^[a-zA-Z0-9_-]+$ and local to the domain; name; and value_type, one of binary, categorical or numeric, which determines the shape of any targeting expression written against the signal.

core/signal-definition.json says where the record lives in its opening line: “Definition of a signal in published adagents.json signals[]. The publishing domain supplies the namespace, so this definition carries a local id rather than a signal_ref.” A data provider hosts adagents.json on its own domain, and signals[] inside it holds the definitions. A product that offers the signal points at it with a signal_ref of scope data_provider. The buyer resolves that ref to the provider’s domain, fetches the file and reads the entry its owner published, so a seller’s account of a segment can be checked against the owner’s record. That check is what separates a signal from an audience the buyer uploaded.

Definition, listing and ref are three different schemas

SchemaRoleWhere it appears
signal-definition.jsonthe record the provider publishesa data provider’s adagents.json signals[]
signal-listing.jsonidentity metadata lifted out of itproduct included_signals, get_signals results
signal-ref.jsona pointer with a scope discriminatortargeting expressions, activation

signal-listing.json states the boundary: “Product-local signals use the listing as the definition boundary and MUST include name and value_type.” signal-ref.json adds three scopes, product, data_provider and signal_source, and states that “scope is the resolution path, not provenance”.

get-signals-response.json carries a fourth shape, signal_id, marked “DEPRECATED. Use signal_ref instead. Legacy SignalId retained for compatibility with older Signals Protocol clients.” A buyer agent written against an older release still sends that shape, and a seller that reads only signal_ref will not see it.

Seven fields are identity and shape: id, name, description, value_type, tags, allowed_values, range. The other 24 describe where the segment came from and under what legal basis. AdCP factors 19 of those 24 into core/signal-definition-enrichment.json, the file the get_signals response reuses; the remaining five live on the definition and nowhere else.

Some of the 24 resolve to a value a buyer agent can branch on. The table below groups the ones that share an enum; the rest are URLs, nested objects, country lists and timestamps.

FieldValue space
methodologyobserved, declared, derived, inferred, modeled
data_sources17 values, web_usage and loyalty_card through public_record_voter_file
subject_typeindividual, household, business, contextual, none
resolution_methoddeterministic_id, probabilistic_device, browser, geographic, content_signal, mixed
audience_scopesingle_domain, cross_domain_owned, cross_domain_unowned, offline
id_typescookie, mobile_id, platform_id, user_enabled_id
refresh_cadence8 values, intra_day to annually; lookback_window shares the enum
consent_basis, art9_basis4 GDPR Article 6 bases; then explicit_consent, manifestly_made_public, substantial_public_interest, vital_interests
restricted_attributesthe closed 10-value registry, 8 of them Article 9 special categories

Two of these fields tell a buyer what not to do with them. criteria_url points at a longer methodology document and then closes off the obvious use: “This is a disclosure pointer; buyers should not branch programmatically on the linked content.” last_updated “indicates freshness of the definition record, not an attestation that the underlying data or model was refreshed at that time”.

The five fields that live only on the definition — subject_type, resolution_method, id_types, audience_scope and originating_domain — never reach the wire. get_signals returns an allOf of exactly two schemas, signal-listing.json and signal-definition-enrichment.json, and the fields projection on get-signals-request.json enumerates 18 field names a buyer can ask for, none of them these five. The projection is not an entitlement: “fields is a projection request, not an entitlement grant; agents MAY redact requested definition fields unless the caller is authorized”, and AdCP does not define what authorises a caller. Establishing whether a segment resolves deterministically or probabilistically therefore means fetching the provider’s adagents.json directly.

The disclosure fields come from the IAB Data Transparency Standard

The 19 enrichment fields track the IAB Data Transparency Standard almost item for item. DTS v1.2, published April 2024, defines up to 20 standardised disclosure fields and ships them as a human-readable Data Label backed by an annual business audit. AdCP carries the same fields as JSON without the audit, replacing it with dts_compliant_version: the “IAB Data Transparency Standard version this signal definition self-attests as satisfying, when applicable.” dts_compliant_version is self-asserted; no party countersigns it and nothing revokes it.

When the conditional disclosure rules fire

All five of the allOf conditionals on signal-definition.json wait for the provider to declare something first.

If the definition declaresIt must then carry
value_type: categorical with a taxonomytaxonomy.value_mappings
audience_scope: single_domainoriginating_domain
methodology: modeleda modeling block
audience_expansion: truethe same modeling block
any of offline_survey, public_record_census, public_record_voter_file, public_record_other, offline_transaction in data_sourcesan onboarder

Each conditional puts a required on its own trigger field — {"if": {"properties": {"methodology": {"const": "modeled"}}, "required": ["methodology"]}} — so each keys on a field the provider is free to omit. A definition that omits methodology, audience_expansion and data_sources triggers none of the five, and a modelled lookalike validates clean as {"id": "auto_intenders_q3", "name": "Auto Intenders Q3", "value_type": "binary"}. additionalProperties is true on the definition, so unknown keys pass validation as well. policy_categories is typed as a bare {"type": "string"} array while the documentation says “Values MUST match the canonical definitions in the Policy Registry”, a constraint that exists in prose only; its neighbour restricted_attributes does $ref its enum.

AdCP states the consequence itself: “Without governance metadata, a governance agent must infer sensitivity from signal names — this is fragile and produces false positives.”

Audience targeting in AAMP

AAMP’s version of this object is one untyped field. Product.audience_targeting in iab-agentic-primitives v0.5.0 is typed {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "default": null} with the description “IAB Audience Taxonomy targeting intent”. No properties, no required keys. content_targeting and ad_product_targeting are shaped identically, and the seller-agent OpenAPI repeats the typing.

The only place a shape is committed to is Product.golden.json, the conformance fixture generated from that schema: "audience_targeting": {"segment_ids": ["1001"]}, an array of opaque strings. The Agentic Real-Time Framework, another repository in the same programme, reduces segments to a single protobuf enum value, ACTIVATE_SEGMENTS = 1.

The IAB Data Transparency Standard appears in no AAMP repository, under any of its names, though IAB Tech Lab wrote that standard and AdCP encoded 19 of its fields.