How to use Google CSE with Drupal

It’s been a long time since I visited my site’s Google Custom Search Engine (CSE) settings page. I was happy to see that in 2012 Google apparently added a new option to sort results by date, as well as site image searching. This should be a real boon for users. But at the same time, I noticed that under the Look and Feel settings, it now says that the iFrame display method is deprecated. That’s fine by me, iFrames have been discouraged by web developers for years, so I’m glad to see that Google is moving away from them. So, I happily inserted the new Google CSE code into my Drupal 6 site and tried out the search function, only to be greeted by this error:

Page not Found

But fortunately, there is a workaround. And it’s not at all easy to find this information on the Internet.

Background

First of all, I should explain how I implemented the Google CSE on my Drupal 6 site. I want users to have the option to use the Drupal search engine if they don’t find what they want in the Google CSE results. But to reduce load on the server, I want to discourage users from using the Drupal search engine by default. So to encourage users to use Google first, I want the Google CSE search box visible on all pages. The Google search results should be integrated into the section of the page where site content usually appears, and the left column should still appear as it does on any other page. But to make the Drupal search option discoverable, I want the Drupal search box to appear on the same page as the Google results. The search URL on my site is simply /search.

Or if the user uses the Google CSE box in the upper part of the left column on any page, he will first see Google results, with the option of searching again with the Drupal engine right from the Google results page.

Setting up the Google CSE

In order to put the Google Custom Search Engine (CSE) search box on all pages and display the results in another page, open the CSE settings page and click on the specific CSE you want to configure. Under the Look and Feel options, use the options.

The important option is the one that says Two page under the section Choose a layout. This will give you two separate code blocks— one for the search box and the other for the search results section. Next, click the Save & Get Code button.

The resulting page will contain two chunks of code for the search box and the search results respectively. There are two text fields that should be filled in. The first field says: Specify the url in your site where you want the search results to appear. I put http://example.com/search. The second field says Specify the query parameter name embedded in the url. This would appear to be the solution to the issue that will be discussed in the next section, but at the time of writing this option doesn’t seem to do anything. At any rate, I changed the default value from q to as_q. Hit the Save Changes button, keep the page open in a tab, and open the Drupal admin page in another tab.

Integrating the Google CSE with Drupal

The easiest way to accomplish the desired setup in Drupal is with blocks. That way we avoid adding the hassle of adding code to the Drupal theme template files. There are Drupal modules for adding Google CSE to a site, but I prefer to avoid the complexity of using extra modules wherever possible.

The block for the Google CSE search box

First of all, create a new block in the region where you want the Google CSE search box to appear. I want the search block to appear on all pages, but if you want to exclude it from some pages you can do so in the Page specific visibility settings section of the Drupal block settings. Also make sure that the input format for the Block body field is set to Full HTML or PHP Code, so that none of the code we are going to add gets filtered out. In the Block body field, add the chunk of code for the search box that was generated in the Google CSE settings.

Now, the issue with the default code generated by Google is that it uses the ?q parameter for the search terms. For example, a search for something would generate the URL http://example.com/search?q=something. But the problem with the q parameter is that is conflicts with the default Drupal q parameter that is used to load pages when clean URLs are disabled. So by default, the Google code generates a Page not found error when a Google search is executed. I don’t know why changing the query parameter name in the Google CSE settings doesn’t work, but I finally found how to manually edit the code thanks to a tip for Wordpress. The line that says:
<gcse:searchbox-only></gcse:searchbox-only>

Needs to be changed to:
<gcse:searchbox-only linktarget="http://example.com/search" queryParameterName="q_as"></gcse:searchbox-only>

Obvious the linktarget parameter needs to be changed to the landing page for the search results on your site. The queryParameterName could probably be set to anything except q, but since the Google Search API specifically mentions as_q I figured it’s best to play it safe. By changing the query parameter, we avoid the conflict with Drupal. My code block looked like this when I was done:

<!-- Put the following javascript before the closing </head> tag. --> <script> (function() { var cx = '010101010101010101010100101010101'; var gcse = document.createElement('script'); gcse.type = 'text/javascript'; gcse.async = true; gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//www.google.com/cse/cse.js?cx=' + cx; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(gcse, s); })(); </script> <!-- Place this tag where you want the search box to render --> <gcse:searchbox-only linktarget="http://example.com/search" queryParameterName="q_as"></gcse:searchbox-only>

The block for the Google CSE results

Now, we need to create the landing page for the Google search results. As explained above, on my site I want the results to appear below the Drupal search box on the /search page so users see they have two options. But if you prefer, you can create a different page and add the search results block there. So create another Drupal block with the Full HTML or PHP input type , and in the Page specific visibility settings section click Show on only the listed pages and type in the name of the page where you want results to appear. I used search. This must be the same as the last part of the URL specified in the modified linktarget in the first block of code for the search box. Now paste in the second block of code from the Google CSE settings for the search results and modify the last line from:
<gcse:search></gcse:search>

to the following:
<gcse:search linktarget="_parent" queryParameterName="q_as"></gcse:search>

Finally, in order for the results code to work correctly, there is a surprising error in the Google code that needs to be fixed. This error is especially evident with Firefox, which refuses to show search results with the default results code provided by Google.
The parenthesis highlighted in yellow are out of place, and because of this error Firefox won’t show search results. So they should be removed. Many thanks to this thread on the Google Product Forums for noticing this; I never would have figured this out otherwise.

Here’s the final code for the search results block:

<!-- Put the following javascript before the closing </head> tag. --> <script> function() { var cx = '0101010101010101010101'; var gcse = document.createElement('script'); gcse.type = 'text/javascript'; gcse.async = true; gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//www.google.com/cse/cse.js?cx=' + cx; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(gcse, s); }(); </script> <!-- Place this tag where you want the search results to render --> <gcse:search linktarget="_parent" queryParameterName="q_as"></gcse:search>

Conclusion

And that’s that. Users can now benefit from the uncannily fast and accurate results of a Google Custom Search Engine without hammering the server… at least not my server! And if they want to use the onboard Drupal search engine, that option is also clearly presented to them. I hope these tips will aid Drupal users in working around the Page not found error by modifying the Google generated code. Thanks again to Servertastic.com for the tip.