Conversion Tracking
Du willst wissen, welche Anfrage aus ChatGPT kam. Der Pixel sagt es dir nicht von allein: Er feuert kein Event, verwirft Meta-Eventnamen und sendet standardmäßig ohne Consent-Abfrage. So baust du beide Wege sauber auf.
Der Pixel ist ein Script, das von bzrcdn.openai.com geladen wird und die Funktion oaiq bereitstellt. Mit oaiq("init", {pixelId: "…"}) wird er initialisiert, mit oaiq("measure", …) meldest du Events, mit oaiq("consent", true|false) steuerst du, ob er senden darf. Mehr Befehle gibt es nicht, ein identify oder set wie bei anderen Pixeln existiert im Code nicht.
Die Conversions API ist der zweite Weg. Dein Server schickt Events per HTTP an denselben Empfänger, mit einem eigenen Schlüssel aus dem Ads Manager, und deckt alles ab, was im Browser nicht sicher passiert: Bestellungen nach Zahlungseingang, vom CRM qualifizierte Leads, Offline-Termine. Für das Optimierungsziel im ChatGPT Ads Manager ist egal, welcher Weg das Event liefert. Und weil oCPC zwar auf dein Conversion-Ereignis optimiert, aber weiterhin pro Klick abrechnet, ist das Tracking die einzige Stelle, an der du erfährst, ob die Kosten deiner ChatGPT Ads etwas eingebracht haben.
Die Conversions API nimmt Events per POST auf https://bzr.openai.com/v1/events?pid=<PIXEL-ID> entgegen, authentifiziert über einen Bearer-Token im Authorization-Header. Der Schlüssel kommt aus dem Ads Manager und gehört ausschließlich auf den Server. Ein Request trägt ein Array events mit bis zu 1.000 Einträgen und optional validate_only:
{
"validate_only": true,
"events": [{
"id": "lead-4711",
"type": "lead_created",
"timestamp_ms": 1756720000000,
"action_source": "web",
"source_url": "https://deine-domain.de/danke/",
"oppref": "<Klick-ID aus der Landing-URL>",
"data": {"type": "customer_action"},
"user": {"emails_sha256": ["<sha256 der E-Mail>"]}
}]
}
Pflicht je Event sind id, type, timestamp_ms, action_source, bei Web-Events source_url und das Objekt data mit seinem type. Das data-Feld ist der häufigste Stolperstein: Fehlt es, antwortet die API mit HTTP 400 und dem Fehlercode missing_event_data. Wir haben beides gesehen: dasselbe lead_created mit data kam mit HTTP 200 und accepted_events: 1 zurück, ohne data mit dem 400er. Der Zeitstempel darf höchstens sieben Tage zurückliegen und zehn Minuten in der Zukunft.
validate_only: true ist dein Trockenlauf: Die API prüft das Event vollständig, speichert es aber nicht. Schalte den Wert erst um, wenn die Antwort sauber ist, sonst zählst du Testbestellungen als Conversions.
Die Deduplizierung läuft über den Schlüssel aus Pixel-ID, Eventname und Event-ID, im Browser event_id, in der API das Feld id. OpenAI formuliert es so: Das erste Event mit einem passenden Schlüssel zählt, spätere Duplikate werden ignoriert. Wiederholungen ohne stabile id erzeugen also Duplikate.
Wer neben dem Tracking auch das Reporting automatisieren will, braucht zwei getrennte Schlüssel. Der Conversions-Key darf Events senden und sonst nichts; ein Versuch, damit Kampagnen- oder Anzeigendaten zu lesen, endet mit HTTP 403. Für Lesezugriffe braucht es einen eigenen Ads-API-Schlüssel mit anderen Rechten. Das kostet Zeit, wenn man es nicht weiß, denn der 403 sieht aus wie ein falscher Schlüssel und ist ein Rechteproblem.
Für neue Pixel ist Automatic Advanced Matching seit Anfang August 2026 voreingestellt, bestehende Pixel wurden am 17.08.2026 umgestellt (ppc.land). Das Flag kommt aus einer Remote-Konfiguration, die der Pixel beim Start lädt. Ist es gesetzt, hängt das SDK Listener auf submit, change, click und keydown, scannt Formularfelder auf E-Mail-Adressen, Telefonnummern und Namen und hasht sie im Browser mit SHA-256, bevor sie mit dem nächsten Event mitgehen. Personenbezogene Daten aus deinen Formularen gehen damit gehasht an OpenAI, ohne dass dein Code das aufruft. Abschalten lässt sich das nur in den Pixel-Einstellungen des Ads Managers, nicht im Snippet. Wer die Ernte nicht will, prüft dort den Schalter und reicht Nutzerdaten kontrolliert nach, etwa mit einem zweiten init, das user mit email_sha256 enthält.
Die vertragliche Rolle ist anders, als viele erwarten. Laut den Conversion Terms von OpenAI sind Werbetreibender und OpenAI für die Conversion-Daten grundsätzlich unabhängige Verantwortliche, nicht Auftraggeber und Auftragsverarbeiter. Nur für das eng gefasste Restricted Processing tritt OpenAI als Auftragsverarbeiter auf; für Daten aus dem EWR ist OpenAI Ireland Limited der Vertragspartner. Ein Auftragsverarbeitungsvertrag allein trägt das Tracking also nicht, du brauchst eine eigene Rechtsgrundlage für die Übermittlung, wie bei Meta auch. Das ist eine Feststellung aus dem Vertragstext, keine Bewertung deines Einzelfalls.
Ein Klick auf eine ChatGPT-Anzeige bringt den Parameter oppref in der Landing-URL mit. Der Pixel legt ihn in sein 30-Tage-Cookie, die Conversions API erwartet ihn unverändert auf Event-Ebene. Auf OpenAI-Seite ist die Zuordnung damit erledigt, auf deiner nicht.
Das haben wir am eigenen CRM gelernt. Unser Funnel schreibt in die Quelle-Spalte den Funnel-Typ, also welchen Check ein Interessent durchlaufen hat, nicht den Kanal. Ein Lead aus einer ChatGPT-Anzeige sah im CRM exakt so aus wie ein organischer. Erst seit wir oppref beim ersten Seitenaufruf selbst auslesen und als eigenes Feld mit dem Lead durchreichen, lässt sich sagen, welcher Abschluss auf eine Anzeige zurückgeht. Dasselbe gilt für Google Analytics: ChatGPT-Klicks ohne UTM-Parameter können dort als „Direct“ erscheinen. Vergib UTM-Parameter in jeder Ziel-URL, mit einer Quelle, die den bezahlten Klick vom organischen ChatGPT-Referral trennt. Organische Nennungen in ChatGPT-Antworten sind ein eigener Kanal, den unsere ChatGPT Agentur bearbeitet, und beide sollen in der Auswertung nicht zusammenfallen.
Das ist die erste Falle, und sie erwischt jeden, der den Pixel wie den Meta-Pixel einbaut. Wer nur den Basis-Snippet aus dem Ads Manager einbaut, misst außer dem SDK-Start und etwas Diagnose-Telemetrie nichts. Im ausgelieferten Code taucht page_viewed ausschließlich in der Event-Tabelle auf, nirgends wird es von selbst aufgerufen. Der Seitenaufruf gehört deshalb direkt hinter das init:
<script>
oaiq("init", {pixelId: "DEINE-PIXEL-ID"});
oaiq("measure", "page_viewed", {type: "contents"});
</script>
Dasselbe gilt für Single-Page-Anwendungen: Ein Routenwechsel feuert nichts, init läuft einmal, jedes weitere Event löst du selbst aus. Ob es angekommen ist, siehst du im Netzwerk-Tab an einem POST auf bzr.openai.com/v1/sdk/events und mit debug: true in der Console an Zeilen mit dem Präfix [oaiq]. Google Tag Assistant kennt den Pixel nicht.
Die zweite Falle ist die Gewohnheit. Wer aus Meta-Kampagnen purchase, lead oder add_to_cart gewohnt ist, sendet diese Namen weiter, und der Pixel verwirft sie still. In der Console steht dann [oaiq] validation failed; event dropped, aber nur, wenn jemand hinschaut. Gültig sind ausschließlich diese Events, jedes mit einem festen Wert im Pflichtfeld data.type:
| Event | data.type |
Typischer Einsatz |
|---|---|---|
page_viewed |
contents |
Seitenaufruf, muss selbst ausgelöst werden |
contents_viewed |
contents |
Produkt- oder Leistungsseite |
items_added |
contents |
In den Warenkorb gelegt |
checkout_started |
contents |
Kasse begonnen |
order_created |
contents |
Bestellung abgeschlossen, mit contents[] je Position |
lead_created |
customer_action |
Kontaktanfrage, Formular abgeschickt |
registration_completed |
customer_action |
Konto angelegt |
appointment_scheduled |
customer_action |
Termin gebucht |
subscription_created |
plan_enrollment |
Abo abgeschlossen, mit plan_id |
trial_started |
plan_enrollment |
Testphase gestartet, mit plan_id |
custom |
custom |
Eigenes Event, braucht custom_event_name |
Für Beträge prüft der Code zwei Regeln hart. amount muss eine ganze Zahl in der kleinsten Einheit der Währung sein: 129,99 Euro sind 12999 mit currency: "EUR", ein Dezimalwert wie 129.99 fliegt bei der Validierung raus. Und wo ein amount steht, muss immer eine currency als dreistelliger ISO-Code dabei sein, sonst wird das Event verworfen. Ein Lead mit Wert sieht so aus:
oaiq("measure", "lead_created",
{type: "customer_action", amount: 50000, currency: "EUR"},
{event_id: "lead-4711"});
Das vierte Argument zählt: event_id ist der Schlüssel, über den Browser- und Server-Event später als dasselbe erkannt werden. Nimm die stabile Bestellnummer oder Lead-ID aus deinem System, nie einen Zufallswert, und feuere das Event erst bei bestätigtem Erfolg, nicht beim Klick auf „Absenden“.
Die dritte Falle ist die datenschutzrechtlich relevanteste. Der Pixel initialisiert seinen Consent-Status mit true. Im Code steht die Prüfung als g.consent !== false, was auch den unentschiedenen Zustand durchlässt, und OpenAI beschreibt es in der eigenen Dokumentation genauso: Consent ist true, solange du ihn nicht auf false setzt oder der Pixel eine gespeicherte Ablehnung findet. Wer den Pixel lädt und auf das Consent-Banner wartet, sendet währenddessen bereits. Die Gegenmaßnahme muss vor dem ersten measure stehen:
oaiq("consent", false); // bis der Nutzer zustimmt
oaiq("consent", true); // nach der Zustimmung
Bei false löscht der Pixel seine Cookies, verwirft die Warteschlange und sendet einen letzten Beacon mit reason: "consent_denied". Er lädt allerdings trotzdem seine Remote-Konfiguration und meldet Diagnosedaten. Für Deutschland ist deshalb ein zweiter Riegel sinnvoll: Lade das Script selbst erst nach der Einwilligung, über den Consent-Trigger deines Tag Managers oder deiner Consent-Plattform. Eine Anbindung an den Google Consent Mode gibt es nicht, auch nicht in der offiziellen GTM-Vorlage von OpenAI.
Warum das nötig ist, zeigen die Cookies. Der Pixel setzt __oppref mit 30 Tagen Laufzeit, die Klick-ID aus der Landing-URL, und __obref mit 365 Tagen, eine zufällige Browser-Kennung. Beide sind nicht technisch notwendig, sie dienen der Zuordnung von Werbeklicks, und fallen damit unter § 25 TDDDG (bis Mai 2024: TTDSG), der vor dem Setzen eine Einwilligung verlangt. Das ist eine technische Feststellung aus dem Code, keine Rechtsberatung. Das Zusammenspiel mit deiner Consent-Plattform beschreibt unsere Seite zu Conversion Tracking und DSGVO, die Fragen des Kanals die Seite zu ChatGPT Ads und DSGVO.
Das ist der Fehler, den wir selbst gemacht haben, und er gehört hierher, weil er mit keiner Zeile Code zu tun hat. Die Conversions API für unseren Funnel war fertig geschrieben und getestet, das Deploy-Skript lag auf dem Server. Ausgeführt wurde es nicht. Neun Tage lang liefen die Anzeigen weiter, jeder Klick wurde bezahlt, und auf der Conversion-Seite stand null, weil das Skript, das die Leads gemeldet hätte, nie gestartet war. Das Ärgerliche ist nicht der Ausfall, sondern dass er nicht rekonstruierbar ist. Die API akzeptiert Zeitstempel bis sieben Tage zurück, neun Tage sind zu viel. Die Lea
Das klären wir im Erstgespräch
Das ist der Fehler, den wir selbst gemacht haben, und er gehört hierher, weil er mit keiner Zeile Code zu tun hat.
Die Conversions API für unseren Funnel war fertig geschrieben und getestet, das Deploy-Skript lag auf dem Server.
Ausgeführt wurde es nicht.
Du legst im Ads Manager einen Pixel an, baust den Basis-Snippet auf allen Seiten ein und löst direkt nach dem `init` ein `page_viewed` mit `type: "contents"` aus, denn von allein feuert der Pixel nichts. Danach meldest du deine Conversion-Events mit den gültigen Namen, etwa `lead_created` mit `type: "customer_action"`, und gibst jedem Event eine stabile `event_id`. Bestellungen oder qualifizierte Leads schickst du zusätzlich über die Conversions API mit derselben ID, damit sie dedupliziert werden.
Die drei häufigsten Ursachen: Du sendest Meta-Eventnamen wie `purchase` oder `lead`, die der Pixel verwirft. Im Event fehlt `data.type` oder der Wert passt nicht zum Eventnamen. Oder `amount` ist eine Dezimalzahl beziehungsweise steht ohne `currency`. In allen Fällen zeigt die Console mit `debug: true` die Zeile `[oaiq] validation failed; event dropped`. Geht gar kein Request an `bzr.openai.com` raus, wurde das Event nie ausgelöst.
Für einen ersten Test reicht der Pixel. Sobald du auf ein Ereignis optimierst, das nicht sicher im Browser passiert, etwa eine Bestellung nach Zahlungseingang oder ein qualifizierter Lead, brauchst du die Conversions API, weil nur dein Server diesen Zustand kennt. Beide Wege mit derselben Event-ID sind der Standard, den wir empfehlen.
Einsetzbar ja, aber nicht ohne Vorarbeit. Die Cookies `__oppref` und `__obref` sind nicht technisch notwendig und brauchen nach § 25 TDDDG (bis Mai 2024: TTDSG) eine Einwilligung vor dem Setzen. Weil der Consent-Status standardmäßig `true` ist, musst du das Script hinter deine Consent-Plattform legen und zusätzlich `oaiq("consent", false)` setzen, bis der Nutzer zustimmt. Laut Conversion Terms ist OpenAI unabhängiger Verantwortlicher, ein Auftragsverarbeitungsvertrag allein reicht daher nicht. Das ist eine Feststellung aus Code und Vertragstext, keine Rechtsberatung.
Ja. OpenAI stellt auf GitHub eine offizielle Tag-Vorlage bereit, alternativ funktioniert ein Custom-HTML-Tag mit dem Original-Snippet. In beiden Fällen musst du die `measure`-Aufrufe über eigene Trigger auslösen, weil der Pixel keine Events von selbst sendet. Eine Anbindung an den Google Consent Mode ist nicht dokumentiert, den Consent löst du deshalb über den Trigger des Tags.
Nur, wenn du den Parameter `oppref` aus der Landing-URL beim ersten Seitenaufruf selbst speicherst und mit dem Lead ins CRM übergibst. Der Pixel legt ihn zwar in ein Cookie, aber dein CRM liest dieses Cookie nicht. Ergänze außerdem UTM-Parameter in den Ziel-URLs, sonst lassen sich die Klicks in Google Analytics oft nicht sauber zuordnen.
Wir prüfen dein Setup vom Pixel bis zur Conversions API: Feuert page_viewed, stimmen Eventnamen und data.type, greift der Consent-Riegel, kommt ein Testlead im Ads Manager an? Das Ergebnis ist ein Tracking, das nachweislich misst, bevor ein Euro Budget läuft.
Ohne Verkaufsdruck, ohne Verpflichtung.
Von der Mechanik über Kosten und Targeting bis zu Tracking und Datenschutz.