Skip to content

Repository files navigation

Google Ads Guard CLI

CI License: MIT Node 20+ GitHub stars

Audit Google Ads with exact account identity, reproducible evidence, and recommendations that cannot silently become account changes.

Google Ads Guard CLI is an independent open-source tool for read-only Google Ads reporting, configuration audits, health checks, and guarded optimization proposals. It is designed for operators and AI agents that need traceable evidence without giving a reporting tool permission to modify an account.

Status: 0.1.0 is intentionally read-only. It has no create, update, remove, mutate, upload, budget-change, or bid-change command.

At a glance

Google Ads Guard CLI
Best for Agencies, operators, analysts, and AI agents that need safe account evidence
Account access Read-only SearchStream requests
Identity gate Customer ID, account name, currency, and timezone must all match
Credentials Environment variables or fixed gcloud calls; never stored in the profile
Output JSON, NDJSON, or CSV with request IDs and query digests
Recommendations Evidence-threshold proposals with missing facts and requiresApproval: true
Account changes Unsupported by design in 0.1.x

Why this exists

Google Ads reporting scripts often solve the API call but leave the dangerous decisions to convention:

  • a customer ID is accepted without verifying the human-readable account identity;
  • developer tokens or OAuth material are stored in JSON or shell history;
  • dates, segments, and limits are inserted into GAQL without one strict validation boundary;
  • a successful response is treated as proof that tracking and business outcomes are healthy;
  • a suggestion is emitted without the evidence threshold or missing facts that produced it.

Google Ads Guard turns those controls into product behavior:

  • exact customer allowlists with name, currency, and timezone readback;
  • a fixed googleAds:searchStream transport and bounded SELECT-only GAQL;
  • no credential values in profile files or CLI arguments;
  • identity-aware gcloud or environment-token authentication;
  • timeouts, limited retries, request IDs, query digests, and redacted errors;
  • explicit evidence thresholds and missing-fact lists for every recommendation;
  • new-file-only output: existing evidence is never overwritten;
  • a bundled Codex skill for evidence-first Google Ads analysis.

The tool is not affiliated with Google, OpenAI, or google-ads-open-cli.

What it does—and does not do

Use Google Ads Guard to:

  • capture campaign performance for an explicit date range;
  • audit conversion-action configuration;
  • inventory campaigns, ad groups, ads, keywords, and campaign negatives;
  • screen search terms, budgets, and bids against declared evidence thresholds;
  • hand a provenance-rich report to another operator or AI agent;
  • explain a saved JSON report without reconnecting to Google.

It does not:

  • create or edit campaigns, ads, keywords, budgets, bids, conversions, or feeds;
  • decide that a recommendation is safe merely because a numeric threshold was crossed;
  • store Google Ads credential values;
  • replace attribution, profit-margin, lead-quality, or experiment analysis.

Safety model

The profile contains identifiers and policy, but no token values. A live request is allowed only after all of these checks pass:

  1. the profile is structurally valid and names an exact allowed customer;
  2. the credential principal matches the configured principal when gcloud is used;
  3. an identity query returns exactly one account;
  4. customer ID, descriptive name, currency, and timezone all match the profile;
  5. the requested query is one bounded SELECT statement;
  6. the request goes only to the SearchStream endpoint.

Recommendations are proposals. Every recommendation contains requiresApproval: true; this package has no mutation transport.

Install from source

Requires Node.js 20 or newer.

git clone https://github.com/Teide131/google-ads-guard-cli.git
cd google-ads-guard-cli
npm ci --ignore-scripts
npm run verify
npm link

npm link exposes the google-ads-guard command on your current machine. If global linking is unavailable, use node dist/cli.js in place of google-ads-guard.

The project is not published to npm yet. Do not install an unrelated package with a similar name.

Configure a read-only profile

Copy examples/profile.example.json to a private local path, replace the synthetic account identity, and keep it outside a public repository if the identifiers are sensitive.

The profile is a fail-closed allowlist:

Field Purpose
apiVersion One explicitly supported Google Ads API version
expectedPrincipal Exact active gcloud account expected by the operator
managerCustomerId Manager account used in the login-customer header, when applicable
allowedCustomers[].id Exact 10-digit client customer ID
name Exact Google Ads descriptive name expected from API readback
currencyCode Exact three-letter account currency
timeZone Exact Google Ads account timezone
policy Row, timeout, retry, and recommendation evidence thresholds

Unknown profile keys are rejected. A live read stops if any configured account identity field differs from API readback.

Authenticate without a credential file

Set only the developer token in the environment when using the recommended gcloud provider:

$env:GOOGLE_ADS_DEVELOPER_TOKEN = "set-in-your-current-secure-session"
gcloud auth login --scopes=https://www.googleapis.com/auth/adwords

On macOS or Linux:

export GOOGLE_ADS_DEVELOPER_TOKEN="set-in-your-current-secure-session"
gcloud auth login --scopes=https://www.googleapis.com/auth/adwords

The CLI invokes gcloud with fixed arguments, verifies the active account against expectedPrincipal, and requests a short-lived access token. Google also documents service-account authentication; a service account can be activated in gcloud and pinned as the expected principal. See the official OAuth overview and service-account guide.

The environment provider is available for CI. It reads the access token and developer token from named environment variables; it does not persist them.

First read-only audit

All profile, query, report, and output paths must be absolute.

# 1. Local-only validation: no token resolution and no Google Ads request
google-ads-guard --profile D:\private\google-ads-guard.json doctor

# 2. Capture an exact date-bounded campaign snapshot
google-ads-guard --profile D:\private\google-ads-guard.json snapshot 1234567890 `
  --start 2026-07-01 --end 2026-07-31 --segment device

# 3. Audit configuration
google-ads-guard --profile D:\private\google-ads-guard.json audit tracking 1234567890
google-ads-guard --profile D:\private\google-ads-guard.json audit structure 1234567890
google-ads-guard --profile D:\private\google-ads-guard.json health 1234567890

# 4. Generate review candidates, never account mutations
google-ads-guard --profile D:\private\google-ads-guard.json recommend negatives 1234567890 `
  --start 2026-07-01 --end 2026-07-31

doctor and profile validate never resolve credentials and never call Google Ads.

For a custom query, put GAQL in a file rather than a shell argument:

google-ads-guard --profile D:\private\google-ads-guard.json query 1234567890 `
  --file D:\private\campaign-query.gaql --allow-raw-query `
  --out D:\evidence\campaigns-2026-08-16.json

The query validator rejects comments, separators, mutation-like keywords, multiple SELECT/FROM clauses, unbounded row counts, and unsupported row limits. Google documents the Search and SearchStream behavior in the reporting guide.

Understand the output

Every online JSON report is an evidence envelope:

{
  "schemaVersion": "1.0",
  "generatedAt": "2026-08-16T00:00:00.000Z",
  "command": "audit tracking",
  "readOnly": true,
  "source": {
    "apiVersion": "v25",
    "principalVerification": "verified",
    "customer": {
      "id": "0987654321",
      "name": "Example Customer",
      "currencyCode": "USD",
      "timeZone": "America/Los_Angeles"
    },
    "requestIds": ["..."],
    "queryDigests": ["..."]
  },
  "data": [],
  "findings": [],
  "recommendations": [],
  "warnings": []
}

Request IDs help investigate API failures. Query digests identify the exact query text without repeating it throughout an audit trail. Neither one proves that tracking, attribution, or business outcomes are correct; those remain separate findings.

Commands

Command Network Purpose
doctor No Validate profile and show the declared boundary
profile validate No Strict schema and unknown-key validation
snapshot Yes Campaign metrics for an explicit date range
audit tracking Yes Conversion-action configuration evidence
audit structure Yes Campaign, group, ad, keyword, and negative inventory
health Yes Tracking and structural health score; not a performance score
recommend negatives Yes Threshold-qualified search-term review candidates
recommend budget Yes Target-ROAS evidence screening only
recommend bid Yes Target-CPA evidence screening only
query Yes One explicitly acknowledged bounded GAQL SELECT
explain No Summarize a saved JSON evidence envelope

Output formats are JSON, NDJSON, and CSV. CSV is available only when data is an array. Every online result includes the verified account identity, API version, principal status, request IDs, query digests, generation time, findings, recommendations, and warnings.

Recommendation philosophy

A recommendation is emitted only when configured minimum evidence gates are crossed. It still includes:

  • the observed values and thresholds;
  • a confidence level;
  • the rationale;
  • facts the report cannot establish;
  • requiresApproval: true.

For example, a high-cost search term with zero returned conversions is a negative-keyword review candidate, not an automatically safe negative. Semantic relevance, offline conversions, assisted value, and match scope remain human verification steps.

What was improved over the reference project

The design review used Bin-Huang/google-ads-open-cli at commit cadc567a9b5a0942609a42d94fe5395da32b9960 as a public reference, then implemented an independent codebase.

Area Reference limitation at reviewed commit Guard design
Credentials Long-lived credential JSON and secret-bearing CLI options are supported Profile contains variable names only; secrets come from environment or fixed gcloud calls
OAuth Local callback flow lacks a documented state/PKCE gate Delegates interactive OAuth to Google Cloud CLI; no custom callback server
Account boundary Customer IDs can be supplied directly Exact allowlist plus ID/name/currency/timezone API readback
GAQL Several user values are interpolated into query strings Validated identifiers, dates, segments, enums, limits, and a guarded raw-query file path
API lifecycle Version is hard-coded in source Strict profile version allowlist, with v25 in the example
Reliability Limited timeout/retry/request-ID evidence Abort timeout, bounded retry, backoff, request IDs, and query SHA-256 digests
Recommendations Query cookbook; limited decision gates Thresholds, consequences, missing facts, confidence, and mandatory approval flag
Testing/release No test suite or release workflow found at the reviewed commit Cross-platform CI, fake-transport tests, package scan, and deterministic verification

The review is documented in docs/reference-review.md.

Development

npm install --ignore-scripts
npm run verify
npm pack --dry-run

Tests use synthetic fixtures and a fake HTTP transport. They do not require a Google Ads account, OAuth token, developer token, or network request.

The public-package scan checks candidate Git files and the package manifest for secret patterns, machine-specific paths, credential files, mutation endpoints, and unintended build residue.

Contributions are welcome. Read CONTRIBUTING.md, and report vulnerabilities according to SECURITY.md. Never put a developer token, OAuth token, customer export, or private account identifier in a public issue.

Known limits

  • No live-account verification is included in the automated test suite.
  • A valid Google Ads developer token and an authorized OAuth principal are still required for live reads.
  • SearchStream quota and response behavior remain governed by Google Ads API limits; request failures preserve request IDs when the server supplies them. See Google's quota guidance and API error guide.
  • Recommendation rules are deliberately conservative and are not a replacement for conversion-quality, attribution, business-margin, or experiment analysis.
  • 0.1.0 does not plan, stage, or execute account mutations.

Roadmap

  • Validate more reporting recipes against separately authorized test accounts.
  • Add versioned JSON Schema files for profiles and evidence envelopes.
  • Add offline comparison of two saved evidence periods.
  • Expand conservative audit coverage without adding mutation support.
  • Publish signed releases after cross-platform CI is proven on the public repository.

Feature requests that preserve the read-only boundary are welcome in GitHub Issues.

License

MIT. See LICENSE.

About

Read-only Google Ads audits, identity-gated evidence, and approval-required recommendations for operators and AI agents.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages