seojuice

Ho creato una dashboard di Google Search Console a costo zero. Ecco il codice.

Vadim Kravcenko
Vadim Kravcenko
· Updated · 15 min read

Riassunto veloce: Google Search Console mette a disposizione, gratis, gli stessi dati su query, pagina, posizione e impression che SEMrush e Ahrefs rivendono a 129–449 $/mese. L’API di GSC offre un limite gratuito di 1.200 richieste al minuto, un payload massimo di 25.000 righe e quattro endpoint che coprono circa il 90 % di ciò che serve a un founder in solitaria. In questo articolo trovi la procedura per configurare l’OAuth via service account, i quattro endpoint davvero utili, uno script Python eseguibile che estrae una matrice CTR query-per-pagina e tre pattern di automazione (cron + Slack, Google Sheets, una view Django leggera) che trasformano le righe grezze dell’API in una dashboard usabile. Se preferisci non gestire tu l’integrazione, SEOJuice offre lo stesso cablaggio come servizio gestito.

Ciò che GSC ti dà già gratis (e che gli strumenti a pagamento riconfezionano)

Il lato frustrante di una suite SEO da 449 $/mese è che circa il 70 % dei dati mostrati in dashboard sono già disponibili gratis in Search Console. Gli strumenti a pagamento aggiungono tre cose: tracciamento di posizione tramite proxy di terze parti, un grafo di backlink estratto da archivi web crawlati e una UI che evita di scrivere SQL. L’ultima è l’unica che serva davvero a un founder singolo, ed è anche la più economica da replicare.

Ecco cosa espone l’API per ogni proprietà di cui hai verificato la proprietà:

  • 16 mesi di dati storici sulle performance: ogni query che ha generato un click o un’impression, con posizione, CTR e data.
  • Dettaglio a livello di pagina per lo stesso periodo: quali URL si sono posizionati per quali query e dove sono atterrati i click.
  • Copertura dell’indice per qualsiasi URL: ultima scansione, stato di indicizzazione, canonica scelta da Google, usabilità mobile, parsing dei dati strutturati.
  • Stato delle sitemap: quali sitemap Google ha recuperato, quando e quante URL sono state scoperte vs indicizzate.
  • Segmentazione per dispositivo, paese e search appearance sugli stessi dati query/pagina.

Manca tutto ciò che esula dalla tua proprietà: ranking dei competitor, crescita dei backlink dei domini rivali, share-of-voice. Per la maggior parte dei founder pre-PMF sono vanity metric che non cambiano cosa rilasci settimana prossima. Ho scritto un pezzo più lungo su come ridurre lo stack SEO a due strumenti; la conclusione regge: GSC più una superficie di scrittura bastano a dare segnali utili.

«I dati in Search Console provengono direttamente da Google. Sono la fonte più accurata per capire come il tuo sito performa nella Ricerca Google.»

Da Search Console Help di Google.

Configurare l’API di GSC con un Service Account

Esistono due flussi di autenticazione validi per l’API di GSC: OAuth user-flow (redirect browser, refresh token) e OAuth via service account (server-to-server, senza browser). Per un founder che lancia un cron su un singolo VPS, i service account sono più brevi e stabili: niente scadenza di refresh token, nessuna schermata di consenso da gestire.

Il provisioning richiede circa 10 minuti e non costa nulla:

  1. Apri la Google Cloud Console e crea un nuovo progetto (o riusane uno). Il free tier basta; non si paga mai.
  2. Abilita Google Search Console API nella libreria API.
  3. In IAM & Admin → Service Accounts crea un nuovo service account chiamato gsc-dashboard-reader. Nessun ruolo a livello di progetto necessario.
  4. Genera una chiave JSON per il nuovo account e scaricala. Trattala come una chiave API: non committarla.
  5. In Search Console, sotto Impostazioni → Utenti e autorizzazioni, aggiungi l’email del service account (che termina in @<project-id>.iam.gserviceaccount.com). Il livello di accesso Limitato basta per la lettura.

Quest’ultimo passaggio è quello che molti founder saltano. Il service account è un’identità Google, ma se non gli concedi esplicitamente accesso alla proprietà di Search Console, l’API restituirà un perentorio 403 user does not have sufficient permission for site. Concedi l’accesso per ogni proprietà; se ne hai più di una, ripeti l’operazione.

Diagramma del flusso OAuth con service account: progetto GCP, service account, chiave JSON, permesso concesso in Search Console
Flusso OAuth con service account per GSC. Il file di credenziali autentica verso Google; il permesso per proprietà dentro Search Console autorizza l’accesso ai dati.

I quattro endpoint che coprono il 90 % di ciò che ti serve

La superficie dell’API GSC è ridotta. Quattro endpoint coprono insieme i dati sulle query, lo stato delle sitemap, l’ispezione per URL e l’elenco delle proprietà accessibili. Ignora il resto della reference finché non hai un motivo concreto per leggerla.

EndpointCosa restituisceCosto quotaUtile per
searchanalytics.queryFino a 25.000 righe con click, impression, posizione, CTR per query, pagina, data, dispositivo, paese1 unit / richiestaDati core di dashboard: quali query portano traffico, quali pagine convertono impression in click
sitemaps.listTutte le sitemap inviate con stato, ultimo fetch, conteggio URL1 unit / richiestaAlert di salute delle sitemap; segnalare sitemap perse o parzialmente indicizzate
urlInspection.index.inspectPer URL: stato copertura, ultima scansione, canonica, usabilità mobile, verdict AMP e dati strutturati2.000 / giorno (quota separata)Spot-check su pagine critiche; audit di indicizzazione automatizzati
sites.listTutte le proprietà leggibili dall’identità auth1 unit / richiestaDashboard multi-property; iterare su un portafoglio

Il limite di 1.200 richieste/min sugli endpoint di lettura è di fatto illimitato per un founder solitario. L’unico vero tetto è quello di 2.000/giorno su URL Inspection, che basta comunque per un audit quotidiano di tutti i 1.500 URL di un sito medio.

Un pull Python reale: top queries e matrice query-per-pagina

La query più utile che puoi lanciare è la breakdown query-per-pagina sugli ultimi 28 giorni. Ti dice quale pagina si posiziona per quale query e com’è il CTR nell’intersezione. Le celle con molte impression e CTR basso sono i target di ottimizzazione a breve.

Installa le due dipendenze:

pip install google-auth google-api-python-client

Lo script minimo indispensabile: auth, query, print. Salva la chiave JSON scaricata come gsc-credentials.json nella stessa cartella:

from datetime import date, timedelta
from google.oauth2 import service_account
from googleapiclient.discovery import build

SCOPES = ["https://www.googleapis.com/auth/webmasters.readonly"]
SITE_URL = "sc-domain:example.com"  # or "https://example.com/"
KEY_FILE = "gsc-credentials.json"

creds = service_account.Credentials.from_service_account_file(
    KEY_FILE, scopes=SCOPES
)
service = build("searchconsole", "v1", credentials=creds)

end = date.today() - timedelta(days=2)  # GSC lags ~2 days
start = end - timedelta(days=27)

request = {
    "startDate": start.isoformat(),
    "endDate": end.isoformat(),
    "dimensions": ["query"],
    "rowLimit": 25,
    "orderBy": [{"field": "clicks", "descending": True}],
}
response = service.searchanalytics().query(
    siteUrl=SITE_URL, body=request
).execute()

for row in response.get("rows", []):
    q = row["keys"][0]
    print(f"{row['clicks']:>5}  {row['impressions']:>6}  "
          f"{row['ctr']*100:>5.1f}%  pos={row['position']:>5.1f}  {q}")

Questa è l’intera integrazione. Eseguila e vedrai le prime 25 query degli ultimi 28 giorni, ordinate per click. Due note: sc-domain:example.com è per le proprietà di dominio (il tipo consigliato); usa la forma URL completa solo per le proprietà URL-prefix. I dati GSC hanno un ritardo di ~2 giorni, ecco perché terminiamo a today - 2.

La matrice query-per-pagina — quella che guida davvero le decisioni — aggiunge una seconda dimensione e alza il limite di righe:

request = {
    "startDate": start.isoformat(),
    "endDate": end.isoformat(),
    "dimensions": ["query", "page"],
    "rowLimit": 5000,
    "orderBy": [{"field": "impressions", "descending": True}],
}
response = service.searchanalytics().query(
    siteUrl=SITE_URL, body=request
).execute()

opportunities = []
for row in response.get("rows", []):
    query, page = row["keys"]
    impressions = row["impressions"]
    ctr = row["ctr"]
    position = row["position"]
    # Cells with >500 impressions and CTR below 2% are CTR-leak candidates
    if impressions > 500 and ctr < 0.02 and position < 15:
        opportunities.append((impressions, query, page, position, ctr))

opportunities.sort(reverse=True)
for imp, q, p, pos, ctr in opportunities[:20]:
    print(f"{imp:>6} imp  pos={pos:>4.1f}  ctr={ctr*100:>4.1f}%  {q}  →  {p}")

Il filtro finale (molte impression, CTR basso, posizione entro la top 15) è la classica lista di pagine a cui riscrivere il title tag. Stai già posizionandoti; il leak è nel click-through. È la stessa logica che gli strumenti a pagamento chiamano “ranking opportunities”, scritta in sei righe.

Esempio di output della matrice query-per-pagina con colonne impressions, CTR, posizione, query e URL di destinazione
Output della matrice query-per-pagina. Ogni riga è un’intersezione query × URL. Le righe con molte impression e CTR basso sono candidate alla riscrittura del title.

Cosa visualizzare: le quattro chart che valgono lo sforzo

Una volta ottenute le righe, la domanda è cosa mettere in grafico. La maggior parte degli strumenti SEO a pagamento ti annega con 40 widget; te ne servono quattro per prendere decisioni settimanali. Usali con la libreria di chart che già adoperi: Chart.js per HTML, matplotlib in Jupyter, i grafici nativi se riversi tutto in Google Sheets.

  1. Line chart giornaliero di click e impression, finestra 90 giorni. Il grafico più importante. Dice se il traffico cresce, è piatto o cala. La divergenza (impression in crescita, click fermi) è il segno tipico degli AI Overview.
  2. Bar chart delle prime 20 query con colore per posizione. Ordinato per click decrescenti. Verde per posizioni 1–5, giallo 6–10, rosso 11+. Mostra quali query stai vincendo, quali sono a rischio, quali meritano un refresh.
  3. Scatter plot del decay di posizione. Asse X: posizione 4 settimane fa. Asse Y: posizione oggi. La diagonale è “nessun cambiamento”. Punti sopra sono scesi; sotto sono saliti. Il cluster di punti rossi in alto a destra è la tua watchlist di decay; vedi l’articolo sulla strategy di content refresh per il workflow.
  4. Stima dell’impatto di AI Overview. Traccia impression e click come due linee sullo stesso asse, normalizzate in modo da sovrapporsi al giorno 1. Quando divergono (impression stabili, click in calo) il gap è, in prima approssimazione, cannibalizzazione da AI Overview. Non è perfetto, ma è indicativo.
Mockup dei quattro grafici GSC core: linea daily click, bar top query, scatter decay di posizione, divergenza impression-click per AI Overview
I quattro grafici chiave. La maggior parte delle dashboard SEO a pagamento ne mostra 40 +; per un founder solitario, questi coprono circa il 90 % delle decisioni.

Pattern di automazione: Cron, Slack, Sheets, Django

Un pull manuale va bene una tantum. La dashboard diventa utile quando gira da sola. Tre pattern di automazione, in ordine di sforzo:

Pattern 1: Cron e alert Slack. L’opzione più economica. Un cron giornaliero esegue lo script e, se scattano tre condizioni — click in calo >20 % week-over-week, una query in top 10 scivola fuori dalla top 20, o una pagina prima indicizzata perde l’indicizzazione — posta su Slack. Circa 80 righe di Python incluso il webhook. Gira in 4 secondi su un VPS da 5 $. La tua dashboard fa una cosa: urlare quando qualcosa cambia.

import json, os, urllib.request

def post_slack(text):
    payload = {"text": text}
    req = urllib.request.Request(
        os.environ["SLACK_WEBHOOK_URL"],
        data=json.dumps(payload).encode(),
        headers={"Content-Type": "application/json"},
    )
    urllib.request.urlopen(req, timeout=10).read()

# After computing wow_change from two consecutive 7-day GSC pulls:
if wow_change < -0.20:
    post_slack(
        f":warning: GSC clicks dropped {wow_change*100:.0f}% WoW "
        f"({last_week} → {this_week}). Top falling queries: {falling[:3]}"
    )

Pattern 2: Sink su Google Sheets. Riversa le righe in un foglio Google tramite l’API Sheets o il wrapper gspread. Il foglio è la tua dashboard: pivot per slicing ad hoc, chart nativi, condivisibile con un co-founder non tecnico. Circa 30 righe sopra il pull GSC. Contro: la freschezza dipende dal cron e Sheets rallenta oltre le 20.000 righe.

Pattern 3: View Django leggera. Una sola view che esegue il pull GSC, cache in Redis per 6 ore e renderizza i quattro grafici inline via Chart.js. Circa 200 righe complessive tra Python e HTML. Vale la pena quando un co-founder vuole dare un’occhiata a metà settimana. La cache è critica: senza, ogni pageview scatenerebbe una chiamata GSC fresca e finiresti la quota al minuto durante un lancio.

«Ho cancellato il mio abbonamento Ahrefs da 329 $/mese dopo aver capito che l’unico widget che controllavo ogni giorno era ‘top organic queries’. L’ho riscritto con l’API Search Console in un pomeriggio.»

Un pattern che ricorre spesso nei thread indie-hacker su Hacker News e negli angoli bootstrapper di IndieHackers.

DIY vs SEMrush vs SEOJuice vs Ahrefs vs UI GSC gratuita

Il confronto che interessa davvero ai founder non è fra tool a pagamento, ma fra: pagarne uno, costruirlo in casa, o usare l’interfaccia GSC gratuita accettandone i limiti. Ecco come si posizionano le cinque opzioni:

OpzioneCosto mensileTempo di setupManutenzioneMulti-propertyDati storici
UI GSC gratuita0 $0 h (già pronta)NessunaSwitch manuale16 mesi, export lenti
DIY API GSC + cron + Sheets0–5 $ (VPS)4–8 h la prima volta~30 min/trimestre (rotazioni auth, deprecazioni API)Loop banale16 mesi, inter­rogabili in secondi
SEOJuice29–99 $~10 minNessuna (gestito)Integrata16 mesi da GSC + storico crawl proprietario
SEMrush139–499 $~30 minNessuna (gestito)Limiti di progetto per pianoOltre 2 anni sui piani a pagamento
Ahrefs129–449 $~30 minNessuna (gestito)Limiti di progetto per pianoOltre 2 anni sui piani a pagamento

Il DIY vince sul costo, pareggia sulla profondità dei dati per tutto ciò che sta dentro la tua proprietà e perde su competitor e backlink. Se sei in early stage e la tua domanda SEO è «cosa funziona sul mio sito?», DIY è la risposta giusta. Se stai scalando, fai ricerca competitor o insegui backlink, gli strumenti a pagamento valgono il prezzo. La pagina strumenti di SEOJuice si piazza in mezzo: integrazione GSC gestita più crawl, audit e tracking AI, senza l’overhead enterprise di SEMrush.

Cosa gli AI Overview sbagliano sui dati GSC

Chiedi a ChatGPT o Gemini come interpretare i dati GSC e otterrai risposte plausibili ma sbagliate in tre modi specifici. Vale la pena evidenziarli: questi errori si propagano in ogni “report SEO generato dall’AI” sul mercato.

Errore #1: «Position è il rank medio che hai tenuto per quella query». In realtà è la media della posizione più alta che uno qualsiasi dei tuoi URL ha tenuto nelle impression in cui la query ha mostrato un risultato che includeva il tuo sito. Se due URL si posizionano per la stessa query nella stessa SERP, conta solo il più in alto. Ecco perché “position” cambia quando pubblichi un nuovo articolo che supera uno vecchio: la posizione dell’URL vecchio non muta, ma quella a livello di query sì.

Errore #2: «Il CTR è calcolato per impression». Il CTR è click ÷ impression al livello di aggregazione che hai chiesto. Solo per data dà il CTR giornaliero di tutto il sito; query+pagina dà il CTR per cella. I numeri non tornano tra livelli diversi perché il denominatore cambia.

Errore #3: «Se una query ha impression ma zero click, la pagina si posiziona male». Nell’era AI Overview questo è sempre più spesso il segnale di essere citato nell’Overview senza ricevere click. Impression stabili, click in calo è il pattern canonico. La pagina non si posiziona peggio; la SERP è cambiata forma. L’articolo sulle citazioni AI Overview approfondisce cosa fare.

Trappole da evitare quando lo costruisci da solo

Cinque spigoli vivi che mordono chi usa l’API GSC per la prima volta. Conoscerli prima ti fa risparmiare una settimana:

  • Il limite di 25.000 righe per richiesta è rigido. Oltre, pagina con startRow. Il wrapper google-api-python-client non lo fa da solo; cicla finché la risposta restituisce meno di 25.000 righe.
  • Le chiavi dei service account non scadono, ma Google le revoca se trapelano. Tratta il file JSON come una password DB: secret manager in produzione, mai in git.
  • Il ritardo di 2 giorni è per giorno, non per query. I dati di oggi tornano vuoti. Due giorni fa sono quasi definitivi; ieri è parziale.
  • Le proprietà di dominio (sc-domain:) e URL-prefix (https://...) riportano numeri diversi. Le proprietà di dominio aggregano su tutti i sottodomini e protocolli. Se registri entrambe vedrai dati sovrapposti ma non identici. Scegline una come fonte di verità.
  • Il bucket “anonymized queries” mangia circa il 15–25 % della coda lunga. Le query a basso volume finiscono in (anonymized) per privacy e non si recuperano. Pianifica le analisi top-query sui nomi espliciti.

Niente di insormontabile, ma ognuno di questi mi è costato un’ora la prima volta. La reference ufficiale li documenta tutti, solo non a chiare lettere.

FAQ

Per quanto tempo l’API GSC conserva i dati storici? 16 mesi. Oltre, i dati spariscono; non esiste un endpoint di archivio. Se ti servono serie più lunghe, salva ogni giorno la finestra mobile nel tuo storage. Un anno in Postgres pesa poche centinaia di MB a proprietà.

Posso usare l’API per inviare URL all’indice? No. La submission URL è stata rimossa nel 2020 per abuso spam. L’Indexing API esiste ma funziona solo per offerte di lavoro ed eventi livestream; usarla per contenuti normali viola le policy Google.

Qual è la differenza tra impressions e clicks? Le impression contano ogni volta che il tuo URL appare in SERP, anche se l’utente non scrolla. I click contano i click effettivi. Il CTR è il rapporto. Nell’era AI Overview il divario si allarga perché gli utenti leggono la risposta in Overview e non cliccano le fonti citate.

Esiste un free tier sopra la quota standard? La quota è uguale per tutti: 1.200 richieste/min per progetto sugli endpoint analytics, 2.000/giorno su URL Inspection. Nessun upgrade a pagamento; gli aumenti quota si chiedono dal Cloud Console ma servono di rado in carichi da founder.

Posso delegare l’accesso senza condividere il mio account Google? Sì, è esattamente lo scopo dei service account. Creane uno per integrazione, dagli accesso Limitato alla proprietà e revocalo senza toccare il tuo login.

Quali binding di linguaggio supporta l’API? Ufficialmente: Python, Node, Java, PHP, Ruby, Go, .NET. Ufficiosamente: qualunque cosa possa chiamare un endpoint REST con un Bearer token. Le forme JSON sono identiche in ogni linguaggio.

Confronto affiancato di UI GSC gratuita, dashboard DIY API GSC, SEOJuice, SEMrush e Ahrefs per costo, setup, manutenzione
Le cinque opzioni per la dashboard SEO di un founder, tracciate su costo e tempo di setup. La via DIY è gratis ma richiede ore di engineering.

Quando il DIY smette di valere la pena

La dashboard DIY si ripaga finché i dati che ti servono vivono dentro la tua proprietà. Nel momento in cui la domanda diventa «perché il mio competitor mi supera?» o «chi gli linka ma non linka me?», hai raggiunto il limite di ciò che GSC espone. Da lì puoi pagare SEMrush o Ahrefs 129–449 $/mese per dati su backlink e competitor, oppure un tool più piccolo come SEOJuice per la stessa integrazione GSC più crawl, audit e tracking AI gestiti, di solito al 15–25 % del costo delle suite enterprise.

Per la maggior parte dei founder solitari, la soglia è tra 500 $/mese di MRR e 5 K $/mese di MRR. Sotto i 500, costruiscilo tu: il tuo tempo di engineering costa meno dell’abbonamento e imparerai i dati nel mentre. Sopra i 5 K, il tuo tempo vale troppo per gestire rotazioni auth e retry di quota. In mezzo è una monetina che dipende da quanto ti diverte scrivere Python a mezzanotte.

L’altra strada: costruisci questo weekend la versione cron + Slack (sei ore incluse le OAuth), usala per un mese e guarda cosa controlli davvero. Se apri solo l’alert “top query in calo” e ignori il resto, hai scoperto che ti serviva un solo widget: continua a costruire, o compra. L’articolo sulle strategie SEO a budget ridotto copre il playbook low-cost.

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "FAQPage", "mainEntity": [ { "@type": "Question", "name": "Per quanto tempo l’API GSC conserva i dati storici?", "acceptedAnswer": { "@type": "Answer", "text": "16 mesi. Oltre, i dati non sono più disponibili; non esiste un endpoint di archivio. Se vuoi serie temporali più lunghe, esegui un cron giornaliero che salva la finestra mobile nel tuo storage." } }, { "@type": "Question", "name": "Posso usare l’API GSC per inviare URL all’indice?", "acceptedAnswer": { "@type": "Answer", "text": "No. L’invio URL è stato rimosso nel 2020 a causa di abusi. L’Indexing API esiste ma supporta solo offerte di lavoro ed eventi livestream; usarla per contenuti normali viola le policy di Google." } }, { "@type": "Question", "name": "Qual è la differenza tra impressions e clicks in GSC?", "acceptedAnswer": { "@type": "Answer", "text": "Le impressions conteggiano ogni volta che un URL è mostrato in una SERP. I clicks conteggiano i click dell’utente sul link. Il CTR è il rapporto. Nell’era AI Overview il divario cresce perché gli utenti leggono la risposta nell’Overview e non cliccano le fonti." } }, { "@type": "Question", "name": "Esiste un free tier sopra la quota standard dell’API GSC?", "acceptedAnswer": { "@type": "Answer", "text": "La quota è uguale per tutti: 1.200 richieste/min sugli endpoint analytics, 2.000 al giorno su URL Inspection. Non esiste un upgrade a pagamento; gli aumenti si richiedono via Google Cloud Console ma servono di rado per carichi da founder." } }, { "@type": "Question", "name": "Posso delegare l’accesso a GSC senza condividere il mio account Google?", "acceptedAnswer": { "@type": "Answer", "text": "Sì. È esattamente lo scopo dei service account. Creane uno per integrazione, concedigli accesso Limitato alla proprietà e revoca senza toccare il tuo login." } }, { "@type": "Question", "name": "Quali binding di linguaggio supporta l’API GSC?", "acceptedAnswer": { "@type": "Answer", "text": "Ufficialmente: Python, Node, Java, PHP, Ruby, Go, .NET. Ufficiosamente: qualsiasi linguaggio capace di chiamare un endpoint REST con un Bearer token. Le strutture JSON sono identiche ovunque." } } ] } </script>