dataLayer Events planen zur Optimierung des INP
Wie das Verzögern von GTM-Events bis nach dem Browser-Paint Ihre INP-Werte verbessert

TL;DR: INP verbessern durch Verzögerung von dataLayer.push()
Wenn dataLayer.push() synchron innerhalb eines Event-Handlers ausgeführt wird, verarbeitet GTM Tags bevor der Browser visuelles Feedback anzeigen kann. Dies blockiert den Main Thread und verschlechtert Ihren Interaction to Next Paint (INP). Die Lösung: Planen Sie dataLayer.push() so, dass es nach dem nächsten Browser-Paint ausgeführt wird, unter Verwendung von requestAnimationFrame. Dieses Muster reduziert den INP auf den meisten Websites um 20 bis 100ms und verwandelt oft einen nicht bestandenen Wert in einen bestandenen. Die Datenerfassung wird um 50 bis 250ms verzögert, was für Analytics und Marketing-Tracking unerheblich ist.
Wie dataLayer.push() Ihren INP verschlechtert
Für einen unserer Kunden haben wir eine Reduktion von 100ms beim Interaction to Next Paint (INP) gemessen, indem wir den Zeitpunkt der Ausführung von dataLayer.push() nach einer Nutzerinteraktion neu geplant haben. Die Lösung ist ein JavaScript-Drop-in-Ersatz, der das Rendering gegenüber dem Tracking priorisiert.
Zuletzt überprüft von Arjen Karel im März 2026
Table of Contents!
- TL;DR: INP verbessern durch Verzögerung von dataLayer.push()
- Wie dataLayer.push() Ihren INP verschlechtert
- Das Problem mit synchronem dataLayer.push()
- Die Lösung: Erst rendern, dann pushen
- Der awaitPaint-Helfer
- Globales Override zum schnellen Testen
- Warum dies den INP verbessert
- Warum keine feste Verzögerung, Idle Callback oder scheduler.yield()?
- Kompromisse
Das Problem mit synchronem dataLayer.push()
Wenn Sie mit Google Tag Manager arbeiten, kennen Sie dataLayer.push(). Es ist die Standardmethode zum Senden von Events an den Data Layer und ist tief in die meisten Website-Funktionalitäten integriert. Das Problem ist, dass niemand hinterfragt, wann es ausgeführt wird.
Wenn dataLayer.push() direkt innerhalb eines Event-Handlers aufgerufen wird (ein Button-Klick, eine Formular-Übermittlung, ein Menü-Toggle), wird es synchron ausgeführt. GTM-Tags, die für dieses Event konfiguriert sind, werden ebenfalls sofort ausgeführt und blockieren den Main Thread, bevor der Browser das Layout aktualisieren kann. Der Besucher klickt einen Button und sieht nichts passieren, während GTM Tracking-Skripte im Hintergrund verarbeitet. Diese Verzögerung ist Ihr Presentation Delay und der Hauptverursacher eines schlechten INP.
Der Performance-Trace unten, von einer großen Nachrichtenwebsite, zeigt GTM-Aktivität nach einer Nutzerinteraktion. Die GTM-Tasks benötigten etwa 90ms zur Ausführung und trieben den gesamten INP auf 263ms. Diese Interaktion besteht die Core Web Vitals nicht.

Die Lösung: Erst rendern, dann pushen
Die Lösung entspricht der INP-Optimierungsanleitung von web.dev: Dem Main Thread nachgeben, damit der Browser rendern kann, bevor nicht-kritischer Code ausgeführt wird. Statt Tracking synchron innerhalb des Event-Handlers auszuführen:
- Führen Sie den Code für die visuelle Aktualisierung sofort aus.
- Lassen Sie den Browser rendern.
- Dann pushen Sie zum dataLayer.
Hier ist dieselbe Interaktion nach Anwendung dieses Musters. Die einzige Änderung ist, dass dataLayer.push() jetzt nach dem nächsten Browser-Paint ausgeführt wird.

Die Interaktion, die zuvor nicht bestanden hat, besteht jetzt komfortabel. Alle Daten erreichen weiterhin den dataLayer. Der Unterschied ist, dass GTM-Skripte nach der Browser-Antwort auf die Nutzeraktion ausgeführt werden, nicht davor.
Der awaitPaint-Helfer
Dieser Helfer verwendet requestAnimationFrame, um einen Callback nach dem Browser-Paint zu planen. Das verschachtelte setTimeout stellt sicher, dass die Funktion nach Abschluss des Paints ausgeführt wird, nicht nur davor. Dies ist das von web.dev empfohlene Muster zum Verzögern nicht-kritischer Arbeit nach einer Interaktion.
async function awaitPaint(fn) {
await new Promise((resolve) => {
// Fallback: ensures we don't hang if RAF never fires (e.g. background tabs)
setTimeout(resolve, 200);
// Schedule after the next paint
requestAnimationFrame(() => {
setTimeout(resolve, 50);
});
});
if (typeof fn === 'function') {
fn();
}
}
Verwendung des Helfers
Umschließen Sie jeden dataLayer.push()-Aufruf mit awaitPaint, um ihn bis nach dem Paint zu verzögern:
function pushToDataLayer(event, data) {
window.dataLayer = window.dataLayer || [];
awaitPaint(() => {
window.dataLayer.push({
event,
...data,
timestamp: new Date().toISOString()
});
});
}
// Usage
document.querySelector('.buy-button').addEventListener('click', () => {
// Visual feedback happens immediately
showLoadingSpinner();
// Tracking fires after paint
pushToDataLayer('purchase_click', { productId: '123' });
});
Globales Override zum schnellen Testen
Um dieses Muster auf Ihrer gesamten Website zu testen, ohne jeden dataLayer.push()-Aufruf umzuschreiben, können Sie die Push-Funktion global überschreiben. Platzieren Sie dieses Skript im <head> direkt nach dem GTM-Container-Snippet.
<script type="module">
window.dataLayer = window.dataLayer || [];
async function awaitPaint(fn) {
return new Promise((resolve) => {
const fallbackTimeout = setTimeout(() => {
if (typeof fn === 'function') { fn(); }
resolve();
}, 200);
requestAnimationFrame(() => {
setTimeout(() => {
clearTimeout(fallbackTimeout);
if (typeof fn === 'function') { fn(); }
resolve();
}, 50);
});
});
}
if (window.dataLayer && typeof window.dataLayer.push === 'function') {
const originalPush = window.dataLayer.push.bind(window.dataLayer);
window.dataLayer.push = function (...args) {
(async () => {
await awaitPaint(() => {
originalPush(...args);
});
})();
};
}
</script>
Dies überschreibt jeden dataLayer.push() auf der Seite. Alle bestehenden GTM-Event-Trigger, fest codierte Tracking-Aufrufe und Plugin-Integrationen profitieren automatisch ohne jegliche Code-Änderungen.
Warum dies den INP verbessert
INP misst die Zeit von einer Nutzerinteraktion bis der Browser die visuelle Antwort rendert. Wenn Sie synchron GTM-Event-Verarbeitung innerhalb eines Event-Handlers ausführen, blockieren Sie den Main Thread und verhindern das Rendering. Der 2024 Web Almanac stellte fest, dass Presentation Delay im Median der größte Verursacher eines schlechten INP ist, und Tracking-Skripte gehören zu den Hauptursachen.
Die Zahlen bestätigen dies. Der 2025 Web Almanac zeigt, dass insgesamt 77% der mobilen Seiten den INP bestehen, aber nur 63% der Top-1.000 meistbesuchten Websites. Diese Top-Websites laden mehr Third-Party-Skripte. Bei Subito (Italiens größtem Kleinanzeigenmarktplatz) senkte das Deaktivieren eines einzelnen TikTok-Tracking-Skripts, das über GTM geladen wurde, den INP von 208ms auf etwa 170ms. Ein Skript, 38ms eingespart.
Indem Sie dataLayer.push() bis nach dem Paint verzögern, verschieben Sie die gesamte GTM-Verarbeitung aus dem kritischen Pfad der Interaktion. Der Nutzer erhält sofort visuelles Feedback. GTM feuert weiterhin, nur 50 bis 250ms später.
Warum keine feste Verzögerung, Idle Callback oder scheduler.yield()?
- Festes
setTimeout(delay): Eine fest codierte Verzögerung (z.B.setTimeout(..., 100)) rät, wann das Rendering abgeschlossen sein wird. Zu lang und Sie verzögern das Tracking unnötig. Zu kurz und Sie blockieren immer noch den Paint. requestIdleCallback: Plant Arbeit ein, wenn der Browser idle ist, garantiert aber keine prompte Ausführung nach einer bestimmten Interaktion. Der Callback könnte viel später ausgeführt werden oder gar nicht, bevor der Nutzer die Seite verlässt.scheduler.yield(): Die moderne API zum Nachgeben an den Main Thread. Sie bewahrt die Task-Priorität (im Gegensatz zusetTimeout, das Ihre Fortsetzung ans Ende der Queue schickt). Allerdings garantiertscheduler.yield()nicht, dass ein Paint stattgefunden hat, bevor Ihr Code ausgeführt wird. Für diesen spezifischen Anwendungsfall istrequestAnimationFramedas bessere Werkzeug, da es an den Rendering-Lebenszyklus gebunden ist. Beachten Sie, dassscheduler.yield()in Safari noch nicht unterstützt wird.
Die Kombination aus requestAnimationFrame + setTimeout ist speziell für dieses Szenario konzipiert. requestAnimationFrame wird kurz vor dem Browser-Paint ausgelöst. Das verschachtelte setTimeout erstellt einen neuen Task, der nach Abschluss des Paints ausgeführt wird. Zusammen garantieren sie, dass Ihr verzögerter Code nach der visuellen Aktualisierung ausgeführt wird, was genau das ist, was INP misst.
Kompromisse
- Minimale Verzögerung bei der Datenerfassung: Events erreichen GTM 50 bis 250ms später als bei synchronem Push. Für Analytics und Marketing-Tracking ist dies unerheblich.
- Datenverlust bei schnellem Verlassen: Wenn ein Besucher ein Event auslöst und die Seite innerhalb des Verzögerungsfensters verlässt, wird dieses Event möglicherweise nicht ausgelöst. Für kritische Events vor einer Weiterleitung oder dem Verlassen der Seite verwenden Sie
navigator.sendBeacon()anstelle vondataLayer.push(). Siehe Argumente für die Begrenzung von Analytics-Skripten für mehr zur Beacon API.
Für die meisten Tracking-Szenarien überwiegt der INP-Gewinn bei weitem die minimale Verzögerung. Wenn Sie millisekundengenaue Event-Protokollierung benötigen (Echtzeit-Bidding, Finanz-Dashboards), ist dieser Ansatz nicht geeignet. Für alles andere ist es ein klarer Gewinn.
Überprüfen Sie nach Anwendung des Overrides die Verbesserung mit Real User Monitoring. Lab-Tests zeigen den Unterschied, aber Felddaten von echten Nutzern auf echten Netzwerken sind das, was für Ihre Core Web Vitals Bewertungen zählt.
Pinpoint the route, device, and connection that fails.
CoreDash segments every metric by route, device class, browser, and connection type. Real time data. Not the 28 day average Google gives you.
Explore Segmentation
