OA
Part 2 of 2  ·  Measure Summit
Organized AI
Google APIs at Scale
Building and managing your entire Google marketing stack programmatically — with AI agents in the loop.
GTM Management API Google Ads API GA4 Admin API GWS CLI GCP MCP
JH
Jordan Hill
Blue Highlighted Text  ·  Organized AI
1 / 20
The real problem
Manual tracking
doesn't scale.
47
Tags per container
Average mid-market DTC brand. Most broken, duplicated, or firing on every page.
6 hrs
Per tracking audit
Clicking through UIs, building screenshots, writing SOPs — every single client.
Scale ceiling
Can't 10x clients with the same manual process. Something has to change.
# Current workflow — repeated for every client, every month 1. Open GTM UI → navigate workspace → manually inspect each tag 2. Open GA4 → validate events in DebugView → check custom dimensions 3. Open Google Ads UI → verify conversion actions → check Enhanced Conv. 4. Write it all up in a doc → attach screenshots → send to client # What the same work looks like programmatically claude --dangerously-skip-permissions "audit all containers, flag broken tags, check GA4 parity, push fixes"
2 / 20
The full toolkit
Google's programmatic
marketing API layer
REST v2

Tag Manager API

Read, write, version, publish GTM containers. Tags, triggers, variables — all writable.

gRPC + REST

Google Ads API

GAQL queries, conversion actions, Enhanced Conversions, Customer Match — fully programmatic.

REST + Admin

GA4 Admin + Data

Provision properties, register events, build audiences, pull funnel reports — without the UI.

REST

Merchant Center API

Product feeds, performance data, account config — scriptable for multi-account management.

CLI

GWS CLI (gcloud)

Google Workspace + Cloud from the terminal. Service accounts, IAM, projects — all scriptable. Pairs directly with Claude Code.

MCP

GCP MCP

Cloudflare Developer Platform MCP exposes GCP primitives as Claude tool calls. Infra-as-conversation.

3 / 20
Command-line layer
GWS CLI
gcloud as your orchestrator
The Google Cloud SDK gives you terminal-level control over every service — and Claude Code drives it.
Service account management
Create, key, and scope service accounts for GTM + Ads + GA4 in one script. No console clicking.
IAM permissions as code
gcloud projects add-iam-policy-binding — grant per-API scopes programmatically.
BigQuery dataset provisioning
Create BQ datasets, set GA4 export targets, configure streaming — before touching the GA4 UI.
Cloud Scheduler for cron jobs
Schedule audit runs, nightly GA4 pulls, weekly Ads health checks — all via gcloud scheduler.
Secrets Manager integration
Store API keys, OAuth tokens, and service account JSON securely. Claude Code reads them at runtime.
Key pattern: Claude Code generates the gcloud commands. You review. Claude executes with --dangerously-skip-permissions. Zero console time.
# Bootstrap a full Google API service account # Claude generates this — you approve once # 1. Create project + enable APIs gcloud projects create organized-ai-tracking --name="OA Tracking" gcloud services enable tagmanager.googleapis.com \ analyticsadmin.googleapis.com \ analyticsdata.googleapis.com \ googleads.googleapis.com # 2. Create + key service account gcloud iam service-accounts create tracking-agent \ --display-name="OA Tracking Agent" gcloud iam service-accounts keys create \ ~/.config/gcp/tracking-agent.json \ --iam-account=[email protected] # 3. Store in Secrets Manager gcloud secrets create TRACKING_SA_KEY \ --data-file=~/.config/gcp/tracking-agent.json # Done — all APIs accessible from Claude Code
4 / 20
Infrastructure as conversation
GCP MCP
Cloud infra in plain English
The Cloudflare Developer Platform MCP exposes GCP primitives directly as Claude tool calls — no console, no SDK boilerplate.
Query GCP resources from Claude
List projects, check service account keys, inspect IAM bindings — all via chat.
Manage Cloudflare ↔ GCP bridges
Hyperdrive, R2, D1 — proxy GCP services through Cloudflare Workers without leaving Claude Code.
BigQuery via Cloudflare D1 bridge
GA4 raw events → BQ → D1 cache → Claude analysis. Fresh data without BQ billing per query.
KV + R2 for audit artifacts
Store GTM container exports, audit reports, and baseline JSONs in R2 — versioned, queryable.
Workers as lightweight API glue
Thin CF Workers connect GTM webhook → GCP Pub/Sub → GA4 Measurement Protocol in one deploy.
The pattern: GWS CLI provisions the GCP side. GCP MCP lets Claude inspect and manage it. Cloudflare Workers sit in front as the public edge.
# claude_desktop_config.json — GCP MCP wired up { "mcpServers": { "cloudflare": { "url": "https://bindings.mcp.cloudflare.com/sse" } } } # Claude Code session — infrastructure conversation # "List all my Cloudflare Workers" → cloudflare.workers_list() # "Create a D1 database for GTM audit storage" → cloudflare.d1_database_create({ name: "gtm-audit-db" }) # "Store this container export in R2" → cloudflare.r2_bucket_create({ name: "gtm-containers" }) # "Query the last audit for this account" → cloudflare.d1_database_query({ database_id: "...", sql: "SELECT * FROM audits ORDER BY ts DESC LIMIT 1" }) # Full infra management — no console, no context switching
5 / 20
API Deep Dive — 01
Tag Manager API
Containers are just JSON.
List all containers + workspaces
GET /accounts/{id}/containers — read every tag, trigger, variable across all clients at once.
Create and update tags via API
POST /workspaces/{id}/tags — build GA4 events, Meta pixels, custom HTML without touching the UI.
Version, preview, and publish
create_version → quick_preview → publish — full deploy chain in one Claude Code script.
Export containers as JSON
Full backup, diff, rollback, or fork. Every client's container versioned in R2.
Workspace change sets per sprint
Isolated workspace per project — QA tested before merging to live container.
Live MCP: GTM MCP connects directly to the Tag Manager API from Claude Code. Full read/write/publish in natural language.
// Claude Code — GTM audit + fix via MCP const containers = await gtm.listContainers({ accountId }); for (const c of containers) { const ws = await gtm.listWorkspaces(c); const tags = await gtm.listTags(ws[0]); // Find orphan tags — no firing rule attached const orphans = tags.filter(t => !t.firingRuleId?.length); // Find undefined variable references const broken = await validateVariableRefs(tags); // Patch + push to staging workspace for (const tag of [...orphans, ...broken]) { await gtm.updateTag({ ...tag, patch: fixConfig(tag) }); } await gtm.createVersion({ name: `AI Audit — ${new Date().toISOString()}` }); } // Full audit + fix across all containers: ~90 seconds
GTM MCP Container versioning R2 export storage
6 / 20
API Deep Dive — 02
Google Ads API
GAQL is SQL for your ad account.
Create + configure conversion actions
POST /conversionActions — type, window, value model, attribution — no UI required.
Push Enhanced Conversions
Send hashed email + phone with conversions for signal recovery in a cookieless world.
Offline Conversion Import pipeline
CRM deal closed → Google Ads credit. Close the lead-to-revenue loop programmatically.
Customer Match via API
Programmatic audience uploads from your CRM. No more CSV drag-and-drop every week.
GAQL — query anything
Any report, any date range, any segment — pulled to JSON and piped into Claude for analysis.
Live MCP: Google Ads MCP — natural language → GAQL → JSON → Claude analysis. No UI needed.
-- GAQL: conversion health audit — real query SELECT conversion_action.name, conversion_action.status, conversion_action.type, conversion_action.counting_type, metrics.conversions, metrics.conversions_value, metrics.all_conversions FROM conversion_action WHERE segments.date DURING LAST_30_DAYS AND conversion_action.status = 'ENABLED' ORDER BY metrics.conversions DESC // Claude Code MCP tool call googleAds.query({ customerId: "XXX-XXX-XXXX", query: gaql }) // Returns JSON → Claude flags zero-value conversions // → drafts fix plan → implements via API
Google Ads MCP Offline Conv. API Customer Match Enhanced Conv.
7 / 20
API Deep Dive — 03
GA4 Admin + Data API
Properties as code.
Admin API — configure
Provision GA4 properties
New client = new property in seconds. Auto-configure data streams + measurement ID.
Register custom events + dimensions
Define your event schema via API — no more clicking through the UI per parameter.
Build audiences programmatically
Remarketing segments created from code, not UI dropdowns. Templated per vertical.
Enable BigQuery export via API
One GWS CLI call + one Admin API call = raw event streaming to BQ. Done.
Data API — query + analyze
// Funnel report — piped into Claude analyticsData.runFunnelReport({ property: "properties/XXXXXXXXX", funnelSteps: [ { name: "View Product", filter: eventFilter("view_item") }, { name: "Add to Cart", filter: eventFilter("add_to_cart") }, { name: "Purchase", filter: eventFilter("purchase") } ], dateRanges: [{ startDate: "30daysAgo" }] })
Pull funnel data on demand. Feed to Claude. Get plain-English drop-off analysis with specific fix recommendations in <60 seconds.
8 / 20
The connection layer
MCP turns APIs into
Claude-native tools.
Natural language
MCP Server
API call
JSON response
Claude synthesis
Active in Claude Desktop
GTM MCP
Tag Manager API
Google Ads MCP
Google Ads API
Meta Ads MCP
Meta Ads API
Cloudflare Dev Platform MCP
GCP + CF edge
sGTM MCP
sGTM infra
Session example
You → Claude Code
"Audit the GTM container, find tags without firing triggers, generate a fix plan, and push to staging."
Claude →
Using gtm.listTags()...
Found 3 orphan tags, 1 undefined variable.
Generating patch JSON...
Publishing to staging workspace. ✓
9 / 20
What this looks like end-to-end
The Organized AI
tracking automation loop
Phase 0.5 — LP Scan  auto
Playwright crawls the site → exports GTM container JSON → Claude checks all tags + event coverage vs. spec. Zero manual steps.
Phase 1 — API Health Check  GTM + GA4 + Ads
GTM MCP queries containers. GA4 Admin API checks event schemas. Ads API verifies conversion action parity. Full report in <2 min.
Phase 2 — Remediation  Claude writes the fix
Claude drafts GTM configs as JSON. GTM API pushes to staging. Playwright QA gate validates before publish. GCP audit log updated.
Phase 3 — Drift Detection  ongoing
Cloud Scheduler cron → GA4 Data API pull → Claude diffs vs. baseline stored in D1 → Slack alert on anomalies.
// Organized Codebase — ships pre-wired scripts/ qa/ playwright-tag-check.ts ← QA gate event-coverage-check.ts ← GA4 parity GTM-CONTAINER-BASELINE.json ← diff source audit/ gtm-api-audit.ts ← GTM API ads-conversion-check.ts ← Ads API ga4-schema-diff.ts ← GA4 API infra/ bootstrap-gcp.sh ← gcloud setup scheduler-create.sh ← cron jobs deploy/ gtm-push-workspace.ts ← auto-publish // One command starts the full loop: claude --dangerously-skip-permissions "run full tracking audit and fix loop for this account"
10 / 20
Skill spotlight
data-audit
Meta Ads account intelligence.
End-to-end audit workflow — from raw account data to scored health reports and implementation roadmaps. Powered by Pipeboard Meta MCP + Stape MCP.
4-Phase workflow
Phase 1 — Data Collection
Account discovery, performance insights (account + campaign level), Stape container analytics. All via MCP tool calls.
Phase 2 — Analysis & Scoring
10-point health score: Attribution (3), ROAS (2.5), CAPI (1.5), Revenue Tracking (1.5), Campaign Structure (1.5).
Phase 3 — Artifact Generation
Executive summary, full audit report, and implementation checklist — auto-generated, client-ready.
Phase 4 — Implementation
CAPI setup, revenue tracking, CRM integration, campaign optimization — tracked through PLANNED → COMPLETE.
# Trigger the skill from Claude Code claude "audit this Meta account" # Phase 1 — automatic data pull get_ad_accounts(user_id="me", limit=200) bulk_get_insights(level="campaign", time_range="last_30d") stape_container_analytics() # Phase 2 — health score output # Attribution Health: 3.0 / 3.0 # ROAS Performance: 2.0 / 2.5 # CAPI Deployment: 0.75 / 1.5 # Revenue Tracking: 0.75 / 1.5 # Campaign Structure: 1.0 / 1.5 # ──────────────────────────── # Total: 7.5 / 10 🟡 Good
Triggers: "audit this Meta account", "analyze ad performance", "evaluate tracking setup", "create CAPI recommendations"
MCPs: Pipeboard Meta MCP (accounts, campaigns, insights) + Stape MCP (containers, domains, CAPI)
11 / 20
What's next
autoresearch for tracking optimization
Karpathy's autonomous experimentation loop — applied to GTM configs instead of neural nets.
Modify config
Deploy
Measure
Keep/revert
Repeat
Fixed measurement window
5-min training budget → 24-hr signal window. Standardized comparison across every config variation.
Single metric: signal quality score
val_bpb → event match quality + dedup rate + conversion parity. One number to beat.
Agent modifies one file
train.py → GTM container JSON. Claude iterates tag configs, trigger rules, variable mappings.
program.md → SKILL.md
Human-curated instructions map to skill files. Domain knowledge guides agent experiments.
github.com/karpathy/autoresearch — same loop, different domain. Agent experiments with tracking configs like it experiments with model architectures.
# autoresearch for tracking — overnight while signal_window_complete: config = gtm.exportContainer(baseline) patch = claude.propose_optimization( config, goal="max event match quality") gtm.updateTag({ ...patch }) gtm.createVersion("exp-042") score = ga4.runReport(match_quality) + ads.query(conv_parity) - dedup.penalty(duplicates) if score > best: gtm.publishVersion() # promote else: gtm.revertWorkspace() # discard # ~12 experiments/day · ~100/weekend
12 / 20
autoresearch results
Wake up to a validated workspace
Run it overnight. Morning deliverables: a staging workspace ready to publish, a versioned config in R2, and a full experiment log.
Staging workspace
GTM workspace with winning config — one-click publish when you're ready.
Versioned JSON
winning-config.json stored in R2 — rollback to any previous night's best.
Experiment log
Every patch tested, scored, and kept or reverted. Full audit trail with diffs.
Playwright QA
Each experiment validated in staging preview — tag firing, parameters, dedup all checked.
~100 experiments over a weekend. Never publishes to live. You review the winner and decide.
# morning deliverables workspace = gtm.getWorkspace( "autoresearch-nightly") # review what changed print(workspace.changelog) # → 14 tags modified # → score: 0.72 → 0.91 # → 47 experiments run # happy? one-click publish gtm.publishWorkspace(workspace) # or grab the JSON for review config = r2.get("winning-config.json") gtm.importContainer(config)
13 / 20
Real deployments — 1 of 2
Custom builds. Agent-driven from day one.
B2B SaaS / LinkedIn Web + Server GTM
LinkedIn InsightTag 2.0 installed from GTM Community Gallery via API — zero manual UI clicks
5-phase autonomous Claude Code execution: variables → tags → validate → preview → publish with rollback hooks
Skills used: gtm-AI, linkedin-capi-setup, gcp-access-gtm, tidy-gtm
Dual-container deduplication: shared event_id across web GTM (GTM-W9S77T7) and server GTM (GTM-KJHX6KJ7)
Global Coaching Platform Meta Ads + CAPI
Interactive CAPI audit dashboard: 42-task tracker across 5 phases — deployed to Cloudflare Pages in one wrangler pages deploy
£111,974 spend + 27,765 leads + 575 purchases analyzed; 4 critical findings with severity scores surfaced via Meta Ads MCP
Webhook → Cloudflare Worker → Pixel Events + Orders API pipeline — fully programmatic lead attribution
Account health score, campaign performance view, and prioritized recommendations all generated from audit data
Indie Film Release GTM + OpenClaw
GTM deployment plan + Bowser OpenClaw agent integration for audience signal collection and remarketing
Plugin marketplace skills pre-wired in .claude/ — newsletter and LinkedIn post auto-generated from codebase on deploy
MCP server config (.mcp.json) + gtm-debug skill for post-deploy validation without opening GTM UI
Agents driving awareness tracking → conversion attribution end-to-end with zero manual platform logins
14 / 20
Real deployments — 2 of 2
Tracking infrastructure. Signal recovery at scale.
E-Commerce / Health DTC Shopify + sGTM
GAQL audit found $0 conversion values on PMAX — cart data mapping issue in sGTM identified and patched via API without touching the container UI
GA4 Data API pull surfaced major Advantage+ vs. Remarketing budget misallocation — reallocation decision made from a single GAQL query
Shopify Web Pixels API + Stape CAPI restored full server-side checkout event coverage after iOS 14+ signal loss
sGTM → GA4 client → Google Ads ECID pipeline rebuilt programmatically; value tracking confirmed via Ads API query
Healthcare SaaS Next.js + Stripe
Web + sGTM containers bootstrapped from a single JSON template via GTM API — consistent config across all environments
Meta pixel wired exclusively through sGTM CAPI — zero client-side pixel footprint for HIPAA-adjacent compliance posture
State-specific consent law compliance enforced via API-driven tag gating — legal team gets config file, not UI instructions
CareValidate intake events → GA4 Measurement Protocol → Google Ads OCI pipeline built with Node + Cloudflare Worker
Legal Services Custom CMS + Node
Phase 0.5 LP scan (Playwright) ran before any API writes — full baseline JSON captured and stored in R2 for future diffs
Playwright QA gate enforced as hard check — no GTM container published without full tag-firing test suite passing first
Codex QA pass run after every Claude Code change — second-agent review catches naming drift and undefined variables before publish
CRM lead event → GA4 Measurement Protocol + Google Ads Offline Conversion Import in a single Express server pipeline
15 / 20
Hard-won lessons — 1 of 2
Key findings from building this in production.
01
MCP reliability is still a gamble
MCP servers drop connections mid-session, rate-limit silently, and some operations aren't exposed as tools yet. Building mission-critical automation on top of MCP uptime is fragile — one dropped connection kills the whole deploy.
The fix — CLI as foundation
CLI first: gcloud, node scripts, direct API calls. MCP sits on top as a convenience layer. If MCP fails mid-session, the underlying CLI script still runs. Every MCP operation has a CLI fallback in scripts/.
02
Claude needs GTM context loaded explicitly
Out-of-the-box Claude has no GTM mental model. Without a skill, it hallucinates tag type names, wrong trigger IDs, and invalid API parameter schemas — and publishes confidently broken configs. We found this out the hard way.
The fix — domain skills
Skills pre-wired in .claude/skills/: gtm-AI (deploy + audit), tidy-gtm (standardize), linkedin-capi-setup, tracking-validation, data-audit. Each skill injects the correct API schema and tag type registry before Claude writes anything.
03
GTM API real-time builds vs. JSON import fallback
GTM API is fast and surgical — patch a single tag in seconds. But every write requires a valid fingerprint, rate limits appear without warning, and one malformed payload can corrupt the entire workspace state mid-session.
The fix — two-path strategy
API-first for real-time surgical changes. JSON export → Claude edits → import as fallback for bulk operations or when rate limits hit. Both paths tracked in CONFIG/phase-state.json. Claude selects the right path automatically based on operation scope.
16 / 20
Hard-won lessons — 2 of 2
Key findings from building this in production.
04
Naming chaos breaks agent reasoning
Tags named "New Tag 47", variables named "undefined_1" — Claude can't reason about intent from the name. Inconsistent prefixes cause the wrong triggers to fire. Container diffs become noise. Bugs get shipped because the agent inferred wrong.
The fix — tidy-gtm enforces this
Tags: Platform - Type - Event ConvID  ·  Variables: {{DL - name}} {{CJS - name}} {{ED - name}}  ·  Triggers: sGTM - CE - EventName
Convention enforced at write-time by the tidy-gtm skill before every publish. Never manually defined again.
05
GTM Preview is the last manual bottleneck
The GTM Preview UI requires a human: open a browser, paste the preview link, navigate to the site, trigger the events manually, read the tag panel, and confirm each tag fired. This breaks the automation loop completely and adds manual QA time to every deploy.
The fix — Playwright drives preview
Playwright loads the GTM preview URL headlessly, fires synthetic events that match the expected triggers, reads the tag summary panel via DOM, and asserts each expected tag fired with correct parameters. The QA gate runs automatically before every gtm.createVersion() call. Zero human clicks required.
Before — manual preview
Open GTM UI  →  Enter Preview  → 
Open site  →  Trigger events  → 
Read tag panel  →  Screenshot  → 
~8 minutes, zero automation
After — Playwright QA gate
playwright.fire(syntheticEvents)
assert(tagPanel.contains(expected))
gtm.createVersion()  ← only if passes
<30 seconds, fully automated
17 / 20
The business case
What programmatic
actually unlocks
90s
Full container audit
vs. 6 hours manually
10x
Client capacity
Same team, same quality
0
Manual UI clicks
For routine audits
Compounding value
Each pattern improves the next
For agencies: Every client you onboard improves the system. Each audit output trains better prompts. The 10th client is faster than the first — by a lot.
For in-house: Stop being the person who manually checks dashboards. Become the person who built the system that monitors everything and surfaces anomalies automatically.
The real unlock: GWS CLI + GCP MCP + GTM API + Ads API + GA4 API — all wired into Claude Code — means your tracking stack is now a conversation, not a series of tabs.
18 / 20
Resources + next steps
Get started today.
Everything is public.
MCP servers — install these first
GTM MCP — Tag Manager API
Tag Manager read/write/publish from Claude.
Google Ads MCP
Full GAQL access + conversion management from Claude.
Meta Ads MCP
Cross-account Meta analysis alongside Google stack.
Cloudflare Developer Platform MCP
Cloudflare Developer Platform MCP — D1, R2, Workers, and GCP infra from Claude.
Organized AI
organizedai.vip  ·  Austin meetups  ·  Claude Code Mastery
Free cert program · job board · plugin marketplace · github.com/Organized-AI
The one prompt to start
# Drop this into Claude Code — right now claude --dangerously-skip-permissions "You are a tracking audit agent. Using the GTM MCP and Google Ads MCP: 1. List all containers for account [ID] 2. Flag tags without firing rules 3. Cross-check conversion actions against GA4 purchase events 4. Generate a remediation plan as JSON 5. Use GWS CLI to log the audit to GCP Secrets Manager 6. Push approved fixes to staging" # That's a full audit + fix cycle. # Time to run: < 2 minutes # Time saved: 6 hours per client
Part 1 replay: "Organized Automation" — Measure Summit recordings. The GTM + sGTM foundation this talk builds on.
19 / 20
Get Started

Tap In With Jordaaan

Ready to deploy your first AI agent fleet on Apple Silicon?

$0
Both deployment modes are free
15 min
Native macOS, any Apple Silicon Mac
12
Pre-wired skills, install-all.sh ready

Start Here

  • Clone github.com/Organized-AI
  • VM-Isolated or Native — your choice
  • Run setup.sh — under 30 min
  • Install 12 skills via install-all.sh
  • Connect a messaging channel
organizedai.vip
github.com/Organized-AI
jobs.organizedai.vip
Scan to Connect
organizedai.vip
organizedai.vip
Website
WhatsApp
OpenClaw Hackathon
WhatsApp Group
LinkedIn
Jordan Hill
LinkedIn
GitHub
Plugin Marketplace
github.com/Organized-AI
20 / 20