Skip to content

[spec] ctx_token binds to click-out content_engaged event; share it on resolve with turn/session totals under partial visibility #28

Closed

Description

@pedroamaralsantos

Specification section

§6.4 (tokens_ingested), §6.5 (excerpt_tokens), §6.6 (content_displayed), §6.7 (content_engaged), §7.1 (ctx_token resolve / click manifest), §7.3 (routing / owner-filtered views).

What you observed

ctx_token resolves to a session, not to a specific click

Section 7.1 defines ctx_token resolution as exposing the click manifest for the owning session: gated content_grounded, content_cited, and content_displayed. The token is not defined as identifying a particular click-out.

Without a bind to a specific engagement, resolve cannot place the click in time inside the chat. Recipients do not know whether the user left on the first answer, after several turns of refinement, or clicked early and kept talking afterward. Those cases imply different influence windows — yet two tokens from the same session can return the same whole-session manifest, with no signal for which destination, which turn, or which moment in the dialogue the click belonged to.

content_engaged belongs on the session, but it is not part of the click manifest. The specification does not require consumers to expose it on resolve; sharing is operator-defined. A resolve-only party gets a gated source list with no engagement event and no standard join from token → “this click at this point in the conversation.”

No turn- or session-wide totals when only some sources are visible

Each visible source carries its own counts (tokens_ingested, excerpt_tokens), but nothing says how large the whole turn or session was — total tokens across all sources, or how many distinct sources were grounded, cited, or displayed. Without those overall totals, a recipient who only sees a subset of sources cannot compute each source’s share of the context, the citations, or the clickable UI surface.

content_displayed is a separate stage from content_cited (§4.3 / §6.6): they might co-occur for the same URL, but display without citation and citation without a display event are both valid. Click-out competition is about what was shown, not only what was cited — yet display has the same partial-visibility problem and no denominator today.

Scenario A — Consent-gated click manifest. Resolve returns only opted-in sources. If five sources grounded and two appear, recipients see absolute counts for those two only. They cannot tell whether the two dominated the mix or were a small slice — and may over-credit them. The same applies when two of twelve links were displayed.

Scenario B — Own-event stream. Under §7.3, publishers (and networks on their behalf) receive only their own content_grounded / content_cited / content_displayed events. Peer sources are not disclosed. From that stream alone, 800 tokens could be most of the context or a small fraction, and one source could be 1 of 2 or 1 of 20 among grounded, cited, or displayed items.

A party with the full ungated session could sum tokens and count distinct sources; under consent gating or owner isolation that information is unavailable. There is no existing field for those totals.

Why it matters

Click-out attribution is about a specific user action at a specific point in the conversation, not just “somewhere in this chat.” Binding the ctx_token only to the session_id blurs multiple clicks together and obscures whether the click happened early or late in the dialogue. Without an overview about display, citation, and grounding at the moment of the click, it becomes extremely difficult to accurately calculate attribution weight—you can't assess how relevant or prominent each citation, grounding, or display event was up to the time of the click.

Fair pay and flexible weighted models also need those overall turn/session totals next to each source’s own counts. Without them, you can re-weight the visible set but cannot tell whether those sources dominated or were a small slice — by tokens, by source count, or by how crowded the displayed / clickable surface was.

Delivering the agent-authored click-out content_engaged to the destination content owner (when that owner participates in telemetry) is equally important. It gives the owner a reliable click signal from the agent itself, reduces dependence on the ctx_token surviving every redirect hop to the landing page, and moves the engagement record from the agent to the owner without requiring the owner to call resolve on the telemetry consumer. Destination-side or network corroboration remains useful, but the owner should not depend on token transport or consumer lookup alone to learn that the click happened.

Proposed direction (optional)

1. ctx_token maps to a specific click-out content_engaged

Change §7.1 so lookup returns the click-out engagement as well as the session:

Today:     ctx_token → gated manifest (whole session)
Proposed:  ctx_token → content_engaged (this click)
                      + gated manifest (whole session)

Therefore, the agent operator MUST issue a content_engaged event to register the user action. Additionally, if the click-out destination (for example, advertiser.com) is an entity that has registered to receive telemetry events—such as content_grounded or content_cited—the agent MUST send the content_engaged event to that entity as well.

2. Turn and session totals (token and source-count)

Add turn- and session-wide totals so a recipient with only a subset of sources can still compute share. Totals MUST count every contributing source (including those omitted from a gated manifest or owner-filtered stream). Recipients learn the numbers only — not peer URLs or publishers.

Scope

Aggregate Covers
Turn All grounded / excerpt tokens and distinct grounded, cited, and displayed sources in this turn
Session Aggregates across turns. On content_engaged: all turns that existed at click time (1..M), not only through the click’s turn_id (N)

Fields to add to content_grounded, content_cited, content_displayed, and content_engaged events

Tokens Distinct sources
Grounded {turn|session}_total_tokens_grounded {turn|session}_total_sources_grounded
Excerpt (cited) {turn|session}_total_excerpt_tokens {turn|session}_total_excerpt_sources
Displayed — (no token fields on §6.6) {turn|session}_total_sources_displayed

Alongside the token/source totals above, click-out content_engaged MUST carry both of the following so recipients can place the click in the dialogue:

Field Meaning
Turn ordinal N Which turn the engaged link came from. Today §5.2.1 allows turn_id to be any emitter-defined string (sequential integer, UUID, opaque id). “Turn N of M” only works if N is ordered and comparable to session_total_turns, so the spec MUST either require turn_id to be a sequential integer string ("1", "2", …) or add a dedicated turn_index (0- or 1-based ordinal). This issue assumes sequential turn_id / turn_index = N.
session_total_turns (integer, new) How many turns existed in the session at click time (M). Session window for session totals is turns 1..M, not only through N.

Together these express “turn N of M at click time.” Example: user is on turn 5 of a 5-turn session but clicks a link from turn 2 → turn ordinal = 2, session_total_turns = 5.

Distinct sources counts unique content items, not events. Key by content_id when present, otherwise content_url. Example: the same URL appears in two content_grounded rows → that is 2 events but 1 source toward *_total_sources_grounded. Token totals still sum every event; source-count fields count each content item once.

Where they appear

All the different totals (grounded, excerpt and display) are added to each event (content_grounded, content_cited, content_displayed, and content_engaged). Grounded without cited, cited without display, and display without citation are all valid under the spec. Shipping only grounded totals on a content_grounded event, for example, leaves a publisher unable to tell whether they dominated the answer mix or were one of twelve links in the sidebar. Putting all three group of totals on each event (content_grounded, content_cited, content_displayed, and content_engaged) is how a content owner (or a network on their behalf) gets a full overview of prominence without seeing peer URLs.

Payload cost is small: a handful of integers (token totals + distinct source counts, turn + session). Peers are not disclosed.

Event Details
content_engaged (click-out) / resolve MUST carry the full grounded + cited + displayed turn/session totals at click time. This is the authoritative “importance” snapshot for attribution: turn N of M; turn totals for the turn the click came from (N), and totals over all turns available at click time (1..M) — including turns after N when the user clicked back to an earlier answer, excluding turns that only happen after the click.
content_grounded / content_cited / content_displayed Each event carries own contribution vs turn/session totals as of that event, without seeing peer sources. Display events carry source-count totals only.

3. Consequences

3.1 ctx_token binding and resolve

  • Each outbound click gets its own ctx_token bound to the agent-authored content_engaged issued for that action.
  • content_engaged event MUST include turn_id and session_total_turns at click time (turn N of M).
  • Looking up the token MUST return that engagement event (no longer operator-optional) and plus the gated whole-session manifest.
  • If a destination or network also reports content_engaged for the same ctx_token, that report MAY be merged into the agent-authored engagement (one resolved event) rather than returned separately. A boolean such as corroborated_click (or equivalent) MAY mark that arrival was independently observed.
  • Resolve still returns the session’s gated citation chain (the manifest) alongside the engagement — not the engagement alone.
  • The agent-authored content_engaged MUST also be delivered to the destination content owner when that destination participates in telemetry (same routing/isolation as other owner-scoped events under §7.3) — so the owner is notified of the click without depending on destination-side reporting or resolve alone.

3.2 Totals under partial visibility

  • Turn and session totals for all three stages (grounded, cited, displayed) MUST appear on the resolved content_engaged. Displayed: source-count fields only.
  • On stage events (content_grounded / content_cited / content_displayed): include the full three-stage (grounded, cited, displayed) turn/session totals
  • On content_engaged: all of turn_id, session_total_turns, turn totals, and session token/source totals (including *_total_sources_displayed) are written at click time (session window = turns 1..M then) and immutable thereafter. On content_grounded / content_cited / content_displayed events: totals are immutable from emit. Resolve MUST NOT rewrite any of these.
  • Totals MUST include every contributing source (including gated or owner-filtered peers). Recipients get counts only — not peer URLs or publishers.
  • With own-source counts plus these totals, a recipient under partial visibility can compute share of context (tokens / grounded sources), of citations (excerpt tokens / cited sources), and of the displayed UI surface (displayed sources) without seeing the rest of the mix — i.e. a publisher-grade overview of how important their content was in that turn/session.

Your perspective

None

Activity

  1. jalexspringer commented on Jul 26, 2026

    @jalexspringer
    Contributor

    Accept the click-binding point for v1. Each outbound click should get a unique ctx_token, bound to the exact content_engaged event and presentation. Resolution should return that engagement and its relevant context, not the whole session indiscriminately.

    I would not add turn/session totals to every event. Early events cannot contain final citation or presentation totals, repeated snapshots could leak hidden activity, and “importance” is a commercial interpretation. We can consider a privacy-bounded summary at resolution time separately.

  2. pedroamaralsantos commented on Jul 30, 2026

    @pedroamaralsantos
    Author

    First of all thanks for your review and input.

    Resolution should return that engagement and its relevant context, not the whole session indiscriminately.

    Could you clarify what exactly you mean by relevant context?

    The whole section would be nice to have, but at least the events that occur until click time would be important. And as described in the issue the cut should be by click timestamp, not by click turn alone. If the user clicks during turn 5 while 10 turns already exist, resolve should include all events from turns 1..10. Limiting until the click turn only would drop relevant context/events that might have contributed to the user engagement. Post-click activity can be excluded.

    That is already a privacy improvement over the initial whole-session proposal. Each event should carry a turn_id so recipients can analyze per-turn contributions. On the bound content_engaged event, turn_id + session_total_turns_at_click (turn N of M) remain essential to place the click within the dialogue (e.g., clicked in turn 10 of 10 vs. turn 2 of 10). This ensures that all events which influenced the user's click are included, allowing for a better understanding of the user journey and, consequently, more accurate attribution models.

    Agent-authored content_engaged to the destination owner — critical for attribution without depending on resolve via the telemetry consumer

    This point was not addressed in your reply, and it is important to us: the agent-authored click content_engaged event MUST be delivered to the destination content owner when they are participating in telemetry (§7.3 owner-scoped routing), with the session_id included in the server-side delivery—just like grounding/citation events today. In fact, if we include this in the specification, issue #29 becomes less significant, because having the session id in the server-side events would allow the receiver to connect a click event to their session events without needing to call resolve. Meanwhile, the ctx_token in the redirect URL remains opaque and resolution-dependent for parties who only see the click chain (the ctx token). We see this as a major step toward publisher empowerment (#29), without weakening the query-string privacy boundary. What are your thoughts on including this in v1?

    Turn/session totals — on each event

    Early events cannot contain final citation or presentation totals

    Our proposal does not require final session totals on every row. Each event would carry session aggregates through the turn it belongs to (turns 1..N), frozen at emit time. That gives a denominator at a defined point in time, not a moving snapshot of the full finished session.

    Recipients can compute explicit ratios from their own fields — e.g. excerpt_tokens / session_total_excerpt_tokens — without seeing peer URLs.

    Example — publisher joins grounding, citation, and click via session_id

    Scenario: 5 turns exist at click time. Publisher A is grounded in turn 2 and cited in turn 3; user clicks A’s link (from turn 4) during turn 5. Publisher A receives only owner-scoped events:

    Event 1 — content_grounded (turn 2, emit time)

    session_id: "abc-123"
    turn_id: "2"
    content_url: "https://publisher-a.com/review"
    tokens_grounded: 600
    session_total_tokens_grounded: 1800       # turns 1..2 at ground time
    session_total_sources_grounded: 3
    session_total_excerpt_tokens: 90            # turns 1..2 at ground time
    session_total_sources_cited: 2
    session_total_sources_displayed: 2
    

    Event 2 — content_cited (turn 3)

    session_id: "abc-123"
    turn_id: "3"
    content_url: "https://publisher-a.com/review"
    excerpt_tokens: 80
    session_total_excerpt_tokens: 240           # turns 1..3 at cite time
    session_total_sources_cited: 4
    session_total_tokens_grounded: 2800
    session_total_sources_grounded: 5
    session_total_sources_displayed: 4
    

    Event 3 — content_engaged (click, same session, server-side delivery)

    session_id: "abc-123"
    turn_id: "4"                                # link came from turn 4
    session_total_turns_at_click: 5             # turn 4 of 5
    content_url: "https://publisher-a.com/review"
    engagement_type: link_click
    session_total_excerpt_tokens: 420           # turns 1..5 at click timestamp
    session_total_sources_cited: 8
    session_total_tokens_grounded: 6100
    session_total_sources_grounded: 11
    session_total_sources_displayed: 6
    

    Publisher A — computed shares (no resolve, no peer URLs)

    Join on session_id + content_url:

    At ground time (Event 1, turn 2):
      grounded token share:    600 / 1800  ≈ 33.3%
      grounded source share:     1 / 3    ≈ 33.3%
    
    At cite time (Event 2, turn 3):
      excerpt token share:      80 / 240   ≈ 33.3%
      cited source share:        1 / 4    = 25%
      grounded token share:    600 / 2800  ≈ 21.4%   (same 600 tokens_grounded from Event 1)
      grounded source share:     1 / 5    = 20%
    
    At click time (Event 3, turns 1..5):
      excerpt token share:      80 / 420   ≈ 19.0%
      cited source share:        1 / 8    = 12.5%
      grounded token share:    600 / 6100  ≈ 9.8%
      grounded source share:     1 / 11   ≈ 9.1%
      displayed source share:    1 / 6    ≈ 16.7%   (if also displayed in session)
    

    What this shows: Each event carries the publisher’s own contribution (e.g. tokens_grounded, excerpt_tokens) plus session denominators at that emit time. From those fields alone, the publisher can compute the shares above — grounded, cited, and displayed — at ground time, cite time, and click time, without resolve or peer URLs. The absolute contributions stay fixed; the ratios change as the session grows. Those ratios are objective, measurable inputs; how they are weighted in payment or attribution is a separate, commercial decision.

    Without totals, a publisher knows they contributed, but not how much (800 excerpt tokens out of how many?). Totals are analytics, not commercial rules in themselves — but they enable fairer, more complex attribution models, because parties can use that data to build payment/commercial logic on top.

    On the concern that repeated snapshots could leak hidden activity — we would like to understand your view better. Our totals are fully aggregated (integer counts only, no peer URLs or identities). In the general case, a publisher only learns that the session mix grew (e.g. from turn 2 → turn 3 → click), not who was added. The one edge case we do see: with only two contributors in a stage, session_total − own_contribution reveals the exact size of the other contribution (still not its identity). We do not see that as a critical leak, as it exposes a volume only in a narrow two-party case — not who contributed.
    We are open to alternative designs(maybe add some noise to the values?). At the same time, it is important to us that publishers can compute share/ratio from their own event stream — at click time for conversion attribution, and at each event emit time for ongoing analysis — without depending on the telemetry consumer.

    About your suggestion, deferring totals to resolve time only may help address privacy, but it reintroduces dependency on the telemetry consumer — the same gatekeeper problem as #29. Even when resolve works, every attribution question flows through the session-holding party, subject to access, consent gating, and operational availability. We would prefer a design where publishers can compute shares from owner-scoped server-side events alone (grounding, citation, display, and agent-authored content_engaged), and treat resolve as a complement for parties that only see the click chain (ctx_token).

    What are your thoughts? Thank you

  3. jalexspringer commented on Aug 12, 2026

    @jalexspringer
    Contributor

    Thanks — answering the "relevant context" question directly.

    Resolution returns the lineage of the clicked reference, not a time-slice of the session. Concretely: the content_engaged event the token is bound to; its presentation record; the citation(s) that presentation realises; and the grounding events for that same content in the turns that produced it. That is the context a publisher needs to interpret the click, and every event in it is one the publisher's content participated in.

    A cut "all events from turns 1..10 at click timestamp" returns the whole session through any one click, including grounding and citation of other publishers' content the clicking publisher never touched. That re-imports the leak the privacy boundary exists to prevent, and repeated clicks would stream session state to whoever holds any token. Cross-content session totals are a commercial aggregate, and belong to reporting-level delivery under the SPUR profile rather than per-click resolution.

    What I will take from your point: the lineage must not be cut by turn. A click in turn 5 on content grounded in turn 2 and re-presented since resolves the full lineage of that content across turns, by content identity rather than by turn or timestamp. The design note covering #23, #28 and #30 will specify the response shape with exactly that rule, plus a privacy-bounded summary option at resolution time (counts, not events) for the partial-visibility case you describe.

  4. added
    v1-coreAccepted for the Content Telemetry v1 core specification
    and removed
    needs-discussionNeeds maintainer or working-group discussion before action
    on Aug 12, 2026
  5. jalexspringer commented on Aug 12, 2026

    @jalexspringer
    Contributor

    The click-context change is up as PR #38: one change covering token pattern and per-presentation binding, the reserved ctx_token/ctx_iss query parameters with redirect propagation, manifest-declared resolution (telemetry.ctx_resolution), and the resolution response specified as the engagement plus the clicked content's lineage by content identity across turns, with an optional count-based session summary. Review welcome there before the 21 August freeze.

  6. jalexspringer commented on Sep 2, 2026

    @jalexspringer
    Contributor

    Landed in v1.0: per-presentation minting and click binding (7.4.1), content-identity lineage and the count-based session summary (7.4.4), owner-scoped delivery of the agent-authored engagement (7.4.5). Closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    v1-coreAccepted for the Content Telemetry v1 core specification

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions