Google Sheets · Apps Script · Zalando · Otto
Lleva datos de productos de Zalando y Otto a Google Sheets
Muchas comparaciones de precios empiezan en una hoja de cálculo: una lista de productos, el precio de hoy, el de la semana pasada. Copiar esas cifras a mano desde Zalando u Otto cansa enseguida. Google Sheets tiene una herramienta de scripts integrada, Apps Script, que puede obtener datos de la web, así que la hoja puede rellenarse sola.
En esta guía añadirás un pequeño script a una hoja de Google Sheets. Un botón actualiza el título, la marca, el precio y la disponibilidad de una lista de enlaces de productos de Zalando; otro rellena una segunda pestaña con los resultados de búsqueda de Otto para un término. Un temporizador diario mantiene los precios al día. Todo se ejecuta dentro de Google: no necesitas un servidor ni un ordenador que se quede encendido.
Actualizado el · por everydata.io
Lo que tendrás al final
- Una pestaña “Zalando” que actualiza precios y disponibilidad de tus enlaces de productos.
- Una pestaña “Otto” que lista la primera página de resultados de búsqueda de cualquier término.
- Un menú everydata en la hoja y una actualización diaria opcional.
Lo que necesitas
- Una cuenta de Google y una hoja de Google Sheets nueva.
- Una clave de API gratuita de everydata.io: créala aquí.
- Algunos enlaces de productos de Zalando (por ejemplo, de zalando.de) y un término de búsqueda para Otto.
01Prepara las dos pestañas
- Cambia el nombre de la primera pestaña a
Zalando. Pon estos encabezados en la fila 1: URL, Título, Marca, Precio, Precio habitual, Disponibilidad, Consultado el. Pega tus enlaces de productos de Zalando en la columna A a partir de la fila 2. - Añade una segunda pestaña llamada
Otto. Escribe “Término de búsqueda” en A1 y tu término (por ejemplo, “highboard”) en B1. Pon los encabezados Producto, Marca, Precio, Precio habitual, Valoración, Enlace en la fila 3.
02Guarda tu clave de API en el script, no en una celda
Abre Extensiones → Apps Script. En el editor, ve a Configuración del proyecto → Propiedades de secuencia de comandos y añade una propiedad llamada EVERYDATA_API_KEY con tu clave como valor. Cualquier persona con la que compartas la hoja puede ver sus celdas, pero no las propiedades del script.
03Pega el script
Sustituye el contenido de Code.gs por el script de abajo y guarda. refreshZalando envía cada enlace de producto al endpoint de Zalando y escribe el resultado a su lado. searchOtto envía el término de búsqueda al endpoint de búsqueda de Otto y escribe una fila por producto.
const API = "https://api.everydata.io";
/**
* One GET request to everydata.io. The key lives in the script properties, not in the sheet.
* Waits when rate limited (429) and retries a failed page load (5xx) once; other errors come back as { error }.
*/
function apiGet(path, params) {
const key = PropertiesService.getScriptProperties().getProperty("EVERYDATA_API_KEY");
const query = Object.keys(params)
.map((k) => encodeURIComponent(k) + "=" + encodeURIComponent(params[k]))
.join("&");
let retried = false;
for (let attempt = 0; attempt < 4; attempt++) {
const res = UrlFetchApp.fetch(API + path + "?" + query, {
headers: { "x-api-key": key },
muteHttpExceptions: true,
});
const code = res.getResponseCode();
if (code === 429) {
// Too many requests at once. The answer says how long to wait: "... Try again in 12 seconds."
const wait = res.getContentText().match(/in (\d+) seconds/);
Utilities.sleep(Math.min(wait ? Number(wait[1]) + 1 : 60, 60) * 1000);
continue;
}
if (code >= 500 && !retried) {
retried = true; // 5xx answers are not counted against your quota
Utilities.sleep(5000);
continue;
}
if (code >= 400) return { error: code };
return JSON.parse(res.getContentText());
}
return { error: 429 };
}
/** Sheet "Zalando": product URLs in column A from row 2; writes columns B–G. */
function refreshZalando() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Zalando");
const lastRow = sheet.getLastRow();
if (lastRow < 2) return;
const urls = sheet.getRange(2, 1, lastRow - 1, 1).getValues();
const rows = urls.map(([url]) => {
if (!url) return ["", "", "", "", "", ""];
const p = apiGet("/zal/zalando-lookup-product", { url: url });
if (p.error) return ["Error " + p.error, "", "", "", "", new Date()];
return [p.productTitle, p.manufacturer, p.price, p.retailPrice, p.warehouseAvailability, new Date()];
});
sheet.getRange(2, 2, rows.length, 6).setValues(rows);
}
/** Sheet "Otto": search term in B1; writes the first page of results from row 4. */
function searchOtto() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Otto");
const keyword = sheet.getRange("B1").getValue();
const data = apiGet("/ott/otto-search-by-keyword", { keyword: keyword, page: 1 });
if (sheet.getLastRow() >= 4) sheet.getRange(4, 1, sheet.getLastRow() - 3, 6).clearContent();
if (data.error) {
sheet.getRange("A4").setValue("Error " + data.error);
return;
}
const rows = (data.searchProductDetails || []).map((p) => [
p.productDescription, p.manufacturer, p.price, p.retailPrice, p.productRating, "https://www.otto.de" + p.dpUrl,
]);
if (rows.length) sheet.getRange(4, 1, rows.length, 6).setValues(rows);
}
/** Adds an "everydata" menu to the spreadsheet. */
function onOpen() {
SpreadsheetApp.getUi()
.createMenu("everydata")
.addItem("Refresh Zalando prices", "refreshZalando")
.addItem("Search Otto", "searchOtto")
.addToUi();
}Vuelve a cargar la hoja de cálculo: aparece un menú “everydata”. La primera vez que lo uses, Google te pedirá que permitas al script conectarse a un servicio externo: se trata de la solicitud a everydata.io.
04Qué se devuelve
Para un enlace de producto de Zalando, la API devuelve la página actual del producto como datos. Ejemplo documentado, reducido:
{
"responseStatus": "PRODUCT_FOUND_RESPONSE",
"responseMessage": "Product successfully found!",
"productTitle": "EVERQUEST TEXAPORE MID - Hikingschuh - dusty olive",
"manufacturer": "Jack Wolfskin",
"url": "https://www.zalando.de/jack-wolfskin-everquest-texapore-mid-hikingschuh-dusty-olive-ja442c00s-n11.html",
"warehouseAvailability": "Auf Lager.",
"retailPrice": 119.95,
"price": 104.97,
"priceSaving": 14.98
}price es lo que cuesta ahora el producto y retailPrice el precio habitual antes de un descuento. En una búsqueda de Otto, cada producto de searchProductDetails se convierte en una fila. dpUrl es una ruta de otto.de, por eso el script le antepone https://www.otto.de:
{
"responseStatus": "PRODUCT_FOUND_RESPONSE",
"responseMessage": "Product successfully found!",
"keyword": "highboard",
"resultCount": 5166,
"searchProductDetails": [
{
"productDescription": "LeGer Home by Lena Gercke Highboard Essentials, Sideboard, Kommode, Anrichte, Schrank, Stauraumschrank, Breite: 111 cm, UV lackiert, Push-to-open-Funktion",
"manufacturer": "LeGer Home by Lena Gercke",
"price": 869.99,
"retailPrice": 1109.99,
"productRating": "1.0",
"dpUrl": "/p/leger-home-by-lena-gercke-highboard-essentials-sideboard-kommode-anrichte-schrank-stauraumschrank-breite-111-cm-uv-lackiert-push-to-open-funktion-1658198337/?variationId=2081559634"
}
]
}05Actualiza los precios cada día
Añade esta función al mismo script, selecciónala en la barra de herramientas del editor y pulsa Ejecutar una vez. A partir de entonces, Google actualiza la pestaña de Zalando cada mañana, aunque la hoja esté cerrada.
/** Run once from the editor: refreshes the Zalando sheet every morning between 7 and 8. */
function installDailyTrigger() {
ScriptApp.newTrigger("refreshZalando").timeBased().everyDays(1).atHour(7).create();
}Para conservar un historial en lugar de sobrescribir los precios, copia la columna Precio en una columna nueva (o en una segunda pestaña) antes de cada actualización.
06Cuántas solicitudes consume
Cada consulta de producto de Zalando cuenta como 2 solicitudes de tu cuota mensual; una búsqueda de Otto cuenta como 1. Por ejemplo, una actualización diaria de un producto de Zalando son unas 60 solicitudes al mes, así que el plan gratuito de 100 solicitudes basta para probarlo. Para listas más largas, consulta los precios.
Evita llamar a la API desde una fórmula de celda personalizada como =ZALANDO(A2). Sheets recalcula las fórmulas cuando le parece, lo que puede repetir solicitudes que no pretendías hacer. Una opción de menú o un temporizador se ejecutan exactamente cuando tú decides.
Endpoints utilizados en esta guía
Product details by URL · API de Zalando
Search products by keyword · API de Otto
Qué más puedes hacer con estos datos
Productos de zalando.de o zalando.co.uk en JSON: título, marca, vendedor, precio, rebaja, imágenes, materiales y cada talla y color con su stock.
Páginas de producto de otto.de en JSON: título, fabricante, price, retailPrice, priceSaving, stock, imágenes, especificaciones y variantes, en tiempo real.
Pruébalo con tus propios datos
El plan gratuito incluye 100 solicitudes al mes, utilizables en todas las plataformas: suficiente para seguir esta guía de principio a fin.