SiteVerdict — Search Console & GA4 Analyst avatar

SiteVerdict — Search Console & GA4 Analyst

Pricing

Pay per event

Go to Apify Store
SiteVerdict — Search Console & GA4 Analyst

SiteVerdict — Search Console & GA4 Analyst

Find out why Google traffic dropped. Compares two periods in Search Console + GA4 with your own read-only Google access: ranking lost vs CTR drop vs demand vs deindexed (URL Inspection), quick wins, cannibalisation, tracking/consent red flags, top 10 actions.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Aman Thakran

Aman Thakran

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 days ago

Last modified

Share

Find out why your Google traffic dropped, and what to do first, in about a minute.

This Actor reads your Google Search Console and Google Analytics 4 data through Google's official APIs, using your own read-only access. It compares two periods and writes up the result the way an SEO analyst would:

  • Why clicks fell, page by page. Each losing page gets a cause: ranking lost, CTR dropped, demand fell or page deindexed. Deindexing is confirmed with Google's URL Inspection API.
  • Quick wins. Queries ranking 5–20 with real impressions, and pages whose CTR is far below what their position should earn.
  • Keyword cannibalisation. Queries where two or more of your URLs split the impressions.
  • Sitemap and index coverage summary.
  • GA4 performance by channel, landing page, device and country, joined to Search Console landing pages. It also estimates the revenue at stake on the pages that lost clicks.
  • Tracking and consent red flags. For example, GA4 organic sessions collapse while Google clicks hold steady, and the Actor finds the day it broke.
  • Top 10 actions, a plain-English summary, evidence tables for every finding, and a shareable HTML report.

Everything is deterministic and rule-based: no AI guessing and no invented numbers. Every finding shows the data behind it.

Try it free first. With Google access = Sample data, it runs on a built-in fictional shop that has every problem planted, so you can see the full report before connecting your own account.

Who it is for

  • SEO consultants and agencies. Diagnose a client's traffic drop and get a prioritised fix list. You can run it on a schedule for every client property.
  • In-house marketers. Answer "why did organic drop?" before the Monday meeting.
  • Developers and analysts. Get a clean JSON of GSC + GA4 deltas for dashboards, or for AI agents through the SiteVerdict MCP server.

What you get

OutputWhere
One dataset item per property: summary, headline metrics, drop causes, top 10 actions, all findings with evidence tables, URL Inspection results, sitemap summary, data notesDataset (views: Overview, Top 10 actions, All findings, Traffic-drop causes)
HTML report covering all propertiesKey-value store REPORT
HTML report per propertyreport-<property>
Full tables (all losing/gaining pages and queries, countries, devices, daily series, GA4 breakdowns, the GSC↔GA4 join)data-<property> (JSON)
Short machine summaryOUTPUT

How causes are decided (transparent rules)

Only the biggest losing pages are classified: up to 25, ordered by clicks lost.

CauseRuleConfidence
Page deindexed / not indexedURL Inspection verdict is not PASS, indexing is blocked (noindex), or Google chose a different canonicalconfirmed
Impressions collapsed by 90% or more and the URL was not inspectedsuspected
Ranking lostAverage position worsened (by at least 1, or 25% of the old position, in the top 10; by at least 3 below that)likely
CTR droppedCTR fell 20% or more while position and impressions heldlikely
Demand fellImpressions fell 20% or more at a stable position. Query-level demand drops are listed toolikely

Each page also shows how much of its loss came from impressions and how much from CTR.

Search Console counts clicks on Google's side, so your tags don't affect it. GA4 depends on your tag and your consent banner. Comparing the two catches measurement problems:

  • GA4 organic sessions per Google click fall 30% or more between periods. Possible broken tag, consent change or GTM publish.
  • The day it happened: the 7-day window where sessions per click collapsed while Google clicks stayed within ±20%.
  • Landing pages with 30 or more Google clicks but zero GA4 organic sessions (tag missing on that template).
  • High shares of "(not set)" landing pages or the "Unassigned" channel. A Direct share jump while organic falls.
  • Key events or revenue collapsing while sessions hold. GA4 Realtime showing 0 users on a busy site.

To confirm a consent issue, run SiteVerdict — Consent Mode v2 & Tracking Auditor on the site. It loads the page with no click, after Reject and after Accept, and decodes Consent Mode v2.

The CTR curve is a benchmark

Opportunity sizes use an approximate industry-average CTR by position, compiled from public CTR studies. Real SERPs with ads, AI Overviews, featured snippets or shopping units earn less. The report also shows your own site's median CTR per position next to it, and you can supply your own curve (ctrCurve).

Setup: connect your own Google data (about 10 minutes, once)

You need a Google account that can already see the site in Search Console and GA4. The Actor only ever asks for read-only scopes (webmasters.readonly, analytics.readonly).

  1. Create or choose a Google Cloud project. Go to https://console.cloud.google.com/ and use the project picker, then New project. The free tier is fine and no billing is needed for these APIs.
  2. Enable the two APIs. Go to APIs & Services > Library. Search for "Google Search Console API" and click Enable. Then search for "Google Analytics Data API" and click Enable.
  3. Create the service account. Go to IAM & Admin > Service accounts > + Create service account. Name it, for example, siteverdict-reader, then click Create and continue > Done. It needs no project roles.
  4. Create a key. Open the service account, then go to Keys > Add key > Create new key > JSON > Create. A .json file downloads. Copy its client_email (looks like siteverdict-reader@your-project.iam.gserviceaccount.com).
  5. Give it Search Console access. In Search Console, select the property, then go to Settings > Users and permissions > Add user. Paste the client_email and choose Restricted (read-only is enough), then Add. Repeat for each property.
  6. Give it GA4 access. In GA4 go to Admin > (Property column) Property access management > + > Add users. Paste the client_email, choose the role Viewer and untick "Notify new users". Click Add.
  7. Find the GA4 Property ID. Go to GA4 Admin > Property details. It is the number, for example 123456789, not the G-… measurement ID.
  8. Run the Actor. Set Google access = Service account and paste the whole JSON file into Service-account JSON key. Under Properties, add for example:
[{ "label": "My shop", "gscSiteUrl": "sc-domain:example.com", "ga4PropertyId": "123456789" }]

gscSiteUrl accepts sc-domain:example.com (Domain property), https://www.example.com/ (URL-prefix property) or just example.com. The Actor matches it against the properties the service account can see and lists them if it can't find yours.

Option B: OAuth client and refresh token (use your own Google login)

  1. In Google Cloud, enable the two APIs (steps 1–2 above).
  2. Set up the consent screen. Go to APIs & Services > OAuth consent screen: choose External, fill the app name and your email, and add yourself as a test user. To stop refresh tokens expiring after 7 days, click Publish app ("In production"). For your own use you can click through the "unverified app" warning.
  3. Create the client. Go to APIs & Services > Credentials > + Create credentials > OAuth client ID > Web application. Add the authorised redirect URI https://developers.google.com/oauthplayground and copy the client ID and client secret.
  4. Get a refresh token from the OAuth Playground:
    • Open https://developers.google.com/oauthplayground. Click the gear icon, tick Use your own OAuth credentials and paste the client ID and secret.
    • In Step 1, enter the scopes https://www.googleapis.com/auth/webmasters.readonly https://www.googleapis.com/auth/analytics.readonly and click Authorize APIs. Sign in.
    • In Step 2, click Exchange authorization code for tokens and copy the Refresh token.
  5. Run the Actor with Google access = OAuth and paste the client ID, client secret and refresh token.

Security and privacy

  • All credential fields are secret inputs. Apify stores them encrypted, and the Actor uses them in memory only to get short-lived access tokens. They are never logged or written to the dataset, key-value store or report.
  • Read-only scopes only. The Actor cannot change anything in Search Console or GA4.
  • You can revoke access at any time. Delete the service-account key in Google Cloud, or remove the user in Search Console / GA4.
  • Only aggregated metrics are requested: no user IDs, client IDs or user-level data. Search Console queries are aggregated and anonymised by Google. If a query ever contains a personal name, treat the output as you would your Search Console export (UK GDPR applies to your own use).

Input

FieldDefaultNotes
authMethodsamplesample, serviceAccount or oauth
serviceAccountJson / oauthClientId / oauthClientSecret / oauthRefreshToken–Secret
properties–[{label, gscSiteUrl, ga4PropertyId}], up to 50 per run. Either id may be omitted
comparisonprevious_periodAlso year_over_year (364 days back, weekday-aligned) or custom
periodDays287–180
dataLagDays3Search Console data is final after 2–3 days
currentStartDate…previousEndDate–For custom
searchTypewebAlso image, video, news, discover or googleNews
brandTerms[]Brand queries are excluded from opportunities and split out
minImpressions100Threshold for opportunities and cannibalisation
maxUrlInspections10Losing pages inspected per property (billed per URL)
includeGa4RealtimetrueOne runRealtimeReport call
dataStatefinalall includes fresh data
maxRowsPerQuery25,000Per report, paged
maxTableRows25Rows per evidence table
ctrCurvebuilt-inYour own CTR by position

Example output (abridged)

{
"label": "My shop",
"status": "ok",
"gsc": { "clicks": { "previous": 11380, "current": 7845, "changePct": -31.1 }, "avgPosition": { "previous": 6.3, "current": 6.8, "changePct": 7.9 } },
"ga4": { "sessions": { "previous": 18023, "current": 10815, "changePct": -40 }, "organicSessions": { "previous": 9230, "current": 4228, "changePct": -54.2 }, "currency": "GBP" },
"dropCauses": [
{ "cause": "page_deindexed", "causeLabel": "Page deindexed / not indexed", "pages": 1, "clicksLost": 875 },
{ "cause": "ranking_lost", "causeLabel": "Ranking lost", "pages": 1, "clicksLost": 965 }
],
"topActions": [
{ "rank": 1, "priority": "critical", "action": "Check GA4 tracking before changing any content: GA4 organic sessions changed -54.2% while Google clicks changed -31.1%. ..." },
{ "rank": 2, "priority": "critical", "action": "Restore indexing on 1 page(s) (top: https://www.example.com/hiking-boots/) - ..." }
],
"findings": [ { "id": "deindexed-pages", "severity": "critical", "title": "...", "evidence": { "columns": ["Page", "..."], "rows": [["https://www.example.com/hiking-boots/", 912, 37, "..."]] } } ],
"reportUrl": "https://api.apify.com/v2/key-value-stores/.../records/report-my-shop"
}

The full sample run is in docs/sample-output.json and docs/sample-report.html.

Pricing

Pay per event:

  • property-analysed: once per property per run. It is only charged after real data has been fetched; errors and empty results are free.
  • url-inspected: per successful URL Inspection call.

Sample mode is free apart from the Apify start event. The Actor stops before it would exceed your run's maximum total charge: inspections are skipped and remaining properties are not started. See PRICING.md for the proposed prices.

Limits and quotas (Google, checked 11 Oct 2026)

Calls run on your Google Cloud project's quota, not a shared one.

APILimitWhat this Actor uses
Search Analytics1,200 queries/min per site and per user; short-term load quota in 10-minute windows. At most 50,000 rows per day per search type are exposed; rowLimit max 25,000About 13 queries per property plus paging
URL Inspection2,000/day and 600/min per sitemaxUrlInspections (default 10), at most 400/min
GA4 Data API (standard property)200,000 tokens/day, 40,000/hour, 14,000 per project per property per hour, 10 concurrent requests14 runReports (≤7 in parallel) plus 1 realtime

Sources: https://developers.google.com/webmaster-tools/limits · https://developers.google.com/webmaster-tools/v1/how-tos/all-your-data · https://developers.google.com/analytics/devguides/reporting/data/v1/quotas

Other limits:

  • Search Console hides rare queries ("anonymised"). The report shows the share of clicks with no visible query.
  • GA4 may threshold, sample or group rows into "(other)". These cases are flagged in notes.
  • The GSC↔GA4 join matches on URL path. GA4 has no hostname in landingPage, so multi-host Domain properties are joined on the host with the most clicks.
  • GA4 "Organic Search" includes Bing and other engines, so treat sessions per click as a sanity ratio.
  • Sitemap "indexed" counts are deprecated in the API. Coverage uses pages with impressions plus URL Inspection samples as a proxy.

FAQ

Does it need my Google password? No. It uses a service-account key or an OAuth refresh token that you create and can revoke.

Will it change anything in my accounts? No. It uses read-only scopes only.

Why does it say it "cannot see" my property? The service-account email has not been added in Search Console (Settings > Users and permissions), or you typed a different property form. The error lists the properties it can see.

It says the API is not enabled. Enable "Google Search Console API" and "Google Analytics Data API" in the same Cloud project as the key, wait a few minutes, then rerun.

My OAuth token stopped working after a week. Apps left in "Testing" status get refresh tokens that expire after 7 days. Publish the consent screen, or use a service account.

Is this AI-generated advice? No. All text comes from fixed templates filled with your numbers, and the rules are documented above.

Compliance and sources

  • Data comes only from Google's official APIs with credentials you supply: Search Console API (searchanalytics.query, sitemaps.list, urlInspection.index.inspect) and Google Analytics Data API v1beta (runReport, runRealtimeReport). There is no scraping.
  • The CTR benchmark is an approximation of public CTR studies and is labelled as such in every output.
  • This is diagnostic analysis, not legal advice (including on consent/PECR/UK GDPR compliance) and not a guarantee of rankings or revenue.
  • Where results are stored: the default dataset and key-value store of the run (the analysis rows, the raw API data per property as data-… records, HTML reports and OUTPUT), inside your own Apify account. These default storages are unnamed. How long Apify keeps them is set by Apify and your plan, not by SiteVerdict (Apify data retention); you can delete them sooner in Apify Console. The Actor keeps no named store.
  • Data licence: your Search Console and GA4 data stays yours; it is fetched under Google's API terms with your own credentials.
  • What SiteVerdict keeps: nothing. The Actor runs in your Apify account; data goes only between Google's APIs and your Apify storage, never to SiteVerdict.

Made by SiteVerdict (BharatFare Travel and Technologies Ltd, UK).