Error en el selector de fechas de Google Search Console: extraer datos via API

Error en el selector de fechas de Google Search Console: extraer datos via API

Última verificación: 16 de octubre de 2026
25 min de lectura
Guía
SEO técnico

#Por qué el selector de fechas de Google Search Console muestra el año 1969

El fallo del selector de fechas en el informe de rendimiento de Google Search Console pone de manifiesto la fragilidad de depender exclusivamente de una interfaz web. El 13 de octubre de 2026, Barry Schwartz describió en Search Engine Roundtable que, al elegir un intervalo personalizado, el informe rechaza el formulario con el mensaje Date can't be after 1969-12-31, es decir: la fecha no puede ser posterior al 31 de diciembre de 1969. El selector se corrigió, el 14 de octubre volvió a fallar y unas horas después funcionaba de nuevo. Mientras dura la avería, los analistas no pueden filtrar datos históricos desde el navegador.

Google no ha explicado la causa, pero la propia fecha da muchas pistas. En el estándar POSIX, el tiempo Unix es el número de segundos transcurridos desde la medianoche del 1 de enero de 1970 UTC. Si un campo de fecha en JavaScript recibe un valor null, una cadena vacía o un objeto sin inicializar, es fácil que acabe en el valor 0. En husos horarios con desfase negativo respecto a UTC, ese punto cero cae el 31 de diciembre de 1969; en los husos de Estados Unidos, entre las 16:00 y las 19:00. Por eso la explicación más probable es una marca de tiempo igual a cero que llegó al validador como límite superior del intervalo.

Con esa hipótesis, el validador compara la fecha elegida con un límite fijado en 1969. Cualquier fecha real es posterior, así que la regla considera el intervalo no válido y bloquea el gráfico.

Para portales de gran escala, tiendas online y agencias que gestionan decenas de sitios, una avería así paraliza el diagnóstico diario. El trabajo de un equipo SEO no puede depender de la estabilidad de una única aplicación de página única (SPA). La solución que garantiza la continuidad analítica es una integración directa con la Google Search Console API oficial.

                  Arquitectura de acceso a datos de Search Console
                  
    [Interfaz web GSC]                [Search Analytics API v1]
             │                                    │
    Errores de UI, 1000 filas            Endpoint REST estable
    Problema Unix Epoch (1969)           25 000 filas por petición
    Sin exportación automática           50 000 filas al día
             │                                    │
             ▼                                    ▼
       [Navegador web]                   [BD local / BigQuery]

#Cuáles son los límites del panel de Google Search Console frente a la API

El panel gráfico de Google Search Console se diseñó para consultar rápidamente los indicadores básicos, no para la ingeniería de datos avanzada. Incluso cuando el selector de fechas funciona con normalidad, la interfaz impone restricciones que distorsionan la visibilidad del dominio.

La primera restricción es el límite rígido de presentación. La tabla del panel de Search Console muestra como máximo 1000 filas. En portales con cientos de páginas y decenas de miles de consultas de long tail, el usuario solo ve una parte de las búsquedas que generan tráfico.

El segundo problema es la retención. Google Search Console elimina los registros con más de 16 meses de antigüedad. Sin un mecanismo automatizado de archivo, resulta imposible comparar resultados interanuales a lo largo de varios años. El tercer factor es la anonimización de las consultas poco frecuentes (anonymized queries): Google las filtra por motivos de privacidad en el panel, en la API y en la exportación a BigQuery. La API, en cambio, no tiene el tope de 1000 filas de la tabla, y las consultas lanzadas por separado para cada día devuelven hasta 50 000 filas al día por tipo de búsqueda (documentación de Google).

AspectoPanel web GSCSearch Analytics API
Límite de filas por petición1 000 filas25 000 filas
Número máximo de filas1 000 (tope rígido de la tabla)50 000 al día por tipo de búsqueda (paginación con startRow)
Periodo de conservación16 meses16 meses, más tiempo si se guardan en una base de datos propia
Exposición a errores del frontendAlta (errores de UI, bloqueos JS)Sin capa de UI (respuesta JSON de un endpoint REST)
Automatización de informesRequiere clics manualesAutomatización completa (cron, workers, CI)
Segmentación multidimensionalFiltros cruzados limitadosCombinación completa: page + query + device + country

Usar la API independiza los informes de los errores del frontend de Google y da a los desarrolladores el control sobre el archivo de datos.

#Cómo configurar una service account para la Google Search Console API

Para consultar la Search Analytics API sin iniciar sesión cada vez en el navegador mediante el flujo OAuth2 para usuarios finales, hay que configurar una cuenta de servicio (Service Account) en Google Cloud Platform. Una cuenta de servicio funciona como una identidad técnica autónoma con su propio par de claves criptográficas.

El primer paso es crear un proyecto en la consola de Google Cloud (console.cloud.google.com). Una vez creado, entramos en la sección APIs & Services, buscamos la Google Search Console API y pulsamos el botón para habilitarla.

El segundo paso es generar la cuenta de servicio en la sección IAM & Admin, dentro del apartado Service Accounts. Le damos un nombre único, por ejemplo gsc-analytics-collector. Tras crearla, abrimos la pestaña Keys y generamos una nueva clave privada en formato JSON. El archivo se descarga al disco local y contiene el identificador de la clave, el correo de la cuenta de servicio y la clave privada RSA en formato PEM.

{
  "type": "service_account",
  "project_id": "seo-enterprise-pipeline",
  "private_key_id": "6d7e8f9a0b1c2d3e",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDD...\n-----END PRIVATE KEY-----\n",
  "client_email": "gsc-analytics-collector@seo-enterprise-pipeline.iam.gserviceaccount.com",
  "client_id": "109283746510928374651",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token"
}

El tercer paso es autorizar la cuenta de servicio en Google Search Console. Copiamos la dirección client_email y abrimos Search Console para el dominio verificado. Entramos en Ajustes (Settings), elegimos Usuarios y permisos (Users and permissions) y añadimos el nuevo correo con el rol Restringido (Restricted) o Completo (Full). A partir de ese momento, la cuenta de servicio puede consultar los endpoints de Search Console para esa propiedad.

El archivo JSON con la clave privada nunca debe llegar a un repositorio público. Hay que añadirlo a .gitignore o pasar su contenido como variable de entorno cifrada en el servidor de producción.

#Cómo comprobar a qué propiedades de Search Console tiene acceso la cuenta de servicio

El motivo más habitual de un error 403 tras configurar la cuenta de servicio es una discrepancia entre la dirección de la propiedad en el script y la que conoce Search Console. En lugar de adivinar, conviene preguntar a la API. El método sites.list devuelve la lista de propiedades a las que tiene acceso la cuenta, y cada entrada incluye dos campos: siteUrl, escrito exactamente como lo esperan los demás métodos, y permissionLevel (documentación del recurso sites).

El campo permissionLevel toma uno de cuatro valores: siteOwner (propietario), siteFullUser (permisos completos), siteRestrictedUser (permisos restringidos) y siteUnverifiedUser (usuario sin propiedad verificada). Si la propiedad no aparece en la lista, el correo de la cuenta de servicio no se añadió en los ajustes de Search Console o se añadió a otra propiedad, por ejemplo al prefijo https://www. en lugar de a la propiedad de dominio.

const { data } = await searchconsole.sites.list();
for (const site of data.siteEntry || []) {
  console.log(site.siteUrl, site.permissionLevel);
}
// sc-domain:wppoland.com siteFullUser

El mismo recurso ofrece los métodos add, delete y get. Para descargar datos basta con el ámbito webmasters.readonly y una llamada a list al arrancar el script: si el siteUrl devuelto no coincide con el configurado, el script puede terminar con un mensaje claro antes de lanzar cientos de peticiones fallidas.

#Cómo consultar sc-domain y prefijos de URL en Node.js

Al trabajar con la Search Console API, los desarrolladores suelen encontrarse con errores 403 o 404 causados por un formato incorrecto del identificador del sitio (siteUrl). Google gestiona dos tipos de propiedad:

  1. Propiedad de dominio (Domain Property): reúne todos los protocolos y subdominios. En la API, su identificador debe llevar el prefijo sc-domain:, por ejemplo sc-domain:wppoland.com.
  2. Propiedad de prefijo de URL (URL-prefix Property): se limita a un protocolo y una ruta concretos. En la API, su identificador es la URL completa con barra final, por ejemplo https://wppoland.com/es/.

En portales multilingües, la mejor práctica es consultar las propiedades de prefijo de cada versión de idioma, o bien la propiedad de dominio y filtrar después las rutas en el código.

El siguiente script en Node.js muestra una implementación completa de descarga de datos analíticos con paginación y guardado en un archivo JSON. Utiliza la librería oficial googleapis.

import fs from "node:fs";
import path from "node:path";
import { google } from "googleapis";

async function exportarDatosSearchConsole() {
  const rutaClave = path.resolve("./scripts/gsc-service-account.json");
  const creds = JSON.parse(fs.readFileSync(rutaClave, "utf8"));

  if (creds.private_key) {
    creds.private_key = creds.private_key.replace(/\\n/g, "\n");
  }

  const auth = new google.auth.GoogleAuth({
    credentials: creds,
    scopes: ["https://www.googleapis.com/auth/webmasters.readonly"],
  });

  const cliente = await auth.getClient();
  const searchconsole = google.searchconsole({ version: "v1", auth: cliente });

  const siteUrl = "sc-domain:wppoland.com";

  // Margen de 3 dias para aguardar la consolidacion definitiva de metricas
  const fechaFin = new Date(Date.now() - 3 * 864e5).toISOString().slice(0, 10);
  const fechaInicio = new Date(Date.now() - 33 * 864e5).toISOString().slice(0, 10);

  console.log(`Iniciando descarga para ${siteUrl} desde ${fechaInicio} hasta ${fechaFin}`);

  const filasTotales = [];
  let startRow = 0;
  const limitePorPeticion = 25000;

  while (true) {
    const respuesta = await searchconsole.searchanalytics.query({
      siteUrl,
      requestBody: {
        startDate: fechaInicio,
        endDate: fechaFin,
        dimensions: ["page", "query", "device", "country"],
        rowLimit: limitePorPeticion,
        startRow,
      },
    });

    const filas = respuesta.data.rows || [];
    filasTotales.push(...filas);
    console.log(`Lote obtenido: ${filas.length} filas (Total: ${filasTotales.length})`);

    if (filas.length < limitePorPeticion) {
      break;
    }

    startRow += limitePorPeticion;
  }

  const archivoSalida = "./reports/gsc-performance-data.json";
  fs.mkdirSync(path.dirname(archivoSalida), { recursive: true });
  fs.writeFileSync(archivoSalida, JSON.stringify(filasTotales, null, 2), "utf8");

  console.log(`Proceso completado. Se guardaron ${filasTotales.length} filas en ${archivoSalida}`);
}

exportarDatosSearchConsole().catch((err) => {
  console.error("Error al consultar la Search Console API:", err.message);
  process.exit(1);
});

El código recorre las páginas de resultados sucesivas mediante el parámetro startRow. Cuando la respuesta de la API contiene menos filas que el límite declarado de 25 000, el bucle termina. Así se descarga el historial completo de consultas sin perder datos del long tail.

#Cómo descargar datos de Google Search Console con Python

Para ingenieros de datos y equipos que trabajan con Pandas y Jupyter, un script en Python es la herramienta más cómoda para extraer y limpiar datos de Search Console. El siguiente ejemplo descarga los datos desglosados por día y los guarda en el formato optimizado Parquet, que ocupa menos espacio que CSV y conserva los tipos de las columnas.

Para ejecutar el script se necesitan las librerías google-api-python-client, google-auth, pandas y pyarrow:

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

Implementación del script:

import datetime
import pandas as pd
from google.oauth2 import service_account
from googleapiclient.discovery import build

def descargar_metricas_search_console(site_url: str, dias_atras: int = 30) -> pd.DataFrame:
    archivo_credenciales = "scripts/gsc-service-account.json"
    credenciales = service_account.Credentials.from_service_account_file(
        archivo_credenciales,
        scopes=["https://www.googleapis.com/auth/webmasters.readonly"]
    )
    
    servicio = build("searchconsole", "v1", credentials=credenciales)
    
    fecha_fin = (datetime.date.today() - datetime.timedelta(days=3)).strftime("%Y-%m-%d")
    fecha_inicio = (datetime.date.today() - datetime.timedelta(days=dias_atras + 3)).strftime("%Y-%m-%d")
    
    registros = []
    start_row = 0
    row_limit = 25000
    
    while True:
        cuerpo = {
            "startDate": fecha_inicio,
            "endDate": fecha_fin,
            "dimensions": ["date", "page", "query", "country", "device"],
            "rowLimit": row_limit,
            "startRow": start_row
        }
        
        respuesta = servicio.searchanalytics().query(
            siteUrl=site_url,
            body=cuerpo
        ).execute()
        
        filas = respuesta.get("rows", [])
        if not filas:
            break
            
        for f in filas:
            registros.append({
                "date": f["keys"][0],
                "page": f["keys"][1],
                "query": f["keys"][2],
                "country": f["keys"][3],
                "device": f["keys"][4],
                "clicks": f["clicks"],
                "impressions": f["impressions"],
                "ctr": f["ctr"],
                "position": round(f["position"], 2)
            })
            
        print(f"Descargadas {len(filas)} filas (startRow={start_row})")
        if len(filas) < row_limit:
            break
            
        start_row += row_limit
        
    df = pd.DataFrame(registros)
    return df

if __name__ == "__main__":
    propiedad = "sc-domain:wppoland.com"
    df_resultado = descargar_metricas_search_console(propiedad, dias_atras=60)
    
    if not df_resultado.empty:
        df_resultado["date"] = pd.to_datetime(df_resultado["date"])
        df_resultado.to_parquet("reports/gsc_performance.parquet", index=False)
        print(f"Exportacion exitosa: {len(df_resultado)} registros guardados en Parquet.")
    else:
        print("No se encontraron registros.")

Guardar los datos en el formato columnar Parquet permite agregar y agrupar rápidamente las consultas por categorías de producto o plantillas de página de WordPress sin cargar la memoria del servidor.

#Cómo obtener datos recientes y por horas de la Search Console API

Los scripts anteriores omiten los tres últimos días porque Google indica que los datos suelen estar disponibles al cabo de 2 o 3 días (guía para obtener todos los datos). La misma guía recomienda una prueba sencilla: una consulta con la dimensión date para los últimos 10 días muestra cuál es el último día disponible.

El parámetro dataState decide si la API devuelve datos preliminares (documentación del método query):

Valor de dataStateQué devuelve la API
final (o sin parámetro)Solo datos consolidados
allTambién datos recientes que aún pueden cambiar
hourly_allDatos desglosados por horas, parciales, para usar con la dimensión hour

Con dataState: "all" y agrupación por fecha, la respuesta incluye en los metadatos el campo first_incomplete_date. Todos los valores posteriores a esa fecha todavía pueden variar de forma apreciable, así que el script de archivo debe guardarlos aparte o sobrescribirlos en la siguiente ejecución. Las horas de los metadatos se expresan en la zona America/Los_Angeles, algo que importa al cruzar los datos con los registros de un servidor en España.

Google añadió la dimensión hour el 9 de abril de 2025. El panel muestra datos por horas solo de las últimas 24 horas, mientras que la API los devuelve para un máximo de 10 días (anuncio en Google Search Central Blog). Esto permite comparar el último día con el mismo día de la semana anterior, por ejemplo tras publicar una entrada o desplegar una plantilla nueva.

{
  "startDate": "2026-10-15",
  "endDate": "2026-10-15",
  "dataState": "hourly_all",
  "dimensions": ["hour"]
}

Las claves de la respuesta tienen la forma 2026-10-15T00:00:00-07:00, es decir, la hora en la zona de Los Ángeles con su desfase. Antes de guardarlas en la base de datos conviene convertirlas a UTC.

#Cómo filtrar páginas y consultas en la Search Analytics API

Una consulta sin filtros devuelve todo el tráfico de la propiedad. En un portal multilingüe se suele necesitar un fragmento, por ejemplo solo las direcciones bajo /es/. Para ello sirve la matriz dimensionFilterGroups. Se puede filtrar por las dimensiones country, device, page, query y searchAppearance, y los operadores disponibles son (documentación del método query):

  • equals (por defecto) y notEquals: coincidencia exacta, con distinción entre mayúsculas y minúsculas para page y query,
  • contains y notContains: coincidencia parcial sin distinguir mayúsculas y minúsculas,
  • includingRegex y excludingRegex: expresión regular con sintaxis RE2.
{
  "startDate": "2026-09-01",
  "endDate": "2026-09-30",
  "dimensions": ["page", "query"],
  "type": "web",
  "dimensionFilterGroups": [{
    "filters": [
      { "dimension": "page", "operator": "includingRegex", "expression": "^https://wppoland\\.com/es/" },
      { "dimension": "query", "operator": "notContains", "expression": "wppoland" }
    ]
  }],
  "rowLimit": 25000
}

El segundo filtro descarta las consultas de marca, un paso habitual antes de analizar el long tail. El parámetro type sustituyó al obsoleto searchType y acepta los valores web (por defecto, la pestaña Todo sin Discover ni Google News), image, video, news (la pestaña Noticias), discover y googleNews. Cada tipo debe descargarse con una consulta independiente.

El parámetro aggregationType determina si las métricas se calculan por propiedad (byProperty) o por URL (byPage); el valor por defecto auto deja la elección a Google. El valor byProperty no funciona con los tipos discover y googleNews.

#Por qué la suma de la API no coincide con el gráfico de Search Console

Tras la primera exportación, casi todos los equipos observan que la suma de clics de las filas es inferior a la cifra del gráfico del panel. El script funciona correctamente: Google describe tres causas (guía para obtener todos los datos):

  1. La API ofrece como máximo 50 000 filas al día por tipo de búsqueda, ordenadas por clics. En sitios grandes, la cola de consultas por debajo de ese umbral no llega a la respuesta.
  2. Al agrupar por las dimensiones page o query, el sistema puede omitir parte de los datos para que el cálculo siga siendo viable.
  3. Las impresiones, los clics, la posición y el CTR se calculan de forma distinta al agregar por página que al agregar por propiedad.

A esto se suman las consultas anonimizadas, que no aparecen en ninguna fuente. La conclusión práctica: toma los totales de tráfico de una consulta sin las dimensiones page y query (solo date) y trata el desglose por consultas como una muestra ordenada por clics. Google también recomienda descargar los datos día a día y paginar de 25 000 en 25 000 filas hasta obtener una página vacía, por separado para cada tipo de búsqueda.

#Cómo guardar los datos de Google Search Console en Google BigQuery

La solución más resistente a fallos para sitios grandes es la exportación automática de los datos de Google Search Console al almacén Google BigQuery. Google lanzó Bulk Data Export el 21 de febrero de 2023: el mecanismo envía cada día un volcado de los datos de rendimiento al proyecto de BigQuery indicado (anuncio en Google Search Central Blog).

Ventajas de este enfoque:

  1. Sin el límite de 16 meses: los datos guardados en BigQuery se conservan todo el tiempo que los necesites.
  2. La exportación no está sujeta al límite diario de filas de la API. Google solo filtra las consultas anonimizadas, por motivos de privacidad.
  3. Posibilidad de cruzar los datos de Search Console con las tablas de la base de datos de WordPress (pedidos de WooCommerce, carritos, conversiones).

La exportación se configura en dos pasos. En Google Cloud Console se habilita la BigQuery API en el proyecto y se conceden permisos a la cuenta de servicio de Search Console. En los ajustes de Search Console se indican el identificador del proyecto y la ubicación del conjunto de datos. Solo el propietario de la propiedad puede configurar la exportación. Search Console simula primero la exportación; si la simulación tiene éxito, todos los propietarios reciben un correo y las exportaciones periódicas comienzan en un plazo de 48 horas. Si hay un error, la alerta aparece de inmediato.

La exportación crea tres tablas:

  • searchdata_site_impression: datos agregados por propiedad, con consulta, país, tipo de búsqueda y dispositivo.
  • searchdata_url_impression: datos agregados por URL, con el detalle de las consultas y de los resultados enriquecidos.
  • ExportLog: registro de los datos que llegaron a la base de datos cada día. Las exportaciones fallidas no se anotan aquí.

Ejemplo de consulta SQL en BigQuery que identifica páginas con muchas impresiones y un CTR bajo (candidatas a optimizar metaetiquetas y encabezados):

SELECT
  url,
  query,
  SUM(impressions) AS total_impressions,
  SUM(clicks) AS total_clicks,
  ROUND(SAFE_DIVIDE(SUM(clicks), SUM(impressions)) * 100, 2) AS calculated_ctr,
  ROUND(SUM(sum_position) / SUM(impressions) + 1, 1) AS avg_position
FROM
  `empresa-analytics.searchconsole.searchdata_url_impression`
WHERE
  data_date >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
  AND country = 'esp'
GROUP BY
  url,
  query
HAVING
  total_impressions > 500
  AND calculated_ctr < 2.0
  AND avg_position BETWEEN 3.0 AND 10.0
ORDER BY
  total_impressions DESC
LIMIT 100;

La tabla searchdata_url_impression contiene, entre otras, las columnas data_date, url, query, country, search_type, impressions, clicks y sum_position, además de indicadores de los tipos de resultados enriquecidos (el ejemplo de Google filtra search_type = 'WEB'). La columna sum_position cuenta la posición desde cero, por lo que la posición media se calcula como SUM(sum_position) / SUM(impressions) + 1, igual que en el ejemplo de Google. La consulta señala términos de la primera página de resultados que obtienen menos del 2 por ciento de clics. Son candidatos para probar un nuevo título, un nuevo encabezado H1 y una nueva descripción; el efecto del cambio hay que medirlo en las semanas siguientes, sin darlo por supuesto.

                  Pipeline Search Console hacia BigQuery
                  
   [Google Search Console] ──(Bulk Export)──> [Google BigQuery]
                                                    │
                                                    ├──> [Panel Looker Studio]
                                                    ├──> [Auditoria de caidas de ranking]
                                                    └──> [Cruce con pedidos WooCommerce]

#Cuándo elegir la Search Analytics API y cuándo Bulk Data Export

Ambas fuentes ofrecen las mismas métricas, pero resuelven problemas distintos. Google escribe en el anuncio de la exportación que resulta especialmente útil para sitios grandes con decenas de miles de páginas o con tráfico procedente de decenas de miles de consultas al día, mientras que los sitios pequeños y medianos tienen acceso a todos sus datos mediante la interfaz, el conector de Looker Studio o la Search Analytics API (Google Search Central Blog).

CriterioSearch Analytics APIBulk Data Export
Límite de filas25 000 por petición, 50 000 al día por tipo de búsquedaSin límite diario de filas
Consultas anonimizadasOmitidasOmitidas
FrescuraDatos preliminares (all) y por horas (hourly_all)Volcado diario
Quién puede configurarloCualquier usuario con acceso a la propiedadSolo el propietario de la propiedad
Destino de los datosDonde los guarde tu scriptTu proyecto de BigQuery

En la práctica, ambos enfoques se complementan. La exportación a BigQuery queda como archivo y fuente para analizar el long tail, y un script ligero sobre la API con dataState: "hourly_all" vigila las últimas horas tras una publicación o un despliegue. Para un blog pequeño en WordPress, el script de las secciones anteriores, ejecutado una vez al día mediante cron, suele bastar.

#Cómo vincular los datos de Search Console con la base de datos de WordPress

Los datos en bruto de Search Console adquieren su mayor valor de negocio cuando se vinculan con la estructura interna de contenidos del CMS. La exportación tradicional de Search Console solo contiene URL completas como cadenas de texto. No indica el tipo de entrada (post, producto de WooCommerce, landing page), la fecha de la última modificación en el editor Gutenberg ni el autor del texto.

La integración consiste en traducir la ruta de la URL al identificador del objeto en WordPress (post_id). En WordPress se usa para ello la función url_to_postid($url) o una búsqueda directa del slug en la tabla wp_posts.

El siguiente fragmento en PHP muestra cómo asignar los datos de consultas importados desde la API al producto o artículo correspondiente de la base de datos:

<?php
/**
 * Vinculacion de metricas de Search Console con entradas de WordPress
 */
declare(strict_types=1);

namespace WPPoland\Analytics;

class SearchConsoleIngestor {
    
    public function registrarMetricasUrl(string $url, int $clics, int $impresiones, float $posicion): void {
        $ruta = wp_parse_url($url, PHP_URL_PATH);
        if (!$ruta) {
            return;
        }

        $postId = url_to_postid($url);
        
        if ($postId === 0) {
            $postId = $this->resolverTerminoTaxonomia($ruta);
        }

        if ($postId > 0) {
            update_post_meta($postId, '_gsc_clics_30d', $clics);
            update_post_meta($postId, '_gsc_impresiones_30d', $impresiones);
            update_post_meta($postId, '_gsc_posicion_promedio', $posicion);
            update_post_meta($postId, '_gsc_fecha_sincronizacion', current_time('mysql', true));
        }
    }

    private function resolverTerminoTaxonomia(string $ruta): int {
        global $wpdb;
        $slugLimpio = trim($ruta, '/');
        $fragmentos = explode('/', $slugLimpio);
        $slugTermino = end($fragmentos);

        $termId = $wpdb->get_var($wpdb->prepare(
            "SELECT t.term_id FROM {$wpdb->terms} t 
             JOIN {$wpdb->term_taxonomy} tt ON t.term_id = tt.term_id 
             WHERE t.slug = %s LIMIT 1",
            $slugTermino
        ));

        return $termId ? (int)$termId : 0;
    }
}

Gracias a esta vinculación, el equipo editorial ve en el panel de WordPress el número exacto de impresiones y la posición de cada página. Si tras actualizar la plantilla o desplegar código nuevo la posición media de un artículo cae del puesto 4 al 18, el sistema puede generar automáticamente un aviso en un canal de Slack o crear una tarea de auditoría para el desarrollador.

En arquitecturas basadas en WordPress headless o en generadores de sitios estáticos, los datos de la Search Console API pueden descargarse durante la compilación del sitio (build time) y servir para generar secciones dinámicas con los temas más populares y los artículos relacionados.

#Cómo comprobar el estado de indexación de las URL exportadas con la URL Inspection API

Una caída de clics de una entrada en los datos de Search Analytics no indica si la página sigue en el índice. La respuesta la da la URL Inspection API, que usa la misma cuenta de servicio y los mismos ámbitos (webmasters o webmasters.readonly). La petición es POST https://searchconsole.googleapis.com/v1/urlInspection/index:inspect con los campos inspectionUrl (la dirección completa, que debe pertenecer a la propiedad), siteUrl (en el mismo formato que antes: sc-domain: o un prefijo con barra final) y el opcional languageCode (documentación del método inspect).

El resultado indexStatusResult incluye, entre otros (descripción de UrlInspectionResult):

CampoQué significa
verdictResultado general: si la URL está indexada
coverageStateSi Google encontró e indexó la página
indexingStateSi una regla noindex bloquea la indexación
robotsTxtStateSi robots.txt bloquea el rastreo
lastCrawlTimeCuándo el rastreador principal descargó la URL por última vez
googleCanonical y userCanonicalLa canónica elegida por Google y la declarada en la página

En WordPress encaja bien con la clase SearchConsoleIngestor de la sección anterior: cuando la posición de una entrada cae, el script inspecciona su URL y guarda coverageState y googleCanonical en los metadatos de la entrada. Una discrepancia entre la canónica de Google y la del plugin SEO suele explicar la caída más rápido que el análisis de consultas. El límite, sin embargo, es bajo: 2000 peticiones al día y 600 por minuto por sitio (límites de la Search Console API), así que conviene inspeccionar solo las URL con señales de caída, no todo el sitemap. El método muestra la versión del índice de Google y no prueba la URL en directo. La diferencia entre esta herramienta y la Indexing API se explica en nuestra guía de GSC e Indexing API.

#Cómo gestionar los límites de cuota y los errores de la API

La Search Analytics API tiene límites descritos en la documentación de Google. Superarlos produce un error de cuota y el script tiene que esperar:

Ámbito del límiteValor
Por sitio (consultas sobre la misma propiedad)1 200 peticiones por minuto
Por usuario (consultas desde la misma cuenta)1 200 peticiones por minuto
Por proyecto de Google Cloud40 000 peticiones por minuto y 30 000 000 al día

Aparte funciona un límite de carga (load quota), calculado en ventanas de 10 minutos y de un día. Según Google, las consultas son costosas cuando se agrupa o filtra por página o por consulta, y la carga crece con la longitud del intervalo de fechas. Google desaconseja expresamente descargar repetidamente los mismos datos, por ejemplo todo el mes anterior en cada ejecución. Por eso el script de archivo debe descargar solo los días que faltan.

Para garantizar la fiabilidad de los scripts que descargan millones de registros en grandes tiendas online, hay que implementar tres mecanismos de defensa:

  1. Retroceso exponencial (Exponential Backoff): si la respuesta devuelve un error 429 o 503, el script no se detiene, sino que espera un número creciente de segundos (2 elevado a n más un jitter aleatorio) antes de repetir la petición.
  2. Fragmentación por días (Daily Date Chunking): en lugar de descargar un año entero en una sola llamada con una paginación enorme, la tarea se divide en bucles de un día. Si una petición falla por un error de red puntual, solo se repite el día que falta.
  3. Reutilización de tokens de autorización: las librerías cliente de Google renuevan automáticamente el token OAuth2 a partir de la clave de la cuenta de servicio, pero en entornos sin servidor (AWS Lambda, Cloudflare Workers) hay que asegurarse de que el token no se genere de nuevo para cada petición HTTP.

El siguiente fragmento muestra un mecanismo de consulta resistente con reintentos:

async function ejecutarConReintentos(accionApi, maxReintentos = 5) {
  let intento = 0;
  while (intento < maxReintentos) {
    try {
      return await accionApi();
    } catch (err) {
      intento++;
      const esLimiteCuota = err.code === 429 || err.status === 429;
      const esFalloServidor = err.code >= 500 && err.code < 600;

      if ((esLimiteCuota || esFalloServidor) && intento < maxReintentos) {
        const demoraMs = Math.pow(2, intento) * 1000 + Math.random() * 500;
        console.warn(`Error ${err.code}. Reintentando en ${Math.round(demoraMs)} ms (Intento ${intento}/${maxReintentos})...`);
        await new Promise((resolve) => setTimeout(resolve, demoraMs));
      } else {
        throw err;
      }
    }
  }
}

Estos tres mecanismos hacen que el archivo de datos SEO funcione con independencia de los errores del panel de Google Search Console en el navegador.

#Cómo gestionar los datos SEO con la Search Console API

Los errores de la interfaz gráfica, como la avería del selector de fechas que hace retroceder el calendario a 1969, recuerdan que los datos analíticos de un sitio deben residir en los sistemas de su propietario, no solo en un panel externo.

Implantar un pipeline propio basado en la Search Console API aporta beneficios medibles:

  • Hasta 50 000 filas al día por tipo de búsqueda en lugar de las 1000 filas de la tabla del panel y, con Bulk Data Export, el conjunto completo sin las consultas anonimizadas.
  • Informes independientes de los errores del frontend de Google.
  • Protección frente a la pérdida de datos históricos al cumplirse los 16 meses gracias al archivo en BigQuery o en una base de datos relacional.
  • Correlación directa del tráfico con los ingresos de la tienda WooCommerce y con los cambios en el código de la plantilla de WordPress.

Para implantar analítica avanzada, automatizar informes o auditar técnicamente su sitio, conviene consultar a un desarrollador WordPress que conecte el pipeline de datos con la arquitectura de su tienda y lo proteja frente a fallos. Para asesoría técnica, póngase en contacto con nuestro equipo.

Siguiente paso

Transforma el artículo en una implementación real

Este bloque refuerza el enlazado interno y lleva al lector al siguiente paso más útil dentro de la arquitectura del sitio.

¿Quieres implementar esto en tu sitio?

Si la visibilidad en Google y en sistemas de IA importa, puedo estructurar contenido, FAQ, schema y enlazado interno para SEO, GEO y AEO.

Cluster relacionado

Explora otros servicios WordPress y base de conocimiento

Refuerza tu negocio con soporte técnico profesional en áreas clave del ecosistema WordPress.

Por qué el selector de fechas de Google Search Console se bloquea en 1969-12-31#
Google no ha publicado la causa. La propia fecha apunta a una marca de tiempo igual a cero, es decir, la medianoche del 1 de enero de 1970 UTC (Unix epoch), que en husos horarios al oeste de Greenwich se muestra como el 31 de diciembre de 1969. Search Engine Roundtable describió el error el 13 de octubre de 2026; el selector se corrigió, el 14 de octubre volvió a fallar y ese mismo día funcionó de nuevo.
Cuántas filas de datos permite descargar la Google Search Console API#
Una sola llamada al método searchanalytics.query devuelve hasta 25 000 filas (1000 por defecto). El parámetro startRow permite paginar los resultados, pero Google ofrece a través de la API como máximo 50 000 filas al día por tipo de búsqueda, ordenadas por clics. Un conjunto más completo, sin las consultas anonimizadas, lo proporciona Bulk Data Export a BigQuery.
Cuál es la diferencia entre consultar sc-domain y un prefijo de URL en la API#
La sintaxis sc-domain agrega todo el tráfico de subdominios y protocolos. Una propiedad de prefijo de URL se restringe a una ruta y protocolo específicos, requiriendo una barra inclinada final en el parámetro siteUrl.
Cuánto tiempo guarda Google los datos en Search Console#
Search Console almacena las métricas de rendimiento durante 16 meses. Pasado ese tiempo, los registros se eliminan definitivamente. Exportar los datos a BigQuery o bases de datos locales garantiza análisis comparativos interanuales (YoY).
Cómo se conectan los datos de la Search Console API con WordPress#
El script asocia la URL de la página devuelta por la API con el registro en wp_posts utilizando la función url_to_postid. Esto permite supervisar impresiones orgánicas y caídas de posicionamiento directamente en el panel de WordPress.

¿Necesitas un FAQ adaptado a tu sector y mercado? Preparamos una versión alineada con tus objetivos de negocio.

Hablemos

Artículos Relacionados