This post describes how you could implement Google custom search on your website. You could use one of the custom search modules out there, however creating your own module is a very good option as it means you can use the latest version of Google custom search, customise it exactly how you want it, and it is very easy to do.

I am describing this for Drupal 6, it is similar for Drupal 7 - see also comment on implementing this in Drupal 7 below.

Step 1 - set up your custom search code on Google

Go to http://www.google.co.uk/cse or a version of this page suitable for your region to set up a new search engine. Fill in the details for the site or sites you want to search. Choose one of the styles - for example the default style. You will be able to customise this a little - for example font colors of your results.

Now go to change the basics, you will now have a control panel listing on the left. We want to create a two page layout where the search box is on one page and the results are on another (so we can have a search box on every page of the site for example). Click save and get code. You will be asked for the url of the page where you want the search results to appear: for testing you can put your local test page (you will need to change this when you put the module mode on your production site).

You will notice on the get code page that there is a box where you can specify a query parameter - Google's default is "q", but we can't use this on a Drupal site as Drupal also uses the "q" parameter. Unfortunately as of 11/01/2013 changing the parameter in this box does nothing - you will have to include this in your code (see below).

Step 2 - create your custom module

Create a folder in the sites/all/modules (or a sub directory of this), and call it mygooglecse for example. In this folder you will need to create three files:

mygooglecse.info
mygooglecse.module
mygooglecse.js

mygooglecse.info

The contents of the mygooglecse.info file should look something like this:

name = My Google Custom Search Engine
description = Search my site with Google custom search.
core = 6.x

mygooglecse.js

Put all the code between the script tags in the first element code which was on the get code page for the search engine that you made in step 1. The code for the results page should be the same, so you don't need to paste this. Below is an example - paste the code corresponding to your search engine.

  (function() {
    var cx = '001234676890123456789:a1rb2cdef3gh';
    var gcse = document.createElement('script'); gcse.type = 'text/javascript'; gcse.async = true;
    gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +
        '//www.google.co.uk/cse/cse.js?cx=' + cx;
    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(gcse, s);
  })();

mygooglecse.module

Now we need to create the module code.

/**
* My Google Custom Search Engine
* 
* This search is set up to work with the two page search option. See: www.google.co.uk/cse/
* 
*/

/**
 * Implementation of hook_block().
 */
function mygooglecse_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks['google_custom_search']['info'] = t('My Google Custom Search');
   // Note, we can't cache this block as it will be set up to include some javascript
   // in the head of the page if the block is called from the cache this javascript 
   // won't be included.
    $blocks['google_custom_search']['cache'] = BLOCK_NO_CACHE;
    return $blocks;
  }
  else if ($delta == 'google_custom_search' && $op == 'view' && user_access('use my google custom search')) {
    $block['title'] = t('Search');
    drupal_add_js(drupal_get_path('module', 'mygooglecse') . '/mygooglecse.js', 'module', 'header');
    // Note, the following comes from the first element code box on Google, but 
    // we have set the query parameter name here so it doesn't interfere with Drupal. 
    // See: libretechtips.com/tips-drupal7-drupal6/how-use-google-cse-drupal
    $block['content'] = '<gcse:searchbox-only queryParameterName="my_gcs"></gcse:searchbox-only>';
    return $block;
  }
}

// We set up a permission to use the search. I did this mainly so that I could do 
// some final testing on the production site with admin access only first to
// check that I had set it up correctly (i.e. you will need to remember to change
// the url of your search results page on your Google search engines settings
// page to the url for the production site.
function mygooglecse_perm() {
  return array('use my google custom search');
}

/**
* Implementation of hook_menu()
* 
*/
function mygooglecse_menu() {
  // Here we set up the page where the results will display:
  $items['my_search/google'] = array(  // Change this url to wherever you want the page to be
    'title' => 'Search',
    'description' => 'My Google Custom Search',
    'page callback' => 'mygooglecse_searchpage', // The function that will be called to set up the search page
    'access arguments' => array('use my google custom search'), // Those with this permission will be allowed to see the results
    'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}
 
// Here we set up the page:
function mygooglecse_searchpage() {
  // puts the call to your javascript file containing the Google code in the header
  // of the page:
  drupal_add_js(drupal_get_path('module', 'mygooglecse') . '/mygooglecse.js', 'module', 'header');
 
  // Now create the content of your page:
  $content = '';
  // This is the search box again - so that it also appears at the top of the search
  // page.
  $content .= '<gcse:searchbox-only queryParameterName="my_gcs"></gcse:searchbox-only>';
  // Drupal search link:
  // This creates a link to the Drupal standard search from the Google results page:
  $content .= l(t('Advanced search'), 'search/node/' . $_GET['my_gcs']);
  
  // This is the code for the results list.
  // Note we also add the queryParameterName setting here to the code. See
  // developers.google.com/custom-search/docs/element#supported_attributes
  // for a full list of supported attributes.
  // I've also set it so links to pages in the results open in the same window rather
  // than a new tab/window which is the default.
  $content .= '<gcse:searchresults-only queryParameterName="my_gcs" linkTarget="_self"></gcse:searchresults-only>';
  return $content;
}

Now, enable your module from the modules page and enable the block this module creates from the Drupal blocks page.

Styling

You can style the Google output code using a css style sheet in your theme. This is a little awkward, and is also likely to break if Google change the HTML of what gets returned from their javascript call. I have myself however used it to slightly improve the look of the results for my site:

div.gsc-webResult div.gsc-result {
  padding: 0;
}

Otherwise I use the styling options given in the Google control panel.

Comments

VM’s picture

In the case that you weren't already aware there is the following: http://drupal.org/project/google_cse

neilt17’s picture

Yes I am aware of that module, and in fact I started off by using it. Unfortunately it uses the older v1 code, and I wanted to use the newer v2 code which produces a nicer formatted output. Doing your own module in this way also gives you more control over the customisation of the search box and results. Of course the Google Custom Search Engine module could be developed to be able to use the v2 code and have a settings page allowing you to set all those customisations there.

occupant’s picture

Great guide. For anyone looking for a Drupal 7 version, I updated the mygooglecse.module (and .info file to version 7) so it would work in D7 (hook_block and hook_perm both needed updating). I've left the original code commented out so the changes would make more sense.

<?php
/**
* My Google Custom Search Engine
* 
* This search is set up to work with the two page search option. See: www.google.co.uk/cse/
* 
*/
function mygooglecse_block_info() {
  // This example comes from node.module.
  $blocks['google_custom_search'] = array(
    'info' => t('My Google Custom Search'), 
    'cache' => DRUPAL_NO_CACHE,
  );
  return $blocks;
}


function mygooglecse_block_view($delta = '') {
  // This example is adapted from node.module.
  //$mymodule_testblock_content = '<gcse:searchbox-only></gcse:searchbox-only>';
  $block['title'] = t('');
  //drupal_add_js(drupal_get_path('module', 'mygooglecse') . '/mygooglecse.js', 'module', 'header');
  //$block['content'] = '<gcse:searchbox-only></gcse:searchbox-only>';
  $block['content'] = array(
    '#markup' => '<gcse:searchbox-only queryParameterName="as_q"></gcse:searchbox-only>',
    '#attached' => array(
        'js' => array(
          drupal_get_path('module', 'mygooglecse') . '/mygooglecse.js',
      ),
    ),
  );
  return $block;
     
}

/**
 * Implementation of hook_block().
 */
/*function mygooglecse_block($op = 'list', $delta = 0, $edit = array()) {
  if ($op == 'list') {
    $blocks['google_custom_search']['info'] = t('My Google Custom Search');
   // Note, we can't cache this block as it will be set up to include some javascript
   // in the head of the page if the block is called from the cache this javascript 
   // won't be included.
    $blocks['google_custom_search']['cache'] = BLOCK_NO_CACHE;
    return $blocks;
  }
  else if ($delta == 'google_custom_search' && $op == 'view' && user_access('use my google custom search')) {
    $block['title'] = t('Search');
    drupal_add_js(drupal_get_path('module', 'mygooglecse') . '/mygooglecse.js', 'module', 'header');
    // Note, the following comes from the first element code box on Google, but 
    // we have set the query parameter name here so it doesn't interfere with Drupal. 
    // See: libretechtips.com/tips-drupal7-drupal6/how-use-google-cse-drupal
    $block['content'] = '<gcse:searchbox-only queryParameterName="my_gcs"></gcse:searchbox-only>';
    return $block;
  }
}*/

// We set up a permission to use the search. I did this mainly so that I could do 
// some final testing on the production site with admin access only first to
// check that I had set it up correctly (i.e. you will need to remember to change
// the url of your search results page on your Google search engines settings
// page to the url for the production site.
/*function mygooglecse_perm() {
  return array('use my google custom search');
}*

/**
 * Implements hook_permission().
 */
function mygooglecse_permission() {
  return array(
    'access mygooglecse_searchpage content' => array(
      'title' => t('Use google custom search'),
    )
  );
}

/**
* Implementation of hook_menu()
* 
*/
function mygooglecse_menu() {
  // Here we set up the page where the results will display:
  $items['search-results'] = array(  // Change this url to wherever you want the page to be
    'title' => 'Search ',
    'description' => 'My Google Custom Search',
    'page callback' => 'mygooglecse_searchpage', // The function that will be called to set up the search page
    'access arguments' => array('Use google custom search'), // Those with this permission will be allowed to see the results
    'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}

// Here we set up the page:
function mygooglecse_searchpage() {
  // puts the call to your javascript file containing the Google code in the header
  // of the page:
  //drupal_add_js(drupal_get_path('module', 'mygooglecse') . '/mygooglecse.js');

  // Now create the content of your page:
  $content = '';
  // This is the search box again - so that it also appears at the top of the search
  // page.
  $content .= '<gcse:searchbox-only queryParameterName="as_q"></gcse:searchbox-only>';
  // Drupal search link:
  // This creates a link to the Drupal standard search from the Google results page:
  //$content .= l(t('Advanced search'), 'search/node/' . $_GET['as_q']);
  // This is the code for the results list.
  // Note we also add the queryParameterName setting here to the code. See
  // developers.google.com/custom-search/docs/element#supported_attributes
  // for a full list of supported attributes.
  // I've also set it so links to pages in the results open in the same window rather
  // than a new tab/window which is the default.
  $content .= '<gcse:searchresults-only queryParameterName="as_q" linkTarget="_self"></gcse:searchresults-only>';
  return $content;
}
?>
neilt17’s picture

Great, I've edited my original post above to link to this comment.

pkhansari’s picture

The code works fine but it shows the result in a blank page. To fix this, change line:

'#markup' => '<gcse:searchbox-only queryParameterName="as_q"></gcse:searchbox-only>',

to:

'#markup' => '<gcse:searchbox-only queryParameterName="as_q" resultsUrl="search-results"></gcse:searchbox-only>',

and line:

$content .= '<gcse:searchbox-only queryParameterName="as_q"></gcse:searchbox-only>';

to:

$content .= '<gcse:searchbox-only queryParameterName="as_q" resultsUrl="search-results"></gcse:searchbox-only>';

silios’s picture

Sweet write up and explanation!
The Drupal 7 version has a minor problem though.
The malformed call to hook_permissions leads to access denied error for anonymous users (although it appears correctly in the user permissions list ).

Replace with the following code in order to have proper permission control over the display of the page

/**
* Implementation of hook_menu()
*/
function mygooglecse_menu() {
  // Here we set up the page where the results will display:
  $items['search-results'] = array(  // Change this url to wherever you want the page to be
    'title' => 'Search ',
    'description' => 'My Google Custom Search',
    'page callback' => 'mygooglecse_searchpage', // The function that will be called to set up the search page
    'access arguments' => array('use_google_custom_search'), // Those with this permission will be allowed to see the results
    'type' => MENU_NORMAL_ITEM,
  );
  return $items;
}

function mygooglecse_permission() {
  return array(
    'use_google_custom_search' => array(
      'title' => t('Use google custom search'),
      'description' => t('Who can have access to the google search results page.'),
    ),
  );
}

Thank you both, you made my day :)

asheresque’s picture

Works great, thanks! Especially helpful to anyone trying to fit the CSE results into a responsive design, as the iframe in the google_cse module really gets in the way. Much better solution here (shouldn't this be presented as an alternative to the google_cse module to help others avoid the same problem?).

rogerinc’s picture

So a block is created for the search box

ardih’s picture

Nice article, just wanted to point out that there is also the more powerful (but not free) Google Site Search branch, that has a nice Drupal module you can use https://drupal.org/project/gss .
Main reason we ended up choosing this over GCS was more customization for the results, ie. letting users filter the results by date, content type, taxonomy etc. Was not that easy to figure it all out, if anyone ever needs it then a little help here http://ardihundt.com/2013/09/15/filtered-google-site-search-for-drupal/

mustardman’s picture

Maybe I am dumb but there were a couple things not obvious to me that took me awhile to figure out.

On the google website http://www.google.com/cse/ you have to set search results details to match the settings in these files.

So the way these files are shown here, on the google end you have to set the query parameter to "as_q" (google default is "q") and the url to "http://yourwebsite.com/search-results".

Seems obvious now but it wasn't at first from reading the instruction provided here over and over again.