GTM Web Container

This step configures the browser-side GTM workspace for the Connect stage. It runs after the tagging endpoint exists and before the GTM server container is configured.

The web container is the bridge from "the tagging endpoint exists" to "the tagging endpoint receives traffic". The app page header reads GTM Web Container. Step 1 picks (or creates) the GSS workspace that GTM edits land in. Step 2 manages the required GTM items in that workspace. Step 3 checks the install (the workspace items GSS authored plus three checks against your live page HTML). Step 4 records what you observe in GTM Preview. GSS writes two browser tags into the selected web workspace: a primary Google Tag that sends events to your browser GA4 property (your real analytics), and a test forwarder Google Tag that sends a parallel copy of those events through the tagging endpoint into a server-only GA4 property.

Happy path

The app renders the workspace setup as its own step (visible marker 1), so the three numbered steps below appear as visible markers 2, 3, and 4 on the page.

  1. Set up the GSS workspace — pick or create the workspace inside your selected GTM web container.
  2. Web GTM items — click Create / Reset / Pick on each row that needs attention until all 7 are Ready.
  3. Check GTM items and site install — click Check; all 7 page-install + workspace-API checks turn green.
  4. Confirm each runtime check after Tag Assistant — open GTM Preview, confirm 3.1 (tag fires) and 3.2 (collect 200) are observed, then click Save.
  5. Continue to GTM Server Container.
Glossary
MID
Measurement ID — the G-XXXXXXXXXX string that identifies a GA4 data stream.
GSS - prefix
Naming convention for GTM items that GSS creates or tracks. Renames can still be Ready when behavior matches.
GSS-managed version
The setup Configure writes. A matching user-created item can still be Ready; behavior-changing differences are shown as Changed.
Required item
One of the 7 tags, triggers, or variables GSS needs in the web container.
Workspace
The unpublished draft inside a GTM container where GSS writes. Step 1 + 2 read this draft, not the published live container.

Not covered on this page: GA4 property setup (GA Properties), tagging endpoint provisioning (Tagging Endpoint), GTM container selection (GTM Containers), or server-container configuration (GTM Server Container).

Before you start

  • Complete GTM Containers so this project has a selected GTM web container.
  • Complete GA Properties so the browser and server GA4 measurement IDs are known.
  • Complete Tagging Endpoint so the tagging server URL is available.
  • Make sure the selected GTM web container snippet is installed on the site you are checking, and that you have edit access to the selected web workspace in Tag Manager.

Decision record

The decision record at the top of the app page summarizes what this step is working against and whether the page is ready to hand off to the next Connect step. Its header reads GTM web container. Use it as the page-level status before reading the numbered steps below.

Field Where it comes from What "done" looks like
Web container Inherited from the earlier GTM Containers decision. Read-only here. Container name and GTM-XXXXXXX public ID are shown.
Workspace The GTM web workspace GSS uses for draft edits and detection. Picked or created in the Set up the GSS workspace step below. A workspace name is shown (not "Not saved").
GTM items Rollup of the Web GTM items step. Counts required GTM items that are Ready vs. need attention. 7 of 7 GTM items ready (or fewer if you intentionally ignored an item).
Configuration checks Rollup of the Check GTM items and site install step. Counts the page-install + workspace-API checks that have passed. 7 of 7 verified after the Check button has run.
Preview verification Rollup of the Confirm each runtime check after Tag Assistant step. Counts the browser-assisted attestations you have saved. 2 of 2 confirmed after you observe each runtime check in GTM Preview and click Save.

You can advance to GTM Server Container as soon as GTM items are Ready and Configuration checks are verified. Preview verification is browser-assisted and can finish in parallel — the bottom nav does not block on it.

1Set up the GSS workspace

GSS writes its tag, trigger, and variable changes into a single GTM workspace dedicated to GSS. Nothing in your live container changes until you publish that workspace in GTM. The app surfaces this as the first step on the page so you decide where GSS will write before any GTM item is touched.

The recommended path is to let GSS create its own workspace — click Create GSS workspace on the page, accept the suggested name, and Save. A dedicated workspace keeps GSS’s edits separate from anything else in this container and lets you undo the whole setup later by deleting just this workspace.

  • Pick an existing workspace instead by clicking Refresh workspaces, choosing a row in the picker, then Save workspace. If that workspace already has draft items, a confirmation modal makes you acknowledge that those drafts will publish alongside GSS’s items.
  • Change later — after a workspace is saved, the bound row gets a Delete or Unlink action. Delete removes the workspace in GTM and re-opens the picker. Unlink keeps the workspace in GTM and detaches it from this project.
  • GTM 3-workspace limit — if the container is already at the limit, the panel surfaces a warning. You will need to delete a workspace in GTM first.
  • Saved workspace deleted in GTM — the status pill flips to "Saved workspace missing" and the picker re-renders so you can pick a replacement.

Steps 2, 3, and 4 below are locked with a grey "Set up the workspace in step 1 first" pill until this step succeeds, because a Configure click would have nowhere to write.

2 Web GTM items

This step (visible marker 2 on the app page; anchored as #step-1 here and from app deep-links) is where configuration happens. Each row is a tag, trigger, or variable that GSS checks in your saved GTM workspace. The action verbs are operation-specific — there is no longer a generic "Configure" button. Use:

  • Create on a Missing row to author the GSS-managed item.
  • Reset on a Changed row to overwrite it with the GSS-managed body.
  • Pick a tag / Pick a trigger / Pick a variable on a Multiple-matches row to tell GSS which existing item to track.
  • Re-check at the top of the step after you edit GTM directly, so the cards reflect the current workspace.
  • Restore only when you want to roll a tracked item back to a prior saved version.

All changes stay as unpublished GTM workspace edits until you publish the container at the Publish stage.

2.aWhat this step writes

Seven required GTM items, in two dependency clusters. The cluster around the Primary Google Tag sends events to your real browser GA4 property; the cluster around the Test Forwarder sends a parallel copy to the tagging endpoint, which writes to the server-only GA4 property.

GSS - Browser MID ─┐ ├─ GSS - Primary Google Tag GSS - Initialization (trig) ─┘ GSS - Server MID ─┐ GSS - Server URL ─┼─ GSS - Test Forwarder GSS - All Pages (trig) ─┘

When a downstream item reports dependency_failed, fix the upstream variable or trigger first — the leaf tag depends on whatever the dependency rows resolved to.

2.bRequired GTM item reference

One block per required GTM item. The header line shows the item name, the GSS-managed name, and the GTM type. The four labeled rows below describe what Create / Reset writes, what the item depends on, what counts as Ready, and how to recover when it needs attention.

Reference note: the deep-dive copy below sometimes uses the noun Configure to describe the GSS-managed authoring step. On the app page itself, the actual buttons are Create (Missing), Reset (Changed), and Pick a {type} (Multiple matches). Read "Configure" as a stand-in for whichever of those applies to the row’s current status.

Browser MID variable GSS - Browser MID Constant variable
Create / Reset writes
Value = the browser GA4 stream measurement ID (e.g. G-XXXXXXXXXX).
Depends on
Browser GA4 stream selected in GA Properties.
Ready when
A Constant variable exists whose value equals the browser measurement ID. A different name can still be Ready when behavior matches.
If it needs attention
No browser GA4 stream is selected, value is blank, value uses the server MID, or the variable type is not Constant. Confirm the browser GA4 property/stream selection, then Configure. If you edited GTM by hand, Re-check.
Deep dive

What it is. A GTM Constant variable in the selected web workspace. It holds the production browser GA4 measurement ID (the G-XXXXXX string) so the Primary Google Tag can reference it as {{GSS - Browser MID}} instead of duplicating the literal across tags.

How Configure builds the item. The generator calls expected_browser_mid(bindings), which reads two bindings in order: ga4_stream_browser first (the bound browser stream's display name, if it starts with G-), then falls back to extracting (G-XXXX) from ga4_property_browser.display_name. The resolved MID is written as a literal string into the variable's value parameter, not a variable reference.

Where the inputs come from. ga4_property_browser is written when you save the browser GA4 property on the Discover page. ga4_stream_browser is auto-derived from that property right after save — you do not pick it explicitly.

Why it might fail. If neither binding has a parseable MID, Configure surfaces: "web.browser_mid_variable cannot generate without an expected browser measurement ID. Bind ga4_stream_browser (preferred) or ga4_property_browser before calling generate." The most common cause is that the audit's Discover step has not been completed for this project, or ga4_stream_browser was cleared by the cascade that fires when the GTM web container changes (it is in the dependent-binding set that gets reset).

How to recover. Open the Discover / GA Properties step, confirm a browser GA4 property is saved, then Configure here again. If you recently swapped the GTM web container, the cascade cleared the stream binding — re-saving the property restores it.

Server MID variable GSS - Server MID Constant variable
Create / Reset writes
Value = the server/test GA4 stream measurement ID.
Depends on
Server GA4 stream selected in GA Properties.
Ready when
A Constant variable exists whose value equals the server measurement ID.
If it needs attention
Server GA4 property has no web stream / measurement ID, or value uses the browser MID. Make sure the server GA4 property has a web data stream, then Configure.
Deep dive

What it is. A GTM Constant variable that holds the server (test) GA4 measurement ID — the MID for the GA4 property GSS uses to verify that traffic reaches the tagging endpoint. Referenced by the Test Forwarder tag as {{GSS - Server MID}}.

How Configure builds the item. The generator calls expected_server_mid(bindings), which reads ga4_stream_server (preferred) then extracts the MID from ga4_property_server.display_name. Resolved MID is written as a literal string in the variable's value.

Where the inputs come from. Both bindings come from the GA Properties page. ga4_property_server is written when you save the server GA4 property; ga4_stream_server is derived during the page's Validate step, which matches your Cloud Run tagging URL against the property's web data streams.

Why it might fail. Configure raises: "web.server_mid_variable cannot generate without an expected server measurement ID. Bind ga4_stream_server (preferred) or ga4_property_server before calling generate." Common causes: the server GA4 property was never saved; the property has no web data stream that matches your tagging URL; or the GTM-container cascade cleared both bindings after a web container change.

How to recover. On the GA Properties page, confirm a server GA4 property is selected and that it has a web data stream matching your tagging endpoint. Re-run Validate so ga4_stream_server resolves, then Configure here.

Server URL variable GSS - Server URL Constant variable
Create / Reset writes
Value = the full tagging server URL with https:// (e.g. https://m.example.com).
Depends on
Tagging Endpoint step complete.
Ready when
A Constant variable exists whose normalized value equals the Cloud Run tagging URL. A trailing slash is treated as equivalent.
If it needs attention
Tagging endpoint is incomplete, value is missing https://, or wrong subdomain is used. Complete or correct the Tagging Endpoint step, then Configure. If the endpoint changed, Configure the dependent tags again so they reference the current URL.
Deep dive

What it is. A GTM Constant variable that holds the full https:// URL of your Cloud Run tagging service. The Test Forwarder tag references it as {{GSS - Server URL}} so changing the endpoint only requires updating one variable instead of every tag that uses it.

How Configure builds the item. The generator calls expected_server_url(bindings), which reads the cloudrun_tagging binding — using its resource_id if it begins with https://, or the uri field on its metadata. Trailing slashes are normalized off; lookups against the live workspace are slash-tolerant.

Where the inputs come from. The Cloud Run page writes cloudrun_tagging when you bind an existing service or create a new one through GSS. Unlike the GA4 bindings, this one is excluded from the GTM-container cascade — changing your web container does not clear it.

Why it might fail. Configure raises: "web.server_url_variable cannot generate without an expected server tagging URL. Bind cloudrun_tagging before calling generate." Almost always means the Cloud Run page step has not been completed for this project, or the binding metadata is missing a usable URI (older binding shape predating the metadata field).

How to recover. Open the Cloud Run page, bind or create the tagging service, and save. If the binding exists but the URL field is empty, re-save through the Cloud Run page to refresh metadata, then Configure here.

Initialization trigger GSS - Initialization Initialization trigger
Create / Reset writes
Unfiltered Initialization trigger — no condition rows.
Depends on
Ready when
An unfiltered Initialization or Consent Initialization trigger exists. Filtered triggers do not pass.
If it needs attention
Trigger has filters, uses the wrong type, or was deleted. Configure recreates the GSS-managed trigger. Do not substitute a filtered trigger — it narrows the setup.
Deep dive

What it is. A GTM Initialization trigger — a built-in trigger type that fires once per page during GTM's init phase, before any other tags. The Primary Google Tag uses it as its only firing trigger so the GA4 stream config is established before any measurement events run.

How Configure builds the item. The generator writes a minimal trigger: {name: "GSS - Initialization", type: "init"}. No conditions, no filters. Filters would narrow when the trigger fires and break the assumption that init happens on every page.

Where the inputs come from. None — this item has no upstream bindings. Configure can succeed independently as long as GSS has GTM API write access to the workspace.

Why it might fail. This item's own generator cannot fail. Failures show up in dependent items instead: if the trigger is missing or its artifact_id is unresolved when the Primary Google Tag tries to generate, that tag's Configure raises a missing-dependency error pointing here.

How to recover. Configure this row directly. If it shows Changed because it is filtered, Configure overwrites it with the GSS-managed unfiltered setup — substitute a filtered trigger only if you intentionally want some pages outside GA4 measurement.

All Pages trigger GSS - All Pages Page View trigger
Create / Reset writes
Unfiltered Page View trigger — no condition rows.
Depends on
Ready when
An unfiltered All Pages-style trigger exists for the test forwarder.
If it needs attention
Trigger is filtered, uses another type, or is missing. Configure. Substitute a filtered pageview trigger only if the test path should run on part of the site by design.
Deep dive

What it is. A GTM Page View trigger with no filters — the GSS-managed "fires on every page" trigger. The Test Forwarder tag uses it as its only firing trigger so the parallel forwarded copy mirrors GA4's pageload coverage.

How Configure builds the item. Minimal: {name: "GSS - All Pages", type: "pageview"}. No condition rows.

Where the inputs come from. None — no upstream bindings.

Why it might fail. This item's own generator cannot fail. If the trigger is deleted or its artifact_id is unresolved when the Test Forwarder tries to generate, the forwarder's Configure raises a missing-dependency error pointing here.

How to recover. Configure this row directly to recreate or rewrite. A filtered Page View trigger will show Changed; Configure replaces it with the unfiltered GSS-managed setup.

Primary Google Tag GSS - Primary Google Tag Web Google Tag
Create / Reset writes
Tag ID = {{GSS - Browser MID}}. Triggering = GSS - Initialization. No extra config rows or routing parameters.
Depends on
Browser MID variable + Initialization trigger.
Ready when
An unpaused web Google Tag exists whose Tag ID resolves to the browser MID and whose trigger is unfiltered Initialization, Consent Initialization, or All Pages.
If it needs attention
Wrong measurement ID, paused tag, blocking trigger, filtered trigger, or extra routing rows that differ from the GSS-managed version. Fix the Browser MID variable first if it is unhealthy, then Configure. Configure only edits the item tracked in the GSS workspace.
Deep dive

What it is. The production-side GA4 Google Tag. It sends real user events to your browser GA4 property — the analytics that powers your reports. In the GSS-managed setup it does not set transportUrl: events go directly to www.google-analytics.com/g/collect, not through the server container. Server-side routing happens via the parallel Test Forwarder tag.

How Configure builds the item. The generator writes a Web Google Tag with: tagId = {{GSS - Browser MID}} (variable reference, not literal) and firingTriggerId = the resolved artifact_id of GSS - Initialization. No extra config rows, no routing parameters.

Where the inputs come from. Two upstream items: web.browser_mid_variable (needs its name) and web.initialization_trigger (needs its resolved artifact_id). The registry resolves dependencies before Configure is called, so dependency failures show up as dependency_failed on the card before the generator ever runs.

Why it might fail. If dependencies are unresolved at generate time, the tag raises: "web.primary_google_tag cannot generate without resolved dependencies: missing web.browser_mid_variable (need .name), web.initialization_trigger (need .artifact_id)." The user-visible failure is almost always upstream: the Browser MID variable is itself failing because no browser GA4 stream is bound. dependency_failed on this card means the root cause is on a dependency card.

How to recover. Fix the upstream dependency cards first (Browser MID variable + Initialization trigger), then Configure here. If the upstreams are already green, Re-check first — the failure may be a stale resolution from before the upstreams went green.

Test forwarder tag GSS - Test Forwarder Web Google Tag
Create / Reset writes
Tag ID = {{GSS - Server MID}}. transport_url param = {{GSS - Server URL}}. Triggering = GSS - All Pages.
Depends on
Server MID + Server URL + All Pages trigger.
Ready when
An unpaused web Google Tag exists whose Tag ID resolves to the server MID, whose transport_url resolves to the server URL, and whose trigger is unfiltered All Pages.
If it needs attention
Wrong server MID, missing transport_url, wrong server URL, paused tag, blocking/filtered trigger, or unhealthy dependencies. Resolve the dependency rows first, then Configure. dependency_failed on the forwarder means the root cause is on one of its dependency cards.
Deep dive

What it is. The web-side tag that copies GA4 events to your tagging endpoint, where the server container can re-process them. Same Google Tag template as the primary tag, but configured with the server measurement ID and a transport_url pointing at your Cloud Run service. Its purpose is to give the server-side build a real source of traffic to verify against, without disturbing the production GA4 stream.

How Configure builds the item. The generator writes a Web Google Tag with: tagId = {{GSS - Server MID}}, transport_url = {{GSS - Server URL}}, and firingTriggerId = the resolved artifact_id of GSS - All Pages. Both parameters are variable references, not literals — that is the GSS-managed version. Older GSS installs may show a GSS - Mirror Forwarding Tag with literal values; detection accepts that as equivalent when behavior matches so existing workspaces keep passing.

Where the inputs come from. Three upstream items: web.server_mid_variable (needs name), web.server_url_variable (needs name), and web.all_pages_trigger (needs artifact_id). Transitively this means a server GA4 property + stream from the GA Properties page and a Cloud Run tagging binding from the Cloud Run page.

Why it might fail. If any dependency is unresolved: "web.test_forwarder_tag cannot generate without resolved dependencies: missing <list>." Most common after a GTM web container change: the cascade clears ga4_stream_server and ga4_property_server (so the Server MID variable cannot generate) but preserves cloudrun_tagging (Server URL variable still works). The card shows dependency_failed; the actual root cause is the Server MID variable card.

How to recover. Fix the dependency cards in order: Server URL is usually intact; Server MID needs the GA Properties page re-saved + Validate run; All Pages is a static trigger you can Configure directly. Once all three dependencies are green, Configure here regenerates the tag.

Detection can classify a matching GTM item as Ready even if the name or exact setup differs from the GSS default. Treat non-behavior changes as optional cleanup; treat behavior-changing differences as something to fix before moving on.

2.cAnatomy of a GTM item card

Each required GTM item renders as a card with a fixed shape. Knowing what each field means makes it faster to decide whether to act on a row.

Card field What it tells you
Title + GTM link icon Required item name. The arrow icon next to the title is a deep link into tagmanager.google.com for the tracked GTM item; it only appears when GSS has a tracked item.
Status LED + label Ready, Changed, Missing, Multiple matches, or Ignored, plus a one-line summary.
GSS tracking Whether GSS is tracking an existing item, has no item selected yet, or is ignoring this item.
Last activity When and how the item was last touched (Configure, Restore, manual edit detected, etc.).
Action button(s) The action needed for the current state. Restore and Ignore/Include sit alongside when applicable.
Technical details Disclosure with internal key, tracking state, fingerprint, last-seen timestamp, why the item has this status, and a lazy-loaded diff between the current item and the GSS-managed version.

2.dReference: card states

Status values you might see

Each item card has a visible status, tracking details, and sometimes an action. Use this table to decide whether you can proceed or need to act.

State shown What it means What to do
Ready GSS found the required GTM item and it works for this setup. Includes both exact GSS-managed matches and equivalent user-created items. Nothing required. Open Technical details to see the tracked item, fingerprint, or GTM link.
Changed, behavior still matches The item behaves correctly but differs from the GSS-managed version — usually name, alias type, or literal value vs. variable reference. You can proceed if intentional. Configure rewrites the GSS-managed version; Restore rolls back to a prior known-good version when one exists.
Changed, behavior may differ The tracked item differs in a way that can change behavior: wrong value, wrong tag parameter, paused/blocked tag, filtered trigger, wrong trigger type. Do not proceed. Open details, fix with Configure (or Restore), then Re-check.
Missing No matching GTM item was found in the detected GTM state. Configure. If Configure fails, check the error response and the dependency rows.
Multiple matches More than one GTM item matches what GSS needs, so GSS cannot tell which one to track. Choose the intended item from the card's selector. Prefer the item in the GSS workspace unless you intentionally want to adopt an existing equivalent item.
Ignored You marked the item out of scope. Detection and publish readiness ignore it until you include it again. Include this item if it should participate. Leave ignored only when you intentionally do not want GSS to manage or require that item.

Couldn’t check GTM items: if the whole step shows this, the item cards are not trustworthy for that render. Click Re-check. If it fails again, reconnect Google access, verify Tag Manager API access to the selected web container/workspace, and confirm the workspace still exists.

Actions on each card
Action When it appears What it does
Create Status is Missing, and the item is editable in the GSS workspace. Authors a new item with the GSS-managed body. Does not publish the workspace.
Reset Status is Changed and the tracked item is editable in the GSS workspace. Overwrites the tracked item with the GSS-managed body. Does not publish the workspace.
Re-check Always available at the top of this step. Re-runs detection only — no writes. Use after editing GTM directly so the item cards reflect the current workspace.
Restore A tracked item has prior saved versions in history. Rewrites the existing item with a stored historical version. If multiple versions exist, a select appears next to the button. Shows a diff preview before confirm.
Pick a tag / Pick a trigger / Pick a variable Status is Multiple matches. Pick which existing item GSS should track. After picking, status moves to Ready or Changed depending on the setup.
Ignore this item Available from the card's More menu unless already ignored. Marks the item out of scope. Detection becomes a no-op for the item and publish readiness ignores it. Confirms before applying.
Include Item is currently ignored. Reverses Ignore. Detection runs again next refresh.
Configure error responses and recovery

Every Step 1 error should map to one of these recovery paths. After any fix, run Re-check; if Step 2 has already been checked, run Check again because Step 1 writes do not by themselves prove the page-side checks.

Error or response Likely cause What to do
Missing required bindings The web container, server container, server GA4 property, or Cloud Run tagging URL is not available to Configure. Return to the prior setup pages shown in the message, complete the missing selection or endpoint, then reload this page and Configure again.
No measurement ID found on server GA4 property The selected server GA4 property has no usable web data stream, so GSS cannot populate the Server MID variable. Create or select a web data stream for the server/test GA4 property, then Configure again.
Cannot configure yet GSS could not resolve or create the workspace path needed for writes. Complete the audit/binding prerequisites, verify GTM access, and re-open this page so workspace detection can run again.
Selected item is not editable in the GSS workspace The selected matching item is not in the workspace GSS can edit, often because it is from live state or another workspace. Create or select the intended item in the GSS workspace, or use Configure to create the GSS-managed item when the required item is missing. Then Re-check.
dependency_failed A required item cannot be generated because one of its dependencies is missing, ignored, ambiguous, behavior-changing, or failed to create. Fix the dependency card first. For Primary Google Tag: Browser MID + Initialization. For Test forwarder: Server MID + Server URL + All Pages.
unhealthy_existing Detection found an existing item, but it differs in a way that can affect behavior or matches more than once. Open the card details. For behavior-changing differences, Configure or Restore the tracked item. For multiple matches, choose the intended matching item first.
GTM create/update raised The Tag Manager API rejected or failed the write — usually permission, stale workspace state, network failure, or a GTM validation error. Retry once. If it repeats, confirm your Google account has edit access to the container/workspace, refresh the workspace in GTM, and check whether another user changed or deleted the target item.
unhandled_exception An unexpected configure failure escaped the modeled error paths. The response includes the exception type and message. Retry once. If it repeats, keep the internal key and message from the error response and check the server logs for the captured traceback.
Choose existing item fails The candidate is no longer present, the item no longer has Multiple matches, or detection changed since the selector rendered. Re-check, then choose again from the refreshed candidates.
Restore fails No tracked item, no stored historical version, the target item was deleted, or GTM rejected the update. If the target was deleted, Configure to recreate it. If no history exists, Configure writes the GSS-managed version. If GTM rejected the update, verify edit access and retry.

3 Check GTM items and site install

This step (visible marker 3 on the app page; anchored as #step-2) does not write GTM items. The single button is labeled Check. Clicking it re-runs detection against the selected workspace and pulls the live page HTML to verify install details that GTM-item detection cannot prove from the GTM API alone.

Read the seven checks in two groups. They surface different failure modes:

  • Page-install checks (2.1–2.3) — GSS fetches the live HTML of the site and looks for the GTM loader and its container ID. If the snippet was just installed or changed, your CDN/edge cache may still serve the old page; bust cache before re-running.
  • Workspace-API checks (2.4–2.7) — GSS calls the Tag Manager API against the selected workspace draft, not the published container. These pass right after Step 2's actions run, even if you have not published yet — that is intentional.

The toolbar shows Last checked after each run. The previous step’s Re-check refreshes role detection but does not re-run the page-install checks; click Check here whenever you change the live snippet, change the container ID, or want to confirm the workspace state from a clean read. Acceptable checks (Step 2.2 noscript-after-body, the three Constant-variable checks, etc.) render an inline Override checkbox if they fail — ticking it tells GSS to ignore that check.

Page-install checks (2.1–2.3)

GSS fetches the live HTML and looks for the GTM loader. Recently changed the snippet? Bust CDN/edge cache before re-running.

2.1GTM snippet is present in the page <head> section

The page HTML must contain the GTM loader script inside the <head> element. This confirms the site can load the selected web container before any workspace item matters.

Where to check: Open the site, view page source, search for gtm.js. It should appear inside <head>.

Fix: In GTM → Admin → Install Google Tag Manager, copy the first code block into the <head> of every relevant page. After redeploying the site, bust CDN cache before re-running.

Deep dive

What it checks. A GTM loader URL appears anywhere in the page response, and a <head> tag exists somewhere in the document. Position is not validated — a loader below </body> would still pass as long as <head> appears somewhere.

How GSS performs the check. Fetches https://{your-domain} with a 10-second timeout, follows redirects, sends the default httpx user-agent, and reads the raw HTML response — no JavaScript is executed. Then it does a lowercased substring search for these candidates in order: {tagging-domain}/gtm.jsgoogletagmanager.com/gtm.js/gtm.js. First match wins.

What counts as pass. One of the three loader candidates is found in the body AND the body contains <head>. Lowercased substring match — no regex, no DOM parser.

Why it might fail. Most common: a CDN or edge cache is serving the pre-install HTML. Less obvious: GTM is injected by client-side JavaScript (single-page apps that mount the snippet via JS would not be visible in a raw-HTML check). Also possible: site returns 4xx/5xx (the error page is checked instead of the live page); SSL handshake fails (response body is empty, check fails silently); the page genuinely lacks a <head> tag.

How to recover. Confirm the snippet is in the server-rendered HTML using curl -L https://{domain} or browser View-Source (not DevTools — DevTools shows the rendered DOM, which can mislead). Bust cache. If you use a SPA framework, ensure the snippet is in the static template, not injected client-side.

2.2GTM noscript iframe is placed immediately after the opening <body> tag

The noscript fallback should be near the top of <body>. This is a page-install check; GSS cannot write it through GTM.

Where to check: In page source, search for noscript near the opening <body>.

Fix: In GTM → Admin → Install Google Tag Manager, copy the second code block immediately after the opening <body> tag.

Deep dive

What it checks. A GTM noscript iframe URL (ns.html) appears anywhere in the page HTML.

How GSS performs the check. Reuses the same raw HTML fetch as 2.1 (no JS execution, follows redirects, 10s timeout). Lowercased substring search for these candidates in order: {tagging-domain}/ns.htmlgoogletagmanager.com/ns.html/ns.html. First match wins.

What counts as pass. Any one of the candidate URLs appears anywhere in the body. Despite the check name, positional placement is not verified — the implementation only confirms presence, not "after opening <body>." Anywhere in the HTML satisfies it.

Why it might fail. The noscript block was never copied (GTM's install instructions deliver it as a separate snippet); CDN cache lag; SPA-style rendering where neither block is in the server HTML.

How to recover. Install per GTM's standard instructions (the second code block goes right after opening <body>). Bust cache. If position matters for your accessibility/SEO posture, fix that too — but it does not affect this check's pass/fail.

2.3GTM snippet references the correct web container ID

The page source must reference the same public container ID shown in the decision record. A mismatch means the site is loading a different GTM web container than the one GSS is configuring — every Step 1 write would land in a workspace the live page never sees.

Where to check: In the GTM snippet URL, confirm the id=GTM-XXXXXXX value matches the selected web container's public ID.

Fix: Either re-install the snippet for the selected container, or revisit GTM Containers to bind the container that the site is actually loading.

Deep dive

What it checks. The bound web container's public ID (the GTM-XXXXXXX string) appears verbatim in the page HTML.

How GSS performs the check. Reuses the same raw HTML fetch as 2.1/2.2. Case-sensitive substring search against the un-lowercased response body for the exact publicId value from the bound web container's metadata. Unlike 2.1/2.2, this one preserves case.

What counts as pass. The bound container's GTM-XXXXXXX is found anywhere in the body. If no web container is bound (the binding's publicId is empty), the check fails immediately with "Container public ID not available" — no fetch is made.

Why it might fail. The site loads a different container than the one bound to this project (the most common cause; check decision record vs. page source). Snippet was not updated after a container swap. Case mismatch (extremely rare — the GTM ID is uppercased everywhere, but a hand-edited snippet could break this). Cache lag.

How to recover. Either re-install the snippet for the bound container, or update the binding on GTM Containers to match the container the site actually loads. Note: changing the bound container triggers a Tier 2 cascade that clears upstream GA4 stream bindings — see Common errors below.

Workspace-API checks (2.4–2.7)

GSS calls the Tag Manager API against the selected workspace draft, not the published container. These pass right after the GTM-items step’s Create / Reset actions run, even if you have not published yet.

2.4GTM variable for browser measurement ID exists in workspace

A Constant variable with the browser GA4 measurement ID must exist in the selected web workspace.

Where to check: GTM → web container workspace → Variables. Look for a Constant variable whose value matches the browser measurement ID.

Fix: Configure on the Browser MID variable item in Step 1, or create the Constant variable manually in the selected workspace.

Deep dive

What it checks. Some Constant (type: "c") variable in the workspace has a value exactly equal to the resolved browser GA4 measurement ID.

How GSS performs the check. Calls tagmanager.googleapis.com/.../workspaces/{id}/variables against the unpublished workspace draft (not the published container). Iterates all variables, filters to type == "c", and compares each variable's value parameter against the expected MID.

What counts as pass. Any Constant whose value matches passes — name does not matter here. A user-created Constant called my GA4 ID with the right value still passes Step 2. This is more lenient than Step 1 item detection, which prefers the GSS-managed name and shows Changed only when the setup differs. Step 2 only cares about behavior.

Why it might fail. The variable was never created (Configure in Step 1 not run); the variable exists but its value is wrong (a different MID); the variable is not a Constant (e.g., changed to a Lookup Table); the variable name is right but the value is empty. Also: the bound workspace was deleted or moved in GTM, in which case the API call errors and the whole workspace-API group fails.

How to recover. Easiest: Step 1 Configure on the Browser MID variable item. If you prefer to manage it manually, create a Constant variable in the bound workspace with the right value and run Check again.

2.5GTM variable for server measurement ID exists in workspace

A Constant variable with the server/test GA4 measurement ID must exist in the selected web workspace.

Where to check: GTM → web container workspace → Variables. Look for a Constant variable whose value matches the server measurement ID.

Fix: Configure on the Server MID variable item in Step 1, or create the Constant variable manually in the selected workspace.

Deep dive

What it checks. Same logic as 2.4, but compared against the server (test) GA4 measurement ID resolved from ga4_stream_server / ga4_property_server bindings.

How GSS performs the check. Reuses the same variables.list API call as 2.4 — one network call covers all four workspace-API checks. Constant-only filter; value-equality match.

What counts as pass. Any Constant whose value equals the resolved server MID. Name-agnostic, same as 2.4.

Why it might fail. Same reasons as 2.4, plus an additional upstream cause unique to the server side: if the server GA4 property has no web data stream, the resolver returns no MID and the check status is needs_config rather than fail. That points the user back to the GA Properties page.

How to recover. If needs_config: GA Properties page → confirm the server property has a web data stream → run Validate so ga4_stream_server resolves → Configure the item in Step 1 → Check. If fail: same path as 2.4.

2.6GTM variable for server container URL exists in workspace

A Constant variable with the tagging server URL must exist in the selected web workspace.

Where to check: GTM → web container workspace → Variables. Look for a Constant variable whose value is the full tagging server URL, including https://.

Fix: Configure on the Server URL variable item in Step 1, or create the Constant variable manually in the selected workspace.

Deep dive

What it checks. Some Constant variable in the workspace has a value exactly equal to https://{server-custom-domain}.

How GSS performs the check. Reuses the same variables.list response as 2.4/2.5. Same Constant-only filter, same value-equality match. The expected URL is built from the project's server_custom_domain config and prepended with https://.

What counts as pass. Exact match including the https:// prefix and no trailing slash. If server_custom_domain is blank in the project config (no tagging endpoint configured yet), the check returns needs_config and skips the API match.

Why it might fail. Most common: a hand-edited Constant has a trailing slash (Step 1 normalizes the slash off; Step 2 expects no slash). The variable was set to the raw Cloud Run service URL (*.run.app) instead of the custom domain. Tagging endpoint not yet configured. Old shape: http:// instead of https://.

How to recover. If needs_config: complete the Tagging Endpoint step so the custom domain binding lands. If fail with a value mismatch: Step 1 Configure on Server URL writes the GSS-managed value, or you can edit the Constant directly to https://{your-tagging-domain} with no trailing slash.

2.7Google Tag referencing browser measurement ID exists and fires on Initialization

The selected workspace must contain a web Google Tag whose Tag ID resolves to the browser measurement ID and whose trigger fires on Initialization or All Pages.

Where to check: GTM → web container workspace → Tags. Open the browser Google Tag and inspect Tag ID and Triggering.

Fix: Configure on the Primary Google Tag item in Step 1. If editing manually, set Tag ID to the Browser MID variable and use an Initialization trigger.

Deep dive

What it checks. A web Google Tag in the workspace whose tagId or measurementId resolves to the browser GA4 measurement ID, AND whose firing trigger is an Initialization or Page View trigger.

How GSS performs the check. Two API calls (alongside variables.list from 2.4–2.6, three workspace calls in total per Check run): tags.list and triggers.list on the unpublished workspace draft. For each tag of type in {"gaawc", "googtag"}, GSS reads either the tagId or measurementId parameter, and resolves one level of {{Variable}} reference (only against Constant variables) before comparing.

What counts as pass. The first matching tag is selected by MID value. Then its firingTriggerId array is checked: built-in IDs 2147479553 / 2147479573 (Initialization) and 2147479558 (All Pages) count, plus any user-created trigger of type in {"init", "pageview"}. Tag name is irrelevant (MID match only). Trigger filters are not validated here — a filtered Page View trigger still passes Step 2; only Step 1 item detection enforces unfiltered.

Why it might fail. The tag's tagId is a literal MID string instead of {{Browser MID}}, and the literal does not match the expected MID. The MID is hidden behind a nested reference ({{outer}}{{inner}}) — only one level of indirection is resolved. The tag fires on a custom Click/Form trigger only (not init/pageview). The tag is paused — note: pause state is not actually checked here, so a paused tag can pass Step 2 but won't fire in Step 3.

How to recover. Easiest path: Step 1 Configure on the Primary Google Tag item. Manual: open the tag in GTM, set Tag ID to {{GSS - Browser MID}} (or any Constant variable whose value matches), and attach an Initialization or All Pages trigger.

4 Confirm each runtime check after Tag Assistant

This step (visible marker 4 on the app page; anchored as #step-3) is attestation, not auto-detection. GSS cannot drive a browser, so you open GTM Preview yourself, observe each runtime behavior, tick the Confirm checkbox on each row, and click Save at the bottom to commit the full set in one POST. Unchecking a previously-confirmed row before Save and re-saving surfaces a warning that you will need to re-confirm before this step passes.

Why you do this manually

GTM Preview runs in your authenticated GTM session and against an unpublished workspace. GSS cannot impersonate that session — only the human in the browser sees what fires. The runtime checks here exist to prove the workspace draft actually behaves the way the previous two steps describe before you publish.

Toggling a checkbox is local until you click Save — the persisted label flips to Confirmed at {timestamp} only after the bulk save commits.

How to open GTM Preview for this workspace
  1. In GTM, open the selected web container and switch into the workspace shown in the decision record.
  2. Click Preview (top-right). Tag Assistant opens in a new tab.
  3. Enter the URL of the page where the GTM snippet is installed and click Connect.
  4. The site opens in a Tag Assistant frame. Browse the page so the initial pageload event fires.
  5. Switch back to the Tag Assistant tab. Use Tags Fired on the initial event to verify Step 3.1, and the browser DevTools Network panel for Step 3.2.

If Tag Assistant cannot connect: verify the snippet is installed on that exact page, that consent banners are not blocking GTM, and that the site is loading the same container ID shown in the decision record (Step 2.3).

3.1Browser GA4 config tag fires on page load

In Tag Assistant for the selected web workspace, with the site connected, load a page. The browser GA4 config tag (GSS - Primary Google Tag or your equivalent) should appear under Tags Fired on the initial pageload event.

In the app: tick this row’s Confirm checkbox once you see the tag in Tags Fired. Click Save at the bottom of the step to commit. To re-verify, untick and Save again.

If it does not fire: check that the tag is unpaused, the trigger is unfiltered Initialization or All Pages (covered in the previous step), and the workspace shown in Tag Assistant matches the workspace in the decision record.

3.2Browser-side collect request returns HTTP 200

With Tag Assistant active, open browser DevTools → Network and filter for collect. A request to www.google-analytics.com/g/collect should return HTTP 200.

In the app: tick this row’s Confirm checkbox after the network request succeeds, then click Save. This is browser-assisted evidence — the app records your attestation rather than fetching it directly.

If the request never appears: the browser GA4 tag did not fire (Step 3.1) or an ad blocker is suppressing it. Try a clean profile.

Common errors & failure modes

Cross-cutting failures that don't sit on a single GTM item card. If a card shows a specific error message, look at the item's If it needs attention field and Deep dive in Step 1.b first; the symptoms below are the page-level patterns.

Symptom Likely cause Where to fix
Workspace / container mismatch
Step 1 Ready, 2.3 fails (container ID mismatch) The site loads a different GTM-XXXXXXX than the one GSS is configuring. Step 1 writes are landing in a workspace the live page never sees. Re-install the correct snippet, or revisit GTM Containers to bind the container the site actually loads.
Step 2 verified, Step 3 tags don't fire in Preview Tag Assistant is connected to a different workspace than the one your site loads. The published container does not include your draft edits. In GTM, switch into the workspace named in the decision record, then click Preview from there. Re-connect Tag Assistant.
Page install & cache
Step 1 Ready, 2.12.2 fail GTM snippet was never installed on the page being checked, or the page URL points somewhere the snippet is not deployed. Install both snippet blocks per GTM install instructions; re-deploy; check the right URL.
Just installed/changed the snippet, page-install checks still fail CDN, edge cache, or browser cache is still serving the old HTML. Bust cache (CDN purge, hard reload, incognito), then click Check again. Built-in retry doesn't bypass cache.
Cascade after upstream changes
Server-side GTM items flip from green to dependency_failed after changing the GTM web container The GTM-container cascade clears ga4_stream_server, ga4_property_server, and ga4_stream_browser. Server URL survives (cloudrun_tagging is not in the cascade). Re-save the browser + server GA4 properties on GA Properties; run Validate; come back here and Configure the affected items.
Browser MID variable fails with "cannot generate without an expected browser measurement ID" No browser GA4 stream / property is bound to this project, or the cascade just cleared it. GA Properties page → save the browser GA4 property. The stream binding auto-derives.
Server URL variable fails with "Bind cloudrun_tagging before calling generate" No Cloud Run tagging service is bound, or the binding's metadata has no usable uri. Tagging Endpoint / Cloud Run page → bind or create the tagging service.
Workspace state changes
Step 1 Ready, 2.42.7 fail right after Configure Workspace was edited externally between Configure and Check, or its state changed underneath GSS. Re-run Step 1 Re-check, then Step 2 Check again.
Item card shows Multiple matches More than one GTM item matches what GSS needs — GSS cannot decide which one to track. Open the card, choose the intended item from the selector. Prefer the one in the GSS workspace.
Configure fails with "Selected item is not editable in the GSS workspace" The matched item lives in live state or another workspace; GSS cannot write through it. Create or select a workspace item (or let Configure create one when the required item is missing); then Re-check.
Preview & runtime
3.1 tag never fires Tag is paused, trigger is filtered, or Tag Assistant is connected to a different workspace than the snippet loads. Confirm Step 1 trigger is unfiltered; confirm tag is unpaused; re-open Preview from the workspace shown in the decision record.
3.2 collect request never appears 3.1 didn't fire (no GA4 tag, nothing to send), or an ad blocker / privacy extension is suppressing the request. Verify 3.1 first. Try a clean browser profile (no extensions) before assuming the tag is wrong.
GTM API write rejected ("GTM create/update raised") Permission lost, workspace stale, or another user changed the target item between detect and write. Retry once; if it persists, confirm Google account has GTM edit access and refresh the workspace in GTM.

Next step

The bottom nav opens GTM Server Container after the GTM item rollup is Ready and configuration checks are verified. Browser preview verification is still important, but the app lets server-container setup proceed while you finish browser-side attestations.