The internal search of WordPress has relatively poor performance and features, which has led to the creation of custom plugins that add many features to this search. If you want to add a powerful custom search to your WordPress theme, in this article we will teach you how to create a custom search in WordPress.
Using this tutorial, you can understand the basics of WordPress search and create a powerful search engine for your website template. You can even use AJAX technology to maximize search possibilities and user experience. If you are not familiar with AJAX, we have provided you with an article entitled How to use AJAX in WordPress.
It is true that by using WordPress plugins, you can add many powerful features to your WordPress website, but sometimes these plugins do not provide the performance you expect. You may even want to create your own custom theme for WordPress, in which case you need to create your own custom search in WordPress. For example, you may want to display some posts and content at the beginning of the search, in which case you will need a custom search.
Creating a custom search engine for a WordPress website is not that difficult and you can easily do this using this tutorial and even add additional features to it.
WordPress search
WordPress itself has an internal search engine based on the WP_QUERY class, which you can use to search the website content. It has an internal widget for this purpose, and you can use the search option by adding it to one of your widget areas (usually the sidebar). Also, nowadays, all modern and standard WordPress templates have a section for searching, which is usually placed in the header of the page.
But as we said, this search engine has limited features. For example, if you want to search AJAX, you should use plugins that allow you to do this, or create a custom search for the WordPress template yourself.
If you have worked with WordPress loop before, you must be familiar with the WP_Query class, but if you haven’t, in this tutorial we will teach you the things related to the search.
If you enter the following address in the address bar of your browser, you will find that the word “wordpress” has been searched.
https://www.your-wordpress-website.com/?s=wordpress
The “s” parameter in the load address of WordPress websites means search. Even if you don’t have a place to search on your website, either in the header or in the sidebar, you can search on the website using this method.
Search By Phrase
By default, WordPress searches by keyword. What this means is that when passed the search query “wordpress search”, WordPress builds the following for the WHERE clause:
((wp_posts.post_title LIKE '%wordpress%') OR
(wp_posts.post_content LIKE '%wordpress%'))
AND
((wp_posts.post_title LIKE '%search%') OR
(wp_posts.post_content LIKE '%search%'))
In fact, because our search term consists of two words, “wordpress” and “search”, WordPress separates them and searches each of them in the title and content of the article.
That is, it searches the word “wordpress” once and the word “search” once in the title and content and merges the returned results from both searches, and displays them to the user.
If you want to search a sentence exactly like “wordpress search”, just add the &sentence=1
parameter to the end of your URL bar. Or if you use the search box, put the phrase in ""
like “your phrase”.
Custom search form
If you want to customize the default WordPress search form, WordPress has a solution for this. WordPress uses the get_search_form() function to call the search form. This function calls the WordPress default search form.
In fact, this first function refers to the template, which displays the search form if the template is implemented, but if it is not implemented, it displays the WordPress default search form.
If you want to implement a custom search form for your WordPress, go to your theme folder in “wp-content/themes/your-theme
” and open the searchform.php
file (if it doesn’t exist, create it).
Write the following codes in the file and save it.
<?php if (!defined('ABSPATH')) {
exit;
}
?>
<div class="search-box-form">
<form role="search" method="get" class="search-form" action="<?php echo esc_url(home_url("/")); ?>">
<input type="search" placeholder="<?php esc_attr_e('Search', 'text-domain') ?>" class="search-field" value="<?php echo esc_attr(get_search_query()); ?>" name="s" />
<button type="submit" tabindex="0" class="search-submit"><?php esc_attr_e('Search', 'text-domain') ?></button>
</form>
</div>
If you view your website page, you will see that the search form has changed. This form is only different from the default WordPress form in terms of appearance, but there is no difference in terms of technical features. This is the starting point for creating a custom search form in WordPress. We will add more features to this form in the future, so stay tuned.
We explained the sentence parameter above. Now, if we want to automatically add this parameter to the end of the address, we just need to add it to the form as hidden.
<div class="search-box-form">
<form role="search" method="get" class="search-form" action="<?php echo esc_url(home_url("/")); ?>">
<input type="search" placeholder="<?php esc_attr_e('Search', 'text-domain') ?>" class="search-field" value="<?php echo esc_attr(get_search_query()); ?>" name="s" />
<input type="hidden" value="1" name="sentence" />
<input type="hidden" value="product" name="post_type" />
<button type="submit" tabindex="0" class="search-submit"><?php esc_attr_e('Search', 'text-domain') ?></button>
</form>
</div>
In this example, the “sentence” parameter is added to the address and “post_type” too. The “post_type” parameter, whose value is “product”, tells WordPress that we want to search for product content.
In WordPress, all content is stored in the wp_posts
table, each of which has its own post type. If you are familiar with custom post type in WordPress, you will realize that the post_type
parameter actually targets product post types.
If you go to your website page and search “wordpress” in the form, the address will be as below.
https://www.your-wordpress-website.com/?s=wordpress&sentence=1&post_type=product
This form calls the same default search system of WordPress, but with the difference that the search will be in the content whose post type is “product”.
Custom search template in WordPress
Each WordPress theme has many files, each of which has its own task. To create a custom search template in WordPress, your template must have the search.php file or its subsets. This is a template file that displays the results of searches in a specified format.
Go to your template folder and open the search.php file. If you use another developer’s template, it is better to use the child template for personalization.
This file contains the search result template in WordPress, in this section we want to personalize the search results page. This file is the same as the archive screen, but with the difference that the title of the archive page is different from the search results page.
Open the search.php file and put the following codes in it.
<?php
get_header(); ?>
<h1 class="search-title">
<?php echo esc_html('Search Results for: ', 'text-domain');?>
<span class="search-term"><?php echo esc_html(get_search_query()); ?></span>
</h1>
<div id="content" class="content">
<?php get_sidebar(); ?>
<div class="entries">
<div class="posts">
<?php if (have_posts()) : ?>
<?php while (have_posts()) :
the_post(); ?>
<article class="post-<?php the_ID(); ?>">
<?php
if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail(); ?>
<?php endif; ?>
<?php $time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>';?>
<span class="entry-date">
<?php $time_string = sprintf(
$time_string,
esc_attr(get_the_date(DATE_W3C)),
esc_html(get_the_date("j M, Y")));
echo wp_kses_post($time_string); ?>
</span>
<?php the_title(sprintf('<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url(get_permalink())), '</a></h2>'); ?>
<div class="entry-meta">
<span class="entry-author">
<span class="byline"><a href="<?php echo esc_url(get_author_posts_url(get_the_author_meta('ID'))); ?>"><?php the_author(); ?></a></span>
</span>
<?php $categories_list = get_the_category_list(); ?>
<?php if ($categories_list) : ?>
<span class="entry-categories clearfix">
<?php printf('<span class="screen-reader-text">%1$s </span>%2$s', esc_html__('Used before category names.', 'text-domain'), wp_kses($categories_list, array('a' => array('href' => array(), 'rel' => array())))); ?>
</span>
<?php endif; ?>
</div>
<div class="entry-content">
<?php the_excerpt(); ?>
</div>
<div class="entry-read-more">
<a href="<?php echo esc_url(get_permalink()) ?>" rel="bookmark" class=""><?php echo __('Continue Reading...', 'text-domain'); ?></a>
</div>
</article>
<?php endwhile; ?>
<?php endif; ?>
</div>
<?php
the_posts_pagination(array(
'prev_text' => __('<<', 'text-domain'),
'next_text' => __('>>', 'text-domain'),
)); ?>
</div>
</div>
<?php get_footer();
This is a simple sample code to display custom search results in WordPress. The page title is displayed at the top of the page.
<h1 class="search-title">
<?php echo esc_html('Search Results for: ', 'text-domain');?>
<span class="search-term"><?php echo esc_html(get_search_query()); ?></span>
</h1>
Then comes the content. As you know, WordPress was created with PHP language, so the content in WordPress is displayed by the WordPress loop, which also uses the PHP loop.
Inside the loop, the content of each post, including the title, date, author’s name, content, and other details is displayed. Finally, there is pagination, which is automatically paginated by WordPress if there are more search results.
WordPress custom search query
So far, we have used WordPress’s own search method, which reduces coding time, but if we want to create a search form with more features, we must use our own search system, such as when we want to display the search result using AJAX. In this section, we will create a custom search form in WordPress using WP_Query, and in the next section, we will add AJAX technology to it using the knowledge of this section.
To use WP_Query in WordPress, we will use WordPress query variables. These variables affect the execution of WordPress queries so that we can extract our desired results from the database. Working with the database in WordPress is done by the functions of WordPress itself, which we can even use to add new tables to the WordPress database or change the data. WP_Query is used to read data from the database.
This class gives us fast and safe access to the database content so that we can retrieve the content from the database without needing to know the SQL language. Even in the loop, the WP_Query class is used behind the scenes to display the content in the above code.
The WP_Query class receives variables as parameters and based on them they fetch the content from the database. For example, if we want to implement the above code with the WP_Query class, it will be like the code below.
<?php
$args=['post_type' => 'post'];
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<article class="post-<?php the_ID(); ?>">
<?php
if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail(); ?>
<?php endif; ?>
<?php $time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>';?>
<span class="entry-date">
<?php $time_string = sprintf(
$time_string,
esc_attr(get_the_date(DATE_W3C)),
esc_html(get_the_date("j M, Y")));
echo wp_kses_post($time_string); ?>
</span>
<?php the_title(sprintf('<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url(get_permalink())), '</a></h2>'); ?>
<div class="entry-meta">
<span class="entry-author">
<span class="byline">
<a href="<?php echo esc_url(get_author_posts_url(get_the_author_meta('ID'))); ?>">
<?php the_author(); ?>
</a>
</span>
</span>
<?php $categories_list = get_the_category_list(); ?>
<?php if ($categories_list) : ?>
<span class="entry-categories clearfix">
<?php printf('<span class="screen-reader-text">%1$s </span>%2$s', esc_html__('Used before category names.', 'text-domain'), wp_kses($categories_list, array('a' => array('href' => array(), 'rel' => array())))); ?>
</span>
<?php endif; ?>
</div>
<div class="entry-content">
<?php the_excerpt(); ?>
</div>
<div class="entry-read-more">
<a href="<?php echo esc_url(get_permalink()) ?>" rel="bookmark" class=""><?php echo __('Continue Reading...', 'text-domain'); ?>
</a>
</div>
</article>
<?php endwhile;
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();?>
The part inside the loop has no difference and only the part of the loop itself is different from the code above.
In the previous method, we could only display the content of the posts and there was no filter on it, but with this method, we can apply more filters and also display the content of other post types.
For example, if we want to return posts written by “Honar Systems”, we just need to apply it to the variables.
$args=[
'post_type' => 'post',
'author_name' => 'Honar Systems'
];
Custom WordPress search form with AJAX
AJAX technology is one of the web application technologies through which you can change a part of the website without reloading the page. AJAX sends a request to the server and receives the results without the user noticing or reloading the page.
This will increase the speed of the website and the user experience. If you are not familiar with AJAX technology, we have provided you with an article entitled AJAX in WordPress, in which we will teach you how to use this technology in WordPress.
In this section, we want to receive the input word from the custom search form in WordPress through AJAX and send it to the server and display the search results.
To start, open the searchform.php file and put the following codes in it. If this file does not exist, create it in the root of your WordPress template.
<div class="search-box-form">
<form role="search" method="get" class="search-form" action="<?php echo esc_url(home_url("/")); ?>">
<input type="search" placeholder="<?php esc_attr_e('Search', 'text-domain') ?>" class="search-field" value="<?php echo esc_attr(get_search_query()); ?>" name="s" />
<input type="hidden" value="1" name="sentence" />
<input type="hidden" value="product" name="post_type" />
<button type="submit" tabindex="0" class="search-submit"><?php esc_attr_e('Search', 'text-domain') ?></button>
</form>
</div>
Open the section where we want the form to be placed and enter the following code. For example, we want the search box to be placed in the header of the page. Therefore, we open the header.php file.
<?php get_search_form(); ?>
<div id="search-results"></div>
Create a JavaScript file named ajax.js in assets/js
path and put the following codes in it.
jQuery(document).ready(function () {
jQuery(".search-form .search-field").on('input',function(){
jQuery.post({
url: PHPVARS.ajaxurl,
data: {
action:'hs_ajax_handler_action',
term: jQuery(".search-form .search-field").val()
},
success: function(msg){
jQuery("#search-results").html(msg);
}
});
})
});
This code sends any word you type in the search form to the server and puts the result in the search-results
element.
The “URL” parameter will be sent by PHP, which we will explain later. This URL is an address from WordPress pages (admin-ajax.php) which is responsible for handling AJAX requests.
WordPress has its own functions and hooks to work with AJAX. Therefore, we also use these hooks. Open the functions.php file and enter the following code in it.
function hs_register_js_files() {
wp_enqueue_script('hs-ajax-script', esc_url(get_template_directory_uri() . '/assets/js/ajax.js'), array('jquery'), '1.0.0', true);
wp_add_inline_script(
"hs-ajax-script",
"const PHPVARS = " . json_encode(array(
"ajaxurl" => admin_url("admin-ajax.php")
)),
"before"
);
}
add_action("wp_enqueue_scripts", "hs_register_js_files");
This first code introduces the ajax.js file to WordPress. In this code, we enqueue the JavaScript file to WordPress and define the inline codes, which is the PHPVARS variable that we have used inside our JavaScript codes. Here we define the address of the admin-ajax.php page.
So far, you have learned how to send data to the server, but there is still part of the code that sends the search results from the server to the client. Enter the following codes in the same functions.php file.
add_action('wp_ajax_hs_ajax_handler_action', 'hs_ajax_action');
add_action('wp_ajax_nopriv_hs_ajax_handler_action', 'hs_ajax_action');
function hs_ajax_action()
{
$args=[
'post_type' => 'post',
's' => $_POST['term']
];
// The Query
$the_query = new WP_Query( $args );
// The Loop
if ( $the_query->have_posts() ) {
while ( $the_query->have_posts() ) : $the_query->the_post(); ?>
<article class="post-<?php the_ID(); ?>">
<?php
if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail(); ?>
<?php endif; ?>
<?php $time_string = '<time class="entry-date published updated" datetime="%1$s">%2$s</time>';?>
<span class="entry-date">
<?php $time_string = sprintf(
$time_string,
esc_attr(get_the_date(DATE_W3C)),
esc_html(get_the_date("j M, Y")));
echo wp_kses_post($time_string); ?>
</span>
<?php the_title(sprintf('<h2 class="entry-title"><a href="%s" rel="bookmark">', esc_url(get_permalink())), '</a></h2>'); ?>
<div class="entry-meta">
<span class="entry-author">
<span class="byline"><a href="<?php echo esc_url(get_author_posts_url(get_the_author_meta('ID'))); ?>"><?php the_author(); ?></a></span>
</span>
<?php $categories_list = get_the_category_list(); ?>
<?php if ($categories_list) : ?>
<span class="entry-categories clearfix">
<?php printf('<span class="screen-reader-text">%1$s </span>%2$s', esc_html__('Used before category names.', 'text-domain'), wp_kses($categories_list, array('a' => array('href' => array(), 'rel' => array())))); ?>
</span>
<?php endif; ?>
</div>
<div class="entry-content">
<?php the_excerpt(); ?>
</div>
<div class="entry-read-more">
<a href="<?php echo esc_url(get_permalink()) ?>" rel="bookmark" class=""><?php echo __('Continue Reading...', 'text-domain'); ?></a>
</div>
</article>
<?php endwhile;
} else {
// no posts found
}
/* Restore original Post Data */
wp_reset_postdata();
wp_die(); // this is required to terminate immediately and return a proper response
}
This code is responsible for searching WordPress content and sending it to the user. These codes are the same as the codes of the previous parts, but with slight differences in the parameters and hook definition.
In the input parameters to WP_Query, there is a variable “s” in which the word we want to search is placed.
Hooks are also used to define this function as returnable values through AJAX.
add_action('wp_ajax_hs_ajax_handler_action', 'hs_ajax_action');
add_action('wp_ajax_nopriv_hs_ajax_handler_action', 'hs_ajax_action');
Both of these hooks must be defined because these hooks must be placed on both the management side and the user side. The name of the action in this hook must be the same as the name of the hook sent in JavaScript.
Plugins to create custom WordPress search
There are plugins that you can use to personalize the search form and search page. Some of these plugins are used to add additional features to the search form, and some are used to design the search results format, which we will introduce below.
1. SearchWP plugin
The easiest way to create a custom WordPress search form is to use SearchWP. This plugin is one of the best WordPress search plugins that has a simple user interface and at the same time gives full control over the display of search results. The search results provided by this plugin are more accurate than the default WordPress form results.
2. Ivory Search plugin
Ivory Search is a simple-to-use advanced WordPress search plugin. It enhances the default WordPress search and also allows you to create new custom search forms.