**TL;DR.** IndexNow ist eine kostenlose, standardisierte API, die es Ihnen ermöglicht, Bing, Yandex, Seznam und Naver sofort über URL-Änderungen zu informieren. Für eine E-Commerce-Website bedeutet das, dass ein neues Produkt innerhalb von Minuten anstelle von Tagen in Bing erscheint. Implementieren Sie es als Warteschlange, die von einem Hintergrundjob abgearbeitet wird, nicht als synchrone Aufrufe.

## Was ist IndexNow

IndexNow ist ein offenes Protokoll, das 2021 von Microsoft und Yandex angekündigt wurde. Suchmaschinen, die teilnehmen, akzeptieren einen einfachen HTTP POST, der URLs auflistet, die sich geändert haben; sie crawlen diese URLs mit Priorität.

Teilnehmende Suchmaschinen:

- Bing
- Yandex
- Seznam (Tschechisch)
- Naver (Koreanisch)

Besonders abwesend: Google. Google nimmt nicht an IndexNow teil; für Google verlassen Sie sich auf reguläres Crawlen oder die Indexing API (die auf Stellenangebote, Livestreams und einige andere Inhaltsarten beschränkt ist).

## Wie es funktioniert

1. Sie generieren einen API-Schlüssel (beliebige zufällige Zeichenfolge mit 32+ Zeichen).
2. Sie hosten den Schlüssel unter `https://yourdomain.com/{key}.txt` — der Inhalt besteht nur aus dem Schlüssel. Dies verifiziert, dass Sie die Kontrolle über die Domain haben.
3. Sie POSTen an `https://api.indexnow.org/indexnow` (oder an den IndexNow-Endpunkt einer teilnehmenden Suchmaschine) mit:

```json
{
  "host": "yourdomain.com",
  "key": "your-api-key",
  "keyLocation": "https://yourdomain.com/your-api-key.txt",
  "urlList": [
    "https://yourdomain.com/products/leather-bag",
    "https://yourdomain.com/products/wool-coat"
  ]
}
```

4. Die Suchmaschine stellt die URLs für das Crawlen in die Warteschlange.

Das war's. Keine Authentifizierung über die Überprüfung des Schlüsseldateibesitzes hinaus, kein Token-System zur Ratenbegrenzung.

## Wann zu pingen

Pingen Sie IndexNow, wann immer sich eine öffentlich indexierbare URL erheblich ändert:

| Ereignis                             | Ping                                         |
| ------------------------------------ | -------------------------------------------- |
| Produkt erstellt                     | Ping neue Produkt-URL                        |
| Produkt aktualisiert (Titel, Beschreibung) | Ping Produkt-URL                          |
| Produkt-Slug geändert                | Ping sowohl alte als auch neue URLs         |
| Produkt nicht veröffentlicht oder gelöscht | Ping URL (Suchmaschine sieht 404/410 und entfernt) |
| Kategorie erstellt                   | Ping Kategorie-URL                           |
| Kategorie aktualisiert               | Ping Kategorie-URL                           |
| Marke oder Seite erstellt/aktualisiert | Ping die URL                                |
| Sitemap regeneriert                  | Optional Sitemap-URL pingen                 |

Pingen Sie nicht für:

- Bestandsaktualisierungen, die den Inhalt nicht ändern.
- Nur interne Änderungen (Preisprüfungsprotokoll, Admin-Aktionen).
- Massenimporte — batchen Sie den Post-Import-Ping.

## Warteschlange, nicht synchron aufrufen

Eine naive Implementierung:

```ts
// SCHLECHT: synchroner IndexNow-Aufruf innerhalb des Produkt-Speicherns
async function saveProduct(product: Product) {
  await db.update(...);
  await fetch('https://api.indexnow.org/indexnow', { method: 'POST', body: ... });
  // ↑ fügt 100–500 ms zu jedem Speichern hinzu
}
```

Besser:

```ts
// GUT: in die Warteschlange stellen, asynchron abarbeiten
async function saveProduct(product: Product) {
  await db.update(...);
  await enqueueIndexNow(product.url);
  // gibt sofort zurück
}

// Hintergrundaufgabe, die alle 1–5 Minuten läuft
export const indexNowDrainTask = task({
  id: 'indexnow-drain',
  cron: '*/1 * * * *',
  run: async () => {
    const urls = await fetchPendingUrls(MAX_BATCH);
    if (urls.length === 0) return;
    await postToIndexNow(urls);
    await markAsDrained(urls);
  },
});
```

Vorteile der Warteschlangenbildung:

- Mutationen bleiben schnell.
- Fehler brechen keine benutzerseitigen Abläufe.
- Einfach zu batchen.
- Einfach pro Versuch zu protokollieren.
- Übersteht Plattformausfälle (Warteschlange bleibt bestehen, wird abgebaut, wenn die API wieder verfügbar ist).

## Umgang mit Slug-Änderungen

Ein häufiges subtiler Fall: Ein Produkt-Slug ändert sich von `/products/old` zu `/products/new`. Stellen Sie BEIDE URLs in die Warteschlange:

- Die neue URL muss gecrawlt werden, damit die Suchmaschine sie zum Index hinzufügt.
- Die alte URL muss gecrawlt werden, damit die Suchmaschine sie erneut abruft, den 301 (oder 410) sieht und sie entfernt.

```ts
async function updateProductSlug(productId: string, oldSlug: string, newSlug: string) {
  await db.products.update({ id: productId, slug: newSlug });
  await writeRedirect({ from: `/products/${oldSlug}`, to: `/products/${newSlug}`, status: 301 });
  await enqueueIndexNow([`/products/${oldSlug}`, `/products/${newSlug}`]);
}
```

Für Löschungen schreiben Sie eine 410-Weiterleitung (Ordikos gone-paths-Tabelle) und pingen die URL. Die Suchmaschine sieht 410 und entfernt die URL dauerhaft aus ihrem Index.

## Batching

Die API akzeptiert bis zu 10.000 URLs pro POST. Häufiges E-Commerce-Muster: 100–500 URLs pro Minute abarbeiten, abhängig vom Mutationsvolumen.

```ts
const MAX_BATCH = 500;
const BATCH_INTERVAL_MS = 60_000;

export const indexNowDrainTask = task({
  id: 'indexnow-drain',
  cron: '*/1 * * * *',
  run: async () => {
    const urls = await fetchPendingUrls(MAX_BATCH);
    if (urls.length === 0) return;

    try {
      const res = await fetch('https://api.indexnow.org/indexnow', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          host: 'yourdomain.com',
          key: process.env.INDEXNOW_KEY,
          keyLocation: `https://yourdomain.com/${process.env.INDEXNOW_KEY}.txt`,
          urlList: urls,
        }),
      });

      if (res.status === 200 || res.status === 202) {
        await markAsDrained(urls, 'ok');
      } else if (res.status === 429) {
        await markAsDrained(urls, 'retry'); // erneut in die Warteschlange für den nächsten Entwässerungszyklus
      } else {
        await markAsDrained(urls, 'failed', `${res.status} ${await res.text()}`);
      }
    } catch (err) {
      await markAsDrained(urls, 'failed', String(err));
    }
  },
});
```

## Protokollierung

Jeder Ping (Erfolg oder Misserfolg) sollte protokolliert werden. Nützliche Audit-Tabelle Schema:

```sql
CREATE TABLE seo_revalidation_events (
  id SERIAL PRIMARY KEY,
  store_id UUID NOT NULL,
  url TEXT NOT NULL,
  step TEXT NOT NULL, -- 'indexnow' | 'revalidate_tag' | 'sitemap'
  status TEXT NOT NULL, -- 'ok' | 'failed' | 'retry'
  error TEXT,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
```

Dies ermöglicht es Ihnen, die Frage "Warum wird dieses Produkt nicht in Bing angezeigt?" zu beantworten, indem Sie die Tabelle für die Produkt-URL abfragen.

## Verifizierung

Bing Webmaster Tools hat ein spezielles IndexNow-Dashboard:

1. Melden Sie sich unter [bing.com/webmasters](https://www.bing.com/webmasters) an.
2. Fügen Sie Ihre Website hinzu.
3. Navigieren Sie zu **IndexNow** in der Seitenleiste.
4. Sehen Sie sich die Einreichungen im Zeitverlauf, Erfolgs-/Misserfolgszahlen an.

Yandex Webmaster hat entsprechende Berichte unter **Indexierung**.

## Wie Ordiko IndexNow implementiert

- Die Spalte `stores.indexNowApiKey` speichert den Schlüssel pro Store.
- Schlüsseldatei wird automatisch unter `/{key}.txt` bereitgestellt.
- Jeder Entitätsdienst (`product.service.ts`, `category.service.ts` usw.) ruft `notifyIndexNowOnChange(url)` bei Änderungen auf.
- Warteschlange: `pending_indexnow`-Tabelle mit `(storeId, url, enqueuedAt)`.
- Trigger.dev Cron-Task `indexnow-drain.task.ts` läuft jede Minute.
- Jeder Entwässerungsprozess protokolliert in `seo_revalidation_events` mit `step: "indexnow", status: ok|failed|retry`.

## FAQ

**Funktioniert IndexNow für Google?**
Nein. Google nimmt nicht an IndexNow teil. Für Google reichen Sie Ihre XML-Sitemap ein und verlassen sich auf reguläre Crawling-Zyklen oder verwenden die eigene Indexing API von Google für begrenzte Inhaltsarten (Stellenangebote, Livestream-Events). Für Bing, Yandex, Seznam und Naver ist IndexNow der schnellste Weg, um Updates zu signalisieren.

**Wie viele URLs kann ich pro Aufruf einreichen?**
Bis zu 10.000 URLs pro POST. Die API gibt 200-OK für akzeptierte Einreichungen zurück. Bei größeren Volumina batchen und ratenbegrenzen — die typische sichere Rate liegt bei 1–10 Batches pro Minute. Der Entwässerungsjob in Ordiko sendet standardmäßig einen Batch pro Minute.

**Was passiert, wenn ich zu aggressiv einreiche?**
Sie erhalten 429 Too Many Requests. Die API sperrt Sie nicht — reduzieren Sie die Frequenz, versuchen Sie es erneut mit exponentiellem Backoff. Anhaltende hochvolumige Einreichungen unveränderter URLs können zu einer Depriorisierung führen, jedoch nicht zu einer Sperrung.

**Wie implementiert Ordiko IndexNow?**
Jeder Entitätsdienst (Produkt, Kategorie, Marke, Seite) ruft notifyIndexNowOnChange bei Erstellung/Aktualisierung/Löschung/Nichtveröffentlichung auf. Die Warteschlangentabelle pending_indexnow hält Einträge; ein Trigger.dev Cron-Task indexnow-drain.task.ts entleert sie nach einem Zeitplan. Jeder Ping wird in seo_revalidation_events für Auditzwecke protokolliert.