Google ADC: The Fastest Way to Make Your Google Stack Agentic
Google Application Default Credentials (ADC) lets Claude Code access Google Ads, Analytics, GTM, and Search Console in a single agent session — no per-tool OAuth, no credential juggling. Full setup, worked examples, and a service account pattern for CI pipelines.
The Google Ads audit just finished in the terminal. Campaign performance is clear — cost per conversion is up 34% on branded search, impressions are holding, and click-through rate is trending down. The natural next question is whether organic is cannibalising branded coverage or whether there are keyword gaps that Ads should be filling. That data lives in Search Console.
In a per-tool MCP world, getting it requires opening a second terminal window, pointing at a second MCP server, completing a second OAuth consent screen, and — if Google Ads and Search Console happen to use different developer tokens or client configurations — juggling a second credentials object. By the time the environment is ready, the audit context has evaporated.
Here is what that credential sprawl looks like in practice:
{
"mcpServers": {
"google-ads": {
"command": "npx",
"args": ["@google-ads/mcp-server"],
"env": { "GOOGLE_ADS_DEVELOPER_TOKEN": "...", "CLIENT_ID": "...", "CLIENT_SECRET": "..." }
},
"google-analytics": {
"command": "npx",
"args": ["@google/analytics-mcp-server"],
"env": { "CLIENT_ID": "...", "CLIENT_SECRET": "..." }
},
"google-tag-manager": {
"command": "npx",
"args": ["@google/gtm-mcp-server"],
"env": { "CLIENT_ID": "...", "CLIENT_SECRET": "..." }
},
"search-console": {
"command": "npx",
"args": ["@google/search-console-mcp"],
"env": { "CLIENT_ID": "...", "CLIENT_SECRET": "..." }
}
}
}Four entries. Four credential blocks. And that is before environment variable conflicts, token expiry on long-running sessions, or the MCP server version drift that tends to happen when four separate packages each pull from a different Google API client library release.
The real cost is not setup time. It is the inability to run a cross-platform query in a single agent session. When each tool manages its own auth lifecycle, the agent cannot naturally pivot from Ads data to Analytics data to Search Console data in one continuous context. Every platform hop is a context break. Cross-referencing becomes manual work — copy-paste from one terminal, paste into another, reconcile manually. That is the gap ADC closes.
Google Application Default Credentials solves this by sitting one level below the tool layer. Rather than each tool managing its own credentials, all Google API calls on the machine share a single authenticated identity. The agent never needs to know which credential belongs to which platform — the credential discovery chain handles it transparently.
What ADC is and why it works here
Application Default Credentials is the authentication pattern Google recommends for programmatic access to its APIs from developer machines and automated pipelines. When you authenticate with the gcloud CLI, it writes a credential file to ~/.config/gcloud/application_default_credentials.json. Every Google client library — the Python SDK, the Node.js SDK, the Go library — checks that file automatically when no explicit credential is provided.
ADC is not a hack or a workaround. It is Google's own documented path for local development and tooling. The Google Cloud documentation describes it as the preferred method for CLI tools, scripts, and local development environments precisely because it removes the burden of credential management from application code.
Claude Code inherits ADC because it calls Google APIs through those same client libraries. There is no special plugin required and no Claude-specific credential format to configure. When Claude Code invokes a Google API call in an agent session — whether through a direct tool, a script it writes and executes, or a library it imports — the client library follows the same credential discovery chain: check GOOGLE_APPLICATION_CREDENTIALS environment variable, then check the well-known file location, then check the GCP metadata server if running in the cloud.
The practical result is that a single gcloud auth application-default login command, run once, makes all four Google marketing platforms available to the agent in the same session. The agent moves from Ads to Analytics to GTM to Search Console without re-authenticating, without switching credential contexts, and without the session state of one tool interfering with another.
The OAuth internals are straightforward: the credential file stores a refresh token tied to your Google account. The client library exchanges it for short-lived access tokens as needed, handles expiry transparently, and retries failed token refreshes automatically. The agent never sees a token — it just calls the API.
One clarification worth making explicit: ADC is not the same as a service account. User ADC is tied to your Google identity and works on your machine. Service account ADC is tied to a GCP service account and works anywhere. The setup section below covers user ADC for local sessions; the CI section later covers service accounts for automation. The credential file format is the same. The credential discovery chain is the same. The only difference is which identity is doing the authenticating.
The one-time setup
Two commands. Run them in order.
gcloud auth login
gcloud auth application-default login \
--scopes=https://www.googleapis.com/auth/adwords,\
https://www.googleapis.com/auth/analytics.readonly,\
https://www.googleapis.com/auth/tagmanager.readonly,\
https://www.googleapis.com/auth/webmasters.readonlyThe first command authenticates your Google account with the gcloud CLI. The second writes the ADC credential file with the specific scopes required for each platform.
What each scope covers:
adwords— read and write access to Google Ads campaign data, reports, and account structureanalytics.readonly— read access to GA4 properties, reports, audiences, and attribution datatagmanager.readonly— read access to GTM containers, tags, triggers, variables, and version historywebmasters.readonly— read access to Search Console performance data, sitemaps, and URL inspection
After running both commands, your credential file lives at ~/.config/gcloud/application_default_credentials.json and looks like this (token redacted):
{
"client_id": "...",
"client_secret": "...",
"refresh_token": "<token>",
"type": "authorized_user"
}From this point, any Google API call on the machine uses these credentials unless the GOOGLE_APPLICATION_CREDENTIALS environment variable is set to point elsewhere — for example, to a service account key file for a specific project. The machine-level credential is the fallback; the environment variable is the override.
Worked examples
The setup is done. Here is how each platform behaves inside a Claude Code session, and where ADC makes the cross-platform work possible.
Google Ads
Google Ads API access requires two things: ADC for authentication and a developer token for API authorisation. They are separate. ADC proves who you are; the developer token proves your application is allowed to call the Ads API at all. You need both.
Get the developer token from the Google Ads UI: Tools → API Centre. If you are accessing a manager account (MCC), the token is issued at the MCC level and applies to all child accounts underneath it.
With both in place, a typical prompt to start a campaign audit looks like:
"Using the Google Ads API with my ADC credentials and developer token[token], pull the last 30 days of campaign performance for customer ID[customer-id]. Show me campaigns ordered by spend, with impressions, clicks, cost, conversions, and conversion value."
The GAQL query the agent will construct or execute:
SELECT
campaign.name,
metrics.impressions,
metrics.clicks,
metrics.cost_micros,
metrics.conversions,
metrics.conversions_value
FROM campaign
WHERE segments.date DURING LAST_30_DAYS
ORDER BY metrics.cost_micros DESCFor MCC accounts with multiple child accounts, the agent can iterate. A prompt like "pull that same report across all active child accounts under MCC [mcc-id] and concatenate the results" works because the MCC structure is accessible via the same API surface. The agent lists child accounts via CustomerService, then loops the GAQL query across each, merging results into a single dataset. This is the kind of multi-account work that is genuinely painful in a dashboard and mechanical in the terminal.
One consideration: if the only task is a single Google Ads audit in isolation, a dedicated Ads MCP server is a reasonable choice. It abstracts the GAQL layer and provides structured tool calls without requiring the agent to construct raw queries. ADC becomes the better option the moment the session needs to span more than one Google platform. Switching platforms in a single session is where the per-tool MCP architecture creates friction and ADC removes it entirely.
Google Analytics 4
GA4 exposes its data through the Data API, which the agent can call directly once ADC is configured. A useful opening prompt for a channel performance audit:
"Using the GA4 Data API, pull 90 days of session and conversion data for property [property-id], broken down by session source/medium. Include total revenue where available."The Data API request the agent will construct:
{
"dateRanges": [{ "startDate": "90daysAgo", "endDate": "today" }],
"dimensions": [{ "name": "sessionSourceMedium" }],
"metrics": [
{ "name": "sessions" },
{ "name": "conversions" },
{ "name": "totalRevenue" }
]
}This produces a channel-level breakdown that is immediately useful: you can see which acquisition channels are driving sessions, which are converting, and the revenue contribution of each. The agent can pivot from there — drill into a specific source, add a date comparison, or filter by landing page.
A second prompt that is particularly useful for paid media work:
"From the GA4 property, export the audience segment of users who visited the pricing page in the last 60 days but did not convert. Format it as a user list I can use for retargeting."
GA4 audience exports via the Data API allow the agent to pull user IDs or audience membership data that can feed directly into Google Ads remarketing lists. This is a multi-platform workflow — audience definition in Analytics, audience activation in Ads — that becomes a single uninterrupted agent session with ADC.
The analytics.readonly scope is sufficient for both reporting and audience export. No additional scopes are required unless you need to write back to GA4, which is rarely useful in a marketing context.
A third prompt worth keeping in a session template:
"Pull event-level data for the generate_lead event over the last 30 days. Break it down by landing page path and device category. Which pages have the highest lead-to-session rate on mobile?"GA4's event model means almost any behavioural signal is queryable through the Data API if it was instrumented. The agent can reason about event data the same way it reasons about campaign data — pulling dimensions, applying filters, comparing periods — without the UI bottleneck of having to configure a custom report and wait for it to load.
Google Tag Manager
GTM audits follow a natural three-step sequence. The agent can work through all three in a single session.
First, list all containers in the account:
"Connect to the GTM API and list all containers in my account. Show the container ID, name, public ID, and whether it's a web or server-side container."
Second, audit active tags and triggers in a specific container:
"For container [container-id], list all active tags with their trigger conditions. Flag any tags that fire on all pages, any tags without pausing triggers, and any tags referencing third-party domains that aren't in our approved vendor list."Third, compare versions to surface what changed:
"Compare GTM container version 42 against the current workspace draft. List every tag, trigger, and variable that differs — additions, deletions, and modifications — in a structured table."
This three-prompt sequence covers the most common GTM audit scenarios: a periodic hygiene review, an audit after contractor work has touched the container, and a pre-launch review before a campaign goes live. The version comparison is especially valuable because GTM's built-in diff view is hard to scan at scale. The agent can process a diff across 40 tags and surface only the meaningful changes — a task that takes 20 minutes manually and about 30 seconds in the terminal.
This three-prompt sequence covers the most common GTM audit scenarios: a periodic hygiene review, an audit after contractor work has touched the container, and a pre-launch review before a campaign goes live.
The version comparison is especially valuable in agency contexts where multiple people touch GTM containers. When a client calls to say "something broke after the new campaign launched," the agent can diff the container version from before the launch against the current state in under a minute. The GTM UI has a version comparison view, but it is cumbersome for containers with more than 20 tags. The agent returns a structured table that makes the diff scannable.
The tagmanager.readonly scope is sufficient for all three prompts. If the audit surfaces issues that need fixing — a misfiring trigger, a legacy pixel — you can switch to a write scope in a fresh ADC login and execute the fix in the same terminal session.
Google Search Console
Search Console performance data is where the ADC investment pays off most visibly, because GSC data is most valuable in combination with Ads data rather than in isolation.
Start with the standard high-impression, low-CTR query audit:
"Using the Search Console API for property [property-url], pull the top 100 queries by impression volume over the last 90 days. Filter to queries where CTR is below 3%. Sort by impressions descending."The API request structure:
{
"startDate": "2026-02-27",
"endDate": "2026-05-27",
"dimensions": ["query"],
"rowLimit": 100
}This surfaces queries where the page is appearing in search results but users are not clicking — typically a title or meta description problem, a position issue, or a query-to-content mismatch worth investigating.
But the cross-platform query is where ADC earns its setup cost:
"Cross-reference the Search Console queries above against the active search terms in the Google Ads account. Which high-impression GSC queries have no Ads coverage? Prioritise by impression volume."
This question needs both GSC data and Ads data in the same session. With ADC, the agent already has access to both. It pulls the GSC query list, pulls the Ads search terms report for the same period, and runs the gap analysis. Queries appearing organically with significant impression volume but no paid coverage are candidates for new keyword additions — particularly valuable when organic positions are low (4–10) and the query has conversion intent.
Per-tool MCP makes this awkward. The agent would need to pull GSC data from one server, cache it somehow, then switch to the Ads server and attempt a cross-reference — a workflow that breaks the natural back-and-forth of an agent reasoning across datasets. ADC makes it trivial. Both APIs are available in the same session, the agent pulls from both, and the correlation happens in a single reasoning step.
The GSC API also supports page-level filtering via a page dimension alongside query. A follow-up prompt that frequently surfaces value:
"From the same GSC data, filter to queries where the average position is between 4 and 15 and CTR is below 5%. These are ranking pages not capturing their potential traffic. List them alongside the query, position, impressions, and CTR."
Positions 4–15 represent a well-known opportunity band — the page is ranking, but not in the top 3, and CTR drops sharply below position 3. Identifying these queries by volume and comparing them against current Ads coverage gives a prioritised list for both content improvement and paid keyword expansion.
Service accounts for CI and automation
User credentials — the kind written by gcloud auth application-default login — are tied to your personal Google account and eventually expire. They are suitable for local agent sessions but not for automated pipelines, scheduled jobs, or server-side execution where there is no human to re-authenticate.
For those use cases, service accounts are the right pattern.
Creating a service account in GCP:
Navigate to IAM → Service Accounts → Create. Give it a descriptive name (ryzo-marketing-automation@[project].iam.gserviceaccount.com). Assign no project-level IAM roles at this step — platform-level access is granted through each tool's own access management, not GCP IAM.
Granting access per platform:
Each Google marketing platform has its own access management UI, and service accounts are granted access the same way human users are — by inviting the service account's email address.
- Google Ads: Ads UI → Account Access → Users → Invite. Paste the service account email. Grant Read-only access for audit use cases.
- GA4: Admin → Account Access Management → Add user. Add the service account email with Viewer role.
- GTM: Admin → Container → User Management. Add the service account email with Read access.
- Search Console: Settings → Users and permissions → Full user. Add the service account email.
After granting access, download the JSON key file from GCP (IAM → Service Accounts → Keys → Add Key → JSON). Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of this file, and the Google client libraries will use it automatically instead of the user credential file.
For Vercel Cron jobs, the pattern is to store the service account JSON as a base64-encoded environment variable, decode it at runtime, write it to a temp file, and set GOOGLE_APPLICATION_CREDENTIALS to that path. Never commit the key file.
A weekly ads audit cron route:
// app/api/cron/ads-audit/route.ts
export async function GET(request: Request) {
const auth = request.headers.get('Authorization');
if (auth !== `Bearer ${process.env.CRON_SECRET}`) {
return new Response('Unauthorized', { status: 401 });
}
// GOOGLE_APPLICATION_CREDENTIALS points to service account key
const report = await runGoogleAdsAudit({
customerId: process.env.GOOGLE_ADS_CUSTOMER_ID!,
developerToken: process.env.GOOGLE_ADS_DEVELOPER_TOKEN!,
});
await postToSlack(report);
return Response.json({ ok: true });
}To handle the base64 credential pattern on Vercel, add a startup step before runGoogleAdsAudit:
import { writeFileSync } from 'fs';
import { tmpdir } from 'os';
import { join } from 'path';
const keyPath = join(tmpdir(), 'sa-key.json');
writeFileSync(
keyPath,
Buffer.from(process.env.GOOGLE_SA_KEY_B64!, 'base64').toString('utf-8')
);
process.env.GOOGLE_APPLICATION_CREDENTIALS = keyPath;Service account keys are long-lived — unlike user tokens, they do not expire on their own. This makes them convenient and dangerous in equal measure. Rotate them quarterly. Store them in a secrets manager (GCP Secret Manager, AWS Secrets Manager, or a vault tool) rather than in environment variable configurations that are hard to audit. Log key usage if your compliance posture requires it.
Security and scopes
The scopes in the setup command are all read-only. adwords, analytics.readonly, tagmanager.readonly, and webmasters.readonly grant no ability to modify campaigns, create tags, change property settings, or submit URLs. An agent session using these scopes can read everything and change nothing.
That is the right starting point for audit and reporting workflows. If a workflow needs to act — pause a campaign, push a GTM version, add a keyword — write scopes are available:
- Google Ads mutations:
https://www.googleapis.com/auth/adwords(same scope, but when used with write operations, it authorises changes — the scope name does not differentiate read from write for Ads) - GTM container edits:
https://www.googleapis.com/auth/tagmanager.edit.containers - GTM version publish:
https://www.googleapis.com/auth/tagmanager.publish
Request write scopes only when the agent session is explicitly intended to make changes. Keeping the default ADC credential read-only reduces the blast radius of a misconfigured prompt or an agent reasoning error that produces an unintended API call.
Add this to .gitignore in any project that might accidentally contain credential files:
# Google ADC credentials
application_default_credentials.json
*-service-account.jsonThe ADC credential file in ~/.config/gcloud/ is outside the project tree and will not appear in git status under normal circumstances. The pattern above guards against key files downloaded into project directories — a common pattern when developers are testing service account access locally and forget the file is sitting in the repo root.
For service account keys: quarterly rotation is a reasonable default. Set a calendar reminder. When rotating, generate the new key, update the secrets manager entry, redeploy, confirm the new key works, then delete the old one from GCP. Never leave orphaned keys active.
What this enables
ADC is Google's own recommended pattern for programmatic access to its APIs from developer tooling. It was not designed for Claude Code specifically — it predates LLM agents by years — but it fits the agentic use case better than any alternative. One credential set, one authentication step, full access to the Google marketing stack in a single session.
The compounding benefit is analytical continuity. An agent reasoning about campaign performance can pull Ads data, pivot to Analytics attribution, check Search Console for organic coverage, and inspect GTM for tracking integrity — in sequence, without context breaks, without credential prompts, and without the session state of one tool contaminating another. Cross-platform questions that were previously a manual, multi-tab exercise become single prompts.
The investment is two gcloud commands and a developer token. The return is a unified Google marketing command line that works the way practitioners actually think about the stack.
If you have not yet run an agentic Google Ads audit, that is the right starting point: How to Audit a Google Ads Account in 15 Minutes with Claude Code.