Hooks und Live-Suche
Über die integrierten Helper hinaus stellt der Assistent einige Hooks bereit – Helper, deren Standardversion nichts tut, sodass sich das Widget genau wie bisher verhält, bis Sie sie überschreiben. Sie überschreiben sie wie jeden anderen Helper (in settings.extensions.helpers oder indem Sie zur Laufzeit von der einbettenden Seite aus skdwn.instance.helpers.<name> zuweisen). Der Kern ruft sie zu bestimmten Zeitpunkten auf, Sie müssen also nichts in ein Template einbauen.
Event-Hooks
| Hook | Wird ausgelöst | Erhält |
|---|---|---|
onQuerySubmitted(query) | Direkt nachdem der Nutzer eine Frage abgeschickt hat. | query – den abgeschickten Text. |
onResponseReceived(result) | Wenn eine Antwort eintrifft. | result – { query, reply, references }. |
onFormSubmitted(formId, values) | Nachdem ein Formular abgeschickt wurde. | formId und das Objekt values mit den abgeschickten Werten. |
Sie geben nichts zurück – nutzen Sie sie für Seiteneffekte wie Analytics, Ihre eigene Oberfläche oder die Benachrichtigung der Host-Seite. Zum Beispiel, um jede Frage und Antwort an Ihre Analytics weiterzuleiten:
// settings.extensions.helpers
{
onQuerySubmitted: (query) => window.analytics?.track('assistant_question', { query }),
onResponseReceived: (result) =>
window.analytics?.track('assistant_answer', {
query: result.query,
sources: (result.references || []).length,
}),
onFormSubmitted: (formId, values) =>
window.analytics?.track('assistant_form', { formId, ...values }),
}
Die Standardversionen tun nichts
Jeder Hook wird als leere Funktion ausgeliefert; ihn unverändert zu lassen, ändert also nichts. Sie zahlen nur für das, was Sie überschreiben.
Live-Suche – searchProvider
searchProvider macht aus dem Suchfeld ein Feld mit Sofortvorschlägen: Während der Nutzer tippt, ruft der Assistent Ihren Provider auf (mit Debounce) und rendert, was dieser zurückgibt, als Dropdown unter dem Feld – bevor überhaupt eine vollständige Anfrage abgeschickt wird. Die Funktion ist deaktiviert, bis Sie einen Provider angeben.
Vertrag
// (query: string, ctx: { assistantId }) => Promise<Item[]> | Item[] | undefined
searchProvider: async (query) => {
const res = await fetch(`https://example.com/search?q=${encodeURIComponent(query)}`);
const rows = await res.json();
return rows.map((r) => ({
title: r.name, // shown text (and the query run if the row has no url)
url: r.href, // optional — see below
summary: r.excerpt, // optional secondary line
image: r.thumbnail, // optional thumbnail
metadata: { price: r.price }, // optional free-form, passed to the template
}));
}
Jedes Element ist { title, url?, summary?, image?, metadata? }:
title– der angezeigte Text und die Anfrage, die ausgeführt wird, wenn eine Zeile
ohne URL (oder ihr Ask-Button) angeklickt wird.
url– optional. Vorhanden → die Zeile ist ein Link, und ein Klick navigiert
dorthin (im selben Tab). Fehlt sie → ein Klick auf die Zeile führt den Titel als Anfrage aus.
summary– optionale zweite Zeile.image– optionales Vorschaubild.metadata– optionales, frei gestaltbares Objekt (Preis, Badges, Bewertung …). Das
ganze Element wird an das Template suggestion übergeben, sodass alles, was Sie hier ablegen, beim Umgestalten der Zeilen verfügbar ist.
Was der Nutzer sieht
- Während der Provider läuft, erscheint im Dropdown ein Lade-Skeleton, sodass das Feld
nie leer ist.
- Jede Zeile hat außerdem einen „Ask“-Button, der den Assistenten mit dem Titel dieser
Zeile als Anfrage öffnet – praktisch, um aus einem Ergebnis eine ausführlichere Frage zu machen.
- Das Dropdown schließt sich, wenn der Nutzer daneben klickt oder das Overlay öffnet.
Begrenzen Sie die Ergebnisse mit settings.suggestionsLimit (Standard 5). Dieser Wert existiert nur in den Einstellungen – legen Sie ihn in der Konfiguration des Assistenten fest; ein Bedienelement in der Oberfläche gibt es nicht.
Gestalten Sie die Zeilen um, indem Sie das Template suggestion (eine Zeile) überschreiben – der äußere Container suggestions bleibt unverändert. Das ganze Element ist als item verfügbar, sodass Sie Ihre metadata rendern können:
{% comment %} settings.extensions.templates.suggestion {% endcomment %}
<div class="skdwn-suggestion-row" role="option">
<a class="skdwn-suggestion" href="{{ item.url }}" onclick="skdwn.instance.helpers.dismissSuggestions()">
<span class="skdwn-suggestion-text">
<span class="skdwn-suggestion-title">{{ item.title | escape }}</span>
{% if item.metadata.price %}<span class="skdwn-suggestion-summary">{{ item.metadata.price }}</span>{% endif %}
</span>
</a>
<button type="button" class="skdwn-suggestion-ask" data-query="{{ item.title | escape }}"
onclick="skdwn.instance.helpers.askSuggestion(this)">{{ 'ask' | t: 'Ask' }}</button>
</div>
Die Identität des Besuchers an Ihren Suchdienst weitergeben
Ein searchProvider läuft im Browser und kann daher jeden Endpunkt aufrufen, den die Seite erreicht. Benötigt Ihre Suche den angemeldeten Nutzer, übergeben Sie ein Token über startOptions.params und lesen Sie es in Ihrem Provider aus – derselbe Mechanismus, den Linked Services nutzen.