Skip to content

RFC #3305 amendment: product topology — sub-product structure for cross-surface meta-products (PMax, Meta Advantage+, Amazon DSP) #4549

@bokelley

Description

@bokelley

Type: spec amendment to #3305
Target: 3.1 (before GA — together with #4548)
Severity: load-bearing for adopter onboarding — PMax / Advantage+ / Amazon DSP are flagship products at their respective platforms; they can't be honestly represented in v2 today
Companion to: #4548 (order-logic scoping — separate axis)

Problem

Several flagship platform products are meta-products that fan out across multiple surfaces with per-surface policies:

  • Google Performance Max (PMax) — one product, six surfaces (Search, Display, YouTube, Discover, Gmail, Maps). Each surface has different creative requirements, tracking models, targeting capabilities, brand safety controls. The advertiser doesn't choose surfaces; PMax ML decides.
  • Meta Advantage+ — Facebook feed + Instagram feed + Reels + Stories + Marketplace + Audience Network. Similar fanout.
  • Snap Public Profile suite — multiple surfaces with different formats per surface.
  • TikTok Spark Ads — For You Page + Following feed + profile views.
  • Amazon DSP — web display + OTT + mobile + Twitch as distinct surface types.

v2 today gives Product a channels: [\"display\", \"video\", \"social\"] array. That's too coarse — it says "this product serves on display channels" but doesn't capture:

  • Per-surface creative requirements (PMax's YouTube surface needs video_hosted; the Search surface needs text-only responsive_creative; the Display surface accepts image or html5 or responsive_creative)
  • Per-surface tracking models (Search has CTR + position; Display has viewability; YouTube has VTR)
  • Per-surface targeting capabilities (Search keyword targeting works on Search surfaces; doesn't apply on Display)
  • Per-surface brand safety / inventory controls

Today a seller has two bad options: (a) declare a single Product with channels: [display, video, social] and lie about uniformity, OR (b) declare six separate Products and lose the "this is one logical product" framing buyers expect. Neither is honest.

Proposed change

Add Product.sub_products: SubProduct[] describing the surface-fanout structure.

{
  \"product_id\": \"google_pmax\",
  \"name\": \"Google Performance Max\",
  \"sub_products\": [
    {
      \"sub_product_id\": \"pmax_search\",
      \"surface\": \"google_search\",
      \"channels\": [\"search\"],
      \"format_options\": [{\"format_kind\": \"responsive_creative\", \"params\": {/* search-specific narrowing */}}],
      \"targeting_capabilities\": {\"keyword_targeting\": {/* see #4548 */}},
      \"reporting_capabilities\": {/* search-specific metrics */}
    },
    {
      \"sub_product_id\": \"pmax_youtube\",
      \"surface\": \"youtube\",
      \"channels\": [\"olv\"],
      \"format_options\": [{\"format_kind\": \"video_hosted\", \"params\": {/* youtube-specific */}}],
      \"targeting_capabilities\": {\"audience_targeting\": {/* see #4548 */}},
      \"reporting_capabilities\": {/* video-specific metrics */}
    },
    {
      \"sub_product_id\": \"pmax_display\",
      \"surface\": \"google_display\",
      \"channels\": [\"display\"],
      \"format_options\": [/* image, html5, responsive_creative */],
      \"targeting_capabilities\": {/* display-specific */},
      \"reporting_capabilities\": {/* display-specific */}
    }
    // ... discover, gmail, maps
  ]
}

Inheritance: a sub-product's fields override the parent Product's fields when present. Pricing, publisher properties, delivery type stay on the parent unless explicitly overridden per sub-product. Buyers reason about the parent Product for "is this a PMax buy?"; they reason about sub-products for "what creative does the YouTube surface accept?"

surface vocabulary: a new shared registry (/schemas/registries/surface-vocabulary.json, governance same as asset-group-vocabulary). Seed entries: google_search, google_display, youtube, google_discover, gmail, google_maps, facebook_feed, instagram_feed, instagram_reels, instagram_stories, meta_audience_network, snap_public_profile, tiktok_fyp, amazon_web_display, amazon_ott, amazon_twitch, etc.

Open questions

  1. Sub-product fanout vs separate Products — Could we get the same expressiveness with multiple flat Products joined via umbrella_product_id: \"google_pmax\"? Pro: less new schema. Con: loses "buyer reasons about PMax as one logical thing"; reporting aggregation requires special-case logic.

  2. Channels at parent vs sub-product — Should Product.channels still exist when sub_products is present? Lean: parent.channels = union(sub_products[*].channels), automatically derived. Buyers see consistent channel coverage either way.

  3. Inheritance semantics — Should sub-product fields override parent fields or merge with them? Lean: override-when-present, inherit-when-absent. Same semantics as applies_to_channels on format_options.

  4. Reporting aggregation — PMax reports aggregate by default but lets you drill down per surface. Does reporting_capabilities apply at the parent level (aggregate) or per sub-product (drill-down) or both? Probably both, with the parent's reporting_capabilities describing the aggregate view and each sub-product's describing the drill-down.

  5. Interaction with applies_to_channels on format_options[i] — Is this redundant once sub_products exists? Lean: no — applies_to_channels is per-creative-option on a flat product (Flashtalking html5 OR internal display_tag on the same display surface); sub_products is per-surface structural fanout (PMax-shaped). Different axes.

Why this matters

PMax is Google's flagship buying product. Meta Advantage+ is Meta's. These can't ship in v2 without either lying about uniformity or fragmenting into six separate Products with no umbrella. Either choice undermines the "v2 is honest about real products" pitch. Adopters working on these integrations have already hit the gap; without a clean structural answer, they'll route around it via platform_extensions or by inventing seller-specific conventions.

Companion work

#4548 (sibling issue) addresses order logic — match types, audience signals, bid modifiers. The two RFCs share the targeting_capabilities / targeting field shape; sub-products in this RFC inherit and override the parent's targeting_capabilities from #4548. Both should land together so the PMax mapping is coherent end-to-end (one parent, six sub-products, each with its own creative envelope + targeting capability set).

Refs

  • #3305 — v2 RFC
  • #3307 — v2 implementation branch
  • #4548 — order-logic scoping companion

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions