Saltar al contenido
ShopentlyLearn

Listar · Consultas — Análisis y reglas de búsqueda

Consulta los datos de «Análisis y reglas de búsqueda». El resultado depende de los parámetros de esta operación.

GET/api/v1/search/queries

Autenticación
Bearer
Disponible desde
STANDARD
Permisos necesarios
search.analytics:read

Ejemplos de código

Ejemplo de solicitud

cURL

: "${SHOPENTLY_SHOP_URL:?}"

curl --disable --globoff --fail-with-body --silent --show-error \
  --proto '=https' --connect-timeout 5 --max-time 30 \
  --request GET \
  --header "Authorization: Bearer ${SHOPENTLY_ACCESS_TOKEN:?}" \
  --url "${SHOPENTLY_SHOP_URL%/}"'/api/v1/search/queries?limit=20'

PHP

<?php
declare(strict_types=1);

$baseUrl = rtrim(getenv('SHOPENTLY_SHOP_URL') ?: '', '/');
$origin = parse_url($baseUrl);
if (!$origin || ($origin['scheme'] ?? '') !== 'https' || empty($origin['host']) ||
    isset($origin['user'], $origin['pass']) || isset($origin['user']) || isset($origin['path']) ||
    isset($origin['query']) || isset($origin['fragment'])) {
    throw new RuntimeException('SHOPENTLY_SHOP_URL must be an HTTPS origin');
}
$credential = getenv('SHOPENTLY_ACCESS_TOKEN') ?: '';
if ($credential === '' || strpbrk($credential, "\r\n") !== false) {
    throw new RuntimeException('Invalid credential');
}
$headers = [];
$headers[] = 'Authorization: Bearer ' . $credential;
$responseHeaders = [];
$handle = curl_init($baseUrl . '/api/v1/search/queries?limit=20');
curl_setopt_array($handle, [
    CURLOPT_CUSTOMREQUEST => 'GET',
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_FOLLOWLOCATION => false,
    CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
    CURLOPT_SSL_VERIFYPEER => true,
    CURLOPT_SSL_VERIFYHOST => 2,
    CURLOPT_CONNECTTIMEOUT => 5,
    CURLOPT_TIMEOUT => 30,
    CURLOPT_HEADERFUNCTION => static function ($handle, string $line) use (&$responseHeaders): int {
        if (str_contains($line, ':')) {
            [$name, $value] = explode(':', $line, 2);
            $responseHeaders[strtolower(trim($name))] = trim($value);
        }
        return strlen($line);
    },
]);
$raw = curl_exec($handle);
$status = curl_getinfo($handle, CURLINFO_RESPONSE_CODE);
$error = curl_error($handle);
curl_close($handle);
if ($raw === false) {
    throw new RuntimeException('Transport error: ' . $error);
}
if ($status < 200 || $status >= 300) {
    throw new RuntimeException('HTTP ' . $status . '; request_id=' .
        ($responseHeaders['x-request-id'] ?? '') . '; retry_after=' . ($responseHeaders['retry-after'] ?? ''));
}
$result = $raw === '' ? null : json_decode($raw, true, 512, JSON_THROW_ON_ERROR | JSON_BIGINT_AS_STRING);
echo json_encode($result, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE), PHP_EOL;

Python

from contextlib import ExitStack
import json
import os
from urllib.parse import urlsplit

import requests  # python -m pip install requests

base_url = os.environ["SHOPENTLY_SHOP_URL"].rstrip("/")
origin = urlsplit(base_url)
if origin.scheme != "https" or not origin.hostname or origin.username or origin.password or origin.path or origin.query or origin.fragment:
    raise ValueError("SHOPENTLY_SHOP_URL must be an HTTPS origin")
credential = os.environ['SHOPENTLY_ACCESS_TOKEN']
if not credential or "\r" in credential or "\n" in credential:
    raise ValueError("Invalid credential")
headers = {}
headers["Authorization"] = 'Bearer' + " " + credential
body = None
if body is not None:
    headers["Content-Type"] = "application/json"

with ExitStack() as stack:
    session = stack.enter_context(requests.Session())
    files = None
    if False:
        image = stack.enter_context(open(os.environ["SHOPENTLY_IMAGE_FILE"], "rb"))
        if os.fstat(image.fileno()).st_size > 5242880:
            raise ValueError("Image exceeds 5 MiB")
        files = {"file": ("article.png", image, "image/png")}
    response = session.request(
        'GET', base_url + '/api/v1/search/queries?limit=20', headers=headers,
        data=body.encode("utf-8") if body is not None else None, files=files,
        timeout=(5, 30), allow_redirects=False,
    )
    if not 200 <= response.status_code < 300:
        raise RuntimeError(f"HTTP {response.status_code}; request_id={response.headers.get('X-Request-ID', '')}; retry_after={response.headers.get('Retry-After', '')}")
    if False:
        if response.headers.get("Content-Type") != "image/webp" or len(response.content) > 5242880:
            raise ValueError("Unexpected image response")
        with open(os.environ["SHOPENTLY_OUTPUT_FILE"], "xb") as output:
            output.write(response.content)
    else:
        result = response.json() if response.content else None
        print(json.dumps(result, ensure_ascii=False, indent=2))

Ejemplo de respuesta 200

JSON
{
  "data": [
    {
      "clicks": 1,
      "last_seen_at": "2026-01-01T12:00:00Z",
      "query_display": "example",
      "query_hash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
      "searches": 1,
      "zero_results": 1
    }
  ],
  "meta": {
    "pagination": {
      "has_more": false,
      "limit": 20,
      "next_cursor": null
    },
    "period": {
      "as_of": "2026-01-02T00:00:00Z",
      "days": 1,
      "started_at": "2026-01-01T00:00:00Z"
    },
    "request_id": "example"
  }
}

Cómo funciona

  • GET /api/v1/search/overview y /api/v1/search/queries muestran estadísticas resumidas y consultas agrupadas.
  • Obtén las apariciones de una consulta mediante su query_hash.
  • Los periodos de informe admiten 7, 30 o 90 días, con los filtros indicados para cada endpoint.
  • Las reglas de búsqueda relacionan frases con productos y categorías seleccionados y se pueden crear, consultar, actualizar o eliminar.
  • Las reglas y el análisis tienen permisos independientes; leer estadísticas de búsqueda no concede acceso a la configuración.

Parámetros

Parámetros de consulta

limitNúmero enteroOpcional

Número máximo de registros en esta página.

minimum: 1maximum: 100
Valor predeterminado: 50Ejemplo: 20
cursorCadena de texto nullOpcional

Valor de continuación opaco devuelto por la página anterior.

Cadena de texto:minLength: 1maxLength: 1024
daysNúmero enteroOpcional

Periodo del informe en días.

Restricciones
enum
[7, 30, 90]
Valor predeterminado: 30
localeCadena de texto nullOpcional

Idioma seleccionado para esta solicitud.

Cadena de texto:minLength: 2maxLength: 20
Restricciones · Cadena de texto 1
pattern
"^[a-z]{2,3}(?:-[A-Za-z0-9]{2,8})*$"
sourceCadena de texto nullOpcional

Origen de la actividad registrada.

Restricciones · Cadena de texto 1
enum
["results", "autocomplete"]
market_idCadena de texto nullOpcional

Identificador del mercado devuelto por el endpoint de contexto.

Restricciones · Cadena de texto 1
pattern
"^[a-z0-9][a-z0-9_-]{0,62}$"
queryCadena de textoOpcional

Texto de búsqueda o filtro de texto de búsqueda.

maxLength: 255
Valor predeterminado: ""
searches_minNúmero entero nullOpcional

Filtro del número mínimo de búsquedas.

Número entero:minimum: 0maximum: 9223372036854775807
searches_maxNúmero entero nullOpcional

Filtro del número máximo de búsquedas.

Número entero:minimum: 0maximum: 9223372036854775807
clicks_minNúmero entero nullOpcional

Filtro del número mínimo de clics.

Número entero:minimum: 0maximum: 9223372036854775807
clicks_maxNúmero entero nullOpcional

Filtro del número máximo de clics.

Número entero:minimum: 0maximum: 9223372036854775807
zero_results_minNúmero entero nullOpcional

Filtro del número mínimo de búsquedas sin resultados.

Número entero:minimum: 0maximum: 9223372036854775807
zero_results_maxNúmero entero nullOpcional

Filtro del número máximo de búsquedas sin resultados.

Número entero:minimum: 0maximum: 9223372036854775807
zero_result_scopeZeroResultScope Opcional

Filtro de búsquedas con o sin apariciones que no devolvieron resultados.

Valor predeterminado: "all"
sortQueryMetricSort Opcional

Orden seleccionado para los resultados.

Valor predeterminado: "last_seen_desc"

Esta operación no acepta un cuerpo JSON.

Respuestas

Respuesta 200

dataLista <MetricData > Obligatorio

Contenido de una respuesta correcta.

Campos · data

MetricData

clicksNúmero enteroObligatorio

Número de clics.

last_seen_atCadena de textoObligatorio

Momento de la aparición más reciente.

format: "date-time"
query_displayCadena de textoObligatorio

Frase de búsqueda mostrada al administrador.

query_hashCadena de textoObligatorio

Identificador estable de la frase de búsqueda agrupada.

searchesNúmero enteroObligatorio

Número de búsquedas.

zero_resultsNúmero enteroObligatorio

Número de búsquedas sin resultados.

metaAnalyticsPageMeta AnalyticsMeta Obligatorio

Metadatos de la respuesta.

Campos · meta

AnalyticsPageMeta

paginationPagination Obligatorio

Metadatos de la paginación por cursor.

periodAnalyticsPeriodData Obligatorio

Periodo del informe y sus límites.

request_idCadena de textoObligatorio

Identificador de la solicitud; en los metadatos de respuesta identifica la solicitud HTTP.

minLength: 1maxLength: 100

AnalyticsMeta

periodAnalyticsPeriodData Obligatorio

Periodo del informe y sus límites.

request_idCadena de textoObligatorio

Identificador de la solicitud; en los metadatos de respuesta identifica la solicitud HTTP.

minLength: 1maxLength: 100
Ejemplo de respuesta

Estado HTTP

200
Respuesta correcta Esquema
400
Solicitud no válida
401
Autenticación necesaria
403
Permiso denegado
404
Recurso no encontrado
409
Conflicto de versión
422
Error de validación
429
Límite de solicitudes excedido
Otros estados HTTP (7)
405
Método no permitido
413
Solicitud demasiado grande
415
Formato no compatible
500
Error del servidor
502
Error de la puerta de enlace API
503
Servicio no disponible
504
Tiempo de espera agotado

Catálogo de errores: ErrorResponse

Cabeceras

401

WWW-AuthenticateCadena de textoOpcional

Esquema de autenticación exigido por el servidor.

405

AllowCadena de textoOpcional

Métodos HTTP admitidos por este recurso.

429, 503

Retry-AfterNúmero enteroOpcional

Espera mínima antes de reintentar, en segundos.

minimum: 0