
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:
- All Code content has been indexed on Google
- No need to manually create or submit indexes to the back end like Algolia, because Google Bot will do it
- Fast enough
- The search results are more accurate even though there are typos
Previously, Petodeik had already used CSE with the embed form method .

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:
- Create a new CSE
- Creating an API Key for API access
- 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)
Fill in the domain name and choose the language, then click create .

After that, go to the Edit Search Engine-> Setup menu . Then, click the Search Engine ID button to get the CSE 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.

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 .

Next, please go to the Dashboard, then click Activate API and Services .

In the search box, search for the keyword "Custom Search".

Next, please activate the Custom Search API service . Click the Activatebutton .

After that, make a priority to access this service. Click the Create Credential button .

Next click what Credentials button do I need?

Then the API Key will appear that we need.

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 ...

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:
vuejs
the core script from vuejs;vue-router.min.js
for routing, we will use later to take a query string from the URL;axios.min.js
to make an HTTP Request to the Google API;lodash.min.js
we need in the scriptsearch.js
;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 :
- The first section to display the form for search
- 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:

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_KEY
and CSE_ID
with 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 post
like this:
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:
q
is a string containing search keywords;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
q
changes, 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
axios
URL 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_KEY
and CSE_ID
with 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
:
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:

Then select Web Browser , because we only use this API Key for web only.

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 .

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.

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.md
like this:
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>

Files are
search.js
inserted 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!
Reference: https://www.petanikode.com/vuejs-search/
0 Komentar untuk "Make a Search Feature with Vuejs and Google Custom Search API"
Silahkan berkomentar sesuai artikel