Google Sheets · Apps Script · Zalando · Otto
Zalando- und Otto-Produktdaten in Google Sheets holen
Viele Preisvergleiche beginnen in einer Tabelle: eine Liste von Produkten, der Preis von heute, der Preis von letzter Woche. Diese Zahlen von Hand bei Zalando oder Otto abzuschreiben, wird schnell mühsam. Google Sheets hat mit Apps Script ein eingebautes Skript-Werkzeug, das Daten aus dem Web abrufen kann – die Tabelle kann sich also selbst füllen.
In dieser Anleitung ergänzen Sie ein Google Sheet um ein kleines Skript. Ein Menüpunkt aktualisiert Titel, Marke, Preis und Verfügbarkeit für eine Liste von Zalando-Produktlinks; ein anderer füllt einen zweiten Tab mit Otto-Suchergebnissen zu einem Suchbegriff. Ein täglicher Timer hält die Preise aktuell. Alles läuft innerhalb von Google – Sie brauchen weder einen Server noch einen Rechner, der eingeschaltet bleibt.
Aktualisiert am · von everydata.io
Was Sie am Ende haben
- Ein Tab „Zalando“, der Preise und Verfügbarkeit für Ihre Produktlinks aktualisiert.
- Ein Tab „Otto“, der die erste Seite der Suchergebnisse für einen beliebigen Suchbegriff listet.
- Ein everydata-Menü in der Tabelle und eine optionale tägliche Aktualisierung.
Was Sie brauchen
- Ein Google-Konto und ein neues Google Sheet.
- Ein kostenloser everydata.io-API-Schlüssel – hier anlegen.
- Ein paar Zalando-Produktlinks (zum Beispiel von zalando.de) und ein Suchbegriff für Otto.
01Die beiden Tabs vorbereiten
- Benennen Sie den ersten Tab in
Zalandoum. Tragen Sie in Zeile 1 diese Überschriften ein: URL, Titel, Marke, Preis, Normalpreis, Verfügbarkeit, Geprüft am. Fügen Sie Ihre Zalando-Produktlinks ab Zeile 2 in Spalte A ein. - Legen Sie einen zweiten Tab namens
Ottoan. Schreiben Sie „Suchbegriff“ in A1 und Ihren Begriff (zum Beispiel „highboard“) in B1. Tragen Sie in Zeile 3 die Überschriften Produkt, Marke, Preis, Normalpreis, Bewertung, Link ein.
02Den API-Schlüssel im Skript speichern, nicht in einer Zelle
Öffnen Sie Erweiterungen → Apps Script. Gehen Sie im Editor zu Projekteinstellungen → Skripteigenschaften und legen Sie eine Eigenschaft namens EVERYDATA_API_KEY mit Ihrem Schlüssel als Wert an. Jeder, mit dem Sie die Tabelle teilen, sieht deren Zellen, aber nicht die Skripteigenschaften.
03Das Skript einfügen
Ersetzen Sie den Inhalt von Code.gs durch das Skript unten und speichern Sie. refreshZalando sendet jeden Produktlink an den Zalando-Endpoint und schreibt das Ergebnis daneben. searchOtto sendet den Suchbegriff an den Otto-Such-Endpoint und schreibt eine Zeile pro Produkt.
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();
}Laden Sie die Tabelle neu: Ein Menü „everydata“ erscheint. Bei der ersten Nutzung bittet Google Sie, dem Skript die Verbindung zu einem externen Dienst zu erlauben – das ist die Anfrage an everydata.io.
04Was zurückkommt
Für einen Zalando-Produktlink liefert die API die aktuelle Produktseite als Daten. Gekürztes dokumentiertes Beispiel:
{
"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 ist der aktuelle Preis des Produkts, retailPrice der Normalpreis vor einem Rabatt. Bei einer Otto-Suche wird jedes Produkt in searchProductDetails zu einer Zeile. dpUrl ist ein Pfad auf otto.de, deshalb setzt das Skript https://www.otto.de davor:
{
"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"
}
]
}05Die Preise täglich aktualisieren
Fügen Sie diese Funktion demselben Skript hinzu, wählen Sie sie in der Symbolleiste des Editors aus und klicken Sie einmal auf Ausführen. Ab dann aktualisiert Google den Zalando-Tab jeden Morgen, auch wenn die Tabelle geschlossen ist.
/** 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();
}Wenn Sie eine Historie behalten möchten, statt die Preise zu überschreiben, kopieren Sie die Preisspalte vor jeder Aktualisierung in eine neue Spalte (oder einen zweiten Tab).
06Wie viele Anfragen das verbraucht
Jede Zalando-Produktabfrage zählt als 2 Anfragen gegen Ihr Monatskontingent, eine Otto-Suche als 1. Eine tägliche Aktualisierung eines Zalando-Produkts ergibt zum Beispiel rund 60 Anfragen im Monat – der kostenlose Tarif mit 100 Anfragen reicht also zum Ausprobieren. Für längere Listen siehe Preise.
Rufen Sie die API nicht aus einer benutzerdefinierten Zellformel wie =ZALANDO(A2) auf. Sheets berechnet Formeln nach eigenem Zeitplan neu, was Anfragen wiederholen kann, die Sie gar nicht stellen wollten. Ein Menüpunkt oder ein Timer läuft genau dann, wenn Sie es entscheiden.
In dieser Anleitung verwendete Endpoints
Product details by URL · Zalando API
Search products by keyword · Otto API
Was Sie mit diesen Daten noch machen können
Jede Produktseite von zalando.de oder zalando.co.uk als JSON: Titel, Marke, Händler, Preis, Rabatt, Bilder, Material und alle Größen und Farben mit Bestand.
Jede otto.de-Produktseite als JSON: Titel, Hersteller, Preis, retailPrice, priceSaving, Lieferhinweis, Bilder, Specs und komplette Variantenmatrix. Live.
Probieren Sie es mit Ihren eigenen Daten
Der kostenlose Tarif enthält 100 Anfragen pro Monat, nutzbar auf jeder Plattform – genug, um diese Anleitung vollständig durchzuspielen.