Connecting the Chat to Your Page#
Once the chat runs on your page, it can answer about the page that the reader is on, treat links to your site differently, take questions from your own buttons, open documents, and report what happens. For adding the chat, see the Add the Chat to Your Page page.
Answer about the Page the Reader Is On#
context tells the chat what the reader is looking at. The simplest option is to let the chat read the page itself, with context: 'auto' in initNeoSdk(), or on the element:
<neo-chat base-url="/api/chat" project-id="YOUR_PROJECT_ID" auth="anonymous" context="auto"></neo-chat>
With auto, each question carries the following:
The title of the page.
Its URL, without the query string or
#part, which often carry tokens or search terms.Its description and main text: the first of
[data-neo-context],#main-content,main,[role=main], andarticleon the page that has text in it, else the whole page body.
The chat never reads navigation, headers, footers, forms, form fields, hidden content, text in the shadow root of another web component, or the chat itself. It does read text that is rendered but out of sight, such as visibility: hidden or off screen. To keep anything else out, mark it with data-neo-exclude:
<div class="account-balance" data-neo-exclude>CHF 12 400</div>
A page can opt out entirely with <meta name="neo-context" content="none">, or send only its title and URL with content="title". Any other value also sends nothing. To tune what is read, pass options instead of 'auto':
context: {
root: '#main-content',
exclude: ['.cookie-banner'],
maxLength: 2000,
url: 'path', // 'canonical' (the default), 'path' or 'full'
},
Or write the function yourself. The chat calls it for each question:
context: () => ({
title: document.title,
url: location.origin + location.pathname,
text: document.querySelector('main')?.innerText ?? '',
}),
The page context goes out with the first question of a conversation, and again only when the reader has moved to another page, a route change in a single-page app included. It becomes part of the conversation stored on your Squirro instance. See the Where Conversations Are Kept section of the What Readers Share page.
Links in Answers#
The chat checks every link in an answer before it shows it:
Only
http,https,mailto, andtellinks are links. Anything else, such as ajavascript:link that a manipulated document could make the agent write, shows as plain text, and so does a link with a user name or password in it.A link is internal when it points at your site: the origin of the page by default, or the origins and URL prefixes in
links.site, which islink-siteon the tag. A prefix matches whole path segments only, sohttps://example.com/help/covers/help/webhooksbut not/helpdesk.Internal links open in a new tab by default, because a page load ends the conversation.
link-internal="same-tab"changes that.External
httpandhttpslinks open in a new tab, with a small icon that says so.link-external="block"shows them as text instead, for a deployment that must never send readers elsewhere.mailtoandtellinks open in the same tab, without the icon.
A single-page app routes internal links in place by giving the chat its router, which the chat calls for links on the origin of the page:
initNeoSdk({
// ...
links: {
site: ['https://docs.example.com'],
navigate: ({ path }) => router.navigate(path),
},
});
On a script-tag page, listen for the neo-chat-link event on the element, and call preventDefault() to take the link over:
<script>
document.querySelector('neo-chat').addEventListener('neo-chat-link', (event) => {
if (event.detail.internal) {
event.preventDefault();
myRouter.go(event.detail.path);
}
});
</script>
callbacks.onLinkClick(link) is the same hook as a function: return false to take the link over. It also suits analytics, since it receives every click except middle clicks.
Open a Document from Your Page#
sdk.openDocument({ itemId }) shows a Squirro document in a full-page overlay in front of your page, and sdk.closeDocument() closes it. Readers open the same overlay by clicking a source in an answer. The optional fields are the following:
title, the accessible name of the overlay, announced when it opens.pageNumber, 1-based, for a PDF.highlightFragments, the text to highlight. With apageNumber, every match is highlighted, but the viewer stays on that page.
For example, to open page 2 of a report from a button:
document.getElementById('open-report').addEventListener('click', () => {
sdk.openDocument({ itemId: 'the-squirro-item-id', title: 'Q3 report', pageNumber: 2 });
});
The overlay covers the whole window, above the floating chat and the fixed header of your site, whatever z-index your layout uses. It closes on Escape or from its close button.
The document view is read-only. Open original in its header opens a PDF, a PNG, JPEG, GIF, or WebP image, or a plain text file in a new tab, and downloads any other file, so that a stored file cannot run a script on your site.
If you pass your own callbacks.onOpenSidePanel, it replaces that behavior: clicking a source calls your callback, and the overlay does not open. You can still call sdk.openDocument() from it.
PDF documents use the Nutrient viewer, which your proxy serves together with its license key, so the page needs no key. See the Serve the PDF Viewer section of the Set Up the Proxy page. Use one pdfViewer setting per page, because the viewer keeps the first one for the whole page.
Listen to What Happens#
events reports what the chat does, for analytics or for your own UI. The onConversationStarted, onQuestionSent, and onAnswerCompleted events carry the ID of the conversation, so leave it out of what you send to analytics. See the What Readers Share page.
For every event, see the Events section of the Configuration Reference page.
For example, to count completed answers and their sources:
events: {
onAnswerCompleted: (event) => {
if (event.reason === 'completed') {
analytics.track('chat_answer', { sources: event.sources.length });
}
},
},