Skip to main content

Catalogs

Catalogs are all the ingredients you give sellers so they can assemble great outcomes for your brand. An e-commerce brand pushes its product catalog — SKUs, prices, images — so platforms can build sponsored product carousels. A travel advertiser pushes flights, hotels, and destination guides. An employer pushes job openings. A retailer pushes store locations and real-time inventory. A brand pushes its offerings, services, and seasonal campaigns. The richer the ingredients, the better the result. On AI platforms especially, your catalog data IS the creative input — the platform’s LLM assembles ads from your products, offerings, and brand context rather than serving a pre-built banner. But catalogs matter beyond AI media too: any seller that dynamically assembles ads from your data — retail media networks, commerce platforms, native ad networks — benefits from richer catalog feeds. Catalogs also connect directly to measurement. Push your store catalog and a seller can correlate ad delivery to store-level foot traffic. Push your product catalog and a retail media network can close the loop on purchase attribution. The same data that enables better creative also enables better measurement.

How it works

  • Formats declare what catalog types they need as catalog asset types in their assets array
  • Buyers sync catalogs to seller accounts via sync_catalogs, with platform review and approval
  • Creatives reference synced catalogs by catalog_id in the manifest’s assets map instead of embedding items inline

Which catalog type should I use?

Pick the catalog type that matches what you’re advertising. Each vertical type (job through app) has a defined AdCP schema with examples — see the catalog item schemas page for field tables and starter templates. Structural types (product, inventory, promotion) use freeform schemas that map to your existing feed format via feed_format and feed_field_mappings.

Where sync_catalogs fits

sync_catalogs is a buyer-to-seller task. The buyer pushes catalog feeds to the seller’s account, and the seller reviews and approves them before they can be used in campaigns.

The actors

Lifecycle position

sync_catalogs sits between format discovery and creative submission. The buyer must know what catalog types a format needs before syncing, and must have approved catalogs before creatives can reference them. This is the same dependency order documented in Account state: sync_catalogssync_creativescreate_media_buy.

When to use sync_catalogs vs inline

Not every workflow requires sync_catalogs. Use it when:
  • Platform review is needed — product catalogs that go through content policy checks (like Google Merchant Center)
  • Feeds change frequently — point to a URL and let the platform re-fetch on a schedule
  • Multiple creatives share the same feed — sync once, reference by catalog_id from many creatives
  • The seller may already have the data — use discovery mode to see what’s already on the account
For simple campaigns with a few items, inline catalogs as assets in the creative’s assets map work fine — no sync step needed.

Catalog types

Catalog types fall into two categories: structural types that describe the data’s role, and vertical types that define industry-specific item schemas.

Structural types

Vertical types

Each vertical type has a defined AdCP item schema, so formats can declare catalog_type: "hotel" and both sides know the required fields without consulting platform-specific documentation.

Typed catalog assets

Vertical catalog items support an assets array using the same OfferingAssetGroup structure as offering-type catalogs. This solves a concrete problem: standard catalog feeds have a single image_url field, but a hotel ad on Snap needs a 1080×1920 vertical image, a display banner needs a 1920×1080 landscape hero, and the advertiser’s logo goes in a separate slot. Without typed pools, a creative agent has to guess which image to use for which slot. By providing assets grouped by role, each catalog item self-describes the images it carries:
The asset_group_id vocabulary is not standardized at the protocol level — each format defines which group IDs it uses via offering_asset_constraints in the catalog asset’s requirements. Common conventions: images_landscape (16:9), images_vertical (9:16), images_square (1:1), logo, video. Video pools are first-class catalog asset groups alongside image pools — beyond the generic video pool, orientation-specific video_vertical (9:16) and video_horizontal (16:9) pool IDs let a feed carry per-orientation video the same way the image pools do. Formats use field_bindings (see Format catalog requirements) to explicitly declare which template slot maps to which asset group.

The Catalog object

Schema URL: /schemas/core/catalog.json
test=false

Conversion events

The conversion_events field creates an explicit link between catalog items and the conversion tracking system. When a buyer syncs a catalog with conversion events declared, the platform knows which events to attribute to which catalog items. The event’s content_ids field carries the item IDs that connect back. The content_id_type field declares what identifier type content_ids values represent — for example, gtin for cross-retailer product matching or job_id for job postings. This tells the platform which field on catalog items to match against. Omit content_id_type when using a custom identifier scheme. Natural mappings by vertical: These mappings are not enforced by the schema — they’re declared by the buyer when syncing a catalog. A job catalog that also tracks lead events alongside submit_application is perfectly valid.

Sourcing catalogs

There are three ways to provide catalog data, each suited to a different stage of maturity:

Inline items

Any catalog type can embed items directly via the items array. The item schema depends on the catalog type:
Vertical types use their industry-specific item schema:

External feed URL

For feeds managed outside AdCP, point to a URL and let the platform fetch:

Reference to synced catalog

For catalogs already on the account via sync_catalogs, reference by catalog_id:

Syncing catalogs

For catalogs that change frequently or require platform review, use sync_catalogs to give them a managed lifecycle on the account. This is the same pattern as sync_creatives — upsert semantics, async approval, per-item status.

Why sync?

  • Platform review: Product catalogs go through content policy checks (like Google Merchant Center reviewing product listings). sync_catalogs returns per-item approval status.
  • Feed management: Point to an external feed URL and the platform re-fetches on a schedule, rather than the buyer re-syncing on every change.
  • Multi-feed creatives: Formats can require multiple catalog types (product + inventory + store). Syncing catalogs separately lets creatives reference them by catalog_id.
  • Approval workflow: Async responses notify the buyer when items are approved, rejected, or flagged for issues.

Sync request

Sync response with item-level review

Discovery mode

Omit catalogs to list all catalogs on the account without modification:
This matters because sellers may already have brand data from other sources — a retailer might have the brand’s product catalog from their commerce platform. Discovery lets the buyer build on existing state rather than re-uploading everything.

Feed field mappings

External feeds rarely match the AdCP catalog item schema exactly. Field names differ, dates use platform-specific formats, prices may be encoded as integer cents, and images arrive as untyped URLs. feed_field_mappings provides a declarative normalization layer — included on the catalog object in the sync_catalogs request — so buyers can describe the translation without preprocessing every feed.
Each mapping entry is one of:

Supported transforms

Multiple mappings can assemble a nested object. The price.amount and price.currency mappings above each write one field of the price object independently.

Item schema reference

Each vertical catalog type has a defined item schema with field tables, required fields, and starter templates. See Catalog item schemas for the complete reference with minimal and full examples for every vertical type.

Format catalog requirements

Formats that render product listings, store locators, or promotional content declare what catalog feeds they need as catalog asset types in their assets array. Each catalog asset carries requirements with fields like catalog_type, min_items, and required_fields. This tells buying agents which catalogs to sync before submitting creatives.
Buying agents check catalog asset types in the format’s assets array after discovering formats, sync the required catalogs via sync_catalogs, then submit creatives that reference those catalogs.

Field bindings

Formats can declare field_bindings inside the catalog asset’s requirements to explicitly map template slots to catalog item fields or asset pools. This makes the format self-describing — creative agents don’t have to guess which catalog field maps to which template slot.
For repeatable groups (carousels where each slide is one catalog item), use format_group_id with catalog_item: true inside the catalog asset’s requirements.field_bindings:
Field bindings are optional — creative agents can still infer mappings from field names and asset types when bindings are absent. Providing them removes ambiguity and enables pre-render validation.

Catalogs in creatives

Creatives reference catalogs as entries in the manifest’s assets map. Each catalog asset is keyed by the asset_id declared in the format (e.g., product_catalog). This is a data reference — it tells the creative what items to render (products for a carousel, locations for a store locator). It is not a campaign expansion directive; campaign structure and budget allocation are handled by create_media_buy packages. When a format declares catalog asset types, the buying agent syncs the required catalogs to the account, then populates the corresponding asset keys in the creative’s assets map to reference the synced data.

Workflow

  1. Discover format requirements — Call list_creative_formats and check the format’s assets array for catalog asset types and their requirements.
  2. Sync catalogs — Use sync_catalogs to push the required feeds to the account. Wait for approval.
  3. Submit the creative — Reference the synced catalog by catalog_id in the corresponding asset key:

Offerings

Schema URL: /schemas/core/offering.json An Offering is an individual promotable item within an offering-type catalog — a campaign, product, service, promotion, or vacancy. Each offering is a semantic unit with its own name, validity window, landing URL, creative assets, and geographic scope.
test=false

OfferingAssetGroup

Schema URL: /schemas/core/offering-asset-group.json A typed pool of creative assets within an offering. Uses the same asset_group_id vocabulary as format-level asset definitions, enabling formats to declare per-group constraints on what each offering must provide.
test=false

OfferingAssetConstraint

Schema URL: /schemas/core/requirements/offering-asset-constraint.json Declared by a format to specify what asset groups each offering must provide. Used within a catalog asset’s requirements to constrain what offerings in a catalog must provide.
test=false

Format requirements for offerings

Call list_creative_formats and check the format’s assets array for catalog asset types to see what catalog types are needed and what each offering must provide:

Stores

Schema URL: /schemas/core/store-item.json A StoreItem represents a physical location within a store-type catalog. Each store carries coordinates, an optional address, and one or more catchment areas that define the geographic reach around that location.
test=false

Catchment areas

Schema URL: /schemas/core/catchment.json A catchment defines the geographic area a store serves. Three methods are supported — provide exactly one per catchment: Isochrone inputs — the platform resolves the shape from travel time and transport mode, accounting for road networks, transit routes, and terrain:
Simple radius — a circle around the store’s coordinates:
Pre-computed GeoJSON — the buyer has already calculated the boundary (via TravelTime, Mapbox, etc.) or has custom trade area data:
A store can have multiple catchments — different modes produce different boundaries. An urban flagship might define a 10-minute walking catchment AND a 15-minute driving catchment:
The catchment_id is what targeting references — a campaign can target the walk catchment of specific stores or the drive catchment of all stores in the catalog.

Inline store catalog

SI integration

Offerings in a catalog can be promoted through Sponsored Intelligence conversations. The brand’s SI agent URL is declared on the brand identity, not on the catalog — SI is a brand-level capability. The offering_id connects a catalog item to a conversation:
  1. User expresses intent — “I need flights to LA next week”
  2. Publisher matches to offering — Uses keywords to find relevant offerings, checks valid_from/valid_to
  3. Publisher initiates SI session — Passes offering_id and user context to the brand’s SI agent
  4. Brand agent responds — With contextual information, UI elements, and a conversational experience
Display creatives and SI can coexist: the same offering can serve a display ad and also be available for a conversational experience.

Use cases

Universal format (asset pool)

The buyer provides multiple offerings, each with their own creative asset pool. The publisher picks the most relevant offering and assembles the best headline/image combination:

Product catalog with synced feeds

For retail media, sync product and inventory feeds, then reference them in creatives:
The publisher assembles the creative from the synced product data and real-time inventory.

Conversational-only

No pre-built creatives — just offerings available for SI conversations. The brand’s SI agent URL is discovered from the brand identity:

Location-specific offerings

For brands with multiple physical locations — restaurants, retail chains, job vacancies — each offering declares its geographic scope via geo_targets:
Geo targets on offerings are about what the offering IS — the Amsterdam vacancy genuinely doesn’t exist for someone in Rotterdam. Campaign-wide geo targeting belongs on targeting_overlay in the package.

Catalogs in the media buy lifecycle

Catalogs flow through the entire media buy lifecycle — from product discovery to delivery reporting.

Catalog-driven discovery

Pass a catalog on get_products to find products that match your catalog items. The seller matches catalog items against its inventory and returns products where matches exist. Products declare which catalog types they support via catalog_types.

Catalog-driven packages

Include a catalog field on a package in create_media_buy to make it catalog-driven. One budget envelope promotes the entire catalog — the platform optimizes delivery across items based on performance. This is the AdCP equivalent of catalog-based campaign types like Google Performance Max or Meta Dynamic Product Ads.

Variants as catalog items

For catalog-driven packages, each catalog item rendered as a distinct ad execution is a creative variant. The variant’s manifest includes the catalog reference with the specific item rendered.

Per-item delivery reporting

get_media_buy_delivery returns by_catalog_item breakdowns within each package, showing per-item impressions, spend, clicks, conversions, and ROAS.

Conversion attribution

Conversion events carry content_ids that identify which catalog items were involved. The catalog’s content_id_type declares the identifier type. Attribution is broad — a user might click item A but convert on item B. The event fires with the actual content_id. See conversion tracking.

Item-level tracking via macros

For impression-level attribution (which item was clicked, which was viewed), use catalog item macros in your creative’s tracker pixel URLs. The macros mirror the content_id_type enum — the same identifiers used at serve time that appear in conversion events:
At serve time, the platform substitutes {OFFERING_ID} with the specific offering being rendered. For a carousel showing 5 offerings, each item’s impression fires with that item’s identifier. Use the macro matching your catalog’s content_id_type: This creates a closed attribution loop: the same identifiers appear in impression trackers (via macros at serve time), click trackers, and conversion events (via content_ids at event time).

Catalog content macros

The macros above resolve to the rendered item’s identifier. Catalog content macros resolve to a rendered item’s scalar field values, for catalog-driven creative templates (sponsored_placement / DPA — Meta DPA, Snap Collection, TikTok Shopping). Each token maps 1:1 to a catalog item field via the same catalog_field dot-notation paths used by field_bindings — content macros reuse that vocabulary rather than defining a parallel one: Content macros use single-brace {MACRO} syntax and substitute under the same substitution-safety rules as the ID macros (NFC normalization → RFC 3986 percent-encoding → one-pass nested-expansion prohibition → URL-context scope). {{double-brace}} is not a content-macro syntax — it stays reserved for downstream ad-server macros the sales agent must neutralize. URL-valued and image-valued fields (landing_url, image pools) bind via field_bindings to url/asset slots, not content macros. Which items render is seller-declared via the fanout_mode enum on the sponsored_placement format (single_item for the Meta-DPA one-item-per-ad pattern, per_item, or multi_item_in_creative) — there is no buyer-side selection field. On ML-optimized DPA surfaces the platform may override buyer-authored overlay text, so content macros are a hint the seller MAY honor.

Best practices

Match asset_group_id to the format’s vocabulary

Read the format definition from list_creative_formats before building offerings. The asset_group_id values must match exactly what the format declares in offering_asset_constraints within each catalog asset’s requirements. Group IDs like headlines, images, or videos are format-defined vocabulary, not protocol constants — each format chooses its own IDs. The protocol provides the container and constraint mechanism; the format defines the vocabulary.

Provide more assets than the minimum

Formats that use asset pools select the best-performing combination. Providing the maximum allowed items gives the publisher more to work with.

Set validity windows

For time-limited promotions, always set valid_from and valid_to. Publishers filter expired offerings automatically.

Use geo_targets for inherently location-specific offerings

When an offering’s identity is tied to a geographic location — a job vacancy, an in-store promotion, a local event — declare its scope with geo_targets. This is not ad targeting; it’s a property of what the offering IS.

Always provide landing_url on catalog offerings

For catalog-driven creatives, landing_url is the per-item click-through destination that platforms map to the ad’s link-out URL (swipe-up, CTA button, carousel card link). Every offering in a catalog should have a landing_url. Include checkout_url as well when direct conversion is supported.

Budget distribution across catalog items

Budget allocation across catalog items is a platform optimization decision — some platforms distribute evenly, others allocate based on performance signals. The protocol does not prescribe a specific distribution method. Budget lives on create_media_buy packages, not on individual offerings. If your campaign requires specific per-item budget caps, use separate packages per offering.