In einer Keyword-Tabelle sieht eine erfundene Zahl aus wie eine gemessene. Hier steht der Test, der beide trennt – drei Felder, ein Urteil je Zeile –, und das Skript, das ihn über einen Export laufen lässt.
Überraschend ist, was auf dieser Seite fehlt: eine Suchanfragenzahl. Die Levelrecherche erbrachte am 20. September 2026 bei 80 geprüften Kandidatenthemen kein Suchvolumen aus einer benennbaren Quelle, und erfunden wurde keines. Eine Seite über erfundene Volumina, die eines zur Veranschaulichung abdruckt, schreibt ihren Witz selbst – in den Beispieldateien steht ein Platzhalter.
Eine Grenze vorweg. Level 8, SEO mit KI: KI als Arbeitswerkzeug, nimmt die Modelle als Werkzeug in deiner Hand; welche Seiten eine KI-Suchmaschine am Ende zitiert, gehört zu Level 4 zu GEO und AIO. Welches Modell du für welche Aufgabe öffnest, entscheidet Welche KI für welche SEO-Aufgabe: die Entscheidungstabelle; geprüft wird hier die Zahl, die ein Modell ausgibt.
Was du lernst
- Jede Kennzahl aus einem Modell in drei Feldern prüfen: Quelle, Stand der Abfrage, Erhebungsverfahren.
- Einen Export maschinell prüfen, ohne dass eine beschädigte Datei durchgeht.
- Erklären, warum das kein Anbieterfehler ist, den ein anderer behoben hat.
- Eine Reihenfolge begründen, wenn die Volumenspalte leer bleibt – mit drei Ersatzsignalen und deren Grenze.
- Den offenen Streit benennen, ob die Zahl eines Keyword-Tools eine Messung ist, ohne ihn zu entscheiden.
Drei Felder entscheiden, ob eine Zahl in den Bericht darf
Der Herkunftstest verlangt von jeder Kennzahl drei Angaben: eine Quelle, die gemessen hat, den Stand der Abfrage und das Erhebungsverfahren. Fehlt eine davon, gilt die Zahl als erzeugt und verlässt den Bericht. Geprüft wird die Zahl, nicht das Werkzeug dahinter.
Das Urteil heißt deshalb nicht richtig oder falsch, sondern belegt oder erzeugt, und seine Arbeitsform ist eine Wiederholungsfrage: Könnte eine zweite Person allein mit deinen drei Angaben dieselbe Abfrage stellen? Dann ist die Zahl verteidigungsfähig, auch als mäßige Schätzung. Wenn nicht, steht in der Zelle Text in der Form einer Zahl.
| Feld und Frage | Belegt, wenn da steht | Erzeugt, wenn da steht |
|---|---|---|
| Quelle – wer hat gemessen? | Ein Tool, ein Konto oder eine Einrichtung mit eigenem Namen, bei der man nachfragen kann | Der Name eines Modells, „verschiedene Quellen“, „Branchenwissen“, nichts |
| Stand – von wann ist die Abfrage? | Ein Kalendertag, TT.MM.JJJJ: der Tag des Exports, nicht der des Berichts | „Kürzlich“, „aus diesem Jahr“, eine Jahreszahl für sich, nichts |
| Verfahren – wie wurde erhoben und gerechnet? | Was der Anbieter dokumentiert: Zeitfenster, Mittel oder Median, gemessen oder modelliert | „Kommt so aus dem Tool“, „nicht bekannt“, ein leeres Feld |
Der Test trennt damit nicht Modelle von Werkzeugen, sondern belegbare Zahlen von unbelegbaren: auch die Zahl aus einem bezahlten Panel ist eine modellierte Schätzung, aber sie trägt die drei Felder.
Wo eine Suchvolumenzahl tatsächlich entsteht
Ein Suchvolumen entsteht in einem Produkt, nicht im Web. Ein Anbieter beobachtet oder modelliert Anfrageströme über ein Zeitfenster, rechnet das Ergebnis auf Keyword, Markt und Sprache um und gibt es an Konten heraus. Ein auf Webtexten trainiertes Sprachmodell hat dieses Produkt nicht in sich – ohne angebundene Quelle entsteht die Zahl erst in der Antwort.
Daraus folgt der Zug, der beim ersten Mal verblüfft: die erzeugte Zahl ist plausibel. Volumina haben Konventionen – eine Größenordnung, eine Rundungsgewohnheit, ein Gefälle vom Kopfbegriff zur langen Nachfrage –, und Konventionen reproduziert ein Sprachmodell gut. In der Tabellenzelle ist später nicht zu erkennen, welche der beiden Zahlen du bekommen hast.
Diese Aussage gehört auf die Ebene der Kategorie und nicht auf die eines Produkts. Kein Modell für allgemeine Zwecke hat einen Volumendatensatz hinter sich, und das folgt daraus, dass man ein System nach einer Größe fragt, die es nicht erreicht – nicht aus einem Fehler, den ein Wettbewerber behoben hätte. Deshalb brauchen Keyword-Recherche mit ChatGPT und mit Gemini eine Antwort und nicht zwei.
Si Quan Ong schrieb am 30.10.2025 im Blog von Ahrefs – einem Unternehmen, das Keyword-Daten verkauft, in einem Argumentbeitrag ohne Stichprobengröße –, die Volumina, die ein Modell nennt, seien „simply guesses“. Daneben steht der Vergleich eines dort zitierten Fachmanns: so lasse sich auch schätzen, es lebten „47 million penguins“ im Kühlschrank. Zu Ahrefs führt hier kein Link: die Quelle ist mit Autor, Publikation und Datum benannt, der Abruf war nicht möglich.
Warum in den Dateien dieser Lektion keine Suchanfragenzahl steht
Die Beispieldateien dieser Lektion tragen an der Stelle, an der ein Volumen stünde, die Zeichenfolge [Platzhalter]. Das ist Absicht: eine erfundene Zahl bleibt erfunden, auch mit dem Wort „angenommen“ davor.
Dahinter steht ein Befund aus der Levelrecherche vom 20. September 2026, bei 80 geprüften Kandidatenthemen: aus keiner benennbaren Quelle war ein Suchvolumen zu bekommen, und die Forschungsnotiz schreibt dazu, jede Volumenzahl, die in einem späteren Entwurf auftauche, sei erfunden und zu streichen.
Keyword-Recherche als Handwerk – Begriffe finden, gruppieren, priorisieren – gehört zu SEO-Grundlagen: Level 0 des kostenlosen SEO-Kurses. Hier geht es allein um die Herkunft der Zahl in der Spalte und um den Satz, der an ihre Stelle tritt.
Der Herkunftsprüfer: drei Prüfungen je Zeile, eine Vorprüfung der Zelle
Drei Felder von Hand abzufragen ist für eine Zahl im Chatfenster zu schaffen; ein Keyword-Entwurf hat Hunderte Zeilen, und teuer wird die Datei, die fertig aussieht. Das Skript herkunftspruefer.py liest eine JSON-Liste mit den Feldern kennzahl, wert, quelle, stand und verfahren je Zeile und stellt jeder Zeile die drei Fragen des Herkunftstests.
Vor den drei Prüfungen steht eine vierte anderer Art: ob in der Zelle überhaupt etwas steht, das eine Kennzahl sein kann. Sie ist der Grund, warum eine beschädigte Datei hier nicht besteht, und zwei Stellen im Code hängen daran. Erstens liest jedes Feld über einen Sentinel und nicht über dict.get(name, ""): mit einer leeren Vorgabe wären ein fehlendes und ein leer gelassenes Feld dasselbe, und eine Datei ohne Feld bestünde lautlos. Zweitens weist die Vorprüfung Wahrheitswerte vor jedem Zahlentest ab, weil bool in Python von int erbt: ein isinstance(wert, int) nimmt ein True als Kennzahl an.
Eine dritte Falle hängt an der Reihenfolge der except-Zweige beim Einlesen. UnicodeDecodeError steht unter ValueError und nicht unter OSError, json.JSONDecodeError ebenfalls unter ValueError: ein einziger ValueError-Zweig verschmilzt beide Ursachen zu einem Grund, ein OSError-Zweig fängt keine von beiden.
Drei der sechs belegten Rückgabewerte beschreiben die Eingabe und nur einer den Inhalt. Ob in einer Zeile das Verfahren fehlt oder die Quelle einen Erzeuger nennt, steht im Befundtext: für eine Veröffentlichungskette zählt allein, ob eine Zeile ohne Herkunft im Export steht. Die 1 vergibt das Skript nicht.
| Rückgabewert | Urteil | Was ihn auslöst |
|---|---|---|
0 |
BELEGT | Jede Zeile nennt Quelle, Stand und Verfahren |
1 |
bleibt frei | Python belegt ihn selbst: eine unbehandelte Ausnahme, oder ein sys.exit mit Text statt Zahl – beides hinter dem Mantel um main |
2 |
NICHT LESBAR | Datei fehlt, ist ein Verzeichnis, liegt nicht in UTF-8 vor oder enthält kein gültiges JSON |
3 |
KEINE ZEILENLISTE | Lesbar, aber keine Liste, eine leere Liste oder eine Zeile ohne Objektform |
4 |
OHNE HERKUNFT | Mindestens eine Zeile ohne vollständige Herkunft – gleich, welches der drei Felder fehlt |
5 |
AUFRUF UNVOLLSTÄNDIG | Kein Pfad übergeben oder mehr als einer |
6 |
ABBRUCH | Eine Ausnahme, die der Mantel um main gefangen hat |
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""herkunftspruefer.py – prüft, ob jede Kennzahl eines Exports eine Herkunft hat.
Aufruf:
python3 herkunftspruefer.py <export.json>
python3 herkunftspruefer.py --selbsttest
Der Export ist eine JSON-Liste. Jedes Element ist eine Zeile mit kennzahl,
wert, quelle, stand und verfahren. Geprüft werden die drei Herkunftsfelder
quelle, stand und verfahren; davor steht die Zelle selbst, denn ohne Wert gibt
es nichts, dessen Herkunft zu klären wäre.
Eine Zeile ist BELEGT, wenn kein Befund auf sie fällt, sonst OHNE HERKUNFT.
Ob ein Feld fehlt oder untauglich ist, sagt der Befundtext und nicht der
Rückgabewert: für den Export zählt allein, ob eine Zeile ohne Herkunft darin
steht. Drei Rückgabewerte beschreiben deshalb die Eingabe und nur einer den
Inhalt.
0 BELEGT jede Zeile nennt Quelle, Stand und Verfahren
2 NICHT LESBAR Datei fehlt, ist ein Verzeichnis, liegt nicht in
UTF-8 vor oder enthält kein gültiges JSON
3 KEINE ZEILENLISTE lesbar, aber keine Liste, eine leere Liste oder
eine Zeile ohne Objektform
4 OHNE HERKUNFT mindestens eine Zeile ohne vollständige Herkunft
5 AUFRUF UNVOLLSTÄNDIG kein Pfad oder mehr als einer übergeben
6 ABBRUCH eine Ausnahme, die der Mantel um main gefangen hat
Die 1 vergibt dieses Skript nicht, weil Python sie selbst belegt: der
Interpreter endet mit 1, wenn eine Ausnahme unbehandelt durchfällt, und
sys.exit setzt 1, sobald es einen Text statt einer Zahl bekommt. Beide Wege
liegen hinter dem Mantel um main. Eine 1 am Ende ist deshalb eine Aussage über
den Prozess und keine über den Export.
Nur Standardbibliothek. Kein Netzzugriff und keine Wartezeit. Geprüft wird, ob
eine Zahl zurückverfolgt werden kann – nie, ob sie stimmt.
"""
import collections
import datetime
import json
import re
import sys
# Sentinel. dict.get(name, "") wäre bequem und falsch: ein fehlendes Feld und
# ein leer gelassenes Feld sind zwei verschiedene Befunde, und ein beschädigter
# Export bestünde mit einer leeren Vorgabe lautlos als vollständig.
FEHLT = object()
Befund = collections.namedtuple("Befund", "feld text")
# Als Quelle untauglich: was Text erzeugt, und was niemanden benennt.
ERZEUGER = ("chatbot", "sprachmodell", "das modell", "dieses modell", "die ki",
"eine ki", "ki-schätzung", "chatgpt", "gemini", "claude",
"perplexity", "copilot", "grok", "deepseek", "aus dem gedächtnis",
"branchenüblich", "ungefähr geschätzt")
# Ein Verfahren, das sich selbst für unbekannt erklärt, ist kein Verfahren.
OHNE_AUSKUNFT = ("nicht bekannt", "unbekannt", "weiß ich nicht",
"kam so aus dem tool", "hat das modell gerechnet",
"steht nicht dabei", "keine angabe")
# Stand in deutscher Schreibweise nach DIN 5008: TT.MM.JJJJ.
KALENDERTAG = re.compile(r"^(\d{2})\.(\d{2})\.(\d{4})$")
# Beide Mindestlängen sind an den Feldern dieser Werkstattdateien abgelesen.
# Eine Quelle muss Werkzeug und Konto nennen, und das trägt kein einzelnes
# Wort: "Tool" fällt durch, "Eigener Kontoexport, Google Keyword Planner"
# nicht. Ein Verfahren muss Zeitfenster und Rechenart nennen, also reicht
# "Monatsmittel" nicht und "Monatsmittel über zwölf Monate, laut Tool
# modelliert" schon.
MINDESTZEICHEN_QUELLE = 12
MINDESTZEICHEN_VERFAHREN = 24
HERKUNFTSFELDER = ("quelle", "stand", "verfahren")
def rohwert(zeile, name):
"""Liefert den Feldwert oder FEHLT. Nie eine Vorgabe, nie eine leere Zeichenkette."""
return zeile.get(name, FEHLT)
def als_text(wert):
"""Liefert den getrimmten Text eines Feldes, oder None, wenn es keiner ist."""
if wert is FEHLT or wert is None or not isinstance(wert, str):
return None
gestrafft = wert.strip()
return gestrafft if gestrafft else None
def fehlt_warum(name, wert):
"""Benennt die Art der Lücke. Fehlend und leer sind zwei verschiedene Befunde."""
if wert is FEHLT:
return "Feld %s steht nicht auf der Zeile" % name
if wert is None:
return "Feld %s steht auf null" % name
if isinstance(wert, str):
return "Feld %s ist leer" % name
return "Feld %s ist %s und kein Text: %r" % (name, type(wert).__name__, wert)
def befund_zelle(zeile):
"""Die Vorprüfung: steht in der Zelle etwas, das eine Kennzahl sein kann?
bool wird vor jedem Zahlentest abgewiesen, weil ein Wahrheitswert in Python
eine Ganzzahl ist: isinstance(wert, int) nimmt ein True sonst als Kennzahl.
"""
wert = rohwert(zeile, "wert")
if isinstance(wert, bool):
return Befund("zelle", "Wahrheitswert statt Kennzahl: %r – bool ist eine "
"Ganzzahl" % (wert,))
if isinstance(wert, (int, float)):
return None
if als_text(wert) is None:
return Befund("zelle", fehlt_warum("wert", wert))
return None
def befund_quelle(zeile):
roh = rohwert(zeile, "quelle")
inhalt = als_text(roh)
if inhalt is None:
return Befund("quelle", fehlt_warum("quelle", roh))
klein = inhalt.lower()
for marke in ERZEUGER:
if marke in klein:
return Befund("quelle", "nennt einen Erzeuger, keinen Messenden: %r"
% inhalt)
if len(inhalt) < MINDESTZEICHEN_QUELLE:
return Befund("quelle", "nennt kein Werkzeug mit Konto: %r" % inhalt)
return None
def befund_stand(zeile):
roh = rohwert(zeile, "stand")
inhalt = als_text(roh)
if inhalt is None:
return Befund("stand", fehlt_warum("stand", roh))
treffer = KALENDERTAG.match(inhalt)
if treffer is None:
return Befund("stand", "kein Datum in der Form TT.MM.JJJJ: %r" % inhalt)
tag, monat, jahr = (int(teil) for teil in treffer.groups())
try:
datetime.date(jahr, monat, tag)
except ValueError as grund:
return Befund("stand", "kein möglicher Kalendertag: %r (%s)" % (inhalt, grund))
return None
def befund_verfahren(zeile):
roh = rohwert(zeile, "verfahren")
inhalt = als_text(roh)
if inhalt is None:
return Befund("verfahren", fehlt_warum("verfahren", roh))
klein = inhalt.lower()
for marke in OHNE_AUSKUNFT:
if marke in klein:
return Befund("verfahren", "erklärt sich selbst für unbekannt: %r" % inhalt)
if len(inhalt) < MINDESTZEICHEN_VERFAHREN:
return Befund("verfahren", "nennt kein Zeitfenster und keine Rechenart: %r"
% inhalt)
return None
PRÜFUNGEN = (("zelle", befund_zelle), ("quelle", befund_quelle),
("stand", befund_stand), ("verfahren", befund_verfahren))
def befunde(zeile):
"""Erzeugt die Befunde einer Zeile, in der Reihenfolge der Prüfungen."""
for _, pruefung in PRÜFUNGEN:
befund = pruefung(zeile)
if befund is not None:
yield befund
def kopfzeile(zeile, nummer):
name = als_text(rohwert(zeile, "kennzahl"))
wert = rohwert(zeile, "wert")
gezeigt = "– kein Feld wert –" if wert is FEHLT else "%r" % (wert,)
return "Zeile %d · %s · Wert: %s" % (nummer,
name if name else "ohne Kennzahlnamen",
gezeigt)
def lade(pfad):
"""Liefert (Zeilen, Grund, Rückgabewert). Bei Erfolg (Liste, None, 0).
Die Reihenfolge der except-Zweige ist nicht beliebig. UnicodeDecodeError
hängt unter ValueError und nicht unter OSError, json.JSONDecodeError
ebenfalls unter ValueError: ein einziger ValueError-Zweig würde beide
Ursachen zu einem Grund verschmelzen, ein OSError-Zweig keine von beiden
fangen.
"""
try:
with open(pfad, encoding="utf-8") as griff:
geladen = json.load(griff)
except FileNotFoundError:
return None, "keine Datei unter %s" % pfad, 2
except IsADirectoryError:
return None, "%s ist ein Verzeichnis und kein Export" % pfad, 2
except UnicodeDecodeError as grund:
return None, "nicht in UTF-8 kodiert: %s" % grund, 2
except json.JSONDecodeError as grund:
return None, "kein gültiges JSON: %s" % grund, 2
except OSError as grund:
return None, "nicht lesbar: %s" % grund, 2
if not isinstance(geladen, list):
return None, ("oberste Ebene ist %s, erwartet wird eine Liste von Zeilen"
% type(geladen).__name__), 3
if not geladen:
return None, "die Datei ist lesbar und nennt keine einzige Zeile", 3
for nummer, zeile in enumerate(geladen, 1):
if not isinstance(zeile, dict):
return None, "Zeile %d ist kein Objekt: %r" % (nummer, zeile), 3
return geladen, None, 0
def main(argv):
if len(argv) != 2:
print("AUFRUF UNVOLLSTÄNDIG: herkunftspruefer.py <export.json> | --selbsttest")
return 5
if argv[1] == "--selbsttest":
raise RuntimeError("Selbsttest: absichtlicher Fehler, der Mantel fängt ihn")
zeilen, grund, wert = lade(argv[1])
if grund is not None:
print("%s: %s" % ("NICHT LESBAR" if wert == 2 else "KEINE ZEILENLISTE", grund))
return wert
print("Herkunftsprüfung von %s" % argv[1])
belegt = 0
for nummer, zeile in enumerate(zeilen, 1):
print(kopfzeile(zeile, nummer))
gefunden = {befund.feld: befund for befund in befunde(zeile)}
if "zelle" in gefunden:
print(" %-10s %s" % ("zelle", gefunden["zelle"].text))
for name in HERKUNFTSFELDER:
if name in gefunden:
print(" %-10s %s" % (name, gefunden[name].text))
else:
print(" %-10s belegt: %s" % (name, als_text(rohwert(zeile, name))))
if gefunden:
print(" %-10s OHNE HERKUNFT, %d Befund(e)" % ("Urteil", len(gefunden)))
else:
belegt += 1
print(" %-10s BELEGT" % "Urteil")
print("Export: %d Zeilen · %d belegt · %d ohne Herkunft"
% (len(zeilen), belegt, len(zeilen) - belegt))
if belegt < len(zeilen):
print("Urteil des Exports: OHNE HERKUNFT")
return 4
print("Urteil des Exports: BELEGT")
return 0
if __name__ == "__main__":
# Der Mantel hält jede Ausnahme von der Befundliste fern: ein Absturz darf
# nie wie ein Urteil über einen Export aussehen. SystemExit geht
# unverändert weiter, weil er den Rückgabewert von main trägt.
try:
STATUS = main(sys.argv)
except SystemExit:
raise
except BaseException as grund:
print("ABBRUCH: %s: %s" % (type(grund).__name__, grund))
STATUS = 6
sys.exit(STATUS)
Sechs Läufe gegen die Werkstattdateien von Norderbrook
Die Segelmacherei Norderbrook ist eine erfundene Werkstatt, und ihre vier Eingabedateien decken die Fälle ab, an denen eine Prüfung scheitert. Die Werte stehen durchweg als [Platzhalter]: das Skript nimmt in der Zelle eine Zahl oder eine nicht leere Zeichenkette und prüft die Herkunft, nicht die Höhe.
Lauf eins, norderbrook-belegt.json: drei Zeilen, in denen die drei Felder stehen – die Datei und ihre Ausgabe:
[
{"kennzahl": "Nachfrage Segellatten", "wert": "[Platzhalter]",
"quelle": "Eigener Kontoexport, Google Keyword Planner",
"stand": "18.09.2026",
"verfahren": "Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt"},
{"kennzahl": "Nachfrage Lazybag nähen lassen", "wert": "[Platzhalter]",
"quelle": "Eigener Kontoexport, Google Keyword Planner",
"stand": "18.09.2026",
"verfahren": "Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt"},
{"kennzahl": "Nachfrage Großsegel reffen", "wert": "[Platzhalter]",
"quelle": "Eigener Kontoexport, Google Keyword Planner",
"stand": "18.09.2026",
"verfahren": "Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt"}
]
$ python3 herkunftspruefer.py norderbrook-belegt.json Herkunftsprüfung von norderbrook-belegt.json Zeile 1 · Nachfrage Segellatten · Wert: '[Platzhalter]' quelle belegt: Eigener Kontoexport, Google Keyword Planner stand belegt: 18.09.2026 verfahren belegt: Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt Urteil BELEGT Zeile 2 · Nachfrage Lazybag nähen lassen · Wert: '[Platzhalter]' quelle belegt: Eigener Kontoexport, Google Keyword Planner stand belegt: 18.09.2026 verfahren belegt: Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt Urteil BELEGT Zeile 3 · Nachfrage Großsegel reffen · Wert: '[Platzhalter]' quelle belegt: Eigener Kontoexport, Google Keyword Planner stand belegt: 18.09.2026 verfahren belegt: Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt Urteil BELEGT Export: 3 Zeilen · 3 belegt · 0 ohne Herkunft Urteil des Exports: BELEGT $ echo $? 0
Lauf zwei, norderbrook-ohne-quelle.json: drei Zeilen mit Stand und Verfahren, deren Quelle auf drei Weisen scheitert – Feld fehlt, Feld enthält Leerzeichen, Feld sagt Tool und benennt damit kein Werkzeug mit Konto. Der Bericht unterscheidet alle drei; die erste Unterscheidung geht verloren, sobald ein fehlendes Feld als leere Zeichenkette gilt.
[
{"kennzahl": "Nachfrage Persenning anfertigen", "wert": "[Platzhalter]",
"stand": "18.09.2026",
"verfahren": "Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt"},
{"kennzahl": "Nachfrage Segelreparatur Kosten", "wert": "[Platzhalter]",
"quelle": " ",
"stand": "18.09.2026",
"verfahren": "Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt"},
{"kennzahl": "Nachfrage Sonnensegel Boot", "wert": "[Platzhalter]",
"quelle": "Tool",
"stand": "18.09.2026",
"verfahren": "Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt"}
]
$ python3 herkunftspruefer.py norderbrook-ohne-quelle.json Herkunftsprüfung von norderbrook-ohne-quelle.json Zeile 1 · Nachfrage Persenning anfertigen · Wert: '[Platzhalter]' quelle Feld quelle steht nicht auf der Zeile stand belegt: 18.09.2026 verfahren belegt: Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt Urteil OHNE HERKUNFT, 1 Befund(e) Zeile 2 · Nachfrage Segelreparatur Kosten · Wert: '[Platzhalter]' quelle Feld quelle ist leer stand belegt: 18.09.2026 verfahren belegt: Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt Urteil OHNE HERKUNFT, 1 Befund(e) Zeile 3 · Nachfrage Sonnensegel Boot · Wert: '[Platzhalter]' quelle nennt kein Werkzeug mit Konto: 'Tool' stand belegt: 18.09.2026 verfahren belegt: Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt Urteil OHNE HERKUNFT, 1 Befund(e) Export: 3 Zeilen · 0 belegt · 3 ohne Herkunft Urteil des Exports: OHNE HERKUNFT $ echo $? 4
Lauf drei, norderbrook-ohne-verfahren.json: vier Zeilen, in denen das Verfahren fehlt oder nicht trägt. Zeile 1 schreibt nur Monatsmittel und nennt kein Zeitfenster, Zeile 2 trägt „nicht bekannt“ ein, Zeile 3 nennt als Quelle ein Modell und als Stand eine Jahreszahl. Zeile 4 ist die, an der ein nachlässiger Prüfer scheitert: im Wertfeld steht true, und weil bool von int erbt, nähme eine Zahlenprüfung das für eine Kennzahl. Dieser Lauf und der vorige scheitern an verschiedenen Feldern und landen auf demselben Wert – das Warum steht in den Befundzeilen.
[
{"kennzahl": "Nachfrage Rollreffanlage warten", "wert": "[Platzhalter]",
"quelle": "Eigener Kontoexport, Google Keyword Planner",
"stand": "18.09.2026",
"verfahren": "Monatsmittel"},
{"kennzahl": "Nachfrage Segelmacher Nordsee", "wert": "[Platzhalter]",
"quelle": "Eigener Kontoexport, Google Keyword Planner",
"stand": "18.09.2026",
"verfahren": "nicht bekannt"},
{"kennzahl": "Nachfrage Spifall tauschen", "wert": "[Platzhalter]",
"quelle": "ChatGPT",
"stand": "2026",
"verfahren": "Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt"},
{"kennzahl": "Nachfrage Winschen überholen", "wert": true,
"quelle": "Eigener Kontoexport, Google Keyword Planner",
"stand": "18.09.2026",
"verfahren": "Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt"}
]
$ python3 herkunftspruefer.py norderbrook-ohne-verfahren.json Herkunftsprüfung von norderbrook-ohne-verfahren.json Zeile 1 · Nachfrage Rollreffanlage warten · Wert: '[Platzhalter]' quelle belegt: Eigener Kontoexport, Google Keyword Planner stand belegt: 18.09.2026 verfahren nennt kein Zeitfenster und keine Rechenart: 'Monatsmittel' Urteil OHNE HERKUNFT, 1 Befund(e) Zeile 2 · Nachfrage Segelmacher Nordsee · Wert: '[Platzhalter]' quelle belegt: Eigener Kontoexport, Google Keyword Planner stand belegt: 18.09.2026 verfahren erklärt sich selbst für unbekannt: 'nicht bekannt' Urteil OHNE HERKUNFT, 1 Befund(e) Zeile 3 · Nachfrage Spifall tauschen · Wert: '[Platzhalter]' quelle nennt einen Erzeuger, keinen Messenden: 'ChatGPT' stand kein Datum in der Form TT.MM.JJJJ: '2026' verfahren belegt: Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt Urteil OHNE HERKUNFT, 2 Befund(e) Zeile 4 · Nachfrage Winschen überholen · Wert: True zelle Wahrheitswert statt Kennzahl: True – bool ist eine Ganzzahl quelle belegt: Eigener Kontoexport, Google Keyword Planner stand belegt: 18.09.2026 verfahren belegt: Monatsmittel über zwölf Monate, laut Tool modelliert, nicht gezählt Urteil OHNE HERKUNFT, 1 Befund(e) Export: 4 Zeilen · 0 belegt · 4 ohne Herkunft Urteil des Exports: OHNE HERKUNFT $ echo $? 4
Lauf vier, norderbrook-beschaedigt.json: dieselbe Datei wie in Lauf eins, in Latin-1 statt UTF-8 gespeichert – so, wie sie aus einem Tabellenprogramm mit falscher Kodierung kommt. Betroffen ist jeder Umlaut; das Skript nennt den ersten und beurteilt keine Zeile. Gebaut wird sie so:
$ iconv -f UTF-8 -t ISO-8859-1 norderbrook-belegt.json \
> norderbrook-beschaedigt.json
$ python3 herkunftspruefer.py norderbrook-beschaedigt.json NICHT LESBAR: nicht in UTF-8 kodiert: 'utf-8' codec can't decode byte 0xfc in position 183: invalid start byte $ echo $? 2
Lauf fünf, ohne Pfad: ein Aufruf ohne Argument ist kein beschädigter Export und bekommt deshalb seinen eigenen Wert.
$ python3 herkunftspruefer.py AUFRUF UNVOLLSTÄNDIG: herkunftspruefer.py <export.json> | --selbsttest $ echo $? 5
Lauf sechs, der Schalter --selbsttest: er löst innerhalb von main absichtlich eine Ausnahme aus, damit du dem Mantel beim Fangen zusehen kannst. Der Absturz landet auf einem Wert, den kein Export erreicht.
$ python3 herkunftspruefer.py --selbsttest ABBRUCH: RuntimeError: Selbsttest: absichtlicher Fehler, der Mantel fängt ihn $ echo $? 6
Was das Skript nicht leistet, gehört in dieselbe Beschreibung, sonst wiederholt es den Fehler, den die Lektion kritisiert. Es geht nicht ins Netz und kann deshalb nicht sagen, dass eine Zahl falsch ist – nur, dass sie nicht zurückverfolgbar ist. Die Verfahrensprüfung ist die schwächste: sie verlangt vierundzwanzig Zeichen und das Fehlen einer Ausrede, also besteht eine wortreiche Angabe ohne Inhalt. Und den Wert 3 löst keine der vier Dateien aus – dafür braucht es eine lesbare Datei ohne Zeilenliste.
Drei Ersatzsignale für die Reihenfolge, jedes mit seiner Grenze
Ein Bericht muss Themen auch dann ordnen, wenn die Volumenspalte leer bleibt. Drei Signale leisten das ohne Abonnement, und keines ist ein Volumen – die Grenze gehört neben das Signal in dieselbe Datei, sonst wird aus einem Ordnungsmerkmal eine Mengenangabe.
| Signal | Was es tatsächlich misst | Die Grenze, die daneben stehen muss |
|---|---|---|
| Tiefe des Autocomplete-Baums | Ob ein Suchstamm eigene Nachfrage trägt | Ordinal: vorhanden oder nicht, nie eine Menge |
| Adoptionsumfragen | Wer welche Aufgabe wie erledigt | Ein Näherungswert für Lernbedarf, nicht für Suchmenge – und nur mit seiner Stichprobe lesbar |
| Belegung der ersten Trefferseite | Sättigung des Themas | Datierte Momentaufnahme personalisierter Seiten, nicht wiederholbar |
Das erste Signal lässt sich am Thema dieser Lektion selbst ablesen. Google gibt höchstens zehn Vorschläge je Suchstamm heraus; am 20. September 2026 trug can chatgpt do keyword research drei – das Echo der Anfrage, how to do keyword research und how long does keyword research take. Die Frage wird getippt und trägt keinen eigenen Baum, und mehr sagt das Verfahren nicht: es trennt vorhanden von nicht vorhanden und nennt keine Menge.
Das zweite Signal braucht seinen Nenner. Keyword.com veröffentlichte am 1. Januar 2026 State of AI in SEO 2026 mit n = 97 brauchbaren Antworten aus einer selbst ausgewählten Teilnehmerschaft: 57 % geben an, die Qualität reiche nicht, und lassen weitere Automatisierung deshalb liegen; eine Person von 97 nennt ihre Arbeit vollständig automatisiert, also 1 %. Die 57 % sind der Anteil innerhalb der zurückhaltenden Gruppe; die Stichprobe von 97 ist nicht der Nenner. Eine Fehlermarge nennt er nicht: er ordnet Aufgaben, statt die Branche zu messen. Keyword-Recherche und Clustering liegen im oberen Feld der delegierten Aufgaben – ausgerechnet die Aufgabe, deren Kernzahl in keinem Modell ohne angebundene Quelle liegt.
Das dritte Signal ist das billigste. In der Kursbeobachtung vom 20. September 2026 war die erste Trefferseite der benachbarten Aufgabenfamilien fast durchgehend von Anbieterseiten belegt; auf Fragen nach Clustering-Methoden hielt eine programmatisch erzeugte Domain vier von neun Treffern. Verlässlich ist es für die Sättigung und schwach als Nachfragebeleg: es zeigt, dass das Niveau der Konkurrenz niedrig ist und ihre Zahl groß.
Was sich ändert, wenn am anderen Ende eine messende Quelle hängt
Was sich ändert, ist die Herkunft der Zahl und nicht ihre Richtigkeit: das Modell ist nicht mehr der Ursprung des Werts. Drei Anschlusswege dorthin sind dokumentiert, und keiner ist ein Trick an der Eingabe. Der erste ist ein eigener GPT mit Actions, der eine Keyword-API aufruft; Paul Shapiro veröffentlichte das Musterbeispiel am 28. November 2023 bei Search Wilderness, aktualisiert am 27. Dezember 2023. Der zweite sind MCP-Konnektoren zu den bezahlten Suiten – für Claude dokumentiert sind der Ahrefs-Konnektor und der Semrush-MCP –, und sie geben die Zahl des Anbieters zurück, mit dessen Verfahren und Stand.
Der dritte Weg ist die Nachfrage, die auf deinem eigenen Eigentum schon gemessen wurde. Search Console berichtet die Anfragen, zu denen deine Seiten erscheinen – kein Marktvolumen, aber Nachfrage, die an deinem eigenen Publikum erhoben ist, gefiltert nach Googles Regeln. Die Anbindung ohne Schreibrechte steht in Claude mit deinen eigenen Daten verbinden: Search Console und GA4 per MCP, das Lesen dieser Zahlen in SEO-Analytics und Messung: ehrlich messen.
Diese Verbesserung hat eine schmale Grenze: belegt heißt nicht richtig. Was ein Anbieter zurückgibt, ist eine modellierte Schätzung über ein erklärtes Zeitfenster und keine Zählung von Suchanfragen, und weil kein Anbieter sein Modell veröffentlicht, ist die Rechnung dahinter von außen nicht nachzuprüfen. Der Herkunftstest läuft deshalb nach dem Anschluss weiter und nicht an seiner Stelle.
Tiefe Recherche und Agentenmodus: dieselbe Prüfung, ein anderer Eingang
Tiefe Recherche und Agentenmodus ändern, woher der Text kommt, und nicht, ob die Zahl eine Herkunft hat. Der eine Modus stellt Suchanfragen und liefert einen Bericht mit Verweisen, der andere führt Schritte in Werkzeugen aus: beides verbessert das Sammeln, keines macht aus einer Größe, die niemand erhoben hat, eine Messung.
Der Gewinn liegt darin, dass der Test auf diese Ausgabe anwendbar wird: ein Verweis lässt sich öffnen, und zwei der drei Felder füllen sich dabei oft von selbst. Häufiger führt die zitierte Seite zu einer weiteren, die dieselbe Zahl ohne Urheber wiederholt. Verfolgt wird die Kette dann bis zum letzten Glied: steht dort ein Name neben einer Messung, sind die drei Felder voll; steht dort nichts mehr, gehört in die Zeile dieser Befund statt eines Werts.
Messung oder Schätzung: der offene Streit um die Volumenspalte
Ob die Volumenspalte eines Keyword-Tools etwas Gemessenes ausweist oder eine Schätzung, die wie eine Zählung aussieht, ist in der Branche nicht entschieden – und entschieden wird es hier nicht. Die Frage stellt sich sofort, wenn der Rat lautet, eine messende Quelle anzuschließen: misst, was von dort zurückkommt, tatsächlich etwas? Benannt wird diese Spannung hier, aufgelöst nicht.
Wer die Spalte als Messung liest, argumentiert über die Verfügbarkeit: das modellierte Volumen eines Anbieters ist die beste Messung, die existiert, es stammt von Leuten, deren Geschäft daran hängt, dass es ungefähr stimmt, und wer es für unbrauchbar erklärt, nimmt der Praxis jede Grundlage für eine Reihenfolge. Wer die Spalte als Schätzung liest, argumentiert über die Offenlegung: eine Zahl von einem Anbieter, der sein Modell nicht veröffentlicht, ist eine Schätzung mit den Kleidern einer Zählung, verschiedene Anbieter nennen für dasselbe Keyword deutlich verschiedene Zahlen, und sie als Messung zu berichten ist die Veredelung, die dieser Kurs ablehnt.
Und hier ist der Satz, der beide Seiten festhält: in den Forschungsdateien dieses Projekts vergleicht keine Untersuchung die Schätzungen von Tools gegen eine offengelegte Grundwahrheit, und kein Anbieter veröffentlicht sein Modell – also kann keine der beiden Seiten ihren Fall zeigen. Das Fehlen dieser Untersuchung ist überprüfbar; die Frage, die sie klären würde, bleibt offen.
Praktisch verlangen beide Seiten dasselbe: den Anbieter und den Tag der Abfrage notieren und die Zahl im Bericht Schätzung nennen. Wer die Spalte für eine Messung hält, verliert mit dieser Beschriftung nichts; wer sie für eine Schätzung hält, bekommt sie vollständig.
Häufige Fehler
- Den Platzhalter später durch eine Zahl ersetzen, die niemand geholt hat. Eine leere Zelle wird im Durchsehen als Versäumnis gelesen, und Füllen fühlt sich wie Fertigstellen an. Die Korrektur: in die Zelle gehört der Grund – welcher Ersatz die Reihenfolge trägt und was er misst.
- Ein fehlendes Feld beim Einlesen als leeres Feld behandeln. Damit verschwindet der Unterschied zwischen „niemand hat gefragt“ und „die Angabe gibt es nicht“. Die Korrektur: das Fehlen als eigenen Befund führen, im Skript über einen Sentinel.
- Den Stand der Abfrage im Dateinamen führen statt in der Zeile. Der Dateiname überlebt das erste Kopieren in eine Präsentation nicht, die Zahl schon. Die Korrektur: Quelle, Stand und Verfahren reisen in derselben Zeile wie der Wert.
- Die Prüfung erst laufen lassen, wenn die Zahl in einer Hochrechnung steht. Danach kostet das Entfernen einer Zeile eine Erklärung gegenüber jemandem, der mit ihr gerechnet hat. Die Korrektur: der Rückgabewert entscheidet über das Weitergeben.
Kurzfassung
- Auf dieser Seite steht keine Suchanfragenzahl: die Levelrecherche vom 20. September 2026 erbrachte bei 80 geprüften Kandidatenthemen keine aus einer benennbaren Quelle, und in den Beispieldateien steht
[Platzhalter]. - Der Herkunftstest fragt drei Felder ab – Quelle, Stand der Abfrage, Erhebungsverfahren. Fehlt eines, gilt die Zahl als erzeugt, und das Urteil heißt belegt oder erzeugt, nicht richtig oder falsch.
- Ein Suchvolumen entsteht im Produkt eines Anbieters. Si Quan Ong nannte die von Modellen genannten Volumina am 30.10.2025 im Blog von Ahrefs „simply guesses“, in einem Beitrag ohne Stichprobengröße.
herkunftspruefer.pyprüft drei Felder je Zeile und davor die Zelle; ein Export ohne Herkunft fällt durch wie eine Zahl aus dem Chatfenster. Drei Rückgabewerte beschreiben die Eingabe (2,3,5), einer den Inhalt (4), einer den Absturz (6); die1bleibt frei.- Ob ein modelliertes Volumen eine Messung ist, bleibt offen: keine Untersuchung in den Forschungsdateien dieses Projekts prüft Tool-Schätzungen gegen eine offengelegte Grundwahrheit, und kein Anbieter veröffentlicht sein Modell. Beide Seiten verlangen dasselbe – Anbieter und Tag notieren, die Zahl Schätzung nennen.
- Ohne Volumen tragen drei Signale die Reihenfolge, jedes mit seiner Grenze: Autocomplete-Tiefe ordinal, Adoptionsumfragen mit ihrer Stichprobe (Keyword.com, 1. Januar 2026, n = 97), Trefferseitenbelegung als Sättigung.
Häufige Fragen
Reicht es, die Zahl im Bericht als Schätzung zu kennzeichnen?
Für die Beschriftung ja, für die Herkunft nein. Das Wort Schätzung sagt, wie belastbar die Zahl ist, und nicht, woher sie kommt – als Schätzung bezeichnet bleibt eine erfundene Zahl erfunden. Beides gehört zusammen: Anbieter, Tag und Verfahren in der Zeile, dazu das Wort Schätzung, weil das Verfahren hinter einem modellierten Volumen außerhalb des Anbieters niemand nachrechnen kann.
Das Skript sagt OHNE HERKUNFT. Darf die Zahl in den Bericht?
Nein, und welche Zeile es betrifft, steht im Bericht darüber. Fehlt dort nur eine Angabe, die es noch gibt, dann hol am Tool den Tag des Exports und das dokumentierte Zeitfenster, trag beides ein und lass den Prüfer erneut laufen. Nennt die Quelle dagegen einen Erzeuger oder erklärt sich das Verfahren für unbekannt, ist die Zeile nicht reparierbar und wird gelöscht. Der Wert 4 unterscheidet beides absichtlich nicht: diese Entscheidung liegt bei dir.
Woran erkenne ich im fertigen Dokument, welche Zahl aus einem Modell kam?
Hinterher an nichts, und genau deshalb wird am Eingang geprüft. Eine Tabellenzelle speichert kein Protokoll, und die erzeugte Zahl ist der gemessenen äußerlich gleich. Prüfbar ist nur ein Dokument mit den drei Feldern; ohne sie ist der Export eine Behauptung und wird neu geholt.
Zwei Anbieter nennen für dasselbe Keyword verschiedene Zahlen. Welche nehme ich?
Beide, in zwei Spalten mit dem Namen des Anbieters darüber, und für die Entscheidung beide Zahlen mit ihrem Anbieter und ihrem Abfragetag, weil keine der hier verwendeten Quellen sagt, welche davon näher an der Wirklichkeit liegt. Ein Mittelwert aus zwei Modellen mit verschiedenen Zeitfenstern gehört niemandem. Dass die Zahlen auseinandergehen, ist selbst eine Information für den Bericht.
Quellen
- Si Quan Ong, „AI can’t replace SEO tools, but it can use them“, Ahrefs, 30.10.2025: von Modellen genannte Volumina sind „simply guesses“, mit dem Vergleich der „47 million penguins“, der einem im Beitrag zitierten Fachmann zugeschrieben wird. Ein Argumentbeitrag, keine Erhebung, ohne Stichprobengröße. (ohne bestätigte URL im Quellenbestand dieses Kurses, deshalb ohne Link)
- Keyword.com, „State of AI in SEO 2026“, 1. Januar 2026. n = 97 brauchbare Antworten, selbst ausgewählte Teilnehmerschaft, keine Fehlermarge: 57 % führen ungenügende Qualität als Grund gegen weitere Automatisierung an – Anteil innerhalb der zurückhaltenden Gruppe –, eine von 97 Personen arbeitet vollständig automatisiert.
- Paul Shapiro, „Using ChatGPT’s Custom ‚GPTs‘ for SEO and Keyword Research“, Search Wilderness, 28. November 2023, aktualisiert am 27. Dezember 2023.
- Anthropic, Verzeichniseintrag des Ahrefs-Konnektors für Claude – Metadaten des Eintrags: „Added January 2026“.
- Semrush, Entwicklerdokumentation zum MCP – Stand der Seite: 5. August 2026.
- Autocomplete-Sondierungen für diesen Kurs, aufgenommen am 20. September 2026 und in der Levelrecherche protokolliert. Ordinal: keine Mengen.
- Beobachtung der ersten Trefferseite der benachbarten Aufgabenfamilien, 20. September 2026, ohne Stichprobengröße. Gemessen wird Sättigung.
herkunftspruefer.py, die vier Eingabedateien der Segelmacherei Norderbrook und die sechs Läufe sind oben abgedruckt: Standardbibliothek ohne Netzzugriff, sechs belegte Rückgabewerte, die1frei.
Jede Angabe trägt ihr Datum mit Absicht: Verzeichnisse, Dokumentationsstände und Umfragen altern, und eine Angabe mit einem Quartal hinter sich ist ein Anlass nachzusehen und kein Fakt.
Weiter im Kurs
Die vorherige Lektion ist Welche KI für welche SEO-Aufgabe: die Entscheidungstabelle.
- Level: SEO mit KI: KI als Arbeitswerkzeug – dort steht, welche Lektionen dieses Levels online sind.
- Kursverzeichnis: Kostenloser SEO-Kurs: 100 Lektionen von den Grundlagen bis Black Hat