Integrating Yext Answers API with Vue.js
The primary aim of this article is to show you how Yext Answers API can be integrated into a Vue.js app. The demonstration uses Vue 3, and Vite is used for scaffolding the app. The app is designed using Tailwind CSS. Note, however, that neither Vite nor Tailwind is a requirement for the app.
This example uses an Answers experience that can answer questions about how to make different beverages. Check out Yext Hitchhikers, where you can make a sandbox account to experiment with adding your own data.
Now let's move on to integrating Yext Answers using Vue 3.
Scaffolding a Vue 3 App and Installing Dependencies
As mentioned, Vite is used to scaffold the application in this article. Vite is often the better alternative to frontend tools like Webpack, Rollup, and Parcel. For one, Vite provides a quick and easy-to-use environment that doesn’t require long builds to get started. For another, it also addresses the problem of slow server start and makes the server start faster. Vite documentation lays out more information about the benefits of using Vite.
To scaffold a new Vue project using Vite, run the following command in your terminal:
npm create vite@latest
After running the command, it'll ask you to specify a package name and the template you want to use. Select Vue for the template, and it'll use Vue 3 by default. As the scaffolding process completes, enter cd
into the directory and run npm i
to install the dependencies. Then run the server with npm run dev
. Your server will start on localhost.
The only necessary dependency needed for this article is the @yext/answers-core
. To install it, run the command npm i @yext/answers-core
in your terminal. Other than that, Tailwind CSS is used to design the app. To better understand how Tailwind can be added to this app, follow the guide to installing Tailwind CSS with Vue 3 and Vite.
Building a Universal Autocomplete Component
This article will showcase how the Answers core SDK can be used.
Create a new file called UniversalAutocomplete.vue
in the components
directory inside the src
folder. Before adding the universal autocomplete feature, you should first review the created file:
<template>
<div class="bg-gray-50 min-w-screen min-h-screen flex justify-center py-10">
<div class="max-w-lg relative space-y-3 text-center">
<h3 class="font-extrabold text-lg">Universal Autocomplete</h3>
<label for="search" class="text-gray-900">
Type the name of a data to search(examples: "how", "cider", etc.)
</label>
<input
type="text"
id="search"
v-model="searchTerm"
placeholder="Type here..."
class="p-3 mb-0.5 w-full border border-gray-300 rounded"
/>
<ul
v-if="result.results !== undefined"
class="
w-full
rounded
bg-white
border border-gray-300
px-4
py-2
space-y-1
absolute
z-10
drop-shadow-md
"
id="results"
>
<li class="px-1 pt-1 pb-2 font-bold border-b border-gray-200">
Showing {{ result.results.length }} results
</li>
<li
v-for="r in result.results"
:key="r.id"
@click="selectResult(r.value)"
class="cursor-pointer hover:bg-gray-100 p-1"
>
{{ r.value }}
</li>
</ul>
<ul
v-if="selectedResult.length"
class="text-lg pt-2 z-0 grid grid-cols-1 md:grid-cols-2"
>
<li
v-for="r in selectedResult"
:key="r.id"
class="
inline-block
bg-gray-200
rounded-md
px-3
py-1
text-gray-700
mr-2
mb-2
"
>
<a class="text-lg font-semibold underline text-blue-600" href="#">{{
r.name
}}</a>
<div v-html="r.description"></div>
</li>
</ul>
</div>
</div>
</template>
<script>
import { ref, watchEffect } from "vue";
import { provideCore } from "@yext/answers-core";
const core = provideCore({
apiKey: '4be28826989e90232722e9bf2769fbf2',
experienceKey: 'cpg-beverages',
locale: 'en',
experienceVersion: 'PRODUCTION',
});
export default {
setup() {
let searchTerm = ref("");
let result = ref([]);
let selectedResult = ref("");
const searchResults = watchEffect(async () => {
if (searchTerm.value === "") {
return [];
}
result.value = await core.universalAutocomplete({
input: searchTerm.value,
});
document.getElementById("results").style.display = "block";
});
const selectResult = async (result) => {
searchTerm.value = "";
const r = await core.universalSearch({
query: result,
});
console.log(r);
let ansArr = [];
r.verticalResults.reduce((acc, cur) => {
cur.results.forEach((res) => {
if (res.description !== undefined) {
acc.push(res);
}
});
return acc;
}, ansArr);
selectedResult.value = ansArr;
console.log(ansArr);
document.getElementById("results").style.display = "none";
};
return {
searchTerm,
result,
searchResults,
selectResult,
selectedResult,
};
},
};
</script>
Focusing on the script
, the first step is to import the necessary objects. The ref
and watchEffect
are imported from vue
, followed by provideCore
, which is imported from @yext/answers-core
.
The Answers Core is then initialized in the core
variable. The provideCore
function takes a AnswersConfig
object as a parameter that needs to include an apiKey, experienceKey, and locale.
💡
If you're using a Yext sandbox account, you'll also need to pass the sandbox endpoints to Answers Core.
The setup
script is the entry point for using the composition API. Inside the setup
function, the searchTerm
value, the selectedResult
value and the result
value are initialized using ref
. The next step is to create a function that will return the search results. The function is named searchResults
, and it uses the watchEffect
hook. The watchEffect
hook is introduced in the Vue 3 composition API. This watchEffect hook runs a function immediately while reactively tracking its dependencies.
Because the API call is asynchronous, async-await
is used. The first step inside this function is to check if the searchTerm
is empty. The searchTerm
is bound with the input field using v-model= "searchTerm"
. If the input field is empty, the result is assigned to an empty array. Otherwise, the code moves forward.
The answers-core
library uses the universalAutocomplete
method to get the autocomplete results. The process takes an object as a parameter where the only required parameter is the query
. The searchTerm
value, received from the input field is passed in the query
key. The result returned from the SDK is stored inside the result
ref.
The selectResult
function below the searchResults
function is used to call the universalSearch
method. This method is used to search across all verticals. Depending on a selected search result, this function is called to get data depending on the query. The universalSearch
method also needs a single necessary parameter, i.e., the query. The selected result from the universalAutocomplete
is passed as the query. The received results are stored in the r
variable. You can see the received result by console logging the variable. The r
variable holds a lot of data. For simplicity in this article, you’ll only use a few values from the result.
When an autocomplete search result is selected, the description received from the universalSearch
method will be shown to the user. Because the universalSearch
method is used to search across all verticals; results received from all the verticals will be merged into a single array. The aim is to show the description and name of each search result.
You can also create separate tabs for search results depending on the verticals. Each vertical holds the results in an array. To merge the results into a single array, an empty array called ansArr
is defined. The verticalResults
object holds all the vertical results. The reduce
method is used in this object. The reduce method
is a higher-order JavaScript function that executes a reducer function on each array element and returns a single value.
On each element, another forEach
loop is run because each element holds an array that contains the results. The image below will help you better understand the structure of the data.
Inside the forEach
loop, if an object description is not empty, the result is pushed into the ansArr
array.
Once the single array is generated, the selectedResult
is initialized with the array. You can now show the results in the DOM. But before moving to show the data, one last step needs to be taken. Whenever a result is selected and the description is shown, you need to hide the search results. A simple display: none;
property is added to the autocomplete search results using JavaScript.
To display the autocomplete results, an unordered list is used. The unordered list is only displayed when the result.results
array is not undefined. The condition is tested using v-if
.
<li class="px-1 pt-1 pb-2 font-bold border-b border-gray-200">
Showing {{ result.results.length }} results
</li>
<li
v-for="r in result.results"
:key="r.id"
@click="selectResult(r.value)"
class="cursor-pointer hover:bg-gray-100 p-1"
>
{{ r.value }}
</li>
The first li
item shows the number of search results. The second list item holds the autocomplete results And renders all the results using a v-for
loop. Whenever a search result is clicked, the selectResult
function is called, and the selected value is passed into the function. The explanation of the function is described above.
Similar to rendering the autocomplete results, the universal search results are also displayed using an unordered list. Only the name
and the description
from the results are shown. Yext Answers also provides the search data in HTML format to make the query bold in the results. To render the raw HTML queries v-html
is used.
If you import the UniversalAutocomplete
component to your App.vue
file and render it, you'll be able to search the available questions. The App.vue
file should look like this:
<script setup>
import UniversalAutocomplete from "./components/UniversalAutocomplete.vue";
</script>
<template>
<UniversalAutocomplete />
</template>
You can similarly make a vertical autocomplete component using the vertical autocomplete method.
The universal search and the universal autocomplete features are shown in the example code, which has been written using the required parameters only. You can customize your search even more using the parameters. You can visit sandbox or GitHub to explore how the searches are implemented.
Conclusion
This article covered the basics of integrating Yext Answers with a Vue 3 app. It also covered how a Yext Answers Experience can be set up. The article's primary aim was to help you get started with the Yext Answers API. If you want to know more about the API and delve deeper, you can create a Yext Hitchhikers account, which can help you learn and experiment with an array of Yext products.
Credits: This article was first published on Yext Hitchhikers by Subha Chanda.
Top comments (0)