Hooks et recherche instantanée

Au-delà des helpers intégrés, l’assistant expose quelques hooks : des helpers dont les versions par défaut ne font rien, de sorte que le widget se comporte exactement comme avant tant que vous ne les surchargez pas. Vous les surchargez comme n’importe quel helper (dans settings.extensions.helpers, ou en assignant skdwn.instance.helpers.<name> à l’exécution depuis la page hôte). Le cœur les appelle à des moments précis : vous n’avez donc rien à câbler dans un template.

Hooks d’événement

HookDéclenchementReçoit
onQuerySubmitted(query)Juste après l’envoi d’une question par l’utilisateur.query : le texte envoyé.
onResponseReceived(result)À l’arrivée d’une réponse.result : { query, reply, references }.
onFormSubmitted(formId, values)Après l’envoi d’un formulaire.formId et l’objet values envoyé.

Ils ne renvoient rien : utilisez-les pour des effets de bord comme l’analytique, votre propre interface ou la notification de la page hôte. Par exemple, pour transmettre chaque question et chaque réponse à votre outil d’analytique :

// 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 }),
}

Par défaut, ils ne font rien

Chaque hook est livré sous forme de fonction vide : le laisser tel quel ne change rien. Vous ne payez que pour ce que vous surchargez.

Recherche instantanée : searchProvider

searchProvider transforme le champ de recherche en champ de suggestions instantanées : pendant que l’utilisateur tape, l’assistant appelle votre fournisseur (avec un debounce) et affiche ce qu’il renvoie dans une liste déroulante sous le champ, avant même l’envoi d’une requête complète. Il est désactivé tant que vous n’en fournissez pas un.

Contrat

// (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
  }));
}

Chaque élément a la forme { title, url?, summary?, image?, metadata? } :

  • title : le texte affiché, et la requête exécutée lorsqu’on clique sur une ligne sans URL

(ou sur son bouton Ask).

  • url : facultatif. Présent → la ligne est un lien et un clic y navigue (même onglet).

Absent → un clic sur la ligne exécute le titre comme requête.

  • summary : seconde ligne facultative.
  • image : vignette facultative.
  • metadata : objet libre facultatif (prix, badges, note…). L’élément entier est transmis

au template suggestion : tout ce que vous placez ici est donc disponible lorsque vous restylez les lignes.

Ce que voit l’utilisateur

  • Pendant l’exécution du fournisseur, un squelette de chargement s’affiche dans la liste

déroulante : le champ n’est jamais vide.

  • Chaque ligne dispose aussi d’un bouton « Ask » qui ouvre l’assistant avec le titre de la

ligne comme requête, pratique pour transformer un résultat en question plus riche.

  • La liste déroulante se ferme lorsque l’utilisateur clique en dehors ou ouvre l’overlay.

Limitez les résultats avec settings.suggestionsLimit (par défaut 5). Cette valeur ne se règle que dans les paramètres : définissez-la dans la configuration de l’assistant ; il n’existe aucun contrôle dans l’interface.

Restylez les lignes en surchargeant le template suggestion (une ligne) : le conteneur extérieur suggestions reste intact. L’élément entier est accessible sous le nom item : vous pouvez donc afficher vos metadata :

{% 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>

Transmettez l’identité du visiteur à votre service de recherche

Un searchProvider s’exécute dans le navigateur : il peut donc appeler n’importe quel endpoint accessible depuis la page. Si votre recherche a besoin de l’utilisateur connecté, transmettez un jeton via startOptions.params et lisez-le depuis votre fournisseur, le même mécanisme qu’utilisent les services liés.

Pour aller plus loin

Nous contacter

Besoin d’aide ?

Dites-nous à quelles questions votre assistant de site web doit répondre. Nous vous aiderons à identifier le bon contenu, les bons réglages et la meilleure façon de le lancer.