Google Search Console es la herramienta por excelencia para los SEO y webmasters. En ella, Google nos ofrece una gran cantidad de información relacionada con el sitio web y su rendimiento en el buscador.
Aunque la herramienta puede ser suficiente en muchas ocasiones, ésta cuenta con algunas limitaciones que nos impedirán o dificultarán la realización de determinados análisis. En este artículo, veremos como podemos saltarnos estas limitaciones utilizando la API de Google Search Console.
Limitaciones de Google Search Console
Aunque Google sigue mejorando la herramienta y nos trae novedades cada cierto tiempo, la interfaz de Google Search Console sigue contando con limitaciones, especialmente a la hora de analizar el rendimiento de la web en la búsqueda orgánica.
La primera limitación con la que nos encontramos en la interfaz a la hora de acceder a la información del apartado de Rendimiento de la herramienta es que esta solo nos ofrece los últimos 16 meses de información. No podrás comprobar el rendimiento del sitio web en un periodo de tiempo anterior a este.
Desde la interfaz solo es posible acceder a 1000 filas de información. Además, al exportar la información manualmente también se aplica ese límite, por lo que cualquier término de consulta o página que no entre en ese rango no será reportado.
Por último, los informes de términos de consulta y páginas se encuentran en pestañas separadas, lo cual dificulta el análisis de los datos ya que tienes que filtrar manualmente cada una de las páginas que quieres analizar y después moverte a la pestaña de consultas para poder ver las keywords. Además, al exportar los datos ambos informes se descargan por separado impidiendo que crucemos una dimensión con otra fuera de la herramienta.
¿Qué es la API de Search Console y qué nos ofrece?
Como acabamos de ver, Google Search Console impone algunos límites en la exportación (máximo 1000 filas y 16 meses de datos) y el análisis de los datos, principalmente en las páginas y las keywords para las que posiciona cada una de ellas.
La API de Search Console, en cambio, nos permite extraer, almacenar y transformar casi cualquier dato como queramos. Aunque en este artículo vamos a centrarnos en la parte de análisis, debes saber que la API cuenta con otras funcionalidades, como la posibilidad de ver, agregar o quitar propiedades, gestionar mapas del sitio o inspeccionar URLs.
¿Cómo conectarse a la API de Google Search Console con Python?
Antes de empezar a trabajar con la API de Search Console, tendrás que seguir algunos pasos previos:
- Crea un nuevo proyecto en Google Cloud.
- Accede al apartado de APIs y servicios, y habilita Google Search Console API.
- Crea tus credenciales desde el apartado Credenciales. Tendrás que elegir el tipo de credencial ID de cliente de OAuth. Configura la pantalla de consentimiento y, en el último paso, selecciona la opción Aplicación de escritorio como tipo de aplicación.
- Una vez creadas las credenciales y la pantalla de consentimiento de OAuth, guarda el ID de cliente y el Secreto de cliente que se han generado.
Ahora que ya tenemos el ID y el secreto de cliente pasamos al editor de código para comenzar a trabajar con la API de Search Console. Lo primero que vamos a hacer es cargar las librerías que vamos a utilizar para este ejemplo:
# Cargo las librerías
from oauth2client.client import OAuth2WebServerFlow
from oauth2client.tools import run_flow
from oauth2client.file import Storage
from googleapiclient.discovery import build
import os
import pandas as pd
import plotly.express as px
En el caso de que no vayas a realizar la visualización de datos con Python y tan solo quieras extraer los datos para llevarlos a otra herramienta, no es necesario que importes la última librería.
El siguiente paso es cargar las credenciales que hemos obtenido antes y conectarnos a la API:
# Introducir el ID de cliente y el secreto de cliente del proyecto de Google Cloud
client_id = 'CLIENT_ID'
client_secret = 'CLIENT_SECRET'
oauth_scope = 'https://www.googleapis.com/auth/webmasters.readonly'
redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
# Creo la instancia de OAuth2WebServerFlow
flow = OAuth2WebServerFlow(client_id, client_secret, oauth_scope, redirect_uri)
# Ruta en la que se almacena el archivo credentials.dat
credentials_path = 'credentials.dat'
if os.path.exists(credentials_path):
# Cargo las credenciales del archivo
storage = Storage(credentials_path)
credentials = storage.get()
else:
# Ejecuto el flujo OAuth y almaceno las credenciales
credentials = run_flow(flow, Storage(credentials_path))
# Monto el servicio
service = build('searchconsole', 'v1', credentials=credentials)
En este paso tendrás que modificar las variables CLIENT_ID y CLIENT_SECRET por el ID y secreto que has obtenido en Google Cloud. Una vez ejecutes el código, se abrirá una nueva pestaña en tu navegador en la que aparecerá la pantalla de consentimiento. Además, se generará un archivo credentials.dat que evitará que tengas que acceder posteriormente a la pantalla de consentimiento.
Llegados a este punto, ya estarás conectado a la API de GSC. ¿Quieres comprobar que la conexión se ha llevado a cabo correctamente y saber cuales son las propiedades de Search Console a las que tienes acceso? Solo tienes que ejecutar este simple código:
# Obtengo una lista de las propiedades disponibles en mi cuenta de Google Search Console
property_list = service.sites().list().execute()
print(property_list)
Si todo está correcto, ya podemos realizar nuestra primera petición de datos a la API de Search Console. Cada petición o request nos devuelve un máximo de 25000 filas, por lo que vamos a utilizar un while loop para poder solicitar toda la información:
# Seleccionar la propiedad, el periodo de tiempo y las dimensiones a extraer
property_url = 'https://ejemplo.com/'
startDate = '2022-09-01'
endDate = '2022-11-31'
dimensions = ['date', 'device', 'country']
# Creo una lista vacía para almacenar las filas de la respuesta
data = []
# Defino startRow
startRow = 0
while startRow == 0 or startRow % 25000 == 0:
# Cuerpo de la petición a la API
request = {
'startDate': startDate,
'endDate': endDate,
'dimensions': dimensions,
'rowLimit': 25000,
'startRow': startRow
}
# Obtengo la respuesta de Google Search Console
response = service.searchanalytics().query(siteUrl=property_url, body=request).execute()
# Actualizo las filas
rows = response.get('rows', [])
startRow = startRow + len(rows)
# Añado las filas a la lista data
data.extend(rows)
Antes de ejecutar el código tendrás que modificar las cuatro variables que aparecen al principio. Introduce el dominio/propiedad del que quieres extraer los datos, el periodo de tiempo a analizar y las dimensiones que quieres obtener.
En este punto debes tener varias cosas en cuenta. Lo primero es que la API tiene unos límites de uso, por lo que es recomendable acotar las fechas de inicio y final, y no extraer datos a lo loco. Si consumes toda la cuota, la petición fallará y se indicará el error.
La selección de dimensiones también es importante. En este punto vas a tener que elegir qué dimensiones quieres obtener. Puedes elegir date, query, page, country y device. En cualquier caso, la petición te devolverá los clicks, impresiones, CTR y posición media de cada dimensión.
Aunque puedes combinar las dimensiones como quieras o incluso extraer todas a la vez, debes saber que al incluir las dimensiones query y/o page el consumo de recursos de procesamiento es mayor y Google descarta algunas filas de datos con el objetivo de reducir los tiempos de espera. Así pues, piensa bien que tipo de análisis vas a realizar antes de extraer los datos y, si no vas a necesitar alguna de esas dos dimensiones, no las solicites.
Estas dimensiones también puedes utilizarlas en la petición en forma de filtro para acotar la extracción de los datos. En este artículo de la documentación de Google puedes encontrar algunos ejemplos de peticiones con las que inspirarte.
Una vez extraídos los datos, vamos a almacenarlos en un DataFrame para poder trabajar con ellos más fácilmente:
# Creo un DataFrame a partir de la lista
df = pd.DataFrame([{
'date': row['keys'][0],
'device': row['keys'][1],
'country': row['keys'][2],
'clicks': row['clicks'],
'impressions': row['impressions'],
'ctr': row['ctr'],
'position': row['position']
} for row in data])
En este caso, estamos siguiendo el ejemplo anterior y estamos extrayendo las dimensiones date, device y country. Sin embargo, habrá que modificar los tres primeros key-values si elegimos diferentes dimensiones. Por ejemplo, si queremos extraer query y device necesitaríamos algo así:
# Creo un DataFrame a partir de la lista
df = pd.DataFrame([{
'query': row['keys'][0],
'device': row['keys'][1],
'clicks': row['clicks'],
'impressions': row['impressions'],
'ctr': row['ctr'],
'position': row['position']
} for row in data])
Siguiendo con el ejemplo anterior de la fecha, dispositivo y país, voy a extraer los datos entre septiembre y octubre del año pasado. En escasos segundos, he podido obtener 19771 filas de datos:
Como he mencionado antes, estos datos puedes guardarlos en un archivo CSV y llevártelos a cualquier otra herramienta para analizarlos. Para ello, tan solo tendrías que incluir lo siguiente:
# Exporto el DataFrame a un CSV
df.to_csv('data.csv')
Te dejo aquí el código completo y actualizado con el que puedes conectarte a la API de Search Console y exportar la información a un CSV. También encontrarás el archivo requirements.txt que incluye las librerías necesarias para que funcione el script. Recuerda que tendrás que incluir el ID y secreto de cliente, modificar las dimensiones que quieres recoger y adaptar acordemente los key-values del DataFrame.
Ejemplos de visualización de los datos extraídos con la API en Python
Una de las ventajas que ofrece Python es que puedes crear visualizaciones de datos desde el propio editor de código. A continuación, vamos a ver algunos ejemplos de visualizaciones simples que podemos generar de forma rápida. Para ello, vamos a utilizar la librería Plotly, que hemos cargado al principio, ya que nos permite crear gráficos interactivos.
El primer gráfico lo vamos a crear a partir de la request utilizada en el ejemplo anterior. Creamos un nuevo DataFrame llamado df_por_fecha a partir del anterior en el que vamos a agrupar los clicks e impresiones por fecha. Con este nuevo DataFrame generamos un gráfico que nos muestra los clicks e impresiones en el periodo de tiempo seleccionado.
# Creo un nuevo DataFrame agrupado por fecha
df_por_fecha = df.groupby('date')[['clicks', 'impressions']].sum().reset_index()
# Creo un gráfico de líneas con Plotly
fig = px.line(df_por_fecha, x='date', y=['clicks', 'impressions'], title='Clicks e Impresiones a lo largo del tiempo')
fig.show()
El gráfico que obtenemos al ejecutar el código es el siguiente:
Para el segundo ejemplo vamos a extraer las dimensiones date y page utilizando el mismo periodo de tiempo que antes. Además, en este caso vamos a incluir un filtro para que la llamada a la API solo nos devuelva las páginas que se están posicionando en España. El request body quedaría así:
request = {
'startDate': '2022-09-01',
'endDate': '2022-11-31',
'dimensions': ['date', 'page'],
'dimensionFilterGroups': [{'filters': [{'dimension': 'country', 'expression': 'esp', 'operator': 'equals'}]}],
'rowLimit': 25000,
'startRow': startRow
}
La petición nos genera 38491 filas, superando ampliamente el límite de 1000 que tiene la interfaz de Search Console. Ahora, generamos un nuevo DataFrame, también agrupado por fecha, que va a contar el número de páginas que tenemos posicionadas.
# Creo un nuevo DataFrame agrupado por fecha
df_contar_paginas = df.groupby('date')['page'].count().reset_index().rename(columns={'page': 'count_pages'})
# Creo un gráfico de líneas con Plotly
fig = px.line(df_contar_paginas, x='date', y='count_pages', title='Número de páginas únicas posicionadas')
fig.show()
Este es el gráfico obtenido al ejecutar el código:
Por último, vamos a ver un ejemplo un poco más complicado. Extraemos todas las consultas realizadas por los usuarios en estos 3 meses (¡218062 keywords!) utilizando este request body:
request = {
'startDate': '2022-09-01',
'endDate': '2022-11-31',
'dimensions': ['date', 'query'],
'rowLimit': 25000,
'startRow': startRow
}
A continuación, creamos una nueva columna en el DataFrame que recoja si se trata de una palabra clave de marca o no. Para ello, tenemos que incluir las keywords que consideramos de marca en la lista keywords_marca y creamos la nueva columna con una expresión lambda.
# Lista de keywords consideradas de marca
keywords_marca = ['keyword 1', 'keyword 2', 'keyword 3', 'keyword 4']
# Creo una nueva columna en el DataFrame para almacenar el resultado de la expresión lambda
df['tipo_keyword'] = df['query'].apply(lambda query: 'branded' if any(term in query for term in keywords_marca) else 'non_branded')
Ahora solo nos queda agrupar por fecha y tipo de keyword, y generar el gráfico:
# Creo un nuevo DataFrame agrupado por fecha y por tipo de keyword
df_keyword_marca = df.groupby(['date', 'tipo_keyword'])['clicks'].sum().reset_index()
# Creo un gráfico de líneas con Plotly
fig = px.line(df_keyword_marca, x='date', y='clicks', color='tipo_keyword', title='Número de clicks por tipo de keyword')
fig.show()
Aquí tenemos el gráfico que hemos obtenido:
Estos son solo algunos ejemplos de gráficos simples que puedes generar con Python, aunque, como he comentado antes, podrías simplemente guardarte los datos en un CSV y llevarlos a otra herramienta de visualización, como Looker Studio, Tableau o Power BI.
Como puedes ver, la API de Search Console nos ofrece una libertad total a la hora de extraer y analizar los datos relacionados con el rendimiento de un sitio web en el buscador de Google.
Aunque es cierto que la configuración inicial puede llevar algo de tiempo, la extracción es muy rápida y sencilla una vez tienes todo listo. Incluso puedes automatizar el script para que se exporten a diario los nuevos datos llegados a la herramienta sin tener que hacer nada.
Espero que esta introducción a la API de Google Search Console te sirva de ayuda y te anime a explorar el nuevo abanico de posibilidades que te abre. Y si tienes cualquier duda, puedes utilizar la sección de comentarios o escribirme directamente por redes sociales.