Publish
Publish is the stage that promotes both staged GTM workspaces (web + server) to live container versions and then proves the new server pipeline is actually moving live traffic. Before this stage, every artifact GSS wrote lives only in unpublished workspace drafts that nobody outside your team sees. After this stage, the world sees your server-side pipeline.
Three steps, run in order: Review staged setup is the readiness checkpoint that confirms every upstream stage is green and stamps publish_confirmed_at. Publish is the most consequential single action in the flow — it audits the staged workspaces, optionally cleans up retired items, then calls the GTM API to publish both containers (server first, web second). Confirm live traffic polls GA4 Realtime and Cloud Run on your live site to prove the just-published pipeline is actually moving traffic, then asks you to attest. The Publish action itself is gated tightly on the Review-staged-setup stamp plus configured staging workspaces in both containers; live-traffic verification happens after the publish, not before.
Stage path: Review staged setup → Publish → Confirm live traffic
What Publish Actually Changes
In one transaction, Publish:
- Snapshots prior live versions for both containers — these become rollback targets.
- Server first, then web:
create_versionon the staging workspace, thenpublish_version. NewcontainerVersionIdper container, name"GetServerSide mirror-pipeline setup". - Updates workspace state: both staging workspaces transition to
status='published'with theirpublished_version_idfield set. - Writes a
publish_audit_record: an immutable log row containing both new version IDs, both prior version IDs, the config hash, and a schema version.
Server publishes first because the web container's tags reference the server endpoint; if you published web first, traffic could briefly hit a server container that didn't yet have the GSS-staged config. Server-first means the server is ready before any web container references it.
The publish_audit_record Contract
Every successful publish — including partial-success — writes one publish_audit_record row. The record is immutable: once written, it's never modified. It captures the state at publish time, not the current state.
- web_published_version_id, server_published_version_id — the new live versions.
NULLfor whichever side failed if partial-success. - web_prior_version_id, server_prior_version_id — the rollback targets. Read before publish, so they're valid even if publish fails midway.
- config_hash — fingerprint of the staging workspace contents. Used downstream by the Changes drift detection.
- schema_version — this contract's version, in case the record format changes.
Partial publish — server succeeds, web fails — writes the audit record with web_published_version_id = NULL. Server-fails-first does NOT write the record (no container changed). This asymmetry matters for rollback: if you have an audit record with NULL web side, you know exactly which side to retry without touching the server.
What Becomes Immutable
- The
publish_audit_recordrow — never updated, never deleted. Each publish appends a new one. - The published
containerVersionIdin GTM — once published, that version exists forever in GTM's history. Re-publishing creates a new version; it doesn't overwrite the old one. - The Tier 3 lock — once
publish_audit_recordexists, the project is in Tier 3 and Audit primary bindings can't be changed without explicit acknowledgement. The lock isn't reversible from the UI.
Re-publish is OK. Each publish creates a new GTM container version + a new publish_audit_record. Rollback is "publish a previous container version via Cloud Console" + "manually clear the workspace's published_version_id if you want GSS to recognize the rollback" — there's no UI for it because rollbacks are rare and operationally specific.
After Go Live
Once the project completes the Go Live cutover, all three Publish step URLs stay reachable but switch to a read-only record shape. Each page keeps its original H1 and swaps the intro paragraph for a read-only notice. The action buttons (Confirm, Publish GTM Changes, Re-validate, Stage deletion, Check, Unlock & re-test) are hidden; if you hit the underlying endpoints directly they return 409 live_project.
What each page shows post-live:
- Review staged setup — the staged-setup review surfaces the
publish_confirmed_atstamp in Step 2 as "Publish confirmation was recorded on <date>. This confirmation is now locked because the project is live." - Publish — Step 3 swaps the orchestration controls for a receipt table (web + server
containerVersionId, publish source, published-at) sourced from the latestpublish_audit_recordrow. - Confirm live traffic — the read-only intro replaces the polling UI; captured realtime evidence remains visible. Legacy projects that never completed live-test see a "Live-test receipt unavailable" banner that points at Health and Changes.
Post-cutover work happens on different surfaces: Go Live for the cutover record, and the Health and Changes pages in the app for ongoing operations.