Nuxtstop

For all things nuxt.js

Getting Started With the Yext Answers API in VueJS

7 0

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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.

vue autocomplete

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.

Yext Answers Universal Search Results

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>
Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode

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.