Hand-off actions

A hand-off action is a route to a person or service that the AI assistant offers with an answer. Examples are a contact form, a phone number, or a live-chat window. You define actions per site. The assistant offers at most one with each reply.

Action types

TypeThe visitor sees
linkA button that opens an https URL.
phoneA button that dials the number. The number is shown as visible text next to the button.
emailA button that opens a new email to the address. The address is shown as visible text next to the button.
messageA block of text you wrote. There is no button.
eventA button that fires a JavaScript event on your page. Your own code decides what happens.

Quant Search does not integrate with any live-chat product. For live chat, use an event action and write the few lines of JavaScript that open your chat product.

Write the label as what the button does

The assistant refers to the button by its label, for example "Use the "Chat with an adviser" button below." Write a label that says what happens when the visitor presses it: "Chat with an adviser", "Call us", "Open the complaints form". Do not use a label such as "Click here" or "More". The assistant knows what each type of button does (a link opens a page, a phone button shows a number to call), but it does not know what your page does with an event. The label is the only description it has.

How the assistant decides

The assistant checks these in order and stops at the first action that applies.

  1. Phrases. If the visitor's question contains one of an action's phrases, the assistant offers that action. Matching is by whole words, ignores case and punctuation, and is not a substring match: the phrase "rate" does not match "accurate". If several actions match, the one earlier in your list wins. A phrase overrides the assistant's own judgement.
  2. Intent. If an action has an intent (a plain-words description of when to offer it) and the assistant judges that the question fits, the assistant offers the action. An action with nointent is never chosen this way. The assistant is told to keep the intent private, but a visitor may be able to make it repeat the text. Write the intent as if visitors can see it: do not put internal information in it.
  3. No answer. If the assistant has no answer, it offers the action marked onNoAnswer. One action per site can have this flag.

Usually the assistant writes its answer as normal and adds the action. If the visitor only asks for a person (for example "I want to talk to a person"), the reply is a short sentence that points to the button, then the action'sresponse if you set one. When a phrase matched, the reply starts with a sentence such as "Use the "Open the form" button below to open the page." For an event action matched by a phrase, that sentence is the whole reply. For a message action, the reply introduces the message and the message follows. A disabled action is never offered.

The assistant offers no action in these cases:

  • A crisis question (self-harm, family violence and similar). The answer shows the emergency-services line, as described in AI Answer Safety.
  • A question that the answer-safety screen blocks, or a site whose plan allowance is used up.
  • A reply where the answer-safety grounding check replaced the answer. Only the onNoAnswer action can appear.
  • Search groups. Groups do not offer actions. Only single sites do.

Phrases match only the words the visitor typed

Phrases are matched against the question after personal details are masked (seeAI Answer Safety). A masked detail, such as a phone number or an address, is removed before matching, so a phrase never matches it. A phrase such as "phone number" matches only when the visitor typed those words.

Business hours

Set hours to offer an action only when your team is available. The check runs on the server.

  • timezone is an IANA name such as Australia/Melbourne. Times in week are 24-hour local times in that zone.
  • Each window includes from and excludes to. A weekday with no entry is closed all day.
  • A window whose from is later than to (for example 22:00 to 06:00) crosses midnight. It belongs to the day it starts on.
  • A date in closedDates is a local date in timezone. It also closes the after-midnight part of a window that started on that date, because the window belongs to its start day.
  • to is exclusive. Use "to": "24:00" for the end of the day: a window of 00:00 to 24:00 is open all day. 24:00 is accepted as to only. A window of 00:00 to 23:59 leaves the last minute of the day closed.
  • from and to must differ: a window with equal times is rejected on save. In the dashboard, a time field cannot show 24:00, so enter From 00:00 To 00:00 for all day. The dashboard saves it as 00:00 to 24:00.
  • When the action that would be offered is closed, the reply shows outsideHoursResponse instead of the action. This applies whether a phrase matched it, the assistant chose it, or it is the no-answer fallback. If you do not set outsideHoursResponse, nothing is offered for that action while it is closed.
  • If a stored hours value is malformed, the action is treated as always open. The API rejects a malformed value on save, so this applies only to records edited outside the API.

The quantsearch:action event

When a visitor activates an event action, the widget dispatches a quantsearch:action event ondocument. The event bubbles and is cancelable.

e.detail.action;    // the eventName, for example "live_chat"
e.detail.actionId;  // for example "act_7f3k29xq1a"
e.detail.widget;    // "chat" | "modal" | "search-page"
e.detail.siteId;
e.detail.question;  // the masked question, or null (see below)
e.detail.data;      // the action's eventData, or {}
  • Call e.preventDefault(). This tells the widget that your page handled the event. If no handler calls it, the widget opens the action's fallbackUrl in a new tab. This covers a script that failed to load, was blocked, or is not deployed on that page.
  • question is null unless the action sets includeQuestionInEvent: true. When it is on, question holds the question after your organisation's answer-safety guardrail masked personal details in it (see AI Answer Safety). Each masked detail appears as plain words, for example "an email address". It is not the text in the input box. If the guardrail did not run for that question, for example because the guardrail call failed, question isnull. Write your handler so that it works without the question.
  • Treat e.detail as untrusted input. Any script on the page can dispatch aquantsearch:action event with any detail, and a handler cannot tell it from a real one. Check action against the event names you expect. Do not insert detail values into the page as HTML.
  • The event carries only the current question. It never carries the conversation.
  • A second activation of the same button within one second is ignored.
  • The same event fires from the chat widget, the modal and the search page. Read widget if your handler must tell them apart.

Worked example: a live-chat product

The action below shows a button on weekdays between 09:00 and 17:00 Melbourne time. It sends the masked question and a queue name to your chat product. includeQuestionInEvent is on so that the adviser sees what the visitor asked.

{
  "name": "Live chat",
  "type": "event",
  "label": "Chat with an adviser",
  "response": "An adviser can help with this.",
  "eventName": "live_chat",
  "fallbackUrl": "https://agency.example.gov.au/contact",
  "includeQuestionInEvent": true,
  "eventData": { "queue": "rates" },
  "intent": "The visitor wants to talk to a person about their rates notice",
  "phrases": ["speak to someone", "talk to an adviser"],
  "hours": {
    "timezone": "Australia/Melbourne",
    "week": {
      "mon": [{ "from": "09:00", "to": "17:00" }],
      "tue": [{ "from": "09:00", "to": "17:00" }]
    },
    "closedDates": ["2026-12-25"]
  },
  "outsideHoursResponse": "Our advisers are offline. Call 03 5555 0100 on a weekday."
}

Add the listener on every page that carries the widget.window.ExampleChat stands in for your own chat product's API.

document.addEventListener('quantsearch:action', (e) => {
  if (e.detail.action !== 'live_chat') return;

  // Tell the widget this page handled the event.
  // Without this call the widget opens fallbackUrl in a new tab.
  e.preventDefault();

  window.ExampleChat.open({
    queue: e.detail.data.queue,
    firstMessage: e.detail.question, // masked text, or null; untrusted input
  });
});

Save the action with PUT /api/sites/{siteId} in customActions. See theSites API for the limits on each field.

Common chat products

The listener below opens Intercom, Zendesk messaging or LiveChat, whichever is loaded on the page. If none is loaded, it does not call e.preventDefault(), so the widget opens fallbackUrl. Keep only the product you use. Vendors change their APIs: check each call against your vendor's current documentation.

document.addEventListener('quantsearch:action', (e) => {
  if (e.detail.action !== 'live_chat') return;
  const question = typeof e.detail.question === 'string' ? e.detail.question : '';

  // Intercom: open the messenger with the question in the composer.
  if (typeof window.Intercom === 'function') {
    e.preventDefault();
    window.Intercom('showNewMessage', question);
    return;
  }
  // Zendesk messaging (Web Widget): open the messenger.
  if (typeof window.zE === 'function') {
    e.preventDefault();
    window.zE('messenger', 'open');
    return;
  }
  // LiveChat: open the chat window.
  if (window.LiveChatWidget && typeof window.LiveChatWidget.call === 'function') {
    e.preventDefault();
    window.LiveChatWidget.call('maximize');
    return;
  }
  // No chat product loaded on this page: do not call preventDefault,
  // so the widget opens fallbackUrl.
});
  • Intercom puts the question in the message composer. The visitor can edit it before they send it.
  • Zendesk messaging and LiveChat open the chat window only. To give the adviser the question, use your vendor's own feature for conversation fields or visitor details, if your plan includes it.
  • Put the vendor's own script on the page as the vendor tells you. Quant Search does not load it. The listener must run on every page that carries the widget.

Test your integration

Do these checks on a test page before you turn the action on for visitors.

  1. Ask a question that contains one of the action's phrases. The reply shows the button with your label.
  2. Press the button. Your chat product opens, and no new tab opens.
  3. If includeQuestionInEvent is on, ask a question that contains an email address. The adviser sees "an email address" in its place, not the address.
  4. Remove the listener or block the chat product's script, then press the button again. The widget opensfallbackUrl in a new tab.
  5. Outside the action's hours, ask the same question. The reply showsoutsideHoursResponse and no button.
  6. Repeat the first two checks in each widget you use: the chat widget, the modal and the search page.

Behaviour to know about

  • The chat widget restores earlier messages from the visitor's browser. A restored reply keeps its text, including the text of a message action. It has no action button, link, phone number or email address, so a changed or disabled action never shows from an old reply.
  • The assistant offers at most one action per reply.
  • Test the replies you depend on, on your site's answer-safety level.

Privacy

Quant Search puts the question in the event only when you turn on includeQuestionInEvent, and only when the answer-safety guardrail masked it. Quant Search does not send it to a third party and does not give your page the conversation. The chat widget keeps its history in the visitor's browser storage across page loads. On a shared device, the next person can see it. The stored history keeps the visitor's messages, the reply text and the reply's source links. It keeps no action control, no event and no question that an action carried.

The quantsearch:action event is a normal DOM event on document. Every script on your page can read it, including third-party scripts such as tag managers, analytics and session-replay tools. Do not put anything ineventData, or turn on includeQuestionInEvent, unless you accept that those scripts can read it. Any script on the page can also dispatch a fake event, so treat e.detail as untrusted input in your handler.

If your handler sends data to a chat vendor or any other service, that transfer is your disclosure to make. Update your privacy notice (APP 5). Assess the use and disclosure (APP 6). If the service is outside Australia, assess the cross-border disclosure (APP 8). Quant Search is not part of that data path.