Introduction of Web Speech API to Chrome and Firefox opens up some new possibilities in general interaction with websites and, more importantly, accessibility. Web Speech API includes two main components: Speech Recognition and Voice Synthesis. In this article, we are going to use the Speech Recognition API to implement basic Voice Search in Magento 2 header search.
In one of my previous articles, I have discussed the importance of accessibility on an eCommerce site, how to test it for accessibility and how to make some basic improvements in order to have a more accessible site. In this article, we will dig into implementing a more advanced improvement.
Before we start, please note that Web Speech API is supported on Google Chrome (enabled by default), Opera and on Mozilla Firefox (needs to be enabled in about:config) with global support of 60%, according to the caniuse.com data at the time of writing of this article.
Benefits of speech recognition functionality
According to the W3C Web Accessibility Initiative, following people would depend on this feature and would found to be essential for their user experience:
- People with physical disabilities who cannot use the keyboard or mouse.
- People with chronic conditions, such as repetitive stress injuries (RSI), who need to limit or avoid using the keyboard or mouse.
- People with cognitive and learning disabilities who need to use voice rather than to type.
- People with temporary limitations, such as a broken arm.
Additionally, people who prefer using voice commands (on mobile devices) rather than type would also benefit from having an option to quickly input their search terms.
Implementing Voice Search to Magento 2
First, in web/js folder, we need to create a JavaScript file where we will add our Speech Recognition functionality. We have created a file called voiceSearch.js with the following code which attaches an event to the button (that we’ll add to our template), listens to a speech, parses the speech, outputs interim results to the search text input, outputs final results to the search input and submits the search form after user has done speaking.
define([
'jquery',
'domReady!'
], function ($) {
'use strict';
var $voiceSearchTrigger = $("#voice-search-trigger");
var $miniSearchForm = $("#search_mini_form");
var $searchInput = $("#search");
window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
function _parseTranscript(e) {
return Array.from(e.results).map(result => result[0]).map(result => result.transcript).join('')
}
function _transcriptHandler(e) {
$searchInput.val(_parseTranscript(e));
if (e.results[0].isFinal) {
$miniSearchForm.submit();
}
}
if (window.SpeechRecognition) {
var recognition = new SpeechRecognition();
recognition.interimResults = true;
recognition.addEventListener('result', _transcriptHandler);
} else {
alert("Speech Recognition is not supported in your browser or it has been disabled.");
}
function startListening(e) {
e.preventDefault();
$searchInput.attr("placeholder", "Listening...");
recognition.start();
}
return function() {
$voiceSearchTrigger.on('click touch', startListening);
}
});
Of course, we will need to add this file to requirejs-config.js in order to be properly loaded when needed.
var config = {
map: {
'*': {
'voiceSearch': 'js/voiceSearch'
}
}
};
After that we will have to edit (or override) our form.mini.phtml file which is located in <Vendor>/<theme>/Magento_Search/templates/form.mini.phtml. Search for the div element with the class of control and add the button with the id of voice-search-trigger and call the voiceSearch when search input has been loaded. You can see the example of the edited code below.
<div class="control">
<button class="action primary" id="voice-search-trigger"><?= /* @escapeNotVerified */ __('Voice Search') ?></button>
<input id="search"
data-mage-init='{"quickSearch":{
"formSelector":"#search_mini_form",
"url":"<?= /* @escapeNotVerified */ $helper->getSuggestUrl()?>",
"destinationSelector":"#search_autocomplete"},
"voiceSearch":{}
}'
type="text"
name="<?= /* @escapeNotVerified */ $helper->getQueryParamName() ?>"
value="<?= /* @escapeNotVerified */ $helper->getEscapedQueryText() ?>"
placeholder="<?= /* @escapeNotVerified */ __('Search entire store here...') ?>"
class="input-text"
maxlength="<?= /* @escapeNotVerified */ $helper->getMaxQueryLength() ?>"
role="combobox"
aria-haspopup="false"
aria-autocomplete="both"
autocomplete="off"/>
<div id="search_autocomplete" class="search-autocomplete"></div>
<?= $block->getChildHtml() ?>
</div>
Result
Before testing this feature, you may also want to edit the CSS, depending on where you have positioned the button and make sure to use the browser which has Speech Recognition supported and enabled. If everything has been done correctly, we can see the following result on our screen.
By clicking on the “Voice Search”, a prompt should appear asking for your permission to use the microphone (if your browser supports this feature). If your browser doesn’t support the Speech Recognition feature, a prompt will appear with the information about the feature support. When the permission has been granted, input text will change to “Listening…” and will wait for your input. Browser should also signal the state that the microphone is in use and is recording.
For example, if we say “Duffle Bag”, we will then be directed to the search results page for “Duffle Bag” products. If you have Magento 2 installed with Sample Data, the following products may appear as your search results.
Conclusion
This is only a small example of a wide range of possibilities for this feature. Why stop at the search functionality? Which bottlenecks in your shop workflow and problems can you fix by adding Speech Recognition?
Speech Recognition and Voice Commands are not only a pretty cool feature to implement for your store, but very important for the accessibility. As stated, this is only a fraction of various possibilities where Speech Recognition could help users in navigating and interacting with the site.
Speech Recognition can also be used to implement commands, like navigating to a specific page (Cart, help page, Account, etc.) or interacting with the site in various ways. It is interesting to see how this API will be used once it gets more global browser support.