Connect GTM Containers
This step (titled Connect GTM Containers in the app) binds the GTM server container that will run inside your Cloud Run tagging service. The web GTM container was audited and bound during the Audit stage and is shown read-only here. If you need to change it, go back to Audit Discovery.
The server container is permanent: the same container goes through Cloud, Connect, Publish, Go Live, and ongoing operation. You don't need separate test and production containers — the configuration inside it changes as you move through the stages, but the container identity stays the same.
Happy path
- Step 1 — click Find containers to discover the GTM containers your Google account can see.
- Step 2 — pick a server container in the picker and click Save server container, OR click Create a new server container in this account and let GSS create one in the same GTM account as your web container.
- Step 3 — click Check; all 5 requirements turn green.
- Continue to Connect GA4.
Glossary▶
- Web container
- A GTM container with usage context
web. Lives in the browser asgtm.js. Identified by a public ID likeGTM-XXXXXXX. - Server container
- A GTM container with usage context
server. Runs in your Cloud Run tagging service, processes events forwarded by the web container, and writes them to GA4. - GTM account
- The top-level container holder in GTM. Web and server containers must be in the same account for workspace operations to work in later stages.
- Public ID
- The
GTM-XXXXXXXstring that's visible in the page source. Used by browsers to load the container snippet. - Container path
- The internal GTM API identifier:
accounts/{a}/containers/{c}. Different from the public ID; used for API calls.
Not covered on this page: changing the web container (Audit Discovery), workspace selection (handled later in the Connect stage), or Cloud Run setup (Cloud Run Services).
Before you start
- Complete GCP Project — Tag Manager API must be enabled.
- Web container was selected during Audit Discovery. If you need to change it, go back there — the change cannot be made on this page.
- Have at least Edit access to the GTM account that holds your web container, so GSS can list and create containers in it.
Decision record
| Row | Where it comes from | What "done" looks like |
|---|---|---|
| Web container | Inherited from Audit Discovery. Read-only here. | Container name and GTM-XXXXXXX shown. |
| Server container | Set in Step 2 below — pick an existing server container or create one. | Container name and GTM-XXXXXXX shown. |
| Requirements | Rollup of Step 3. | 5 of 5 verified after Step 3's Check button has run. |
1 Discover GTM containers available to your account
Click Find containers the first time you visit this page. GSS calls the Tag Manager API for the GTM account that holds your bound web container and lists every container in that account (both web and server). After the first run the button becomes Refresh containers — use it whenever you add or remove containers in GTM.
The status line shows how many GTM containers were found in total and how many of those are server-context candidates for Step 2. If the container you expect doesn't appear, your account probably doesn't have at least Edit access on the GTM account — fix the access in GTM Admin, then click Refresh containers.
2 Which GTM server container should GSS configure?
The web container is shown above the picker as inherited context (you can only change it from Audit/Discover). The picker below lists every server-context container in the same GTM account as the web container. You can pick one that already exists or have GSS create a new one in this account — both paths land at the same final state, just with different provenance metadata.
This step stays locked with a "Locked" banner until both prerequisites are met: a web container is bound in Audit, and Step 1 discovery has run. The Save button stays disabled until you pick a row different from what's already saved; switching to a different server container clears Step 3's requirement results and you'll need to re-run Check.
Option A — Pick an existing server container
If you already have a server container in the right GTM account, click its row in the picker and then Save server container. The picker filters to server-context containers in the same account as the web container, so you should only see eligible candidates. Each row links its GTM-XXXXXXX ID out to the workspace view in tagmanager.google.com.
GSS records this binding with created_by: user metadata so the Resources page can label it as user-managed. Behavior is identical either way; the metadata is only for display.
Option B — Create a new server container in this account
Click the Create a new server container in this account link below the picker (or Create server container in this account if no server containers were found). The modal has just two visible fields:
- Container name — pre-filled with a project-derived suggestion (a numeric suffix is appended if the name is already in use in the account). Editable; required.
- Account (read-only) — the GTM account that holds your web container. GSS always creates the new server container in this account so the same-account requirement check passes automatically.
Click Create. GSS calls the Tag Manager API to create the container, binds it to the project, and re-renders Step 2 with the new container selected; Step 3's requirement results are cleared so you'll need to re-run Check. If the API call fails, the error is shown inline next to the Create button — retry or pick an existing container instead.
GSS records this binding with created_by: gss metadata.
Rebinding the server container later
Changing the server container is allowed and only triggers a small cascade: the gtm_server_workspace binding clears (workspaces are container-scoped, so the old workspace can't carry over) and this stage's check rows reset. Your GA4 bindings, GCP project, Cloud Run services, and the web container are not affected. The big destructive cascade lives upstream in Audit Discovery — changing the web container or browser GA4 property there is the action that wipes downstream bindings.
3 Can GSS work with both containers?
Click Check to validate that both containers are reachable, the server container has the correct server usage context, both live in the same GTM account, and the web container's public ID has the expected GTM-XXXXXXX format. GSS makes one or two Tag Manager API calls (one if both containers are in the same account, two if they happen to be in different accounts — though that itself fails the same-account requirement).
Step 3 stays locked until both Step 2's server container and the Audit web container are bound. After a successful Check the page nav at the bottom unlocks the link to Connect GA4.
2.1Web container is accessible
The web container selected during Audit must still be reachable via the Tag Manager API.
Where to check: GTM → Admin → Container Settings. Verify the container exists and your account has access.
Fix: If the container was deleted or you lost access, go to Audit Discovery and pick a different web container.
Deep dive ▶
What it checks. The web container's path (accounts/{a}/containers/{c}) appears in the Tag Manager API's container list for that account.
How GSS performs the check. One list_containers(web_account) call. The same response is reused for 2.2 if the server container is in the same account.
What counts as pass. Path match in the response.
Why it might fail. Container deleted in GTM. Your Google account lost access to it. The bound container path was corrupted (rare).
How to recover. Re-run Audit Discovery and pick the correct web container. If it's a permissions issue, ask the container owner to grant your account access.
2.2Server container is accessible
The server container picked or created in Step 2 must be reachable via the Tag Manager API.
Where to check: GTM → Admin → Container Settings. The server container should be listed.
Fix: If the container was deleted, pick a different one or create a new one in Step 2.
Deep dive ▶
What it checks. The server container's path appears in the Tag Manager API's container list.
How GSS performs the check. Reuses the list_containers(web_account) response from 2.1 if both containers are in the same account. If the server container is in a different account, makes a second list_containers(server_account) call.
What counts as pass. Path match.
Why it might fail. Container deleted. Lost access. Container moved between accounts (rare).
How to recover. Pick a different server container in Step 2, or create a new one. If you intentionally moved the container, re-bind it.
2.3Server container has server usage context
The bound server container must have usageContext: server. Container type is set at creation and cannot be changed afterward — picking a web container by mistake is a hard re-do.
Where to check: GTM → Admin → Container Settings → Container type. It should show "Server".
Fix: Pick a different container in Step 2, or create a new one via the Create link (which always creates a server-context container).
Deep dive ▶
What it checks. "server" appears in the container's usageContext array.
How GSS performs the check. No additional API call — reads usageContext from the container object already retrieved in 2.2.
What counts as pass. The array contains "server". A container with ["web"] only fails.
Why it might fail. User picked a web container by mistake. The picker should filter to server-context containers, but if you bound one through the JSON API directly or via legacy paths, you might end up with the wrong type.
How to recover. Container type is immutable in GTM. Pick a different existing server container, or create a new one in Step 2.
2.4Both containers in the same GTM account
The web and server containers must be in the same GTM account. Cross-account workspace operations are not supported by the GTM API in the way GSS uses them.
Where to check: GTM → Admin. Both containers should appear under the same account in the account list at the top.
Fix: Move the server container to the web container's account (GTM Admin → container settings), or pick a different server container that's already in the right account.
Deep dive ▶
What it checks. The first two segments of both containers' paths match — i.e., both have the form accounts/{same-id}/containers/....
How GSS performs the check. No additional API call — pure path comparison on the bound resource_ids.
What counts as pass. Both account IDs identical.
Why it might fail. User picked or bound a server container in a different account than the web container. (The picker filters to same-account candidates, so this usually only happens with manually-bound containers or via direct API.)
How to recover. Either pick a same-account server container in Step 2, or create one via the Create link (always uses the web account). If you really want them in different accounts for some reason, that's not currently supported — moving forward will fail in later stages.
2.5Web container public ID format
The web container's public ID must follow the GTM-XXXXXXX format. This is the ID embedded in the GTM snippet on your site.
Where to check: GTM → Admin → Container Settings. The public ID is shown at the top.
Fix: Failure here is rare — GTM containers always have GTM-prefixed IDs. If you see a fail, the binding metadata is corrupt; re-run Audit Discovery to refresh it.
Deep dive ▶
What it checks. The web container's publicId field starts with GTM-.
How GSS performs the check. Reads publicId from the container object retrieved in 2.1.
What counts as pass. Prefix match: publicId.startswith("GTM-").
Why it might fail. Effectively never — every GTM container ID has the prefix. This check exists as a sanity rail in case the binding metadata was hand-edited or corrupted.
How to recover. Re-run Audit Discovery to refresh the web container metadata; or directly edit the binding via the JSON API as a last resort.
Common errors & failure modes
| Symptom | Likely cause | Where to fix |
|---|---|---|
| Binding state | ||
| Save returns 422 "No web container — fix your audit selection first" | No web container is bound (Audit not completed or its binding was cleared by an upstream cascade). | Audit Discovery — pick a web container, save, then return here. |
All 5 checks show needs_config |
Either binding (web or server) is missing. | Confirm the web container is bound (Audit Discovery), then pick or create a server container in Step 2. |
| Wrong container picked | ||
2.3 fails with usageContext: ["web"] |
User picked a web container as the server container. Container type is immutable. | Step 2 — pick a different server container, or click the Create link to make a new one in the right account. |
| 2.4 fails — different accounts | Server container is in a different GTM account than the web container. | Move the server container in GTM Admin (rare) or pick a same-account container. The Create link always uses the web account. |
| Create server container | ||
| Create modal shows an inline error "Could not create the server container" | Provider call failed (network, GTM API quota, or container name collision after the suffix logic). | Retry once. If it persists, check Cloud Console → APIs → Tag Manager API for quota, or pick an existing container instead. |
| Create modal won't submit with an empty Container name | The name field is required. The pre-fill is just a suggestion; you can override but not blank it. | Type a name and retry. |
| Workspace state | ||
After changing the server container, Connect stage shows needs_config for workspace |
Expected: changing the server container clears gtm_server_workspace (workspaces are container-scoped). The Connect stage will set up the workspace afresh. |
No action needed here. Continue forward; the Connect stage handles workspace selection. |
| "Validation failed — please try again." shows next to the Check button | Network or credential failure during the requirements check. HTMX skipped the swap so existing rows are preserved. | Retry once. If it persists, reconnect Google access in the app. |
Next step
Once Step 3's check passes, the page nav unlocks the link to Connect GA4 property — picking or creating the GA4 Test Server property that will receive forwarded events during Build verification.