Tracking · Fehler

Das GTM-Tag feuert nicht: warum dein Trigger schweigt

Formular sendet, Trigger schweigt? Meist schluckt ein Plugin das Ereignis. Die Kette vom gestoppten Bubbling bis zum dataLayer-Push, in Prüfreihenfolge.

Kostenlos & unverbindlich · sinnvoll ab ca. 10.000 € monatlichem Werbebudget.

Das Formular ist raus, die Bestätigungsmail liegt im Postfach, und im Tag Manager: Stille. Kein Ereignis, kein Tag, keine Conversion. Wer jetzt wahllos an Trigger-Einstellungen dreht, verliert schnell einen halben Tag. Denn das Problem sitzt fast nie im GTM. Es sitzt im JavaScript der Seite.

Diese Seite gehört zur Fehler-Serie: geprüft wird in der Reihenfolge der Häufigkeit. Und die führt fast immer zum Formular-Trigger auf WordPress.

Zwei Minuten Grundcheck, bevor du gräbst

Öffne den Vorschaumodus und lade die Seite neu. Drei Ereignisse müssen immer in der linken Spalte stehen: Container Loaded, DOM Ready, Window Loaded. Fehlen sie, hat irgendein Skript den dataLayer neu zugewiesen statt zu pushen (meist ein kopiertes window.dataLayer = [...]). Damit sind alle automatischen Trigger tot, obwohl der Container brav lädt.

Stehen die drei da, schau beim Absenden auf die Liste. Kein Ereignis: Die Seite verschluckt es. Ereignis da, Trigger springt nicht an: Bedingungen prüfen, „enthält“ gegen „ist gleich“, Groß- und Kleinschreibung. Trigger springt an, Tag schweigt: Ausnahme.

Der Klassiker: Formular-Trigger auf WordPress

Warum sterben ausgerechnet Formular-Trigger so oft? Weil GTM anders lauscht, als die meisten denken: nicht mit einem Listener an jedem Element, sondern mit einem einzigen ganz oben am Dokument. Das ist sparsam und erfasst auch nachgeladene Elemente. Die Bedingung dabei: Das Submit-Ereignis entsteht unten am Formular und muss durch alle Elternelemente nach oben durchgereicht werden, bis es dort ankommt. Bubbling heißt das im Browser.

Und genau da grätschen Formular-Plugins rein. Viele validieren per JavaScript und stoppen das Ereignis danach: mal per stopPropagation, mal mit dem jQuery-Klassiker return false, der preventDefault und stopPropagation in einem Befehl vereint. Das Ereignis stirbt auf halber Höhe, GTM hört nichts. Variante zwei sind Ajax-Formulare: Sie senden beim Buttonklick per Skript, ein echtes Submit-Ereignis entsteht nie.

Daher das typische Bild: Formular funktioniert, Mail kommt an, Trigger schweigt. Das Formular hatte nie ein Problem. Nur die Nachricht nach oben wurde gekappt.

Der Capture-Workaround: Pflaster, kein Fix

Ereignisse laufen zweimal durch die Seite: von oben nach unten (Capture-Phase), dann wieder hinauf (Bubbling). Gestoppt wird fast immer nur der Rückweg. Ein Capture-Listener sieht das Ereignis auf dem Hinweg, bevor das Plugin es abwürgt. Im GTM nutzt der Trigger „Alle Elemente“ diese Phase (eigene Listener: drittes Argument true).

Warum trotzdem nur Pflaster? Du misst den Versuch, nicht den Erfolg: Auch das Submit mit leerem Pflichtfeld läuft durch die Capture-Phase. Beim Ajax-Formular hilft Capture gar nicht, es gibt ja kein Ereignis. Und „Alle Elemente“ kann nicht auf Tags warten; leitet die Seite sofort weiter, ist der Request weg.

Der Königsweg: ein eigenes dataLayer-Event

Die dauerhafte Lösung: Das Plugin oder der Entwickler meldet den Erfolg selbst, eine Zeile im Erfolgs-Callback, erst wenn die Sendung wirklich durch ist: dataLayer.push({event: "formular_gesendet"}). Im GTM ein Custom-Event-Trigger darauf, fertig.

Warum Königsweg? Du misst den Erfolg statt des Versuchs, und das Event hängt nicht am Markup, es übersteht jedes Redesign. Viele Formular-Plugins bringen dafür längst eine Einstellung oder einen Hook mit (oft keine Viertelstunde Arbeit). Ja, du musst dafür einmal mit dem Entwickler oder der Plugin-Doku reden. Das ist der ganze Preis.

Zwei Regeln dabei: immer pushen, nie neu zuweisen, sonst bricht der Container still. Und immer mit event-Schlüssel, denn nur der löst Trigger aus. Wie ein Container von Anfang an auf solchen Events aufbaut, steht in der Anleitung Google Tag Manager einrichten.

Zwei stille Killer: Ausnahmen und Selektoren

Springt der Trigger in der Vorschau an und der Tag feuert trotzdem nicht, lies den Ausnahmen-Block des Tags. Eine Ausnahme gewinnt immer gegen den auslösenden Trigger, und sie meldet sich nirgends. Gern übersehen: eine alte Blockier-Ausnahme auf einen Seitenpfad, der seit dem Relaunch anders heißt.

Der zweite Killer: Trigger an CSS-Selektoren und Klassennamen. „Klick auf .btn-primary“ funktioniert genau bis zum nächsten Theme-Update. Dann heißt der Button anders, der Trigger ist tot, und nichts wird rot. Solche Trigger haben ein Verfallsdatum, es steht nur nirgends drauf. Auch hier ist die Antwort das dataLayer-Event von oben.

„Gefeuert“ heißt nur: GTM hat es versucht

Der letzte Stolperstein ist die Vorschau selbst. „Tag fired“ heißt: Der Container hat den Tag ausgeführt. Ob der Request die Seite je verlassen hat, zeigt nur der Netzwerk-Tab der Entwicklertools: Filter auf „collect“ oder den Endpunkt deines Zielsystems, absenden, Request suchen. Fehlt er, war meist ein Blocker schneller oder eine Weiterleitung dazwischen.

Merk dir die drei Wahrheiten: Vorschau (was im Container ankommt), Netzwerk-Tab (was rausgeht), Echtzeit-Ansicht des Zielsystems. Ein Fall ist zu, wenn alle drei dasselbe sagen. Nicht vorher.

Die Diagnose als Wenn/Dann-Liste

Zum Mitnehmen die Prüfreihenfolge am Stück, beim ersten Treffer aussteigen:

Wenn das, dann dort suchen
Sortiert nach Häufigkeit. Punkt zwei löst die meisten Fälle.

Wenn nicht mal Container Loaded, DOM Ready und Window Loaded auftauchen, dann wurde der dataLayer neu zugewiesen. Snippet suchen, auf push umbauen.

Wenn beim Absenden kein Formular-Ereignis erscheint, dann stoppt das Plugin das Bubbling oder sendet per Ajax. Fix: dataLayer-Push im Erfolgs-Callback.

Wenn das Ereignis da ist, der Trigger aber nicht anspringt, dann passen die Bedingungen nicht. Werte aus der Vorschau kopieren statt abtippen.

Wenn der Trigger anspringt und der Tag stumm bleibt, dann blockt eine Ausnahme. Ausnahmen-Block des Tags lesen.

Wenn der Tag „gefeuert“ meldet und nichts ankommt, dann prüf den Netzwerk-Tab. Kein Request: Blocker oder Weiterleitung.

Wenn der Trigger nach einem Theme-Update starb, dann hing er an Klassennamen. Auf ein dataLayer-Event umbauen.

Meistens endet die Suche beim zweiten Punkt, dem Formular-Plugin. Die Liste ist unspektakulär. Aber sie ersetzt Stochern durch Diagnose, und das ist der halbe Fix.

Häufige Fragen

Das Formular sendet, aber der GTM-Trigger feuert nicht. Warum?

Weil das Ereignis GTM nie erreicht. Formular-Plugins stoppen das Bubbling (oft per jQuery return false) oder senden per Ajax ganz ohne Submit-Ereignis. GTM lauscht oben am Dokument und hört dann nichts.

Im Vorschaumodus fehlen Container Loaded, DOM Ready und Window Loaded. Was heißt das?

Dass Fremdcode den dataLayer neu zugewiesen hat statt zu pushen. Damit sind alle automatischen Trigger tot. Das Snippet suchen (window.dataLayer = …) und auf push umbauen.

Ist der Trigger „Alle Elemente“ die Lösung bei gestopptem Bubbling?

Als Pflaster ja: Er nutzt die Capture-Phase und sieht das Ereignis vor dem Plugin. Aber er misst den Versuch statt des Erfolgs und kann nicht auf Tags warten. Dauerhaft sauber ist nur der dataLayer-Push.

Warum feuert der Trigger seit dem Theme-Update nicht mehr?

Weil er an Klassennamen oder CSS-Selektoren hing und das Update das Markup geändert hat. Solche Trigger sterben ohne Meldung. Der Umbau auf ein dataLayer-Event macht sie update-fest.

Der Tag steht auf „gefeuert“, aber im Konto kommt nichts an?

„Gefeuert“ heißt nur, dass GTM den Tag ausgeführt hat. Ob der Request wirklich rausging, zeigt allein der Netzwerk-Tab. Fehlt er dort, war meist ein Blocker oder eine schnelle Weiterleitung dazwischen.

Der Trigger will einfach nicht?

Formular-Plugins und Themes sind die üblichen Täter. In der kostenlosen Potenzialanalyse schaue ich in dein Setup und benenne den Fix.

Kostenlos und unverbindlich. Antwort innerhalb von 48 Stunden, persönlich von mir.