Widget laden wie ein Profi: Snippet, Timeout, Fallback
Das Zendesk-Snippet ist eine Zeile HTML. Deshalb wird sein Einbau selten zu Ende gedacht. Drei Dinge entscheiden, ob sich das Widget wie ein Teil deiner Seite anfühlt oder wie ein Fremdkörper: wann es rendert, wie du Ladefehler abfängst und was du zeigst, wenn es nicht lädt.
Das Snippet und die Warteschlange
<script id="ze-snippet" src="https://static.zdassets.com/ekr/snippet.js?key=DEIN_KEY"></script>
Sobald das Snippet ausgeführt ist, existiert window.zE, zunächst aber nur als Warteschlange: Aufrufe werden gesammelt und beim Boot nachgeholt. Deshalb funktioniert zE('messenger:set', 'locale', 'de') direkt nach dem Snippet, obwohl das Widget noch gar nicht da ist.
Der Haken: Nach dem Boot ersetzt Zendesk diese Funktion durch die echte API. Wer sich zE früh in eine Variable gelegt hat, ruft später die tote Warteschlange auf, ohne Fehler und ohne Wirkung. Die Lösung ist ein Wrapper, der window.zE bei jedem Aufruf frisch auflöst:
const ze = (...args) => window.zE?.(...args);
Auto-Render abschalten, bewusst rendern
Wer das Widget einbettet oder mit eigenem Launcher zeigt, will nicht, dass es beim Laden als Blase erscheint:
window.zEMessenger = { autorender: false };
// … Snippet laden, dann bewusst:
zE('messenger', 'render', { mode: 'embedded', widget: { targetElement: '#chat' } });
Wichtig: Die Flagge muss vor dem Snippet gesetzt sein, und pro Seite gibt es genau ein Snippet und einen Render-Modus.
Ladefehler sind der Normalfall, nicht die Ausnahme
static.zdassets.com steht auf den Blocklisten vieler Adblocker und Firmen-Proxies. Ohne Vorsorge bleibt dann einfach eine leere Fläche. Der Einbau gehört deshalb in eine kleine Ladefunktion mit onerror und Timeout:
function ladeWidget(key, timeoutMs = 8000) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => reject(new Error('timeout')), timeoutMs);
const script = document.createElement('script');
script.id = 'ze-snippet';
script.src = `https://static.zdassets.com/ekr/snippet.js?key=${key}`;
script.onload = () => { clearTimeout(timer); resolve(); };
script.onerror = () => { clearTimeout(timer); reject(new Error('blockiert')); };
document.head.appendChild(script);
});
}
Im Fehlerfall zeigst du statt des Widgets einen gestalteten Fallback: kurzer Hinweis («Vermutlich blockiert ein Adblocker …»), ein Neu-laden-Knopf, alternative Kontaktwege. Die Werkstücke hier zeigten diesen Zustand im Livebetrieb, solange sie das echte Snippet luden; seit sie als lokale Nachbildung ohne externe Requests laufen, bekommt ihn kaum noch jemand zu sehen. Für jeden echten Einbau bleibt das Muster Pflicht.
Checkliste
- Ein Snippet pro Seite,
autorenderbewusst gesetzt window.zEnie in eine Variable einfrierenonerror+ Timeout abfangen, Fallback gestalten statt leerer Fläche- Container fürs Einbetten muss beim Render existieren und Masse haben