2026-05-23

An AI Analytics Agent Needs a Measurement Contract, Not GTM Publish

A 38-case contract admits bounded GA4 shadow reports while blocking PII, identifier drift, broad queries, admin writes, and every GTM publish path.

An AI Analytics Agent Needs a Measurement Contract, Not GTM Publish cover illustration

Measurement-chain admission test

A tag firing in Preview, an event arriving in Google Analytics 4, and a row appearing in a report are three different facts. An AI analytics agent should reconcile those facts against one measurement contract. It should not acquire Google Tag Manager publish authority merely because a number is missing.

That boundary changes the shape of the automation. The agent receives an exact event name, schema version, parameter allowlist, consent state, environment, Measurement ID, numeric Property ID, GTM container and workspace, report query, completed date range, property timezone, and output destination. It may admit a read-only shadow report when every field agrees. It may not edit a tag, patch a property, or publish a container version.

A deterministic fixture tested that contract across 38 synthetic cases. Three complete packets reached READY_FOR_SHADOW_REPORT. The remaining 35 stopped with one of 20 blocking or hold decisions. No Google account, credential, event stream, GTM workspace, GA4 property, or API was contacted.

Retained result: 38 of 38 expected decisions matched, with 21 observable decision states. Fixture SHA-256: 6bae13c722c68b37c58ce532f90c5203ef1110f8c6c08355e544a2effbd2d475.

Start with the measurement chain, not the dashboard

A dashboard can be internally consistent and still measure the wrong thing. A broad trigger can count form views as submissions. A duplicate listener can emit twice. GTM Preview can show the intended tag while production serves a different container version. The GA4 interface can display an event from the wrong property or timezone. A report can query a plausible metric across the wrong date range and still return rows.

The contract therefore begins upstream of Analytics. For a synthetic lead_submit event, the source application must confirm that a submission completed. The event carries a stable event ID, a pinned schema version, and only two allowlisted parameters. Consent must be known before admission. The test environment is explicit. None of those facts can be inferred from a chart after collection.

Application receiptConfirmed source action, event ID, schema version, parameter allowlist, consent, and environment.
Delivery identityMeasurement ID plus exact GTM container and workspace paths, kept distinct from the Analytics property.
Report receiptNumeric Property ID, allowed dimensions and metrics, completed date range, timezone, and private output.

Google documents recommended GA4 events and their expected parameters. When a recommended event matches the product action, use it rather than inventing a synonym. A custom name can still be valid, but it needs a local schema and stable ownership. The fixture uses lead_submit deliberately as an organization-specific example; it does not claim that this name is a Google recommendation.

The important part is the receipt. “The event exists” is too weak. The agent needs to know which source action justified it, which schema produced it, and whether the same event ID was already admitted.

Identifier mix-ups are not typing errors

Three identifiers that must never blur together

Analytics setup is full of identifiers that look interchangeable when copied into a prompt. They are not.

  • A Measurement ID identifies the GA4 web data stream used by the collection tag.
  • A numeric Property ID scopes a Google Analytics Data API request such as properties/1234:runReport.
  • A GTM container and workspace path identifies where tags, triggers, and variables are inspected or edited.

Passing the Measurement ID where the report expects a numeric property should fail before any request. So should a property that is valid but not the approved property. The same logic applies to a neighboring GTM workspace: validity is not authorization.

Modular illustration of three differently shaped identifier keys approaching exact gates before a sealed analytics report
A Measurement ID, Property ID, and GTM workspace are different keys. A plausible neighboring identifier should stop at the jig rather than silently query or alter the wrong resource.

Validation stopped thirty-five plausible packets

The base packet described one completed test-environment event. It pinned measurement-v3, event schema lead-submit-v2, two parameters, granted analytics consent, one Measurement ID, one Property ID, one container, one workspace, an allowed properties.runReport query, a seven-day completed range, the property timezone, and a local private output.

Each negative case changed one boundary. The decision function is ordinary JavaScript with a fixed order. It does not call a model or try to decide whether a value “looks close enough.”

38synthetic contract cases
3shadow reports admitted
35held or blocked
21observable states
MutationObserved decisionBoundary retained
The event came from a page inference or stale spreadsheet rather than the source application.BLOCK_EVENT_SOURCEA downstream row cannot manufacture upstream confirmation.
The event name or schema version drifted.BLOCK_EVENT_NAME or BLOCK_SCHEMAA familiar label does not substitute for the approved contract.
The event ID was already seen.BLOCK_DUPLICATERetries cannot turn one submission into two accepted facts.
A parameter was not allowlisted, or a value contained email, phone, or freeform text.BLOCK_PARAMETER or BLOCK_PIICollection is rejected before privacy-sensitive data reaches Analytics.
Consent was denied or unknown.HOLD_CONSENTThe agent cannot infer consent from the presence of a tag.
The Measurement ID, Property ID, container, workspace, date range, or timezone did not match.One exact identity or range blockEvery resource and reporting boundary stays independently pinned.
The query requested an unapproved dimension, metric, or report method.BLOCK_DIMENSION, BLOCK_METRIC, or BLOCK_TOOLRead access is bounded by query shape, not only by credentials.
The packet requested a GTM or Analytics admin write.BLOCK_ADMIN_WRITEMeasurement reconciliation never becomes configuration authority.
The output targeted a public sheet or message send.BLOCK_OUTPUTA safe query does not justify an uncontrolled disclosure channel.

The matrix is a policy fixture, not an experiment on a live property and not evidence of reporting accuracy, attribution quality, consent compliance, or business lift.

Why the check order matters

The function rejects source, event, schema, duplication, unexpected parameters, and PII before evaluating Google resource identifiers. It checks consent and environment before report shape. It checks the report method before admin-write intent and output destination.

This order reduces misleading partial success. A packet with an unapproved properties.patch method stops at BLOCK_TOOL; a valid report method paired with an explicit GTM update stops at BLOCK_ADMIN_WRITE. Both capability and declared intent must stay inside the read-only role.

Three packets passed: the base event-count query, a date-dimension variant, and a total-users variant. Each used only allowed query fields. Admission means the query shape is consistent with the retained contract. It does not mean the returned data will be correct.

The privacy gate belongs before collection

Google's Analytics policy says not to pass data that Google could use or recognize as personally identifiable information. Its examples include email addresses, personal mobile numbers, and social security numbers. The guidance also warns that URLs, URL parameters, page titles, custom dimensions, campaign parameters, search terms, and event dimensions can carry PII inadvertently.

That makes “remove the email field” an incomplete rule. A freeform parameter can contain an email. A URL can place it in a query string. A campaign label can contain a customer name. The admission gate must inspect parameter names and value classes before the event enters the measurement path.

The fixture applies two controls. First, only form_variant and placement are accepted keys. Second, a separate PII/freeform signal rejects disallowed values even under an approved key. The latter is necessary because an allowlisted key does not make every value safe.

Modular privacy gate passing two approved event tokens while diverting envelope phone and freeform shapes away from a private report
The allowlist controls shape; the privacy check controls content. Both run before a token reaches the bounded report path.

Consent is a retained input, not a guess

A tag's presence says nothing about whether analytics consent was granted for this event. The contract stores the consent state that the source application observed. Unknown and denied states both pause admission. That is intentionally stricter than attempting to reconstruct consent later from a report.

The design does not claim to implement a consent-management platform or interpret regional law. It only refuses to treat missing consent evidence as permission. Real deployments still need legal and product review of their consent model, retention policy, regional configuration, and user controls.

Read-only reporting and GTM publication are different jobs

The Google Analytics Data API documents properties.runReport as a property-scoped method. Its request can name dimensions, metrics, date ranges, filters, ordering, limits, and related options. That is already a broad read surface. A narrowly useful agent should receive a wrapper that fixes the property and permits only the query fields the review actually needs.

Google Tag Manager exposes workspace methods such as list, get, status, quick preview, sync, and update. Publishing is a separate container-version operation. That separation is the architectural clue: inspecting a workspace and publishing a container version are different authorities, even when the same API family exposes both.

The analytics agent does not need the second authority. If it finds a discrepancy, its output is a reconciliation packet:

{
  "contract": "measurement-v3",
  "event": {
    "name": "lead_submit",
    "source": "application_confirmed",
    "schema": "lead-submit-v2",
    "consent": "analytics_granted"
  },
  "resources": {
    "measurementId": "G-DEMO12345",
    "propertyId": "123456789",
    "container": "accounts/100/containers/200",
    "workspace": "accounts/100/containers/200/workspaces/300"
  },
  "query": {
    "method": "properties.runReport",
    "dimensions": ["eventName"],
    "metrics": ["eventCount"],
    "dateRange": ["2026-07-14", "2026-07-20"],
    "timezone": "Etc/UTC"
  },
  "decision": "READY_FOR_SHADOW_REPORT",
  "adminWriteAllowed": false
}

A human can use the packet to decide whether a tag, trigger, consent configuration, event schema, or report definition needs repair. If a GTM change is approved, execute it through a separate change workflow with an exact workspace, diff, reviewer, preview evidence, version creation, publication approval, rollback reference, and post-publish verification.

Tool policy must match the sentence “read only”

A prompt that says “do not publish” is not a capability boundary. The agent should receive a report wrapper, not a generic browser session, shell, full GTM token, or unrestricted Google API client. OpenClaw's tool-policy documentation makes the same distinction: deny rules take precedence, and broad execution remains broad even if named write tools are absent.

The output channel matters too. A report that contains internal event counts or campaign structure should not be posted automatically to a public spreadsheet or chat. The fixture allows only a local private artifact. Delivery can be a later, separately reviewed action.

This costs convenience. The agent cannot “fix the tag while it is there.” That is the point. Measurement diagnosis is evidence gathering; container publication changes what production records. Combining the two makes a mistaken inference immediately operational.

Evidence and the untested boundary

The retained evidence is official documentation plus synthetic local JavaScript. No Google account, GA4 property, web stream, GTM account, container, workspace, tag, credential, consent record, event collection, Data API request, report, admin mutation, or publish operation was accessed or executed. Before adopting the contract, test it against a dedicated non-production property and container, verify consent and PII handling with the responsible legal and product owners, and require a separate reviewed path for every production measurement change.