Skip to content

Add GAM cohort attribution for Trusted Server traffic - #1034

Merged
prk-Jr merged 26 commits into
mainfrom
docs/gam-ts-cohort-attribution-spec
Aug 20, 2026
Merged

Add GAM cohort attribution for Trusted Server traffic#1034
prk-Jr merged 26 commits into
mainfrom
docs/gam-ts-cohort-attribution-spec

Conversation

@prk-Jr

@prk-Jr prk-Jr commented Aug 17, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Add a default-off gam_attribution_enabled GPT option that applies fixed page-level ts=true targeting to eligible publisher documents whose rewritten head is emitted by Trusted Server, allowing GAM to describe treatment delivery while the production/control path remains unmarked.
  • Apply targeting before publisher GPT initialization through the early bootstrap, with an exact document.currentScript attribute-gated TSJS fallback that fails closed and isolates setConfig failures.
  • Preserve auction behavior, consent, the slot-level ts_initial lifecycle, and publisher/Prebid targeting while documenting the collision audit, reporting contract, rollout, monitoring limits, and drain-safe rollback sequence.

Changes

File Change
crates/trusted-server-cli/tests/config_env_overlay.rs Verify the GAM attribution environment override is applied when the corresponding TOML leaf exists.
crates/trusted-server-core/src/creative_opportunities.rs Characterize that operator-provided slot-level ts targeting remains forwarded unchanged.
crates/trusted-server-core/src/html_processor.rs Add integration-provided attributes to publisher TSJS tags and cover enabled, disabled, and source-order behavior.
crates/trusted-server-core/src/integrations/gpt.rs Add the default-off setting and drive both inline activation and fallback authorization from the parsed GPT configuration.
crates/trusted-server-core/src/integrations/gpt_bootstrap.js Queue page-level ts=true before the existing adInit guard and isolate attribution failures from later GPT commands.
crates/trusted-server-core/src/integrations/registry.rs Add and test the integration hook that supplies trusted static attributes for publisher bundle tags.
crates/trusted-server-core/src/publisher.rs Cover streaming-head attribution semantics and operator-targeting preservation.
crates/trusted-server-core/src/tsjs.rs Render trusted static attributes on publisher TSJS tags without changing generic or creative tag output.
crates/trusted-server-integration-tests/browser/tests/shared/script-injection.spec.ts Verify attribution metadata is absent from the default-off integration fixture.
crates/trusted-server-integration-tests/fixtures/configs/trusted-server.integration.toml Keep the new configuration leaf explicit and disabled in integration tests.
crates/trusted-server-js/lib/src/integrations/gpt/index.ts Add the executing-script-gated bundle fallback for page-level GAM targeting.
crates/trusted-server-js/lib/test/integrations/gpt/ad_init.test.ts Verify SPA cleanup does not clear the page-level ts key.
crates/trusted-server-js/lib/test/integrations/gpt/gpt_bootstrap.test.ts Exercise activation ordering, disabled behavior, unavailable or throwing setConfig, and bootstrap continuity.
crates/trusted-server-js/lib/test/integrations/gpt/index.test.ts Cover exact fallback authorization, fail-closed cases, duplicate-ID decoys, cloned tags, and error isolation.
crates/trusted-server-js/lib/test/integrations/prebid/index.test.ts Characterize publisher and Prebid-generated ts targeting across refreshes.
docs/guide/integrations/gpt.md Document configuration, environment-overlay requirements, attribution semantics, collision checks, reporting, rollout, and rollback.
docs/superpowers/plans/2026-07-15-gam-ts-cohort-attribution.md Add the reviewed implementation and verification plan.
docs/superpowers/specs/2026-07-15-gam-ts-cohort-attribution-design.md Finalize the fixed marker contract, streaming meaning, reporting scope, and operational safeguards.
trusted-server.example.toml Add the explicit default-off setting and environment-overlay guidance.

Launch gates

This PR completes the repository implementation. Starting the cohort remains gated on target-network GAM provisioning, cross-system collision and privacy/CSP audits, a paired-report dry run, and router-controlled treatment validation described in the design.

GAM results are descriptive delivery attribution, not causal treatment-effect estimates.

Closes

Closes #1027

Test plan

  • cargo test-fastly && cargo test-axum
  • cargo clippy-fastly && cargo clippy-axum
  • cargo fmt --all -- --check
  • JS tests: cd crates/trusted-server-js/lib && npx vitest run (44 files, 847 tests)
  • JS format: cd crates/trusted-server-js/lib && npm run format
  • Docs format: cd docs && npm run format
  • WASM build: cargo build --package trusted-server-adapter-fastly --release --target wasm32-wasip1
  • Manual testing via fastly compute serve: confirmed the inline flag, activation attribute, GPT page targeting, and decoded cust_params containing ts=true on a real GAM request
  • Other: Cloudflare and Spin adapter tests/clippy, cross-adapter parity, native CLI tests, and Next.js/WordPress browser integration suites

Checklist

  • Changes follow CLAUDE.md conventions
  • No unwrap() added to production code
  • Logging follows project conventions; no direct stdout/stderr logging was added
  • New code has tests
  • No secrets or credentials committed

@ChristianPavilonis ChristianPavilonis left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Approved after a thorough review of the GAM cohort-attribution implementation. I found no actionable correctness, security, compatibility, or test-coverage findings.

Several required GitHub Actions jobs are currently red because runner setup could not download actions from GitHub codeload (429/503); rerun those checks before merge.

@aram356 aram356 added this to the 202608 milestone Aug 18, 2026

@aram356 aram356 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Tightly scoped implementation of the default-off gam_attribution_enabled marker. The risky surfaces check out: attribution is queued before the adInit guard and any display()/refresh(), the bundle fallback fails closed on document.currentScript (duplicate-ID decoys and cloned tags covered), the default path is byte-for-byte unchanged, creative documents keep the unmarked unified tag, streaming emits both activation signals in the first head chunk, and no cleanup path touches the page-level ts key. The double setConfig application (bootstrap + bundle) is intentional and idempotent per the design doc.

No correctness bugs found; the requested changes below are hardening and consistency items on the new surfaces.

CI Status

  • fmt: PASS
  • clippy (fastly/axum/cloudflare/cloudflare-wasm/spin-native/spin-wasm): PASS
  • rust tests (fastly/axum/cloudflare/spin/parity/CLI): PASS
  • js tests (vitest, browser integration): PASS
  • formats (typescript/docs), CodeQL: PASS

Comment thread crates/trusted-server-core/src/integrations/registry.rs
Comment thread crates/trusted-server-core/src/tsjs.rs
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Outdated
Comment thread crates/trusted-server-core/src/integrations/gpt_bootstrap.js Outdated
Comment thread crates/trusted-server-js/lib/test/integrations/gpt/gpt_bootstrap.test.ts Outdated
Comment thread trusted-server.example.toml Outdated
@prk-Jr
prk-Jr requested a review from aram356 August 19, 2026 04:43

@aram356 aram356 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

Re-review at bbadec3: all seven findings from the previous review are resolved — first-wins attribute dedupe with a conflict test, debug-build charset guards on publisher tag attributes with WASM-safe panic tests, guarded ts.log.warn in the bootstrap attribution catch with test coverage, quote normalization synchronized with the Rust ordering test, dead mock member removed, and capability-based overlay wording. Approving; the two inline comments below are optional polish.

Both inline comments carry a one-click GitHub suggestion — use Commit suggestion (or Add suggestion to batch) to apply them as commits on the PR branch.

Non-blocking

♻️ refactor

  • Warn when a conflicting duplicate attribute value is dropped — see inline at crates/trusted-server-core/src/integrations/registry.rs:1064

⛏ nitpick

  • Example-TOML overlay comment reads circularly — see inline at trusted-server.example.toml:107

CI Status

All 19 checks PASS: cargo fmt (required), cargo test (required), format-typescript (required), format-docs (required), cargo test (axum native), cargo test (cross-adapter parity), cargo test (ts CLI, native), cargo check (cloudflare native + wasm32-unknown-unknown), cargo check/build/test (spin native + wasm32-wasip1), vitest, browser integration tests, integration tests, integration tests (Fastly EC lifecycle), prepare integration artifacts, Analyze (actions), Analyze (javascript-typescript) ×2, Analyze (rust), CodeQL.

Comment thread crates/trusted-server-core/src/integrations/registry.rs Outdated
Comment thread trusted-server.example.toml Outdated
prk-Jr and others added 3 commits August 20, 2026 12:48
First-wins dedupe silently dropped a conflicting duplicate value. Log a
warning naming the integration and attribute when a later injector emits a
different value for an already-claimed attribute name, matching the
registry's existing skip warnings. Identical duplicates stay silent.
The prior wording read circularly: the environment overlay can never create
a missing configuration leaf. State the intent directly — keep the leaf so the
override can apply.
@prk-Jr
prk-Jr merged commit 845cc3c into main Aug 20, 2026
19 checks passed
@prk-Jr
prk-Jr deleted the docs/gam-ts-cohort-attribution-spec branch August 20, 2026 07:59
prk-Jr added a commit that referenced this pull request Aug 20, 2026
Brings in the squashed #1034 (GAM cohort attribution) and #1025 (GPT
diagnostics attribution docs), whose implementation branches were already
merged here. Conflict resolutions keep main's post-review versions:
attribute-name/value debug assertions and duplicate-attribute dedup in the
registry, the GAM attribution warn log, and the reworded docs.

Kept rc-only work where main's squash would have regressed it: the
`getConfig` mock surface in the bootstrap test, and the deleted
`tsjs_unified_helpers_use_all_module_ids` test, which contradicts the
hashless unified script source introduced by the cache header policy work
on this branch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GAM attribution for Trusted Server A/B traffic (page-delivery marker)

3 participants