Closed nicholaskillin closed 3 years ago
Hi @nicholaskillin .
First, thanks for the great feedback.
With the naming you chose for your index zendesk_all_articles
, most of the functionality should work as expected because we mostly use the subdomain
param to compute the index name (we also use it for the powered by link, that you can remove with poweredBy: false
if you're a paying customer).
Just a few notes for future readers that would like to do the same:
en-us
in /hc/en-us/articles
):
all
index needs to have locale.locale
in attributesForFaceting
articleSubdomain
Then you'll hit the main roadblock: clicking on a result will not redirect to the correct location.
Indeed, as you can see, both our autocomplete
& instantsearch
will use an absolute URL without the domain:
The reason for that is a cosmetic one: when a user hovers over the link in instantsearch, we don't want to display https://algolia-support.zendesk.com/hc/en-us/articles/123
, but rather https://support.algolia.com/hc/en-us/articles/123
.
To override the behavior on selection, you have the possibility to override the autocomplete:selected
event of the autocomplete.
To do so, you can first store the result of algoliasearchZendeskHC
in a variable.
This stores a variable for the Autocomplete instance, which itself stores all the autocomplete.js
instances.
Modifying this is considered as a hack, and you shouldn't expect future updates' code to be compatible with this, you should hence pin the library version as described here.
var zendeskSearch = algoliasearchZendeskHC(/* ... */);
var autocompletes = zendeskSearch.search.autocompletes || [];
for (let i = 0; i < autocompletes.length; ++i) {
var autocomplete = autocompletes[i];
autocomplete.off('autocomplete:selected'); // Remove default handler
autocomplete.on('autocomplete:selected', function (event, suggestion, dataset) {
console.log(event, suggestion, dataset);
// Your custom redirect logic here
});
}
EDIT: This is not enough, see answer below for a complete solution for the autocomplete.
For instantsearch, it will be easier to handle.
As you can see from the link before, the links there are handled directly as <a>
tags in the instantsearch.hit
template.
You can read how to override a template here: https://community.algolia.com/zendesk/documentation/#modifying-templates .
Assuming you've put each record's subdomain in a subdomain
attribute, you could modify it to have the complete URL with something like this:
algoliasearchZendeskHC({
appId: 'xxxx',
// ...
templates: {
instantsearch: {
hit: algoliasearchZendeskHC.compile(`
<div
class="search-result"
>
...
<a class="search-result-link" href="https://[[subdomain]].zendesk.com[[ baseUrl ]][[ locale.locale ]]/articles/[[ id ]]">
[[& _highlightResult.title.value ]]
</a>
...
</div>
`)
}
}
});
Hi @Jerska,
Thank you for the detailed answer! That all makes sense to me in theory. However, I added all of that to my document_head.hbs
file in Zendesk and it didn't seem to change anything. I suspect this is because that for loop is running when the page first loads, and at that time, there are no autocompletes. I tried adding a simple console.log
to the for loop and nothing ever gets logged after searching. Here is what I have:
<script type="text/javascript">
var zendeskSearch = algoliasearchZendeskHC({
applicationId: [applicationId],
apiKey: [apiKey],
subdomain: 'all',
debug: true,
});
var autocompletes = zendeskSearch.search.autocompletes || [];
for (let i = 0; i < autocompletes.length; ++i) {
var autocomplete = autocompletes[i];
console.log(autocomplete)
autocomplete.off('autocomplete:selected'); // Remove default handler
autocomplete.on('autocomplete:selected', function (event, suggestion, dataset) {
console.log(event, suggestion, dataset);
// Your custom redirect logic here
});
};
</script>
I have a feeling I just have this code in the wrong place. Any advice for how to get this loop working?
So it turns out if I console.log(zendeskSearch.search)
from inside a $(document).ready()
function I can see that autocompletes
is an array with 3 objects in it.
However, if I console.log(zendeskSearch.search.autocompletes)
from the same function I just get an empty array.
That would indeed make sense, as this is only populated when render
is called, which is only called instantly if the DOM is already ready or on DOM ready when it's not yet the case.
I tried to run this code on an already loaded page from my console and didn't think twice about whether or not this would work right after the invocation.
There is one little thing we need to do to also handle future calls, as you properly suggested in your initial message: overriding Autocomplete._onSelected
.
Fortunately, JavaScript is a language which allows us to modify an object methods, so it could be done like so:
var zendeskSearch = algoliasearchZendeskHC(/* ... */);
function handleSelected(event, suggestion, dataset) {
console.log(event, suggestion, dataset);
// Your custom redirect logic here
}
// Handle future `render` invocation
if (zendeskSeach.search.__proto__._onSelected) {
zendeskSearch.search.__proto__._onSelected = function () {
return handleSelected;
}
}
// Handle already called `render`
var autocompletes = zendeskSearch.search.autocompletes || [];
for (let i = 0; i < autocompletes.length; ++i) {
var autocomplete = autocompletes[i];
autocomplete.off('autocomplete:selected'); // Remove default handler
autocomplete.on('autocomplete:selected', handleSelected);
}
As long as you keep your code in the document_head.hbs
template, it should always only rely on the "Handle future render invocation" code path, but my guess is that it's safer to have both.
That worked great. Thank you so much!
Thanks for keeping us updated! I'm glad it did!
Just as an update to this, turns out this did not fully fix the integration for us. If someone searches and hits return
instead of selecting an article, then they are taken to a new page that displays the results.
InstantSearch has an onClick
handler that has the same behavior as onSelected
, so we had to override onClick
as well for that page.
For anyone reading in the future, to fix this we just added this to the above solution.
if (zendeskSeach.search.__proto__._onClick) {
zendeskSearch.search.__proto__._onClick = function () {
return handleSelected;
}
}
Thanks for the follow-up @nicholaskillin . I'm suprised though, nowhere do we define this function in the sources.
Also, in the code you provide, I would have expected handleSelected()
not handleSelected
.
For me, the solution in the instantsearch page is to override the hit template, which includes the link to the article. (See my first message, "Instantsearch" section)
🤦 Oops. I wrote onClick
but overrode trackClick
which has a totally different purpose. I'll try overriding the template instead. Thanks!
Hey,
So we are using this integration with Zendesk and love it. However, we have run into a bit of a snag with one of our subdomains.
We have several subdomains for different products, with each of them using this integration as is.
We also have one subdomain that is the main landing page for our support. We want to build out a search here that searching all of our articles across all of our indices.
We have already created the main index that houses all of those articles and you can search all of the articles from our main support page.
However, when you select an article, the URL that is passed to the window location is a relative link. Since the articles don't actually live in this subdomain, that is causing things to break.
We would love it if we had the option to pass in a custom URL formula that is used in the
_onSelected
function of the AutoComplete class. Any change this is something you would consider?