---
slug: origin-trial-tokens
type: pattern
summary: "The operational deployment of an origin-trial token: registering an origin, receiving a signed token, and serving it via the Origin-Trial header or meta element, with the scope, expiry, and third-party rules that decide whether the feature actually activates."
created: 2026-05-12
updated: 2026-06-09
last_link_verified: 2026-06-09
sources_audited: 2026-06-07
related:
origin-trial:
relation: depends-on
note: "The governance pattern is the prerequisite; token deployment is the operational surface that activates a trial the project has already opened."
four-channel-pipeline:
relation: uses
note: "A token activates the feature across whichever channels carry an active trial, from Canary through Stable, so the same deployment reaches every channel at once."
feature-flag-guarding:
relation: complements
note: "The token is the site-operator counterpart on the client side; feature-flag guarding is the implementation-side gate the token activates."
zombie-origin-trial:
relation: contrasts-with
note: "Deploying a token after the trial has ended is the operator-side analogue of the Zombie Origin Trial, in which a trial's gate outlives the trial."
wicg-explainer:
relation: informed-by
note: "The Explainer in a WICG or W3C repository is the upstream artifact that names the feature whose token the operator is deploying."
stable-trust-boundary:
relation: uses
note: "Tokens exist because an experimental feature has not yet crossed into Stable by default; the boundary is what makes per-origin opt-in necessary."
---
# Origin Trial Token Deployment
> **Pattern**
>
> A named solution to a recurring problem.
*The operational pattern for participating in an origin trial: registering an origin, receiving a cryptographically signed token, and serving it via the `Origin-Trial` HTTP response header or a `` element, so that an experimental Chromium feature activates for that origin and no other.*
> **📝 Where the name comes from**
>
> A token here is not an API key and not a session credential. It is a self-contained, signed assertion: the bytes carry the origin they are bound to, the feature they enable, and the expiry past which they mean nothing. Chrome verifies the signature locally and reads those fields out of the token itself. Nothing is checked against a server at request time, which is why a token that has technically expired still parses, still looks valid to a casual inspection, and still produces a silently disabled feature.
A site operator trying a new web-platform feature has already cleared the governance question: the trial exists, and the feature owner wants production feedback. The remaining work is a deployment problem that looks trivial and is not. A token scoped to the wrong origin, served on the wrong response, or deployed a week after the trial closed produces a feature that is absent, with no console error and no hint that the token was the cause. The [Origin Trial](origin-trial.md) governance pattern explains why the mechanism exists; this entry is about what it takes to make a token actually fire.
## Context
Token deployment sits at the operational end of the release-discipline axis. Above it is the governance question of whether a trial should exist at all, settled by API owners on `blink-dev`. Below it is nothing: the token is the last hop before a feature either runs in the operator's production traffic or does not. The operator interacts with three surfaces: the Chrome Origin Trials portal where the token is issued, the response path where the token is served, and the browser's local verification logic that decides, per document, whether the feature flips on.
The reader here is the engineer deploying the token, not the Chromium contributor who built the feature. That engineer needs the token to validate against real production traffic before the [Intent to Ship](intent-ship-pipeline.md) gate closes the trial. They also need to know within minutes whether deployment worked, because the trial window does not wait.
## Problem
A token is issued for one origin, one feature, and one expiry. A Chrome client enables the feature only when all three match the document being loaded. The operator's deployment has to satisfy a verification path that fails closed and fails silently: any mismatch disables the feature without raising an error visible in normal browsing. The common mistakes look different in deployment: a token scoped to `https://example.com` served on `https://www.example.com`, a token deployed on a fetch response rather than a document response, or a token that expired between registration and deployment. In the browser they collapse into the same symptom: "the feature isn't working," with nothing in the response or the console pointing at the token as the cause.
## Forces
- **Self-contained token vs. silent failure.** A token that carries its own scope and expiry needs no server round-trip, which is fast and offline-friendly, but means an expired or misscoped token fails locally and quietly rather than returning an actionable error.
- **Header vs. meta deployment.** The `Origin-Trial` response header reaches every document the server controls but requires server-side configuration; the `` element ships in the HTML itself and works on static hosting, but cannot enable features the browser consults before the document's `
` is parsed.
- **Origin precision vs. operator intuition.** The token's origin is scheme + host + port with no subdomain wildcarding by default; operators reason about "their site" and forget that `www.` and the apex, or `http` and `https`, are different origins to the verifier.
- **First-party scope vs. third-party libraries.** A feature an embedded script wants to use lives in a different origin than the document; enabling it requires the third-party token variant, which most operators have never heard of until a library's feature silently fails.
- **Trial window vs. deployment lead time.** A token is only useful while its trial is active; a deployment pipeline measured in weeks can ship a token that expired before it reached production.
## Solution
The Chromium project issues each trial participant a signed token bound to a single origin, a single feature, and an explicit expiry, and the Chrome client enables the feature for a document only when the token verifies against all three. The deployment sequence:
1. **Register the origin.** At the Chrome Origin Trials portal, the operator selects the feature, names the origin as `scheme://host:port`, accepts the trial terms, and receives the token. The origin is exact: `https://example.com` and `https://www.example.com` are distinct registrations, and a token for one doesn't enable the feature on the other.
2. **Serve the token on the document.** The operator deploys the token through one of two channels:
- The `Origin-Trial` HTTP response header, set on the document response: `Origin-Trial: `. This is the form to use when the server controls its response headers and when the feature must be available before any HTML is parsed.
- A `` element in the document ``. This is the form to use on static hosting where response headers aren't configurable. It can't enable features the browser consults before parsing the ``.
3. **The client verifies, per document.** On each document load, Chrome checks the token's signature against the embedded trial public key. It confirms that the token's origin matches the document's origin, the trial is currently active, and the token has not expired. Only after those checks pass does Chrome flip the per-document feature flag the [Feature Flag Guarding](feature-flag-guarding.md) pattern declared on the implementation side.
4. **At trial end, the token stops mattering.** Once Chrome no longer treats the trial as active, tokens stop enabling the feature and the feature falls back to its default. That default is off unless an Intent to Ship has authorized default-on shipping by then. A token deployed after this point is inert: it parses, but the trial it names is no longer active.
The third-party token variant covers the case a first-party token can't reach. When a JavaScript library wants to enable a trial feature on behalf of every site that embeds it, the library author registers a **third-party** token, bound to the library's script origin rather than the embedding document's origin and carrying an `isThirdParty` assertion. The library injects the token at runtime through a script-inserted `` element, and Chrome enables the feature for documents that load the library's script. This is how an analytics or framework vendor enables a trial feature across its entire embedder base without each embedder registering a token of its own.
What makes the pattern work is that the token is the whole contract. Because the origin, the feature, and the expiry are signed into the bytes, the verifier needs nothing but the token and the document to decide. That same property is what makes the failure modes silent: a token that's wrong about any of the three isn't rejected loudly, it simply doesn't enable the feature, and the operator sees a feature that's absent rather than a token that was refused.
## How It Plays Out
A product team at a SaaS company decides to validate a new layout API mid-trial in upstream Chromium. An engineer registers `https://app.example.com` at the portal, receives a token, and adds an `Origin-Trial` response header at the CDN edge. The feature works in staging. In production it doesn't, and the console is clean. The cause: production serves the app from both `https://app.example.com` and a legacy `https://example.com/app` path, and the legacy path's documents carry a token scoped to the wrong origin. The engineer registers the apex origin as a second trial participant, deploys a second token on the legacy path's responses, and the feature activates everywhere. The token's origin precision, which felt like pedantry during registration, was exactly the thing that decided whether the feature fired.
A second case is a library vendor. An embeddable widget wants a trial feature for performance, and the vendor can't ask every embedder to register an origin. The vendor registers a third-party token bound to the widget's script origin and injects it at load time. The feature activates on every site that loads the widget, the vendor collects the compatibility data the trial was meant to produce, and no embedder touches their own response headers. Had the vendor deployed a first-party token instead, it would have been scoped to the vendor's own origin and would have enabled the feature on nothing the embedders served.
A third case is a deployment that ships too late. A team registers a token, files a change, and lets it move through a release pipeline that takes three weeks to reach production. By the time the token is live, the trial has closed and the Intent to Ship has cleared. The feature ships to Stable by default, so the token is moot for new users, but the team's monitoring still reads the deployed token as the activation mechanism. In a later enterprise channel where the feature has not defaulted on yet, the expired token does nothing. The team learns to treat a trial token as perishable: it is deployed against a calendar window, not held in a config file indefinitely. A token that lingers past its trial is the operator-side shape of the [Zombie Origin Trial](zombie-origin-trial.md): gate present, trial gone.
## Consequences
**Benefits.** The operator gets first-mover access to a platform feature against real production traffic, scoped to exactly the origins they choose, with no risk to users on origins they did not register. The token's self-contained shape means deployment needs no coordination with the Chrome team beyond the initial registration, so the operator controls when and where the token is served. The third-party variant lets a library enable a feature across an entire embedder base from one registration. Local public-key verification also means deployment works the same offline, behind a corporate proxy, or in an air-gapped enterprise build.
**Liabilities.** Every failure mode is silent. A misscoped origin, a header on the wrong response, a `` element that loads too late, an expired token: each produces an absent feature with no console error. Debugging a non-activating token therefore means checking the token's claims by hand against the document. The origin-exactness rule routinely surprises operators who reason about "their site" rather than scheme-host-port. Tokens are perishable: a deployment pipeline slower than the trial window can ship a token that is already inert. The third-party mechanism, which solves the library case, is itself a source of confusion, because most operators do not know it exists until a library's feature silently fails on their site.
The pattern doesn't guarantee the feature is a good bet. A site can deploy a token correctly for a feature that never ships to Stable, and absorb the cost of having built against it. What correct deployment guarantees is narrower: the feature activates for exactly the origins the operator chose, for exactly as long as the trial runs, and the compatibility data the operator's traffic generates reaches the Intent to Ship thread that decides the feature's fate.
## Notes for Agent Context
When wiring an origin-trial feature into a site's deployment, scope the token to the exact origin that serves the documents: `scheme://host:port`. Treat `www.` and the apex as distinct origins; treat `http` and `https` as distinct origins. Prefer the `Origin-Trial` response header for features the browser consults before the `` is parsed. Use the `` element only when response headers cannot be configured, and never for features needed before parse time. For a feature an embedded third-party script must enable, register and inject a third-party token bound to the script's origin, not a first-party token bound to the document. Treat the token as perishable: verify the trial is still active before deploying, and remove the token at trial end rather than leaving it to outlive the trial. Do not treat an absent feature as a code bug before confirming the token's origin, feature, and expiry all match the document, because token failures are silent and produce no console error.
## Sources
The Origin Trials token format and verification path were designed by the Chrome team that operates the framework; the per-origin signed-token shape and its medical-trial analogy trace to Alex Russell's [*Doing Science on the Web*](https://medium.com/@slightlylate/doing-science-on-the-web-af26d9be2faa), which the official Chrome Origin Trials explainer cites as the conceptual origin. The third-party token mechanism was added to the framework to cover the embedded-library case that a first-party token can't reach, and is documented in the Chrome team's third-party origin-trials guidance. The token-deployment forms (the `Origin-Trial` response header and the `` element) are specified in the [GoogleChrome/OriginTrials](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) repository's developer documentation, the canonical operator-facing reference maintained alongside the framework itself.
## Technical Drill-Down
- [Origin trials developer guide](https://developer.chrome.com/docs/web-platform/origin-trials) — the operator-facing process surface: registration, the header and `` deployment forms, and the token-scope rules.
- [Chrome Origin Trials portal](https://developer.chrome.com/origintrials/) — the registration interface that issues tokens; the list of active trials and their expiry dates is public here.
- [Third-party origin trials guide](https://developer.chrome.com/docs/web-platform/third-party-origin-trials) — the third-party token variant for libraries enabling a feature across their embedder base; the `isThirdParty` assertion and runtime injection are documented here.
- [GoogleChrome/OriginTrials developer documentation](https://github.com/GoogleChrome/OriginTrials/blob/gh-pages/developer-guide.md) — the canonical token-format and deployment reference maintained alongside the framework.
- [`chromestatus.com`](https://chromestatus.com/) — the per-feature state machine; an operator can confirm a trial is still active and read its end milestone before deploying a token.
---
- [Next: Stable as Trust Boundary](stable-trust-boundary.md)
- [Previous: Feature Flag Guarding](feature-flag-guarding.md)