How To Add Search To Your Static Site
Tags: javascript, jamstack, html
Published: 2020-08-30 20:39:43

---
title: How To Add Search To Your Static Site
published: true
date: 2020-08-30 20:39:00 UTC
tags: javascript, jamstack, html
canonical_url: https://agckb.xyz/posts/static-site-search/via-search-engine/
---

> This post was originally posted on [The Algorithmic Cookbook](https://agckb.xyz/) under [How To Add Search To Your Static Site](https://agckb.xyz/posts/static-site-search/via-search-engine/). This post is also on [YouTube](https://youtu.be/DDzaKO_3CrQ)

In this post, I’ll go over how to add search to a static site by adding a form which points to a search engine.

## What’s The Search Form Should Have

For the search form to work, it needs:

- The `form` with `role` attribute `search`, a `method` attribute (usully `GET`) and an `action` attribute with a URL to your search provider,
- the (labelled) text input field with the `name` attribute set to what the search engine uses as the search field **whose value include `site:yourdomain.example`** , and
- a submit button along with
- some optimizations like multiple search engines and hiding the `site:yourdomain.example` in the search field.

I’ll assume that search engines don’t use [anti-CSRF tokens](https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html) which you’ll need to find a way to submit with the rest of the form.

I’ve already added a [search form in my site’s header](https://agckb.xyz/posts/static-site-search/via-search-engine/#search_query) if you wanna try it out and it looks like this.

![input field and button which says Search in a Google](https://agckb.xyz/posts/static-site-search/via-search-engine/agckb-search.png)

## Examining the Search Engine

To start off, go to a search engine and see how it works. Here I&rsquo;ll be using [Google Search](https://google.com). Inspecting the home page, the search box is an `input` field with name `q`. Moving up to the form element, we can see an action of `/search` (which resolves to `https://www.google.com/search`) and a method of `GET`. Trimming the unnecessary stuff, Google’s search form looks like this (&hellip; is truncated code).

```
<form ... action="search" ... method="GET" name="f" ...role="search">
  ...
  <input ... name="q" ... aria-label="search">
  ...
  <input ... value="Google Search" ... name="btnK" type="submit">
  ...
</form>

```

If I then search for `site:agckb.xyz`, Google gives me the search results on my website, the Algorithmic Cookbook.

![Google search results for site:agckb.xyz](https://agckb.xyz/posts/static-site-search/via-search-engine/agckb-search-results.png)

Those are shown by this URL.

```
https://www.google.com/search?sxsrf=ALeKk01GA8FFoL3T8g20i8cZI0hBiXwdCw%3A1598164783561&source=hp&ei=Lw9CX5m8H4mQlwSxsZDoAw&q=site%3Aagckb.xyz&oq=site%3A&gs_lcp=CgZwc3ktYWIQAxgAMgQIIxAnMgQIIxAnMgIIADICCAAyAggAMgIIADICCAAyAggAMgIIADICCAA6BQgAEJECOgQIABBDOggIABCxAxCDAToICC4QsQMQgwE6CgguEMcBEKMCEEM6BwguELEDEEM6AgguULrgBViH7wVg0PYFaAFwAHgAgAH_A4gB4BWSAQU0LTUuMZgBAKABAaoBB2d3cy13aXo&sclient=psy-ab

```

It looks horrendus with all the other parameters (which were hidden), but all you need is the `q` parameter with the (URI encoded) search field. So this works just as well.

```
https://www.google.com/search?q=site%3Aagckb.xyz

```

Using what we’ve discovered, we can make our own form.

```
<form method="GET" class="search-form" action="https://www.google.com/search" role="search" name="search-form">
    <label for="search-form_query" class="sr-only search-form_label">Search Term</label>
    <input class="search-form_query" type="text" name="q" id="search-form_query" value="site:agckb.xyz ">
    <button class="search-form_button" type="submit">Search on Google</button>
</form>

```

Here we’ve taken what we’ve seen from the Google search and moved it into a form.

The form’s action points to what we saw on Google’s search form `https://www.google.com/search/` with method GET. There’s also a [role=`search`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/Search_role) to expose the form as a search landmark for assistive technologies.

There’s a label for the search input. The `sr-only` is to visually hide the label so that assistive technologies can still understand what the input is for. There are other [accessible labeling techniques](https://www.w3.org/WAI/tutorials/forms/labels/) in case you really don’t want a `label` element.

The input itself has name `q`, type text, the id for the label and a pre-filled value of `site:agckb.xyz␣` (`␣` represents whitespace `U+020`). **The pre-filled label is necessary to search your site, otherwise it will search the web instead of your specific site**.

What I’ve done above is the most supported, barebones way of searching through a search engine. No JavaScript needed. I’m also confident that it’ll work across various search engines with their respective form actions and search query parameters.

## Multiple Search Engines

If search engines use the same search button form parameter, you could add a button with the `formaction` to another search engine. For instance, Google and DuckDuckGo use `q` as a search parameter. I could support DuckDuckGo by adding this button:

```
<button action="submit" formaction="https://duckduckgo.com/">Search DuckDuckGo</button>

```

In DuckDuckGo’s case, you can also search via POST and you can add `formmethod=POST` to do just that.

## Hiding the `site:yoursite.example` from the form input

The reason I used Google is because it makes this easier. We can add a second input with a name `q` with a `hidden` attribute and assign `site:yoursite.example` as the value.

```
<input type="text" name="q" label="site:agckb.xyz" hidden>

```

This is search engine specific, but browsers will supply the two `q` parameters and the search engine may merge them together.

If you can’t do this, you can then use JavaScript to remove it on load and replace it when the user wants to submit the form submitting the form.

```
const searchForm = document.forms['search-form'];

window.addEventListener('load', () => {
  searchForm.q.value = '';
});

searchForm.addEventListener('submit', function(e){
  e.preventDefault();
  searchForm.q.value += 'site:yoursite.example';
  e.currentTarget.submit();
});

```

If you don’t want to hard code the `site:yoursite.example`, you can do `'site:' + window.location.hostname` instead.

## Comparison of Search Engines

I’ve put this table together to compare how various search engines are set up. I could probably get away with just listing 4 or 5 of these, but discovering these search engines was fun.

| Search Engine | Form URL | Methods | Search Term Name | Merges Multiple Inputs? | Cross Compatable With |
| --- | --- | --- | --- | --- | --- |
| Google | `https://www.google.com/search` | `GET` | `q` | Yes | DuckDuckGo, Ecosia, Bing, Yooz, Quant, Parsijoo |
| Bing | `https://www.bing.com/search` | `GET` | `q` | No | Google, DuckDuckGo, Ecosia, Yooz, Quant, Parsijoo |
| Yahoo | `https://search.yahoo.com/search` | `GET`, `POST` | `p` | No | |
| DuckDuckGo | `https://duckduckgo.com/` | `GET`, `POST` | `q` | No | Google, Ecosia, Bing, Yooz, Quant, Parsijoo |
| Yandex | `https://yandex.com/search/` | `GET` | `text` | No | |
| Baidu | `https://www.baidu.com/s` | `GET` | `wd` | No | |
| Ecosia | `https://ecosia.org/search` | `GET` | `q` | No | Google, DuckDuckGo, Bing, Yooz, Quant, Parsijoo |
| Startpage | `https://www.startpage.com/sp/search` | `GET`, `POST` | `query` | No | SwissCows |
| Swisscows | `https://swisscows.com/web` | `GET` | `query` | Maybe (it mashes them, but didn’t have results) | `query|Startpage| |
| Yooz | `https://yooz.ir/search` | `GET` | `q` | No | Google, DuckDuckGo, Ecosia, Bing, Quant, Parsijoo |
| Quant | `https://quant.com/` | `GET` | `q` | No | Google, DuckDuckGo, Ecosia, Bing, Yooz, Parsijoo |
| Parsijoo | `https://parsijoo.ir/web` | `GET` | `q` | No | Google, DuckDuckGo, Ecosia, Bing, Yooz, Quant |

## Conclusion

And that&rsquo;s how you can add search to your static site through a form pointing to a search engine. This isn’t the only way to add search to a static site and I hope to explore other ways in the future.

As a teaser, I’ve made a [purely front-end search solution on my old website](https://web.archive.org/web/20200114203452/https://fgandiya.me/codelab/v8-redesign/adding-search/) with [lunr.js](https://lunrjs.com/), but it’s a horrible front end strategy as it:

- adds ~450KB of JavaScript on the webpage,
- doesn’t prebuild the search index and
- does all the work on the main thread.

Given what I know now, it’s time I improved this approach. Heck, I might even be able to move this logic onto a backend as is and leverage serverless functions to do the actual searching. Possibilities are endless<sup id="fnref:1"><a href="https://agckb.xyz/posts/static-site-search/via-search-engine/#fn:1" role="doc-noteref">1</a></sup>.

<section role="doc-endnotes">
<hr>
<ol>
<li id="fn:1" role="doc-endnote">
<p>Possibilities are probably not endless, unless you calculate every permutation of code that can do exactly this, then they are I guess? Then again, you’re limited to a few general approaches. But aren’t the specifics distinct algorithms as subsets of the general approaches? Should have just left this as a cliche ending. <a href="https://agckb.xyz/posts/static-site-search/via-search-engine/#fnref:1" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</section>

Thanks for reading! If you&rsquo;ve enjoyed this post, you can support me by

- sharing this post,
- becoming a [Patron](https://patreon.com/faraixyz),
- send me some money on either [Paypal](https://paypal.com/fgandiya), [Ko-fi](https://ko-fi/faraixyz) or [Buy Me A Coffee](https://www.buymeacoffee.com/faraixyz) or
- Get a domain on using [my Namecheap affiliate link](https://shareasale.com/r.cfm?b=467188&u=2110247&m=46483&urllink=namecheap%2Ecom&afftrack=farai%2Exyz). Note that I&rsquo;ll earn a comission on anything you buy with that link.