Hybrid Search — Events
Run your own code when a search goes out, when its results and its answer show, and when the reader rates the answer.
Hybrid Search runs two parts, the search results and the answer, and each part
emits its own events. Below we listen to both, list the events each part goes
through, and then look at the data event, which tracks the responses
themselves.
You need a working Hybrid Search page first. See Hybrid Search — Quick Start.
Listen to an event
Call on with the event name and a function. The search results emit on
client.ui.hybridSearch, and the answer emits on
client.ui.hybridSearch.answer:
const workflow = client.ui.hybridSearch;
workflow.on("done", () => {
console.log("Results shown");
});
workflow.answer.on("done", () => {
console.log("Answer done", workflow.questionId);
});
An event on one part does not reach the other. To know when the answer is
done, listen on answer.
on returns a function. Call it to remove the listener:
const off = workflow.on("request", ({ payload }) => {
console.log("Search", payload.q);
});
off();
Search results events
Each search goes through these events in order. Each one fires at most once for a search:
| Event | Fires when |
|---|---|
request | The SDK sends a request to Miso. payload is the request body. |
loading | The request is out, and the SDK waits for the results. |
ready | The results show. |
done | The results show. Hybrid Search emits it right after ready. |
interrupt | A new search replaced this one before its results arrived. |
error | The search failed. |
finally | The search has ended, in any of the three ways above. |
A search always ends with one of done, interrupt and error, and then
with finally.
A new query starts a new search, and so does a change of facet or sort order.
The events above then fire again. When the reader scrolls for more results,
the search stays the same, so only request and data fire.
request carries type, which says why the SDK sent it:
type | Sent when |
|---|---|
query | The reader searches. |
refine | The reader changes a facet or the sort order. |
more | The reader scrolls for more results. |
Apart from request, these events carry:
| Property | What it holds |
|---|---|
session | The session of the search. A new search gets a new session. |
status | loading, ready or erroneous. |
Answer events
The answer starts with each new query. A change of facet or sort order keeps the answer as it is. Each answer goes through these events in order:
| Event | Fires when |
|---|---|
request | The SDK asks Miso for the answer, after the search results arrive. |
loading | The SDK waits for the answer. |
ready | The answer starts to show. |
blocked Since 1.13.0 | Miso withheld the answer, for example at a metering limit. blockedReason says why. |
done | The full answer is on screen. |
interrupt | A new query replaced this one before its answer finished. |
error | The answer failed. |
finally | The answer has ended, in any of the three ways above. |
These events carry session, status and ongoing. ongoing is true while
more of the answer is on the way.
ready and done follow what is on screen. done fires when the last word of
the answer shows, which is after the last part of the response arrives. To act
on the response as it arrives, use the data event.
The answer also emits answer-stage each time its progress label changes,
with the label in answer_stage. Use it for display only. The labels change
without notice, so do not branch on them.
Feedback event
feedback fires on the answer when the reader clicks Helpful or Not
helpful:
const workflow = client.ui.hybridSearch;
workflow.answer.on("feedback", ({ value, unselected }) => {
if (unselected) {
return; // the reader cleared their choice
}
console.log(workflow.questionId, value);
});
value is helpful or unhelpful. A second click on the same button clears
the choice. The event then carries unselected: true and no value.
The SDK sends the feedback to Miso by itself. Listen to this event only to send it somewhere else as well.
The data event
data fires each time the data of a part changes. Each part has its own
data event, and each one carries the data object:
| Property | What it holds |
|---|---|
session | The session of the search or the answer. |
status | initial, loading, ready or erroneous. |
ongoing | On the answer, true while more of the response is on the way. |
request | The request that the SDK sent, with the body in request.payload. |
value | The response. See below for each part. |
error | The error, when status is erroneous. |
The event shows the data after each
data processor has run, so
a field you changed there arrives changed here. The event cannot change the
data. To change what Hybrid Search shows, use useDataProcessor.
Search results
On client.ui.hybridSearch, value is the
Hybrid Search API response, with products,
total and facet_counts:
client.ui.hybridSearch.on("data", ({ status, value }) => {
if (status !== "ready") {
return;
}
console.log(value.products.length, "of", value.total);
});
For one search, data fires with status: "initial", then loading, then
ready. When the reader scrolls for more, it fires again with loading and
then ready. value.products then holds every result loaded so far, the new
page included.
Answer
On client.ui.hybridSearch.answer, value is the
Answer API response, with answer, sources and the
other fields:
client.ui.hybridSearch.answer.on("data", ({ status, ongoing, value }) => {
if (status !== "ready" || ongoing) {
return;
}
console.log(value.sources);
});
For one answer, data fires in this order:
status: "initial"when the new query starts.status: "loading"while the search and then the answer are on the way.status: "ready"andongoing: truefor each part of the response. This repeats as the answer streams in.status: "ready"andongoing: falsewhen the response is complete.
data comes before the lifecycle events. The response is complete at
ongoing: false, but the answer can still be typing out on screen until
done.
If it does not work
| Symptom | Cause |
|---|---|
| The answer emits nothing | The listener is on client.ui.hybridSearch. Set it on client.ui.hybridSearch.answer. |
loading and done do not fire for more results | Scrolling for more stays in the same search. Listen to request or data. |
value.answer is undefined | The listener is on the search results. Set it on answer. |
| A listener runs many times for one answer | It listens to data, which fires for each part of the response. Use done, or check ongoing. |
| Nothing fires and an error shows in the console | The function throws. The SDK logs the error and goes on. |
Next
- API Configuration — change the request and the response.
- Ask — Events — the events of the question box.
- Events & Custom JS — run your own code on the page.
