Blog for Learning

| lesson material | material summary | questions and answers | definitions | types and examples | other information | materi pelajaran | ringkasan materi | pertanyaan dan jawaban | definisi | jenis-jenis dan contoh-contoh | informasi lainnya |

Powered by Blogger.

Pages

Make a Search Feature with Vuejs and Google Custom Search API

Vuejs Search with Google Custom Search API
Blogging using static site generator (SSG) like Hugo does have advantages and disadvantages.
One of the drawbacks:
"SSG doesn't use databases to store content"
But this can actually be an advantage, because it can reduce costs and certainly be safer.
But to create a search feature, we must provide our own back-end or use a third-party back-end.
There are several back-end that can be used to make a search on SSG:
  • Using Algolia
  • Using Duckduckgo
  • use lunrjs
  • use typesense.org
  • Use Google CSE (Custom Search Engine)
  • etc.
Please choose yourself as needed ...
I chose Google CSE, because:
  1. All Code content has been indexed on Google
    Code index on Google
  2. No need to manually create or submit indexes to the back end like Algolia, because Google Bot will do it
  3. Fast enough
  4. The search results are more accurate even though there are typos
Previously, Petodeik had already used CSE with the embed form method .
Search with Google CSE
Weaknesses of this method ... the search results we cannot custom ourselves.
I hope, the results of the search can be made by CSS itself to follow the design in the Code.
Finally I found a way to use the API.
Languages ​​don't make it like this:
  1. Create a new CSE
  2. Creating an API Key for API access
  3. API implementation to our website
For implementation, we will use Vuejs. Because I think it's simpler than using JQuery.
Okay, then, let's start ...

1. Create a Custom Search Engine (CSE)

Please open: https://cse.google.com/cse/create/new to create a new CSE.
Fill in the domain name and choose the language, then click create .
Creating a Custom Search Engine
After that, go to the Edit Search Engine-> Setup menu Then, click the Search Engine ID button to get the CSE ID.
Custom Search Engine ID
Save the ID, because we will use it to access it from the API.

2. Create an API Key

After we create a custom search engine, we then create the API key to access it via the API.
The Key API can be created through the Google Developer Console.
Before creating an API Key, we must have an application project in the Google Developer Console.
Please create a new project, open this link https://console.developers.google.com .
Creating a New Project
Click the select button when you have created or click the create button to create a new project.
We just made a new one ...
Fill in the project name, then click CREATE .
Make a project
Next, please go to the Dashboard, then click Activate API and Services .
Activation of Google services
In the search box, search for the keyword "Custom Search".
Search for CSE services
Next, please activate the Custom Search API service . Click the Activatebutton .
Activation of CSE services
After that, make a priority to access this service. Click the Create Credential button .
Create an API Key for CSE services
Next click what Credentials button do I need?
Create an API Key for CSE services
Then the API Key will appear that we need.
Create an API Key for CSE services
Keep this API Key well, because we will need to access CSE services.

3. Access CSE through the API

The following is the URL used to access CSE:
https://www.googleapis.com/customsearch/v1?key=API_KEY&cx=CSE_ID&q=KEYWORDS
Pay attention to the URL address, there are some parameters needed:
  • API_KEY is the API Key that we have created;
  • CSE_ID is the ID of the custom search that has been created;
  • KEYWORDS is a search keyword.
Let's try ...
I will use a parameter like this:
  • API_KEY=AIzaSyBAEEvhRcBk8FVOmxv6jJON2VhMUpqQgI8
  • CSE_ID=000680021646118888977:u60wgdclz_0
  • KEYWORDS=nodejs
Then we can arrange the URL to be like this:
https://www.googleapis.com/customsearch/v1?key=AIzaSyBAEEvhRcBk8FVOmxv6jJON2VhMUpqQgI8&cx=000680021646118888977:u60wgdclz_0&q=nodejs
Try opening the URL via the browser ...
API Access Experiment
We will get search results data in JSON form. This data is what we will display to users with the help of Vuejs.

4. Make a Search Feature with Vuejs

First, please create the HTML file.
HTML Code:
<div id="search-app" class="container">
    <!-- Search form section -->
    <section class="my-5 row justify-content-center">
            <div class="col-md-6">
                <div class="input-group mb-3">
                    <input type="text" v-model="q" class="form-control" placeholder="Kata kunci..." aria-label="Recipient's username" aria-describedby="basic-addon2">
                    <div class="input-group-append">
                        <button class="btn btn-secondary" type="button" v-on:click="doSearch()">Cari</button>
                    </div>
                </div>
            </div>
    </section>
    <!-- Search result -->
    <section class="row mb-5">
        <post-card
            v-for="post in searchResult.items"  
            v-bind:post="post">
        </post-card>
    </section>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
<script src="/js/search.js"></script>
There are five Javascript files that we need in this search feature:
  1. vuejs the core script from vuejs;
  2. vue-router.min.js for routing, we will use later to take a query string from the URL;
  3. axios.min.js to make an HTTP Request to the Google API;
  4. lodash.min.jswe need in the script search.js;
  5. search.js is an application script from the search feature that we will create.
Then in the HTML code above, we divide it into two sections :
  1. The first section to display the form for search
  2. The second section for displaying search results.
In the search results we use components <post-card>, then we will create the components.
If we look in the browser, it will look like this:
Search form with Vuejs
Anyway, the HTML code above uses Bootstrap 4.
Next, we will create the search script. Please create a file search.js with the contents as follows:
// Membuat Component
Vue.component('post-card', {
    props: ['post'],
    template: '<div class="col-md-6 col-lg-4 mb-4 d-flex">'+
                    '<div class="card card-shadow">' +
                        '<a :href="post.link">' +
                        '<img class="card-img-top" :src="post.pagemap.cse_image[0].src"/>'+
                        '</a>'+
                        '<div class="card-body">'+
                            '<h5 class="card-title">'+
                                '<a class="text-dark" :href="post.link">{{ post.title }}</a>' +
                            '</h5>' +
                        '</div>' +
                    '</div>' +
                '</div>'
})

// Membuat Router
var router = new VueRouter({
    mode: 'history',
    routes: []
});

// Aplikasi Fitur Pencarian
var app = new Vue({
    router,
    el: '#search-app',
    data: {
        q: "",
        searchResult: ""
    },
    watch: {
        q: function () {
            // console.log(this.q);
            this.debouncedDoSearch()
        }
    },
    created: function () {
        // _.debounce is a function provided by lodash to limit how
        // often a particularly expensive operation can be run.
        // In this case, we want to limit how often we access
        // yesno.wtf/api, waiting until the user has completely
        // finished typing before making the ajax request. To learn
        // more about the _.debounce function (and its cousin
        // _.throttle), visit: https://lodash.com/docs#debounce
        this.debouncedDoSearch = _.debounce(this.doSearch, 500);
        this.q = this.$route.query.q;
        // console.log(this.q);
    },
    methods: {
        doSearch: function(){
            var app = this;

            if (this.q != undefined && this.q !== "") {
                let API_KEY = "AIzaSyBAEEvhRcBk8FVOmxv6jJON2VhMUpqQgI8";
                let CSE_ID = "000680021646118888977:u60wgdclz_0";
                axios.get('https://www.googleapis.com/customsearch/v1?key='+API_KEY+'&cx='+CSE_ID+'&q=' + this.q)
                    .then(function (response) {
                        app.searchResult = response.data;
                        console.log(app.searchResult);
                    })
                    .catch(function (error) {
                        console.log(error);
                    })
            }
        }
            //console.log(this.q);
    }
});
Please change the value API_KEYand CSE_IDwith yours.
The description:
First of all, we start from the first component:
// Membuat Component
Vue.component('post-card', {
    props: ['post'],
    template: '<div class="col-md-6 col-lg-4 mb-4 d-flex">'+
                    '<div class="card card-shadow">' +
                        '<a :href="post.link">' +
                        '<img class="card-img-top" :src="post.pagemap.cse_image[0].src"/>'+
                        '</a>'+
                        '<div class="card-body">'+
                            '<h5 class="card-title">'+
                                '<a class="text-dark" :href="post.link">{{ post.title }}</a>' +
                            '</h5>' +
                        '</div>' +
                    '</div>' +
                '</div>'
})
This is the component that we will use to display search results.
Note, there is props: ['post'], meaning later when using this component ... we have to bring up an object postlike this:
Bind the parameter to the Vuejs component
Next make a router ...
// Membuat Router
var router = new VueRouter({
    mode: 'history',
    routes: []
});
We need this router to retrieve the value from the query string in the URL.
Example string query:
https://www.petanikode.com/search/?q=katakunci
There is a query string q=katakunci, to take this value, we can use a router like this:
this.$route.query.q
Next in the search application, we provide two data:
  1. q is a string containing search keywords;
  2. searchResult is a JSON object from the results obtained from the API.
Then the method watch()functions to monitor changes from the data q.
watch: {
    q: function () {
       // console.log(this.q);
       this.debouncedDoSearch()
    }
}
If the value qchanges, we execute the function this.debounceDoSearch()This function is actually to determine the pause, when the keyboard will stop typing. For example, in 500 milliseconds.
If we don't do this, then every keyboard type ... This program will send an HTTP Request as many letters as typed.
This is certainly a waste. ðŸ˜„
Therefore, we give a 500 millisecond pause to make an HTTP Request to the API after the keyboard is pressed.
Last and most important:
Execute method doSearch().
This function will do an HTTP Request with the axiosURL or API Endpoint. Then the results will be stored in the data searchResult.
doSearch: function(){
    var app = this;
    if (this.q != undefined && this.q !== "") {
        let API_KEY = "AIzaSyBAEEvhRcBk8FVOmxv6jJON2VhMUpqQgI8";
        let CSE_ID = "000680021646118888977:u60wgdclz_0";
        axios.get('https://www.googleapis.com/customsearch/v1?key='+API_KEY+'&cx='+CSE_ID+'&q=' + this.q)
            .then(function (response) {
                app.searchResult = response.data;
                console.log(app.searchResult);
            })
            .catch(function (error) {
                console.log(error);
            })
    }
}
Don't forget to change values API_KEYand CSE_IDwith yours. Because I'm sure, using the API Key and CSE_ID above won't work.
Now please try ...
Here's the result, search with keywords nodejs:
Search results with Google CSE

5. API Key CSE protection

Actually, writing standards such as passwords and key APIs in the program code is not recommended, because it can be stolen by people .
How come, then?
Whereas our program runs on top of the browser and the source code can be seen by everyone.
The solution:
Google has provided a limitation for the use of the API Key. For example, the API Key can only be used on certain domains and IP addresses.
To enable this protection, we can set it in the API Restrictions settings .
First enter first into the Database , then click the API Key that was created:
Setting restrictions on API Key usage
Then select Web Browser , because we only use this API Key for web only.
Setting restrictions on API Key usage
Don't forget to fill in the domain that will use the API Key.
Then in the API Restrictions section , select the Custom Search API .
Setting restrictions on API Key usage
After that, click Save .
Thus, our API Key will only be able to be used on the domain that we have just registered.
Why should the API Key be protected?
Because the free version of the CSE service has a limit of 100 queries per day. If it is used in many places, our CSE may be faster than the limit.
Limitations on the use of CSE per day

Implication at Hugo

For implementation in the Hugo Template, we must create a special page for search.
How:
First create content with a name search.mdlike this:
Content for serach page
Then create a layout for the search page layouts/search/single.html like this:
<!DOCTYPE html>
<html>
    <head>
        <!-- {{ partial "head.html" . }} -->
        <!-- isi dengan partial milik anda -->
    </head>
    <body class="bg-light">

        <!-- {{ partial "nav.html" . }} -->
        <!-- isi dengan partial milik anda -->

        <div id="search-app" class="container">
            <!-- Search form section -->
            <section class="my-5 row justify-content-center">
                    <div class="col-md-6">
                        <div class="input-group mb-3">
                            <input type="text" v-model="q" class="form-control" placeholder="Kata kunci..." aria-label="Recipient's username" aria-describedby="basic-addon2">
                            <div class="input-group-append">
                                <button class="btn btn-secondary" type="button" v-on:click="doSearch()">Cari</button>
                            </div>
                        </div>
                    </div>
            </section>

            <!-- Search result -->
            <section class="row mb-5">
                <post-card
                    v-for="post in searchResult.items"  
                    v-bind:post="post">
                </post-card>
            </section>
        </div>

        
        <script src="https://cdn.jsdelivr.net/npm/vue"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
        <script src="/js/search.js"></script>
    </body>
</html>
Hugo's layout for serach page
Files are search.jsinserted into a folder static/js/.
Done!
Now try running the server, then open it http://localhost:1313/search/.
Anyway, don't forget to turn off the API protection before you can try it on localhost.
Good luck!

0 Komentar untuk "Make a Search Feature with Vuejs and Google Custom Search API"

Silahkan berkomentar sesuai artikel

 
Template By Kunci Dunia
Back To Top