Google Search Console data
Connect Google Search Console data to your SEO reports and understand the limits before you trust the numbers. Add Google Analytics only when it helps.
Search Console shows how a verified property performed in Google Search. Google Analytics shows what happened after measured visitors reached your site. Joining them can turn a vague traffic problem into a page, query, and post-click investigation.
The sources are still different datasets. They will not reconcile row for row, and a gap in one should not be filled with numbers from the other.
See verified properties without copying IDs
Run the guided setup:
seo start
The browser asks you to approve read-only Search Console and Analytics access. The CLI then lists the properties available to that Google account. Choose the Search Console property first and add Google Analytics only when you want post-click context.
If one Google Analytics web stream clearly matches the property you chose, the CLI attaches that Google Analytics property and shows the stream and hostname it matched. When several Google Analytics properties match, or none is clear, it asks you to choose or skip Google Analytics. Skipping it is fine. You can attach Google Analytics later.
You do not need to copy a property id if Google can list it. You also do not need Google Analytics to crawl a public site or run Search Console-only opportunity reports.
Use these commands to check the connection later:
seo auth whoami
seo auth status
seo sites
seo projects list
Connect more than one Google account
Run the login command again to add another account. Earlier logins stay saved on this machine.
seo auth login
seo auth accounts
During seo start, choose one account for Search Console and another account
for Google Analytics if the site needs that split. The project profile keeps
both choices. Reports that use the project then select the correct login for
each data source.
Agents and CI can make the same choice with explicit flags:
seo start \
--site sc-domain:example.com \
--search-console-account <search-account-email> \
--google-analytics-property 123456789 \
--google-analytics-account <analytics-account-email> \
--json
Use seo auth use <email> to change the default login for commands that do not
use a saved project. Direct property commands also accept --account <email>.
Remove one login with seo auth logout --account <email>, or remove every
login with seo auth logout --all.
Use Search Console to find search demand and affected pages
Search Console reports clicks, impressions, CTR, and average position for the property and dimensions you request, and the CLI uses that evidence for reports such as quick wins, page-two opportunities, decaying pages, cannibalisation review, query clusters, and update comparisons.
Google’s Search Console introduction explains the product’s search performance and indexing views. The Google Search Console API gives the CLI programmatic access to part of that evidence. It is not a rank tracker and does not expose every impression as a raw event.
Expect query rows to be smaller than chart totals
Google omits anonymized queries from Search Console tables and the API. The chart can therefore show more clicks than the sum of exported query rows. Google documents that difference in its performance data explanation.
The API also says it returns top rows rather than guaranteeing every row. Its performance data limits currently describe a maximum of 50,000 rows per day per search type, sorted by clicks.
That changes how you should read a report:
- “No returned query matched” is not the same as “the query never appeared.”
- A query list can rank the evidence it received without claiming to cover all demand.
- Adding page, query, device, or country dimensions can change aggregation and returned rows.
- A zero is trustworthy only when the result says the relevant source was complete enough to support it.
Reports keep caps, filters, and data availability in their source details so an agent can make that distinction.
Ask Search Console a precise question
seo gsc-query gives you the Search Analytics rows behind the higher-level
opportunity reports. Use it when you need a specific date range or dimension
combination and a focused report would make too many decisions for you.
It helps with questions such as:
- Which queries sent impressions to one page last month?
- Did mobile and desktop visibility move differently?
- Which countries account for a change in clicks?
- What rows did Search Console retain for a page and query combination?
Run a query with explicit dates and dimensions:
seo gsc-query --project example --start-date 2026-05-01 --end-date 2026-05-31 --dimensions query,page --limit 100 --json
seo gsc-query --help
The command requests clicks, impressions, CTR, and average position grouped by
the dimensions you choose. Supported dimensions include query, page, country,
device, and date. --type changes the Search Console search type. Advanced
users can pass a complete Search Analytics request with --body or
--body-file.
JSON output includes the property, request body, returned rows, rows fetched, API call count, and the number of rows kept after the local output limit. Human output shows a compact table of the first rows.
This is returned Search Console data, not a complete keyword database. Anonymized queries are missing, dimensional rows may not reconcile with property totals, and Google returns top rows rather than promising every row. Keep the request dates, dimensions, search type, filters, and row limits beside any conclusion.
Use quick-win review, segment impact, or decaying pages when you want the CLI to turn those rows into a limited investigation queue.
Check the indexed version Google reports for one URL
seo url-inspect calls the Search Console URL Inspection API for a URL inside
a property you can access. Use it when the decision depends on Google’s stored
index evidence rather than another live fetch from your computer.
seo url-inspect --project example --url https://example.com/pricing --json
seo url-inspect --help
The request checks that the URL belongs to the selected property, then asks Google for its inspection result. Human output shows the verdict, coverage state, robots state, last crawl time, and Google-selected canonical. JSON keeps the complete structured response returned by the API.
The result describes Google’s indexed snapshot. It is not a live test and it does not prove that the page appears for a query today. A URL can also change after Google’s recorded crawl. URL Inspection has provider quotas, so use it for important URLs and representative samples rather than trying to inspect a large site in one run.
Run audit one page to compare the current live URL with that indexed evidence. Use index monitoring when you need a repeatable, quota-limited sample across a sitemap.
Compare finalized Search Console windows
Recent Search Console data can be incomplete. Google defines finalized data as
the default API state and dates its metadata in the America/Los_Angeles time
zone. The
Search Analytics API reference
also warns that rows after the first incomplete date may change noticeably.
The CLI uses finalized windows for comparisons that need a directional verdict. That matters for traffic anomalies, update analysis, SEO tests, and before-and-after measurement. Comparing a complete month with the last five unfinished days can manufacture a decline that never happened.
Check the dates in every result. Use --refresh when you need to bypass the
local cache, but remember that a fresh API response can still contain provider
data that is not final.
Use official Google update windows
seo updates lists ranking updates from the official Google Search Status
Dashboard. Use it to confirm the name, start date, end date, and status of a
known update before comparing search performance around it.
seo updates --product Ranking --limit 10
seo updates --product Ranking --limit 10 --json
seo updates --help
The command requests official incidents for the selected product and returns
their start time, end time, type, name, and status. An open incident has no end
date yet. --limit bounds the rows returned.
This feed does not include third-party volatility scores, unconfirmed chatter, or a diagnosis for your site. Matching dates establish timing context only. A release, migration, tracking change, seasonality, competitor, or demand shift can overlap the same window.
Use update correlation to compare a property with overlapping official windows. Use the Google update postmortem when you also need page, query, device, country, and known-confounder evidence.
Add Google Analytics when post-click behavior changes the decision
Google Analytics can add landing-page sessions, users, engagement, events, key events, sources, campaigns, and known AI referrals. It helps answer a different set of questions:
- Did the landing page receive measured sessions after its search clicks changed?
- Did a traffic shift affect engagement or a configured key event?
- Which known referral sources sent measurable visits?
- Does one page group behave differently from another after the click?
Google Analytics cannot restore visits that were never measured, identify a referrer that was stripped, or prove that an SEO edit caused a conversion change.
List the properties available to the connected account before running a raw report:
seo analytics google properties
Then use the numeric property ID when you need a supported Google Analytics dimension and metric combination:
seo analytics google report \
--property 123456789 \
--start-date 2026-05-01 \
--end-date 2026-05-31 \
--dimensions landingPage \
--metrics sessions,totalUsers,eventCount \
--limit 100 \
--json
seo analytics google report --help
The command uses the Google Analytics property saved in the project profile unless you pass
--property. It requests the date range, dimensions, metrics, and row limit you
provide. Advanced users can pass a complete Data API request with --body or
--body-file.
Human output shows the selected property, row count, and a compact table. JSON
keeps the Data API response, including headers, rows, totals, metadata, and row
count when Google returns them. This makes seo analytics google report useful when you
need raw post-click evidence without a higher-level SEO interpretation.
local-search-demand can use the same property for one narrow geography
question. Pass googleAnalyticsPropertyId to request sessions by landing page,
country, region and city. The report removes the landing-page query string and
keeps only exact paths already returned by its local Search Console analysis.
It reports source caps, unmatched rows, missing values, malformed rows,
duplicates and Google quality warnings beside the location totals.
This join adds measured location context to a landing page or repeated local template. It does not establish the physical location behind a Search Console query. The query and Analytics rows remain separate evidence.
Use AI referrals for known assistant referral sources. Use measure change when a recorded page or page-group change needs equal before and after windows.
Leave room for Google Analytics processing and data controls
Google says Analytics data can change while events are processed. Its data freshness guidance notes that processing can take 24 to 48 hours and that recent reports can use stricter row limits before daily data is ready.
The Data API can also return sampled data, estimated unique counts, thresholded
rows, and an (other) row when a dimension has many unique values. Google’s
Data API reporting expectations
explain why an API response and a UI report can differ even when both are
working as designed.
Reports preserve available metadata for those states. If a result is partial or thresholded, use it for limited direction rather than an exact all-site total.
Understand the local OAuth handoff
The public package can include the project’s Google desktop OAuth client. The
CLI opens the Google authorization page, listens on a temporary loopback
address for the response, exchanges the code, then stores the resulting tokens
in your system keychain when it is available. A private local file with 0600
permissions is the fallback for headless machines, locked keychains, and any
machine where you choose file storage.
Google recommends loopback redirects for installed desktop apps on macOS, Linux, and Windows in its OAuth guide for desktop apps. The browser is talking to Google during consent. The loopback redirect only returns the authorization response to the CLI running on your machine.
Use your own Google OAuth client
The published package normally uses the verified SEO Skill OAuth client. You can use a Google Desktop OAuth client from your own Cloud project instead. This is useful for local development, a private installation, or a build that does not include the shared client.
Create a separate Google Cloud project for this client. In APIs and services enable these APIs:
- Google Search Console API
- Google Analytics Data API
- Google Analytics Admin API
Open Google Auth Platform and configure the project in this order:
- Under Branding add the app name, support email, and developer contact.
- Under Audience choose External and leave the publishing status as Testing for a private setup. Add every Google account that will use the client as a test user.
- Under Data access add the four scopes used by the CLI.
openid
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/webmasters.readonly
https://www.googleapis.com/auth/analytics.readonly
- Under Clients create an OAuth client with the Desktop app application type. Copy its client ID and client secret.
Google’s Google Auth Platform setup guide shows where each part lives in the current Cloud Console. The API project owns the quota for requests made through this client.
Save the Desktop client locally:
seo auth setup-client
seo auth login
seo auth whoami
seo auth setup-client stores the client configuration in your local SEO
config directory. Do not commit it to the repository. Environment-based setups
can provide SEO_GOOGLE_CLIENT_ID and SEO_GOOGLE_CLIENT_SECRET instead.
The CLI records which client created each saved login. If you switch from the
shared client to your own client, run seo auth logout --all before signing in again.
seo auth status shows whether the active login uses the shared SEO Skill app
or your own client.
Keep a private OAuth client in testing
A Google OAuth project in Testing does not need to complete verification. It still needs the APIs, scopes, Desktop client, and test users described above. Testing changes who can use the client. It does not remove the permissions the CLI needs to request.
Testing mode is best for one person or a small known team. Google applies these limits:
- Only Google accounts added as test users can sign in.
- The project can have no more than 100 test users.
- Test users see a warning during authorization.
- Authorizations that include sensitive scopes expire after seven days, so the user must sign in again.
Google documents those limits in its OAuth audience and testing guide. For a personal client this is usually fine (the seven-day login is the annoying bit). A client intended for public use should move to In production and complete the verification required for its sensitive scopes.
Use seo auth status to see where the active tokens are stored. You can make
the choice yourself when a local setup needs it:
seo auth storage --keychain
seo auth storage --file
Changing storage carries an existing local login across. A file fallback does not make the CLI less private. It keeps the token file readable only by your user account.
Use a service account in CI or a container
Browser sign-in belongs on a person’s machine. A GitHub Actions runner, a container, or a server needs a credential with no browser involved. The CLI supports one Google service account JSON credential for that job.
A service account does not use the shared Desktop OAuth client or open a user consent screen. It requests short-lived server-to-server tokens for its own identity, so the public OAuth app verification flow is not part of this path. The service account can only read properties where its email address has been given access. The CLI does not support domain-wide delegation. Google’s server-to-server OAuth guide explains how this differs from a person granting access in the browser.
Create the service account in a Google Cloud project with the Search Console API, Google Analytics Data API, and Google Analytics Admin API enabled. Then grant the service account email access to the properties it needs:
- In Search Console, a property owner adds the service account email under Settings, then Users and permissions. Google explains the available Search Console roles and user setup.
- In Google Analytics, grant the service account access to the property before expecting it to appear in account summaries. Google’s Admin API quickstart covers service-account property access and API setup.
Keep the JSON key in your platform’s secret store. Do not commit it, put it in a project profile, or copy a personal OAuth token into a deployment image.
GitHub Actions can pass the whole JSON key as one secret:
- name: Run the main SEO report
run: |
npm i -g seo
seo report --site sc-domain:example.com --json > seo-report.json
env:
SEO_GOOGLE_SERVICE_ACCOUNT_JSON: ${{ secrets.SEO_GOOGLE_SERVICE_ACCOUNT_JSON }}
The service account uses the same read-only Search Console and Analytics scopes as browser sign-in. Run these commands in the job log to confirm which credential source is active and which properties Google returned:
seo auth status
seo sites
For a local container or server, prefer a mounted read-only file:
export SEO_GOOGLE_SERVICE_ACCOUNT_FILE=/run/secrets/seo-google-service-account.json
seo auth status
seo report --site sc-domain:example.com --json
GOOGLE_APPLICATION_CREDENTIALS is also accepted as a file-path alias. The CLI
does not search for local gcloud credentials or write a private key
to disk. Set only one of the three variables. A configured service account
takes precedence over a saved browser login, so unset it before running
seo auth login.
If Google denies a property, check that the service account email was granted
access to that exact Search Console or Google Analytics property. seo auth status shows
the active identity without printing the key. seo doctor also checks the
credential configuration before a report runs.
Remove access and local tokens
seo auth logout --all
seo privacy
This command deletes all locally stored Google tokens. It does not delete your Search Console property or Google Analytics property. The privacy policy documents the local paths and network requests, while the setup guide covers project profiles and first-run troubleshooting.