Internet-Draft MSF Ad Creative Signaling November 2026
Riedl Expires 5 May 2027 [Page]
Workgroup:
Media Over QUIC
Internet-Draft:
draft-riedl-moq-ad-creative-signaling-01
Published:
Intended Status:
Informational
Expires:
Author:
S. Riedl
Paramount

Ad Creative Signaling over the MSF Event Timeline

Abstract

This document defines the carriage of ad creative signaling -- creative identity, tracking events, and measurement verification metadata as specified by SVTA 2053-1 -- in records on a Media over QUIC (MOQT) Streaming Format (MSF) Event Timeline track. It complements the carriage of SCTE-35 splice signaling over the same mechanism: splice events describe where placement opportunities occur on a media timeline, while the event class defined here describes the creatives that fill them and how their playback is to be measured. This binding is the MSF counterpart of the DASH and HLS carriage bindings defined by SVTA 2053-1, which defines none for MOQT.

About This Document

This note is to be removed before publishing as an RFC.

The latest revision of this draft can be found at https://riedlse.github.io/draft-riedl-moq-ad-creative-signaling/draft-riedl-moq-ad-creative-signaling.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-riedl-moq-ad-creative-signaling/.

Discussion of this document takes place on the Media Over QUIC Working Group mailing list (mailto:moq@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/moq/. Subscribe at https://www.ietf.org/mailman/listinfo/moq/.

Source for this draft and an issue tracker can be found at https://github.com/riedlse/draft-riedl-moq-ad-creative-signaling.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 5 May 2027.

▲

Table of Contents

1. Introduction

SCTE-35 messages [SCTE35] carried on an MSF Event Timeline track [SCTE35-MOQ] give Media over QUIC deployments the function SCTE-35 was built for: signaling placement opportunities -- break windows and splice conditioning -- on a shared media timeline, using the Event Timeline mechanism of the MOQT Streaming Format (Section 8.1 of [MSF]). What that layer deliberately does not carry is a description of what plays inside those windows.

On HLS and DASH, that gap is filled at the manifest: a packager or stitcher decorates each session's playlist with creative identity and tracking metadata. On a one-to-many publish/subscribe transport [MOQT] there is no per-session manifest to decorate -- every subscriber receives the same cached objects -- so anything a client needs at render time (which creative is playing, which tracking resources to request at which quartiles, which verification script to load) must be delivered in band, on the shared timeline, ahead of the splice point.

This need is not incidental. Accurate measurement of server-side ad insertion increasingly means client-requested tracking -- per-device accounting at render time rather than server-side firing at publish time, which measures the wrong clock -- and verification means initializing a measurement script [OMSDK] before the slot renders. SVTA 2053-1 [SVTA2053] already standardizes exactly this payload: a Pod/Slot/TrackingEvent/Verification data model (Section 4 of [SVTA2053]), explicitly agnostic to client-side, server-side, and server-guided insertion, with carriage bindings defined per stream format -- DASH EventStream, HLS EXT-X-DATERANGE, HLS Interstitials -- and none for MOQT.

This document fills that gap using the structures [MSF] and [SCTE35-MOQ] already put in place: it defines an Event Timeline event class whose records carry SVTA 2053-1 Version 2 carriage envelopes, specifies how those records are timed and correlated with splice signaling, requires that each record carry the distributor's signature so that a subscriber can verify it independently of the relay path, and gives operational guidance for tracking on one-to-many delivery. It changes nothing in the SVTA 2053-1 data model; payload normativity remains with [SVTA2053], and this binding could additionally be published as a carriage section in a future revision of that specification.

On status: [MSF] is an adopted work item of the MoQ Working Group, and its Event Timeline mechanism is the substrate here; this document and [SCTE35-MOQ] are individual submissions layered on that substrate, and this one is written to track [MSF] as it evolves under WG change control -- including following its registry, wherever that registry ultimately lands. The event class is deployed: a continuously running server-side ad insertion deployment publishes it, and Section 11 reports what was measured.

2. Conventions and Definitions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

This document uses the terms Track, Group, Object, Event Timeline, and the index reference fields t, l, and m as defined in [MSF], and the terms Pod, Slot, Tracking Event, Verification, and carriage envelope as defined in Sections 4 and 5 of [SVTA2053].

The index keys are spelled as in the published [MSF]. The MSF editor's copy has since renamed them T, L and M; this document will follow whichever spelling MSF settles on, and implementations may wish to accept both in the meantime.

Additionally:

Distributor:

The party operating the publisher that emits the media and signaling tracks (typically the party performing ad insertion).

Placement opportunity:

A window on the media timeline, typically signaled by SCTE-35, in which advertising content plays.

Splice signaling track:

An Event Timeline track carrying SCTE-35 records per [SCTE35-MOQ].

Capability URL:

A URL whose knowledge alone grants the ability to perform a narrow action, used here as a short-lived, opaque reference to a distributor-operated tracking endpoint [CAP-URLS].

3. Track Properties

An MSF track carrying ad creative signaling:

Because eventType is uniform for a track, and because implementations do not mix payload flavors within one Event Timeline track (see Section 4.3 of [SCTE35-MOQ] for the same rule applied to SCTE-35), ad creative signaling is carried on a sibling Event Timeline track alongside any splice signaling track, not interleaved within it.

A splice signaling track is not required. Ad creative signaling describes what plays inside a placement opportunity; it does not depend on how the boundaries of that opportunity were signaled. A deployment MAY carry ad creative signaling with no SCTE-35 records present, leaving break detection to another mechanism entirely -- in-band timed metadata such as ID3, an emsg box, or the timing carried by the creative records themselves. Where a splice signaling track is present, the alignment rules in Section 5.2 let the two be correlated; where it is absent, those rules simply do not apply.

4. Record Format

4.1. Structure

Each record is a JSON object [RFC8259] following the Event Timeline data format of Section 8.1 of [MSF]. A record MUST contain:

  • exactly one index reference field -- t (wallclock), l (MOQT Location), or m (media time) -- selected per Section 4.2 and typed as Section 8.1 of [MSF] defines it: t and m are JSON Numbers of milliseconds (a wallclock index is milliseconds since the Unix epoch, not a date string), and l is an Array of two Numbers, the MOQT Group ID and Object ID;

  • a data field whose value is exactly one Version 2 carriage envelope as defined in Section 4.3; and

  • a sig member holding the distributor's signature over the record, as Section 4.5 defines.

Records are carried in the Objects of the track as Section 8.3 of [MSF] specifies: the first Object of each Group is the independent array of every record accumulated and accessible so far. A subscriber that joins at a Group boundary during a placement opportunity therefore receives its record, provided the publisher keeps the record accessible until the opportunity has ended.

4.2. Index Reference Selection

Records describing creatives spliced into the media timeline SHOULD use the m (media time) index, expressed in the coordinate space of the depends media track and sharing that track's timeline zero point. The t (wallclock) index MAY be used where a placement opportunity is defined in wallclock terms and no media time is available. The l (MOQT Location) index MAY be used for records bound to a delivery position rather than a media time.

When a splice signaling track accompanies this track, records on the two tracks that describe the same point on the media timeline SHOULD carry index values of the same kind, chosen by the same precedence, so that a consumer can correlate them without converting between index types (Section 5.2). The requirement is on the observable result -- comparable indices for co-timed records -- not on adopting any particular document's selection algorithm. A deployment carrying SCTE-35 records per [SCTE35-MOQ] satisfies it by applying that specification's index selection rules (its Section 4.2) to both tracks.

4.3. Payload: Version 2 Carriage Envelope

The data field carries one SVTA 2053-1 Version 2 carriage envelope (Section 5.2.2.1 of [SVTA2053]) directly:

{ "version": 2, "type": "...", "payload": [ ... ],
  "features": { ... } }

The envelope is self-describing -- version and payload type are fields -- so no additional wrapper member is defined.

Unlike the DASH and HLS bindings, where bare Version 1 payload objects are also legal, records in this binding MUST carry Version 2 envelopes only. On a fan-out transport the envelope's features flags are the only capability-signaling mechanism available, and the envelope type field is what allows a uniform track to carry pod, slot, trackingEvent, and verification payloads interchangeably -- the four types Section 5.2.2.1 of [SVTA2053] defines.

The envelope and its payload objects use the member names and units of [SVTA2053] unchanged. In particular, every timing member inside the envelope (start, duration, offset, skipOffset) is a MediaTime: a number of seconds (Section 4.2.1 of [SVTA2053]), not milliseconds. Only the record's index reference is in milliseconds, because [MSF] defines it so.

A publisher MUST NOT set to true any features flag that [SVTA2053] does not define. Under Section 5.2.2.1 of [SVTA2053], an interpreter that meets a flag set to true that it does not support raises an error and ignores the payload, so an undefined flag makes every conforming interpreter discard the record. The only flag defined today is remoteFields, which [SVTA2053] requires to be true when the payload uses $remote (Section 7); a payload that does not use $remote can omit features entirely.

This document places no requirement of its own on receivers. A receiver applies Section 5.2.2.1 of [SVTA2053] unchanged: a flag set to true that it does not support means it ignores that payload, while a flag set to false, or an absent features member, asks nothing of it. The publisher-side rule is needed because on one-to-many delivery the publisher never learns that a record was discarded (item 6 of Section 10).

Two inconsistencies in [SVTA2053] matter to parsers. Its TrackingEvent payload table (Table 11) lists start and duration where its object model (Section 4.4.5) defines offset, and its Remote Fields table (Table 16) says a $remote.verifications URI resolves to an envelope of type verifications where the envelope (Table 15) defines verification. This document follows the object model and the envelope definition: TrackingEvent timing is offset, and the envelope type is verification.

It is RECOMMENDED that a publisher emit one pod envelope per placement opportunity. The slot, trackingEvent, and verification envelopes MAY be used (mirroring the granularity options of the DASH binding), but deduplication under redelivery is simplest at pod granularity, and a decomposed record loses the structural link to the slot it belongs to (see Section 10).

4.4. Subscriber Invariance

Records on this track MUST be subscriber-invariant: no field value may vary between subscribers. Per-session values enter only after delivery, either by client-side macro substitution (Section 6 of [VAST]) against broadcast templates, or by request-time indirection through capability URLs (Section 7). A macro template is conformant precisely because the template is identical for every subscriber; substitution is a post-delivery operation.

The DASH and HLS bindings of [SVTA2053] assume a per-session manifest, so payload fields carrying session-scoped tracking values are well-formed in those bindings. That assumption does not hold here: records on a shared Event Timeline track are delivered identically to every subscriber and are relay-cacheable, so a session-scoped field would both leak across sessions and defeat caching.

4.5. Record Signature

Every record MUST carry a sig member holding a signature by the distributor over the rest of the record, so that a subscriber can verify a record's origin and integrity without trusting the relay path (Section 12.1). The signature is a JWS [RFC7515] in the JWS Compact Serialization with a detached, unencoded payload [RFC7797]: the protected header carries "b64": false and "crit": ["b64"], and the sig value has the form BASE64URL(protected header) ".." BASE64URL(signature).

The JWS Payload is the JSON Canonicalization Scheme [RFC8785] serialization of the record object with its sig member removed: the index reference and the data envelope, canonicalized. The canonical form is the signing input only. The record is transmitted in whatever serialization the publisher produces, and a relay or library may re-serialize it -- member order, whitespace, number formatting within the rules of [RFC8785] -- without invalidating the signature. The signature is per record rather than per Object because Section 8.3 of [MSF] re-forms the array of accumulated records at every Group; a per-record signature survives that and lets each record be verified on its own.

The protected header MUST contain alg and kid. Publishers and verifiers MUST support "alg": "EdDSA" with Ed25519 keys [RFC8032] [RFC8037]; other asymmetric JWS algorithms MAY be used where a distributor and its clients agree. The algorithm MUST be an asymmetric signature: "none" and the MAC algorithms (HS256, HS384, HS512) MUST NOT be used by publishers and MUST be rejected by verifiers, because every subscriber holds the verification key, and a key that verifies a MAC also forges one. Verifiers MUST NOT take keys from jku, jwk, x5u or x5c header parameters; a record that carries them is verified against the provisioned key set as if they were absent.

A distributor publishes its verification keys as a JWK Set [RFC7517], each key carrying the kid its signatures name. How a client obtains the key set is out of scope for this document; a deployment typically provisions it with the playback session, alongside the client identifier of Section 7.1. Keys are rotated by publishing the new key before any record is signed with it, and retiring the old key only after every record signed with it has left the accessible window (Section 4.1). A distributor SHOULD use a distinct kid per channel, so that a verifier can reject a validly signed record substituted from another channel.

A verifier MUST check that the sig member is present and well formed, that alg is permitted, that kid names a key in the current set, and that the signature verifies over the canonical payload. A record that fails any of these checks MUST be treated as absent for the purposes of Section 7: no tracking, $remote, verification or click-through resource it names is requested. Media playback is unaffected; the record is advisory. A verifier MAY report the failure to the distributor over a channel established out of band, which gives the distributor evidence of tampering on paths it does not operate.

The signature is subscriber-invariant (Section 4.4) and so remains relay-cacheable. It costs one 64-byte signature and a short protected header per record, and one Ed25519 verification per record received. [VECTORS] contains a signed record with the test key that signed it and a script that signs and verifies records; the example in Section 6 omits sig for brevity.

5. Timing and Correlation

5.1. Shared Index Space

A creative signaling record's index values are interpreted in the same coordinate space, with the same timeline zero point, as the depends media track -- and therefore the same space as an accompanying splice signaling track that names the same media track.

5.2. Correlation with Splice Signaling

The record or records describing a placement opportunity SHOULD carry the same index value as the SCTE-35 record whose splice point opens that opportunity (the same m, or the same l Location when the splice is immediate). A pod whose start differs from the splice point MUST carry an index within the window the splice defines.

5.3. Publication Lead

The publisher SHOULD publish a placement opportunity's creative signaling record(s) at least one full Group ahead of the media Group containing the splice point. Clients render seconds behind delivery, while render-time tracking and verification fire windows are sub-second: the tracking table must already be resident on the device when the first ad frame displays, with no time for a lookup round trip.

5.4. Container-Relative Interior Timing

Within the envelope, timing is container-relative, per Sections 4.4.2 and 4.4.5 of [SVTA2053]: a Slot's start is relative to its Pod, and a Tracking Event's offset is relative to its container. Only the record's index reference is absolute. Consequently, redelivery, looped schedules, and regional timeline shifts never require payload rewrites -- which matters where relays cache and re-serve objects.

When an envelope carries Slot or TrackingEvent objects without their Pod (a slot or trackingEvent envelope), the record's index stands in for the missing container: a Slot's start and a Tracking Event's offset are relative to the record's index. A standalone Slot therefore normally has start 0, as the per-slot events of the DASH binding do (Section 6.1.2 of [SVTA2053]).

6. Worked Example

An SCTE-35 record on the splice signaling track (reproduced from Section 5.1 of [SCTE35-MOQ]) announces a splice at media time 480500 ms:

{
  "m": 480500,
  "data": {
    "scte35_payload":
      "/DAhAAAAAAAAAP/wFAUAAArXf+/+AAAAAH4AARSyAAAAAA=="
  }
}

The companion record on the ad creative signaling track, published at least one Group earlier (Section 5.3), carries the same index. It describes a 45.045-second pod with two slots: explicit quartile tracking and a verification resource on slot 1 (no offset on the quartile events, so timing is driven by event-type semantics per Section 4.4.5 of [SVTA2053]), and lazily resolved tracking on slot 2 via $remote (Section 7):

{
  "m": 480500,
  "data": {
    "version": 2,
    "type": "pod",
    "payload": [{
      "duration": 45.045,
      "slots": [
        {
          "type": "linear",
          "start": 0.0,
          "duration": 30.03,
          "identifiers": [{
            "scheme":
      "urn:smpte:ul:060E2B34.01040101.01200900.00000000",
            "value": "ABCD1234567H"
          }],
          "tracking": [
            { "type": "impression", "urls": [
              "https://beacons.example.net/c/7f3a92/imp"
            ] },
            { "type": "firstQuartile", "urls": [
              "https://beacons.example.net/c/7f3a92/q1"
            ] },
            { "type": "midpoint", "urls": [
              "https://beacons.example.net/c/7f3a92/q2"
            ] },
            { "type": "thirdQuartile", "urls": [
              "https://beacons.example.net/c/7f3a92/q3"
            ] },
            { "type": "complete", "urls": [
              "https://beacons.example.net/c/7f3a92/done"
            ] }
          ],
          "verifications": [{
            "vendor": "vendor.example-omid",
            "parameters": "key=value",
            "resource":
              "https://cdn.vendor.example/omid-verify.js"
          }]
        },
        {
          "type": "linear",
          "start": 30.03,
          "duration": 15.015,
          "identifiers": [{
            "scheme": "urn:com:example:ads:id",
            "value":
              "972c79e1-2363-403e-9287-a0fa4323c389"
          }],
          "$remote": {
            "tracking":
              "https://beacons.example.net/c/9d41c7/trk"
          }
        }
      ],
      "tracking": [
        { "type": "podStart", "urls": [
          "https://beacons.example.net/c/p8842/start"
        ] },
        { "type": "podEnd", "urls": [
          "https://beacons.example.net/c/p8842/end"
        ] }
      ]
    }],
    "features": { "remoteFields": true }
  }
}

The remoteFields flag is set because slot 2 uses $remote. This record is also published as the worked-example test vector. The appendix on test vectors (Appendix "JSON Schema and Test Vectors") shows a record captured from the running deployment.

7. Tracking Indirection and Capability URLs

Two patterns satisfy Section 4.4. In the first, the record carries broadcast tracking templates and the client performs macro substitution locally at activation; SVTA 2053-1 payloads carry over from the DASH and HLS bindings unchanged and no distributor infrastructure is required, at the cost of exposing vendor endpoint inventory in shared bytes, inflating every record by the full tracking list, and leaving per-device accounting to the macros alone. The second, described in the remainder of this section, defers resolution to a distributor-operated endpoint. Both are conformant; a publisher chooses per deployment.

Section 5.2.2.2.2 of [SVTA2053] already says interpreters SHOULD defer $remote resolution until the containing object is about to become active. That deferral maps naturally onto broadcast fan-out, with one addition: on a shared timeline, the URLs in tracking and $remote fields SHOULD be short-lived capability URLs [CAP-URLS] referencing a distributor-operated tracking endpoint (a "beacon proxy"), rather than raw measurement-vendor URLs.

At activation, the client requests the capability URL (or resolves $remote from it), appending a client identifier (Section 7.1). The endpoint performs macro substitution per Section 6 of [VAST] (as Section 5.2.3 of [SVTA2053] provides) and requests the corresponding vendor resources with the calling device's context. Two properties fall out for free on one-to-many delivery:

7.1. Client Identity and Per-Device Accounting

Because every subscriber receives identical records, per-device measurement requires the device to identify itself at request time, not in the payload. A client SHOULD append a pseudonymous, session-scoped client identifier (issued and signed out of band, for example with the playback session) as a query parameter when requesting capability URLs. This mechanism applies to the indirection pattern; under client-side substitution, per-device accounting rests on the macro values alone. The tracking endpoint can then deduplicate on (resource, event, client identifier), count unique reach, and forward at most one request per device per event to vendor resources with that device's context -- preserving per-device measurement semantics without per-device payloads. Raw device identifiers MUST NOT appear in requested URLs.

7.2. Load Shaping

On a shared fixed timeline, every subscriber reaches the same tracking instant at the same wallclock moment; naive activation-time behavior synchronizes both the $remote resolution fetches and the tracking requests of the entire audience. This applies with particular force under client-side substitution, where no distributor endpoint sits in the path to absorb the burst. Clients SHOULD resolve $remote fields within a randomized window ahead of activation (the publication lead of Section 5.3 provides the margin), and SHOULD apply bounded random jitter to tracking requests whose measurement semantics tolerate it, carrying the original event time as data where the measurement moment must be preserved. Verification-critical requests with sub-second fire windows are the exception and are expected to be provisioned for.

8. Per-Session Insertion Plans

Everything above is deliberately identical bytes for every subscriber -- that is what makes it relay-cacheable. Server-guided insertion, per-session capability URLs, and entitlement-scoped fields are per-session by definition and cannot ride the shared timeline. The authors believe the standardization target for that layer is a separate per-session insertion plan mechanism: a unicast-scoped metadata track (or equivalent side channel) carrying distributor session metadata -- the session's pod assignment for each shared-timeline placement opportunity, its capability URLs, and policy fields -- which composes with the shared events defined here (the shared timeline announces placement geometry and the broadcast/default pod; the insertion plan overlays the per-session decision).

Between those two extremes there is a third scope worth naming, because the choice is not binary. Records can be published per cohort: one track per distinct ad decision, shared by every device that resolves to it. Per-device plans are by definition uncacheable -- one subscriber per track -- which forfeits the fan-out that motivates one-to-many delivery in the first place and reduces to per-session manifest stitching with extra steps. Cohort scope keeps relay fan-out within each cohort and bounds the number of distinct tracks by the number of decisions rather than the number of viewers. Server-guided insertion can therefore be served at whichever of the three scopes the deployment's decisioning actually requires.

The event class defined here is unchanged across all three: shared, per-cohort, and per-session differ in the scope of the track carrying the records, not in the records themselves. That is deliberate -- scope is a deployment decision, and this binding should not have to be redefined to follow it.

That per-session mechanism is out of scope for this document and deserves its own. It is named here only as a design constraint: the event class defined in this document is intended to be overridden or parameterized by such a layer without being redefined by it.

9. Track Split and Future Carriage

This section is informative; nothing in it changes the requirements above.

Ad signaling is expected to grow by function rather than by record size. Interactivity, click-through handling, and third-party verification are each better carried on their own sibling Event Timeline track, with its own eventType, the same depends media track and the same index space, than as further members of the records defined here. A client then subscribes only to the functions it implements, which settles much of the feature-negotiation question for whole functions (item 6 of Section 10), and each function's records keep their own size, cadence and failure behavior. The cost is the missing placement identifier (item 8 of Section 10): once records describing one placement opportunity are spread across tracks, a shared index identifies the opportunity but not the slot within it.

Separately, [MOQT] today defines properties at Track and Object scope only. A proposal before the MoQ Working Group [MOQT-SUBGROUP-PROPS] would carry properties in the subgroup header, where they travel with every stream that carries the subgroup, including FETCH responses, instead of riding a first Object that a mid-Group joiner, a filter or a FETCH range can miss. If it is adopted, break-level state -- an opportunity identifier, the remaining break duration, the Group at which content resumes -- could be carried in the subgroup headers of the media track itself. That would complement the records defined here rather than replace them: subgroup properties describe the break at the delivery position as it is delivered, while the Event Timeline describes the creatives ahead of the splice.

The data model itself is also growing. SVTA is preparing a 3rd edition, [SVTA2053-2], for non-linear (concurrent) ad and editorial presentations such as overlays, squeezebacks and L-shapes. It is specified as an additive extension of the Version 2 carriage envelope (a Viewport data type, a PresentationType enumeration and layout control) and defines carriage for DASH and HLS. This document carries the Version 2 envelope without interpreting the payload objects (Appendix "JSON Schema and Test Vectors"), so payloads using those extensions would ride unchanged on an ad creative signaling track. Carriage over the MSF Event Timeline, as defined here, is a candidate for a later SVTA2053 edition.

10. Open Issues

This section lists issues to be resolved through working group discussion; it is to be removed before publication.

  1. Granularity: one pod envelope per placement opportunity (the RECOMMENDED default), or slot, trackingEvent and verification envelopes per creative? Redelivery deduplication is simpler at pod granularity. The deployment described in Section 11 publishes pod envelopes only and has not needed anything finer.

  2. Update semantics for live: pods change close to air. Is a later record at the same index a full supersede (last-writer-wins), or is a patch rule needed? [SVTA2053] has no cancel/supersede concept; SCTE-35 inherits cancellation from its payload semantics. Implementation experience favors the simple rule. When a splice fails, the deployed publisher publishes a complete new record with the same m, dropping the failed slot and moving the later ones to where they really air, and its player replaces only the events it has not yet fired. No patch rule has been needed so far.

  3. Deduplication and late joiners: the DASH/HLS bindings give each event a manifest-unique id for dedup on re-encounter; MSF records carry no id. Is (eventType, index, payload) a sufficient dedup key under relay redelivery and FETCH catch-up -- and which past records MUST a mid-break joiner fetch? Experience so far: with one pod record per opportunity, m alone has served as the record key (a changed payload at a known m is a supersede), and the player fires each event at most once per (m, slot, event type). For late joiners the deployed publisher keeps each record in every independent Object until 60 s after its pod ends, and re-sends the retained array as a new Group about every 3 s when nothing has changed, so a subscriber that starts at the next Group rather than the latest one holds the timeline within seconds. Whether that re-send deserves a SHOULD is open.

  4. Switching sets: when ladder rungs are separate tracks, does one creative signaling track depends on all of them? Splice conditioning can land at slightly different media times per rung; container-relative interior offsets survive that, but a single m may not. Sender-side track switching under discussion in the MOQ Working Group sharpens this: if relays select the delivered rung per subscriber and switch at Group boundaries, (a) these records must remain valid for every rung of a switching set, (b) splice conditioning must keep switching sets coherent at placement boundaries, and (c) the delivered rendition is known only at the client, so rendition-level measurement is necessarily client-observed.

    That mechanism now has a concrete shape to test against. The SWITCH_FROM proposal distinguishes an aligned switch, where Group IDs from the two tracks are compared, from an unaligned switch, where they are not. The distinction decides this issue directly: a single m on one signaling track can only address a switching set if switches are aligned, since an unaligned switch leaves no common Group-ID frame in which one index means the same instant on every rung. Under unaligned switching the interior offsets survive but m does not, which would push the binding toward either a per-rung signaling track or an index defined against something other than the media track's Group IDs. The proposal was not resolved at the 2026-09-08 interim; at the 2026-10-14 interim the working group took the direction of reducing it to the group-aligned mode, with other modes left to extensions, and a consensus call is pending as of this revision. At least one implementation (MOQtail) reports partial draft-18 support, so experience should be available before this document has to choose.

  5. Common-format scope: is the Event Timeline binding the whole story, or is a container-level mapping (the envelope in CMAF emsg) also wanted so one payload survives packager transit across HLS/DASH/MOQT boundaries?

  6. Feature negotiation on one-to-many: [SVTA2053] interpreters SHOULD error on unsupported flagged features -- sensible unicast behavior, but a broadcast publisher cannot negotiate per subscriber. Should the catalog advertise which features a track uses so clients subscribe eyes-open? The features member this rests on is confirmed: the Version 2 base carriage envelope defines it as an object of boolean flags, with features.remoteFields as the only flag so far, and requires that an interpreter encountering a flag it does not support SHOULD raise an error and ignore the payload. This revision settles the easy half by forbidding flags that [SVTA2053] does not define (Section 4.3); the hard half -- a defined flag that some subscribers do not support -- remains. That rule is written for unicast, where the publisher learns of the failure; on one-to-many the publisher never hears, so the burden has to move to subscribe time. Note also that if the per-function tracks of a split (Section 9) are published as separate broadcasts rather than sibling tracks, a subscriber selects the functions it supports by subscribing to them, which answers much of this for the split case but not for flagged features within a single track.

  7. Record integrity: resolved in this revision in favor of per-record signing (Section 4.5: a detached JWS over the canonical record, EdDSA with Ed25519 mandatory to implement; Section 12.1 gives the reasoning). Two questions remain. Key distribution: the key set is provisioned out of band today; a key, or a key set location, pinned in the catalog or in a track property would let a client that found the track by name verify it without a separate channel, and is a possible [MSF] follow-up. And the sig member is a binding-level addition to the record structure of Section 8.1 of [MSF]; a record signature defined by [MSF] itself would serve every Event Timeline event class, and the authors intend to raise it there. A COSE encoding was considered and set aside because the records are JSON.

  8. No stable placement identifier: [SVTA2053] gives neither the Pod nor the Slot object an identifier. A Pod carries start, duration, slots and tracking; a Slot carries type, start, duration, media, identifiers, tracking, verifications, skipOffset and clickThrough. MediaReference does have an id, but the specification states that uniqueness of that value "is desired, but not required", so it cannot be relied on as a key. The Slot identifiers array identifies the creative, not the placement: the same creative may legitimately appear twice in one pod, and each appearance is measured separately.

    While an envelope carries a whole pod, correlation is structural and the absence costs nothing. It only bites once records are decomposed -- which [SVTA2053] itself already does in two places, the $remote fields that resolve slots, tracking and verifications separately, and the HLS Interstitial ASSET-LIST mapping, whose own note observes that it "separates the Slot objects from the Pod objects without explicit reference". This document decomposes further still if the event class is split by function across sibling tracks (Section 9), because then a tracking or verification record and the creative record it belongs to arrive on different tracks: a shared index identifies the placement opportunity, not which slot within it.

    Three ways out. Derive a composite key from what already exists -- creative identifiers plus the slot's ordinal position within the pod, anchored by the shared index -- which needs no change to [SVTA2053] but is positional and therefore fragile under pod rewriting. Or request stable id fields on Pod and Slot from the SVTA Advertising Working Group, which is the clean fix and the one their ASSET-LIST note already argues for. Or define identifiers in this document, which is the wrong layer: payload normativity belongs with [SVTA2053] and this binding should not fork the data model. The first is what an implementation can do today; the second is what the ecosystem should have.

    The deployed player (Section 11) takes the first way, with an occurrence count in place of the raw ordinal: a slot's key is its identifiers plus the number of earlier slots in the same pod that carry the same identifiers. That keeps a superseding record that drops a slot from shifting the other slots' firing history. It would still mis-key two appearances of one creative if a rewrite reordered them.

11. Implementation Status

(This section follows [RFC7942] and is to be removed before publication as an RFC.)

The author operates a continuously running server-side ad insertion deployment over MoQ: fixed-timeline linear channels, publisher to relay to browser, with ad creatives spliced server-side into one shared broadcast, so every subscriber receives the same media objects -- the condition that motivates this document (Section 1). The relay is the open-source moq-relay, version 0.17.9 as of this revision; the publisher and player are not publicly available. Since 2026-10-22 the deployment publishes the event class this document defines. This section reports what it does, what was measured, and what is not yet implemented. Contact: the author.

Publisher, live on both of the deployment's ad-inserted channels since 2026-10-22:

Added on 2026-10-25:

Measured:

Unchanged from the previous revision:

NOT yet implemented:

No independent implementation of this document is known to the author.

12. Security Considerations

12.1. Integrity of Tracking Records

Tracking URLs move money. A relay path is not end-to-end confidential or authentic by default: each hop has its own transport security, but a relay, a cache, or any party able to rewrite Objects between publisher and subscriber can alter a record, and a tampered creative signaling record turns a large synchronized audience into a request cannon aimed at an arbitrary URL -- amplifying the denial-of-service concerns already noted for splice records (Section 6.3 of [SCTE35-MOQ]) with an attacker-chosen target. The same party can suppress measurement by deleting tracking entries, or misattribute it by substituting a record meant for another placement.

This is why Section 4.5 requires every record to carry a public key signature that the subscriber verifies: transport authentication protects a hop, the signature protects the record. The signature covers the whole record -- index reference and envelope -- so deletion, insertion and reordering of tracking entries are detectable, not only changes to URLs. It is asymmetric so that holding the verification key, as every subscriber does, confers no ability to forge; a shared secret would make every subscriber a potential publisher. Deployments MUST additionally authenticate the publication path for this track: an unauthenticated publisher cannot forge a record that verifies, but it can replace or suppress the track, which no signature prevents. Receivers SHOULD restrict tracking requests to URL authorities the distributor has designated; capability URLs at a distributor endpoint make this restriction natural.

Verification has limits. A hostile client can skip the check, so the signature is detection and deterrence on the network path, not prevention at the device; enforcement against forged requests belongs at the distributor's tracking endpoint. A signature over content proves origin, not freshness. Replay is bounded by the index reference -- a record is acted on at the media time it names, and the accessible window of Section 4.1 is short -- and substitution is bounded by per-channel keys (Section 4.5); a deployment that needs tighter binding can place further context in the protected header by agreement with its clients. In return, verifying clients give the distributor something a publisher cannot otherwise observe on one-to-many delivery: evidence of tampering on paths it does not operate.

12.2. Amplification and Load

Even absent an attacker, activation-synchronized behavior across a broadcast audience is a self-inflicted denial of service; the mitigations in Section 7.2 are accordingly stated as client SHOULDs. Capability URLs bound the blast radius of both cases: devices address the distributor's endpoint, which applies its own policy before any vendor is contacted.

12.3. Payload Validation

Receivers MUST treat record payloads as untrusted input: enforce size and nesting limits on the JSON envelope, and accept only https URLs in tracking, $remote, and verification fields. Verification resources are executable code; clients MUST apply their platform's script-loading policy and SHOULD load them only for slots that will actually render.

12.4. Privacy

By construction, the shared timeline carries no per-user data: records are identical for every subscriber, per-device identity is appended by the client at request time (Section 7.1), and identifiers are pseudonymous and session-scoped. Indirection through capability URLs additionally keeps vendor endpoint inventories and macro-expanded values out of relay caches. Distributor tracking endpoints handle real device context (addresses, user agents) and MUST apply applicable consent and data-protection policy before forwarding it to vendors.

13. IANA Considerations

This document requests registration of the following entry in the "MSF Event Timeline Types" registry established by Section 14.2 of [MSF]. [SCTE35-MOQ] registers entries in that same registry; this document follows the same pattern.

Table 1: Addition to the MSF Event Timeline Types registry
Event Type Description Reference
urn:svta:advertising-wg:ad-creative-signaling SVTA 2053-1 ad creative signaling, Version 2 carriage envelope This document; [SVTA2053]

Editor's note (to be resolved before publication): the URN is defined and owned by the SVTA Advertising Working Group; this registration is made in coordination with that group.

14. References

14.1. Normative References

[MSF]
Law, W. and S. Nandakumar, "MOQT Streaming Format", Work in Progress, Internet-Draft, draft-ietf-moq-msf-01, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-msf-01>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC7515]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, , <https://www.rfc-editor.org/rfc/rfc7515>.
[RFC7517]
Jones, M., "JSON Web Key (JWK)", RFC 7517, DOI 10.17487/RFC7517, , <https://www.rfc-editor.org/rfc/rfc7517>.
[RFC7797]
Jones, M., "JSON Web Signature (JWS) Unencoded Payload Option", RFC 7797, DOI 10.17487/RFC7797, , <https://www.rfc-editor.org/rfc/rfc7797>.
[RFC8032]
Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital Signature Algorithm (EdDSA)", RFC 8032, DOI 10.17487/RFC8032, , <https://www.rfc-editor.org/rfc/rfc8032>.
[RFC8037]
Liusvaara, I., "CFRG Elliptic Curve Diffie-Hellman (ECDH) and Signatures in JSON Object Signing and Encryption (JOSE)", RFC 8037, DOI 10.17487/RFC8037, , <https://www.rfc-editor.org/rfc/rfc8037>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[RFC8259]
Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/rfc/rfc8259>.
[RFC8785]
Rundgren, A., Jordan, B., and S. Erdtman, "JSON Canonicalization Scheme (JCS)", RFC 8785, DOI 10.17487/RFC8785, , <https://www.rfc-editor.org/rfc/rfc8785>.
[SVTA2053]
Streaming Video Technology Alliance (SVTA), Advertising Working Group, "Ad Creative Signaling in DASH and HLS", SVTA 2053-1, Revision 1.0, , <https://www.svta.org/product/svta2053-1/>. This document uses the Version 2 data carriage scheme and object model (Sections 4 and 5.2).

14.2. Informative References

[CAP-URLS]
Tennison, J., "Good Practices for Capability URLs", W3C First Public Working Draft, , <https://www.w3.org/TR/capability-urls/>.
[MOQT]
Nandakumar, S., Vasiliev, V., Swett, I., and A. Frindell, "Media over QUIC Transport", Work in Progress, Internet-Draft, draft-ietf-moq-transport-22, , <https://datatracker.ietf.org/doc/html/draft-ietf-moq-transport-22>.
[MOQT-SUBGROUP-PROPS]
Hošna, M., "Add Subgroup Properties", moq-transport Pull Request 2023, , <https://github.com/moq-wg/moq-transport/pull/2023>.
[OMSDK]
IAB Technology Laboratory, "Open Measurement SDK", <https://iabtechlab.com/standards/open-measurement-sdk/>.
[RFC7942]
Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, DOI 10.17487/RFC7942, , <https://www.rfc-editor.org/rfc/rfc7942>.
[SCTE35]
Society of Cable Telecommunications Engineers, "Digital Program Insertion Cueing Message", ANSI/SCTE 35 2022, .
[SCTE35-MOQ]
Law, W. and S. Nandakumar, "SCTE35 transmission over MSF Event Timeline", Work in Progress, Internet-Draft, draft-wilaw-moq-scte35-event-timeline-00, , <https://datatracker.ietf.org/doc/html/draft-wilaw-moq-scte35-event-timeline-00>.
[SVTA2053-2]
Streaming Video Technology Alliance (SVTA), "Non-Linear (Concurrent) Ad and Media Experiences: SVTA2053-2 Ad Creative Signaling in DASH and HLS, 3rd Edition, with Reference Implementations", <https://www.svta.org/project/non-linear-concurrent-ad-and-media-experiences-svta2053-2-ad-creative-signaling-in-dash-and-hls-3rd-edition-with-reference-implementations/>. Work in progress; publication planned by January 2027.
[VAST]
IAB Technology Laboratory, "Digital Video Ad Serving Template (VAST), Version 4.2", , <https://iabtechlab.com/standards/vast/>.
[VECTORS]
Riedl, S., "draft-riedl-moq-ad-creative-signaling source repository: schema/ and vectors/", <https://github.com/riedlse/draft-riedl-moq-ad-creative-signaling>.

Acknowledgments

This document deliberately reuses the carriage pattern established by Will Law and Suhas Nandakumar in [SCTE35-MOQ], and is designed to compose with it. Will Law also suggested splitting ad signaling by function across Event Timeline tracks (Section 9). The payload data model is the work of the SVTA Advertising Working Group [SVTA2053].

Thanks to Will Law, Suhas Nandakumar, Gwendal Simon and Giovanni Marzot for early review and discussion of this document.

JSON Schema and Test Vectors

A JSON Schema for the record shape and a set of test vectors are published in the schema/ and vectors/ directories of this document's source repository [VECTORS].

The schema encodes the record requirements of Section 4.1 and Section 4.3: exactly one index reference field, typed as Section 8.1 of [MSF] requires, and a data member holding one Version 2 envelope that satisfies the envelope rules of Section 5.2.2.1 of [SVTA2053] -- version 2, one of the four envelope types, a non-empty payload array, and no features flag set that [SVTA2053] does not define. It does not validate the payload objects themselves; those are governed by [SVTA2053], not by this document. It checks the shape of the sig member of Section 4.5 when one is present but does not require it, so that it continues to validate the unsigned records the deployment publishes today (Section 11); verifying a signature is in any case not a schema check.

The vectors come in two sets, and both matter: ten files holding twelve records that MUST validate, and eleven records that MUST NOT. A validator that accepts everything passes the first set alone. The valid set covers each envelope type and each index type, back-to-back placement opportunities, the worked example of Section 6, one Object captured from the running deployment, and signed-pod, a record carrying the sig member of Section 4.5; the Ed25519 test key that signed it is published beside it under vectors/keys/, with a script under scripts/ that signs and verifies records. Each rejecting case is otherwise valid, so it fails for the reason its name claims; together they pin the constraints most likely to be implemented loosely:

Table 2
Vector Rejected because
two-index-fields carries both m and t; exactly one is allowed
no-index-field carries none
string-wallclock-index t is a date string; [MSF] requires a Number
missing-data index only, no envelope
v1-bare-payload a bare Version 1 payload object, which the DASH and HLS bindings accept and this one does not (Section 4.3)
unwrapped-pod a Version 2 Pod object with no envelope around it
wrong-envelope-version "version": 1 in an otherwise Version 2 envelope
unknown-envelope-type a type outside pod, slot, trackingEvent and verification
empty-payload an empty payload; the envelope requires at least one object
undefined-feature-flag sets a features flag that [SVTA2053] does not define, so a conforming interpreter discards the record
malformed-signature a sig member that is not a detached compact JWS (Section 4.5)

The following record is the first of the two in the captured-object vector: one Event Timeline Object, captured read-only from the running deployment (Section 11) on 2026-10-26 and then anonymized. The creative identifiers, the identifier scheme, and every tracking URL (scheme, host and path) were replaced with placeholders; everything else is as published -- the index, the MediaTime values, the slot structure, and the event types and their order. The slot durations are measured from the spliced media rather than declared, which is why they are not round numbers:

{
  "m": 82005596,
  "data": {
    "version": 2,
    "type": "pod",
    "payload": [{
      "duration": 60.117,
      "slots": [
        {
          "type": "linear",
          "start": 0.0,
          "duration": 30.058,
          "identifiers": [{ "scheme": "urn:com:example:ads:id",
                            "value": "example-30s-a" }],
          "tracking": [
            { "type": "impression", "urls": [
              "https://beacons.example.com/c/d916217e/imp" ] },
            { "type": "start", "urls": [
              "https://beacons.example.com/c/d916217e/start" ] },
            { "type": "firstQuartile", "urls": [
              "https://beacons.example.com/c/d916217e/q1" ] },
            { "type": "midpoint", "urls": [
              "https://beacons.example.com/c/d916217e/q2" ] },
            { "type": "thirdQuartile", "urls": [
              "https://beacons.example.com/c/d916217e/q3" ] },
            { "type": "complete", "urls": [
              "https://beacons.example.com/c/d916217e/done" ] }
          ]
        },
        {
          "type": "linear",
          "start": 30.058,
          "duration": 30.059,
          "identifiers": [{ "scheme": "urn:com:example:ads:id",
                            "value": "example-30s-b" }],
          "tracking": [
            { "type": "impression", "urls": [
              "https://beacons.example.com/c/2ea7e414/imp" ] },
            { "type": "start", "urls": [
              "https://beacons.example.com/c/2ea7e414/start" ] },
            { "type": "firstQuartile", "urls": [
              "https://beacons.example.com/c/2ea7e414/q1" ] },
            { "type": "midpoint", "urls": [
              "https://beacons.example.com/c/2ea7e414/q2" ] },
            { "type": "thirdQuartile", "urls": [
              "https://beacons.example.com/c/2ea7e414/q3" ] },
            { "type": "complete", "urls": [
              "https://beacons.example.com/c/2ea7e414/done" ] }
          ]
        }
      ],
      "tracking": [
        { "type": "podStart", "urls": [
          "https://beacons.example.com/c/bf847920/start" ] },
        { "type": "podEnd", "urls": [
          "https://beacons.example.com/c/bf847920/end" ] }
      ]
    }]
  }
}

The urls values are capability URLs (Section 7). No event carries an offset, so each event's timing follows from its type (Section 4.4.5 of [SVTA2053]). The second record of the captured Object, about 100 s later on the same timeline, is a four-slot pod of 15 s creatives.

Apart from captured-object, the vectors are conformance examples authored against this specification. Every vector other than the two signature vectors was checked two ways: against the schema, with a JSON Schema draft 2020-12 validator; and against the record and payload checks of the implementation in Section 11, the same checks its read-only validator applies to live tracks, which beyond the record rules verify the [SVTA2053] shape of each payload (member names and types, MediaTime values in seconds, required identifiers, non-empty urls, and defined event types). Both accept every valid vector and reject every invalid one, each for the reason its name gives. The two signature vectors were checked against the schema, and signed-pod was verified with the published script, which also rejects it once any byte of the record changes and accepts it re-serialized with its members reordered.

Changes since draft-riedl-moq-ad-creative-signaling-00

(To be removed before publication.)

Author's Address

Steven Riedl
Paramount