Einen Preis- und Bestandswächter mit MutationObserver bauen
Du willst diesen Artikel, aber nur zum richtigen Preis — oder du willst in dem Moment Bescheid wissen, in dem ein ausverkauftes Produkt zurück ist. Den ganzen Tag den Tab neu zu laden ist keine Art zu leben. Dieser Artikel baut einen Preis- und Bestandswächter mit einer JustZix-JS-Regel: Ein MutationObserver beobachtet das relevante Element, vergleicht den Wert und benachrichtigt dich, wenn deine Bedingung erfüllt ist.
Wie der Wächter funktioniert
Der Plan hat vier Teile, und jeder entspricht einem Abschnitt weiter unten:
- Wähle einen stabilen Selektor für das Preis- oder Bestandselement.
- Hänge einen
MutationObserveran, damit du auf Änderungen reagierst, ohne zu pollen. - Parse den Text in eine vergleichbare Zahl oder einen Boolean.
- Benachrichtige dich selbst — ein Banner auf der Seite oder eine System-Benachrichtigung — und merk dir den letzten Wert.
Alles läuft clientseitig im Tab. Halte die Produktseite offen (ein angepinnter Tab ist ideal), und die Regel übernimmt das Beobachten.
Einen stabilen Selektor wählen
Der Wächter ist nur so zuverlässig wie sein Selektor. Öffne die DevTools, Elements-Panel, und finde das Element, das den Preis hält. Bevorzuge, in dieser Reihenfolge:
- Einen semantischen Anker:
[itemprop="price"],[data-price],[data-testid="product-price"]. Die ändern sich selten. - Eine stabile ID:
#priceblock_ourprice,#product-price. - Eine aussagekräftige Klasse:
.price-now,.product__price.
Vermeide gehashte Klassen (.css-1a2b3c) und lange Nachfahren-Ketten — sie brechen beim nächsten Deploy. Viele Shops betten auch strukturierte Daten in einen <script type="application/ld+json">-Block ein; ist das sichtbare DOM unübersichtlich, ist das Parsen dieses JSON oft der stabilste Weg.
Den MutationObserver einrichten
Ein MutationObserver löst einen Callback aus, wann immer sich der beobachtete Teilbaum ändert — kein Polling, keine verschwendete CPU. Beobachte den Preisknoten auf Text- und Kindänderungen:
const SELECTOR = '[itemprop="price"]'; // your stable selector
const priceEl = document.querySelector(SELECTOR);
if (!priceEl) {
console.warn('[watcher] price element not found - check the selector');
} else {
const observer = new MutationObserver(() => checkPrice(priceEl));
observer.observe(priceEl, {
childList: true,
subtree: true,
characterData: true
});
// Also check once on load - the price may already be a deal
checkPrice(priceEl);
}
Single-Page-App-Shops ersetzen beim Update manchmal den ganzen Preisknoten. Wird dein Observer still, beobachte einen stabilen Eltern-Container mit subtree: true und frag den Preis im Callback neu ab.
Den Preis in eine Zahl parsen
Preistext ist unübersichtlich: Währungssymbole, Tausendertrennzeichen, Dezimalkommas. Reduziere ihn vor dem Vergleich auf eine saubere Zahl:
// Turn "$1,299.00" or "1 299,00 zl" into 1299
function parsePrice(text) {
if (!text) return NaN;
// Keep digits, dot and comma; drop everything else
let s = text.replace(/[^0-9.,]/g, '');
// If comma is the decimal separator, normalise it
if (/,\d{2}$/.test(s)) s = s.replace(/\./g, '').replace(',', '.');
else s = s.replace(/,/g, '');
return parseFloat(s);
}
Gegen eine Schwelle vergleichen
Jetzt die Entscheidungslogik. Vergleiche den geparsten Preis mit deinem Ziel und benachrichtige nur, wenn er sie tatsächlich überschreitet — und nur einmal pro Senkung, damit du nicht bei jeder kleinen DOM-Mutation zugespammt wirst:
const TARGET = 999; // alert when price drops to/below this
const STORAGE_KEY = 'jz-watch-' + location.pathname;
function checkPrice(el) {
const price = parsePrice(el.textContent);
if (Number.isNaN(price)) return;
const last = parseFloat(localStorage.getItem(STORAGE_KEY)) || Infinity;
localStorage.setItem(STORAGE_KEY, String(price));
console.log('[watcher] price now', price, '- last', last);
// Fire only when we newly cross the threshold
if (price <= TARGET && last > TARGET) {
notify('Price drop! Now ' + price + ' (target ' + TARGET + ')');
}
}
Auf Wieder-verfügbar achten
Gleiches Muster, anderes Signal. Statt einer Zahl beobachtest du einen Boolean — ist der Kaufen-Button aktiviert, ist das „nicht vorrätig"-Label weg:
function checkStock() {
const soldOut = document.querySelector('[class*="out-of-stock" i], .sold-out');
const buyBtn = document.querySelector('button[name="add-to-cart"], .add-to-cart');
const inStock = !soldOut && buyBtn && !buyBtn.disabled;
const wasInStock = localStorage.getItem('jz-stock') === 'yes';
localStorage.setItem('jz-stock', inStock ? 'yes' : 'no');
if (inStock && !wasInStock) {
notify('Back in stock! Grab it now.');
}
}
Dich selbst benachrichtigen
Eine Benachrichtigung nützt nichts, wenn du sie nicht siehst. Nutze zwei Kanäle: ein unübersehbares Banner auf der Seite plus eine System-Benachrichtigung für den Fall, dass der Tab im Hintergrund ist.
function notify(message) {
// 1. On-page banner - always visible in the tab
let bar = document.getElementById('jz-watch-bar');
if (!bar) {
bar = document.createElement('div');
bar.id = 'jz-watch-bar';
bar.style.cssText =
'position:fixed;top:0;left:0;right:0;z-index:2147483647;' +
'background:#16a34a;color:#fff;font:600 15px/1.4 sans-serif;' +
'padding:12px 16px;text-align:center;';
document.body.appendChild(bar);
}
bar.textContent = 'JZ watcher: ' + message;
// 2. System notification - works when the tab is hidden
if (Notification.permission === 'granted') {
new Notification('JustZix watcher', { body: message });
} else if (Notification.permission !== 'denied') {
Notification.requestPermission();
}
}
Der z-index von 2147483647 ist die maximale 32-Bit-Ganzzahl — er garantiert, dass das Banner über allem sitzt, was die Seite rendert. System-Benachrichtigungen brauchen eine Erlaubnis, die der Browser nur aus einer Nutzergeste oder einem zuvor genehmigten Ursprung erteilt, also fordert der erste Lauf sie vielleicht nur an; das Banner deckt dich in der Zwischenzeit ab.
Den zuletzt gesehenen Wert speichern
Du hast oben localStorage verwendet gesehen, und es leistet echte Arbeit. Es überlebt Neuladevorgänge, sodass der Wächter weiß, ob eine Änderung wirklich neu ist. Es entdoppelt auch Benachrichtigungen — du vergleichst mit dem gespeicherten Wert und benachrichtigst nur bei einem echten Überschreiten. Schlüssele es pro Seite (location.pathname), damit mehrere Produktwächter koexistieren können, ohne sich gegenseitig zu überschreiben.
In JustZix verdrahten
- Erstelle eine Regel mit dem URL-Muster des genauen Produkts, z. B.
https://shop.example.com/product/12345*. - Füge das kombinierte Skript in den JS-Tab ein — setze
SELECTORundTARGETfür dieses Produkt. - Pinne den Tab an und lass ihn offen; der Observer reagiert, wann immer der Shop das DOM aktualisiert.
- Willst du auch ohne DOM-Änderungen eine regelmäßige Neuprüfung? Füge ein
setIntervalhinzu, das die Seite alle paar Minuten neu lädt.
Siehe auch
- Dark Patterns abschalten — entferne falsche Dringlichkeit, damit du den echten Preis siehst.
- API-Antworten mocken — teste deinen Wächter gegen einen gefälschten Preis-Feed.
- JustZix-Anwendungsfälle für mehr Automatisierungsideen.
Hör auf, diesen Tab neu zu laden. Installiere JustZix, leg das Wächter-Skript in eine Regel pro Produkt und lass den Browser dir den Moment melden, in dem der Preis stimmt.
Bewerte diesen Beitrag
Noch keine Bewertungen — sei der Erste.