How to Add Voice Search Capability to Your WordPress Site

on in WordPress, Blog, JavaScript
Last modified on

How to Add Voice Search to Your WordPress Site

Ever wanted to offer voice search functionality on your WordPress site? If you’ve used voice assistants like Siri, Google, or Cortana, you’re familiar with how they can simplify searching. The good news is, you can integrate a similar feature into your WordPress website to enhance user experience.

Demo

The demo below is an actual, fully functional search box.

In this guide, I’ll walk you through adding voice search to WordPress.

I am going to use the SpeechRecognition API, which has limited availability.

The Web Speech API enables you to incorporate voice data into web apps. The Web Speech API has two parts: SpeechSynthesis (Text-to-Speech), and SpeechRecognition (Asynchronous Speech Recognition.)

SpeechRecognition

The controller interface for the recognition service; this also handles the SpeechRecognitionEvent sent from the recognition service.

Table of Contents

Why Should You Add Voice Search to WordPress?

Voice search can significantly improve the user experience on your site. By allowing visitors to search for content using voice commands, it eliminates the need for typing, making browsing faster and easier.

Voice search is especially beneficial for users with visual impairments or those who struggle with typing. It offers a more accessible and convenient way for this audience to find information or products on your site.

Additionally, voice search can speed up your workflow. Instead of manually clicking through menus or typing, you can simply speak to find the pages or posts you need.

Now, let’s dive into how to add this feature to WordPress.

Adding Voice Search to WordPress

I will create a simple shortcode:

function whiskey_faceted_voice_search() {
    $out = '<div class="search-field-wrapper--voice">
        <form role="search" method="get" id="searchform--voice" class="search-form" action="https://example.com/">
            <label for="s--voice" class="screen-reader-text">Search</label>
            <input type="text" class="search-field--voice" placeholder="Search..." value="' . get_search_query() . '" name="s" id="s--voice" required>
            <input type="submit" class="search-submit--voice" value="Search">
        </form>
    </div>
    <div class="search-info" style="font-size: 10px;"></div>';

    return $out;
}

add_shortcode( 'faceted-voice-search', 'whiskey_faceted_voice_search' );

That’s the shortcode you can add to any post, page, or template part.

You can also add it as a PHO function directly into your theme’s templates, like below:

<?php echo whiskey_faceted_voice_search(); ?>

Next, use the JavaScript below to power the actual voice search:

/**
 * Adds voice search functionality to a WordPress search form
 * using the browser's SpeechRecognition API.
 *
 * Voice Commands: 
 * - "stop recording": Stops speech recognition.
 * - "reset input": Clears the search input field.
 * - "go": Submits the search form.
 * 
 * This script checks if the browser supports SpeechRecognition and then
 * adds a microphone button to the search form that triggers voice search.
 * 
 * @since 1.0.0
 */

document.addEventListener('DOMContentLoaded', () => {
    // Check if the voice-enabled search form exists
    if (document.getElementById('searchform--voice')) {
        const searchForm = document.querySelector('#searchform--voice'); // The voice search form
        const searchFormInput = searchForm.querySelector('#s--voice'); // The search input field
        const info = document.querySelector(".search-info"); // Element for displaying search info/commands

        // Define the SpeechRecognition API from the browser window object (cross-browser support)
        const SpeechRecognition =
            window.SpeechRecognition || window.webkitSpeechRecognition; // For browsers with webkit support

        // Check if SpeechRecognition is supported by the browser
        if (SpeechRecognition) {
            console.log("Your Browser supports speech Recognition");

            // Initialize a new SpeechRecognition object
            const recognition = new SpeechRecognition();
            recognition.continuous = true; // Keep listening until manually stopped
            recognition.lang = "en-US"; // Set recognition language to US English

            // Add a microphone button to the search form
            searchForm.insertAdjacentHTML(
                "beforeend",
                '<button type="button"><i class="ai-microphone"></i></button>'
            );
            searchFormInput.style.paddingRight = "50px"; // Add padding to accommodate mic button

            const micBtn = searchForm.querySelector("button"); // The microphone button
            const micIcon = micBtn.firstElementChild; // The microphone icon

            // Add click event listener to the microphone button
            micBtn.addEventListener("click", micBtnClick);

            /**
             * Handles the microphone button click event.
             * Starts or stops speech recognition based on the current icon state.
             */
            function micBtnClick() {
                if (micIcon.classList.contains("ai-microphone")) {
                    // Start voice recognition if mic is clicked
                    recognition.start(); // User needs to grant access to the microphone
                } else {
                    recognition.stop(); // Stop voice recognition
                }
            }

            // Start speech recognition event listener
            recognition.addEventListener("start", startSpeechRecognition);

            /**
             * Fired when speech recognition starts.
             * Updates the microphone icon and focuses on the input field.
             */
            function startSpeechRecognition() {
                micIcon.classList.remove("ai-microphone");
                micIcon.classList.add("ai-airplay-audio");
                searchFormInput.focus();
                console.log("Voice activated, SPEAK");
            }

            // End speech recognition event listener
            recognition.addEventListener("end", endSpeechRecognition);

            /**
             * Fired when speech recognition stops.
             * Resets the microphone icon and focuses on the input field.
             */
            function endSpeechRecognition() {
                micIcon.classList.remove("ai-airplay-audio");
                micIcon.classList.add("ai-microphone");
                searchFormInput.focus();
                console.log("Speech recognition service disconnected");
            }

            // Speech result event listener
            recognition.addEventListener("result", resultOfSpeechRecognition);

            /**
             * Handles speech recognition results.
             * Parses the speech input and executes commands or fills the search form.
             *
             * @param {Event} event The speech recognition result event.
             */
            function resultOfSpeechRecognition(event) {
                const current = event.resultIndex; // Get the current result index
                const transcript = event.results[current][0].transcript; // Get the recognized speech text

                // Commands based on recognized speech
                if (transcript.toLowerCase().trim() === "stop recording") {
                    recognition.stop(); // Stop recognition when "stop recording" is said
                } else if (!searchFormInput.value) {
                    searchFormInput.value = transcript; // Set input field to recognized speech if empty
                } else {
                    // Handle commands like "go" and "reset input"
                    if (transcript.toLowerCase().trim() === "go") {
                        searchForm.submit(); // Submit the search form
                    } else if (transcript.toLowerCase().trim() === "reset input") {
                        searchFormInput.value = ""; // Clear the search input
                    } else {
                        searchFormInput.value = transcript; // Fill the input with recognized speech
                    }
                }
            }

            // Display available voice commands
            info.textContent = 'Voice Commands: "stop recording", "reset input", "go"';
        } else {
            // If SpeechRecognition is not supported, display an error message
            console.log("Your Browser does not support speech Recognition");
            info.textContent = "Your Browser does not support Speech Recognition";
        }
    }
});

Note that I am using Akaricons for the icons. You can use any icon font you want, just make sure to properly replace the elements and classes above.

Also, if you want to style it like the demo above, see below:

<style>
.search-field-wrapper--voice {
    position: relative;
}
#searchform--voice button {
    background-color: transparent;
    cursor: pointer;
    outline: none;
    border: none;
}
</style>

Once you’ve added the voice search shortcode, visit your site to check if it’s working correctly.

You should now see a microphone icon within your WordPress search box. Click it, speak your search query, and watch as the plugin retrieves the content based on your voice input.

Testing Voice Search Functionality

After setting it up, be sure to test the feature. Simply click the microphone icon, speak your search term, and check if the voice input is processed correctly.

If you’re using a custom WordPress search plugin, this code won’t be compatible with your search form.

Adding Speakable Schema

The speakable schema.org property identifies sections within an article or webpage that are best suited for audio playback using text-to-speech (TTS). Adding markup allows search engines and other applications to identify content to read aloud on Google Assistant-enabled devices using TTS. Web pages with speakable structured data can use the Google Assistant to distribute the content through new channels and reach a wider base of users.

Read the official documentation here.

<script type="application/ld+json">
{
     "@context": "https://schema.org/",
     "@type": "WebPage",
     "name": "My Awesome Website",
     "speakable":
     {
      "@type": "SpeakableSpecification",
      "xPath": [
        "/html/head/title",
        "/html/head/meta[@name='description']/@content"
        ]
      },
     "url": "https://www.example.com/path/to/my/page/"
}
</script>

Related posts