Google Search Appliance software version 6.0
Posted June 2009
The Google Search Appliance has features that enable system administrators to enhance the search experience for end users. This chapter describes advanced customizations that administrators can make to search and results pages.
This section describes the audience for this document, the organization of the material, and some additional sources of information.
This document is for search administrators and webmasters who want to customize the search interface. To perform most customization tasks, you need privileges to edit search appliance front ends and eXtensible Stylesheet Language Transformation (XSLT) stylesheets. For some customizations, you must also have privileges to edit your web portal and content pages.
This document provides detailed procedures to direct general users in the steps for editing HTML markup or XSLT code. Some background in HTML, XSLT, and search appliance query parameters is helpful for understanding the customization examples and replicating them in your environment.
This document uses examples to illustrate customizations. Each customization is described in a separate section with detailed explanation of the required markup or code. Each example is also illustrated in the context of example pages based on a fictional fishing fly-tying business.
The following customizations are described and illustrated in this document:
| Customization | Description | Example Page |
|---|---|---|
| Presenting the Search Interface in an Inline Frame | Present the search and results pages in an inline frame within a static page. | Inline Frame Example Page |
| Creating an HTML Form Search Box | Integrate an HTML-based search box directly into your web page instead of using the default search page. | HTML Form Example Page |
| Combining an HTML Form Search Box with Inline Results | Combine inline frame presentation of the results page with a custom search box. | HTML Form Example Page |
| Replacing the Secure Search Radio Button with a Check Box | Save screen space by using a checkbox for the secure search option in place of default radio buttons. | Inline Frame Example Page |
| Specifying Query Parameters with XSLT | Make the search page submit selected query parameters with each search request. | Inline Frame Example Page |
| Including an Image Link for Results | For each result with a product illustration or other image, present a thumbnail image in the result item on the results page. | HTML Form Example Page |
| Replacing the Result Snippet with Custom Text | Make each search result show a product description or other specific custom text in place of the standard description snippet. | HTML Form Example Page |
The HTML form example page shown below illustrates a custom HTML form box, results image links, and custom description text.

To view the source code for this page and its supporting XSLT stylesheet, see Optional Example Materials.
The inline frame example page shown below illustrates Google search presented in an inline frame with a custom secure search checkbox. The code for the search button in this example page has been customized to submit selected search parameters that limit the number of results displayed in the limited screen space of the inline frame.

To view the source code for this page and its supporting XSLT stylesheet, see Optional Example Materials.
Many basic customizations, such as displaying a custom logo or changing colors and fonts, are not included in the scope of this document. For information on performing basic customization work and an overview of the search process, see Customizing the User Interface.
Some of the advanced customizations require you to set or modify query parameters. For more information on query parameters, see the Search Protocol Reference and "Using Front End Query Parameters" in Customizing the User Interface.
Keep in mind that the advanced customizations described in this document are not supported. Google Support cannot support or debug your customized HTML or XSLT code.
Customized XSLT stylesheets are not automatically upgraded when you update the search appliance software version. To enable new features in future versions, you may need to modify your customized stylesheets, or add your customized code to the default stylesheet for newer versions.
If your goal is to integrate search into existing web pages that have a particular style and identity, you can modify or minimize the visual effect of the default search and results pages. This section describes three levels of integration:
Using inline frames, you can present the search interface within the context of an otherwise static web page as illustrated in the Inline Frame Example Page.
The integrated search interface in the example page is derived from an inline frame tag with a src attribute pointing to iframe-example-frontend. As shown below, the inline frame is presented within a table cell:
<table border="0" cellpadding="0" cellspacing="0" width="800"> <tr><td>
<p>Search our extensive database of flies:</p>
<tr><td> <iframe id="iFrame" name="FlyFrame" frameborder="0" width="800" height="700" scrolling="auto" OnLoad="window.scroll(0, 0);" src="http://appliance_hostname/search?site=default_collection &client=iframe-example-frontend&output=xml_no_dtd&proxystylesheet=iframe-example-frontend"></iframe>
</td></tr>
</table>
At a minimum, the source attribute for an inline frame tag must specify the protocol and search appliance hostname, http://appliance_hostname. If you provide only the hostname, the default front end search interface appears in the inline frame.
In the inline frame example, the source URL contains custom query parameters to load the front end named iframe-example frontend, which is customized for optimal display of the search interface in an inline frame. The front end includes XSLT code that makes the search button submit selected parameters that affect the display of the search results page. For more information, see Specifying Query Parameters with XSLT and Search Protocol Reference.
To add the search interface inside an inline frame in a web page:
src attribute of the inline frame tag, specify http://appliance_hostname/, where the host name is the correct value for your search appliance.widthheight attributes to make sure the inline frame is large enough to accomodate the search results page. Add a noresize attribute if you want to prevent end users from changing the size. You can set any optional attributes of the inline frame (scrolling, align, and so on.) depending on your design goals for the page.With a simple HTML form such as the one depicted in the HTML Form Example Page, you can integrate a simple search box directly into your web page instead of using the default search page. This approach allows an end user to focus on the page content with minimal distraction from the search interface. However, if the user needs to perform a search, the search box is readily available, as shown below.

The HTML code for the search box used in the example is derived from a form tag in the side navigation of the page.
<form method="GET" target="FlyFrame" action="http://appliance_hostname/search"> <input type="text" name="q" size="32" maxlength="256" value="" /> <input type="submit" name="btnG" value="Search" /> <input type="hidden" name="site" value="default_collection" /> <input type="hidden" name="client" value="example-frontend" /> <input type="hidden" name="output" value="xml_no_dtd" /> <input type="hidden" name="proxystylesheet" value="example-frontend" /> <input type="hidden" name="filter" value="p" /> <input type="hidden" name="getfields" value="*" /> </form>
This form submits a GET request to the search engine, requesting results in the format specified by example-frontend. The example form includes optional input fields for a submit button and for query parameters that enhance the visual effect of the page. These parameters turn off duplicate directory filtering (filter), retrieve meta tag values (getfields), and specify the stylesheet associated with example-frontend (proxystylesheet).
The requirements for an HTML for search box are:
GET method and the path http://appliance_hostname/searchqsite, client, and output as hidden input fieldsproxystylesheetIn addition to the required fields, you can include any valid query parameter as a hidden input field in the HTML form. See the Search Protocol Reference for more information on query parameters.
Search boxes should be big enough to accomodate multiple word entries. Users typically enter queries that fit in the search box, so if the search box is small, they may enter only single words. Since Google supports multi-word, phrase, or natural language queries, make your search box big enough for your users to enter larger queries. The recommended minimum size for a search box is 20-30 characters.
To add an HTML form search box to a web page:
appliance_hostname is the correct value for your search appliance:
<form method="GET" action="http://appliance_hostname/search">
q, and provide values for size and maximum length (the absolute search appliance limit is 2048 characters):
<input type="text" name="q" size="32" maxlength="256" value="">
site, client, and output as hidden input fields:
<input type="hidden" name="site" value="default_collection">
<input type="hidden" name="client" value="default_frontend">
<input type="hidden" name="output" value="xml_no_dtd" />
If you want to direct the search request to a non-default collection or front end, enter appropriate values for site and client.
proxystylesheet. Typically, this value is the name of the front end you specified for client.
<input type="submit" name="btnG" value="Search">
You can combine inline frame presentation of the results page with a custom search box. This combination of factors allows users to first view the frame populated with static content, and then replace that content with a list of search results if needed.
This approach is used in the HTML Form Example Page. The HTML form in this example page collects the search terms in a custom search box, submits them to the search engine, and then directs the results page to open in the inline frame "FlyFrame" as specified by the target attribute in the form tag:
<form method="GET" target="FlyFrame" action="http://appliance_hostname/search">
When using this approach, you may prefer to remove redundant search boxes from the results page by setting the XSLT stylesheet variables show_top_search_box and show_bottom_search_box to zero.
A production web site using a form box and inline frame at the time of writing is Toolfetch.com:

You may prefer to use the default Google search and results pages, but with a degree of customization. This section describes two modifications to the the default search query experience: using a checkbox for secure search, and adding query parameters to a front end. Both of these customizations make only slight changes in the visual effect and behavior of the default search box.
Using a check box for secure search saves space on the search query page and gives it a cleaner look. The following screen capture from iframe_index.html depicts a customized search box in place of the default radio buttons:

This customized search box is defined by XSLT rules in the stylesheet associated with iframe-example-frontend. In this stylesheet, the default code for the search box input form is overwritten with the following block of custom code.
<xsl:choose>
<xsl:when test="$access='p'">
<input type="checkbox" name="access" value="a" />
</xsl:when>
<xsl:otherwise>
<input type="checkbox" name="access" value="a"
checked="checked" />
</xsl:otherwise>
</xsl:choose>
Include secure content
This conditional clause with <choose> tests the value of the access parameter, and then defines the checkbox accordingly. When access is the default value of "p," the unchecked box sets the value to "a" if checked by the end user. If the value is already set to "a," the checkbox is displayed checked.
For more information on the access query parameter, see the Search Protocol Reference.
To modify a stylesheet to replace the secure search radio buttons with a checkbox:
<!-- **********************************************************************
Search box input form (Types: std_top, std_bottom, home, swr)
********************************************************************** -->
<xsl:if test="$show_secure_radio != '0'">
This conditional clause contains the default radio button code, shown below in boldface and bracketed by start/end comments (these comments are not found in your default stylsheet):
<xsl:if test="$show_secure_radio != '0'">
<tr>
<td colspan="2">
<font size="-1">
<!-- Start cut. Between here and End cut is the code you
must replace with the secure search checkbox code. -->
Search:
<xsl:choose>
<xsl:when test="$access='p'">
<label><input type="radio" name="access" value="p"
checked="checked" />public content</label>
</xsl:when>
<xsl:otherwise>
<label><input type="radio" name="access" value="p"/>
public content</label>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="$access='a'">
<label><input type="radio" name="access" value="a"
checked="checked" />public and secure content</label>
</xsl:when>
<xsl:otherwise>
<label><input type="radio" name="access" value="a"/>
public and secure content</label>
</xsl:otherwise>
</xsl:choose>
<!-- End cut. Between here and Start cut is the code you
must replace with the secure search checkbox code. -->
</font>
</td>
</tr>
</xsl:if>
choose clause with similar logic appropriate for a checkbox. <xsl:if test="$show_secure_radio != '0'">
<tr>
<td colspan="2">
<font size="-1">
<!-- Start paste. Between here and End paste is the correct
location for the secure search checkbox code. -->
<xsl:choose>
<xsl:when test="$access='p'">
<input type="checkbox" name="access" value="a" />
</xsl:when>
<xsl:otherwise>
<input type="checkbox" name="access" value="a"
checked="checked" />
</xsl:otherwise>
</xsl:choose>
Include secure content
<!-- End paste. Between here and Start paste is the correct
location for the secure search checkbox code. -->
</font>
</td>
</tr>
</xsl:if>
choose statement. The default search box for a front end is defined by the associated XSLT stylesheet. You can modify the XSLT stylesheet to include selected parameters in every query submitted from the query box in a front end. Valid parameters are documented in the Search Protocol Reference.
Though it is not immediately apparent, the search box in the Inline Frame Example Page is customized in this way. Each query submitted from the search box explictly retrieves selected meta tag values and limits the number of results to optimize the limited page space.
The source attribute of the inline frame tag in the Inline Frame Example Page points to the customized front end, iframe-example-frontend. This front end submits selected parameters as defined by the XSLT code shown in bold at the bottom of the following code example.
<!-- *** form_params: parameters carried by the search input form *** -->
<xsl:template name="form_params">
<xsl:for-each
select="PARAM[@name != 'q' and
@name != 'ie' and
not(contains(@name, 'as_')) and
@name != 'btnG' and
@name != 'btnI' and
@name != 'site' and
@name != 'filter' and
@name != 'swrnum' and
@name != 'start' and
@name != 'access' and
@name != 'ip' and
(@name != 'epoch' or $is_test_search != '') and
not(starts-with(@name ,'metabased_'))]">
<input type="hidden" name="{@name}" value="{@value}" />
<xsl:if test="@name = 'oe'">
<input type="hidden" name="ie" value="{@value}" />
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:for-each>
<xsl:if test="$search_collections_xslt = '' and PARAM[@name='site']">
<input type="hidden" name="site" value="{PARAM[@name='site']/@value}"/>
</xsl:if>
<!--Add these fields to every query string submitted from this front end-->
<input type="hidden" name="getfields" value="rank.price.fly-type" />
<input type="hidden" name="num" value="3" />
</xsl:template>
When users click the search button in this front end, getfields="rank.price.fly-type" and num="3" are included in the search request along with the standard parameters. Consequently, the result set will be limited to three results per page, and the specified meta tags will be retrieved for each result.
To add query parameters to a front end by modifying the associated stylesheet:
<!-- **********************************************************************
Search Parameters (do not customize)
********************************************************************** -->
<!-- *** form_params: parameters carried by the search input form *** -->. This section contains an XSLT template named form_params.<xsl:template name="form_params">. </xsl:if> tag, add hidden input fields for all parameters you want to submit from the search form. For example, to retrieve all meta tag values in the results, add this line:
<input type="hidden" name="getfields" value="*" />
The custom front end for the Inline Frame Example Page is configured to show meta tags in the results. Each result displays the three meta tags, rank, price, and fly-type, that are explicitly retrieved by the custom search form:

To modify a front end to show meta tags in results:
<xsl:variable name="show_meta_tags">1</xsl:variable>
getfields is included in search requests, and that it is assigned the correct values to retrieve the desired meta tags. For more information on the getfields query parameter, see the Search Protocol Reference. Customization can serve your goals for the visual effect and content of results pages. This section describes two ways to enhance results pages: including image links in results, and replacing the result snippet with customized text.
Placing small images in the search results enhances the visual appeal of the results page. Because experience has trained many users to click icons and pictures, it is helpful to make each image a link to the search result, just as the result title is a link to the result. The HTML Form Example Page shows image links presented in the results pages.

The thumbnail-sized image links in the example pages are derived from a small block of XSLT code added after the variable declarations in the "single result" section of example-frontend_stylesheet.en.xslt. To find this block in the example stylesheet, search for the comment text "<!--Include image" and look for the following code:
<!--Include image from meta tag in results list-->
<xsl:for-each select="MT">
<xsl:if test="@N='product-image' and @V!=''">
<a href="{$protocol}://{$escaped_url}">
<img align="left" height="60" width="80" src="{@V}"/>
</a>
</xsl:if>
</xsl:for-each>
The XSLT image block iterates through each MT (meta tag) element in the result set and tests for non-empty values for the tag product-image. Then it includes the meta tag value inside a link to the results URL as represented by the concatenated variables protocol and escaped_url.
It is important to locate this XSLT block after the variable declarations located at the beginning of the "single result" XSLT block. Because the image block uses two of these variables, it will throw an error in the XSLT stylesheet editor if it is located before the variable is declared.
Each product description page in this example includes a meta tag named product-image containing an absolute link to a thumbnail image. Because relative links do not work in the search results page, the meta tag values must be absolute links. For example, on mywebserver the prince nymph example page would include this meta tag:
<meta name="product-image" content="http://www.mywebserver.com/example/images/prince_small.jpg" />
The exact meta tag name is important, because it is required as a value for the search request parameter getfields and also it is tested in a conditional clause in the XSLT code. All pages for which you want to present a results image must include a meta tag like this one, with the name properly referenced in the stylesheet and in getfields.
You must explicitly retrieve the meta tags you want from the result set in order for them to be transformed by the XSLT code. You can do this by adding getfields="meta_tag_name" to your search request, or use getfields="*" to retrieve all meta tags. See the Search Protocol Reference for more information on adding query parameters to the search request.
To modify a stylesheet to include image links in the results:
<!-- **********************************************************************
A single result (do not customize)
********************************************************************** -->
<!-- *** Indent as required (only supports 2 levels) *** -->
<!--Include image from meta tag in results list-->
<xsl:for-each select="MT">
<xsl:if test="@N='meta_tag_name' and @V!=''">
<a href="{$protocol}://{$escaped_url}">
<img align="left" height="60" width="80" src="{@V}"/>
</a>
</xsl:if>
</xsl:for-each>
Google's automated selection of a result snippet is a useful feature that helps users evaluate the relevance of a result. However, you may prefer to force the result to show a product description or other specific custom text related to the result.
For the fictional fishing fly business of the example pages, imagine that writers in the marketing department create succinct product descriptions for each item. The short descriptions are stored in meta tags and the longer descriptions are stored in the product page text. If the product page for a fly doesn't have a description tag, the results page uses the automated snippet derived from the page text. This approach is illustrated in the HTML Form Example Page, in which some results include a custom description and some results includes a standard result snippet with ellipses and search terms displayed in boldface.

The product descriptions in the results for the example are derived from a small block of XSLT code added to the "Snippet Box" section of the stylesheet. This custom block includes and augments the default code for displaying the snippet. Note the differences and similarities in the default snippet box and the customized version in these two examples:
Default Snippet Box
<!-- *** Snippet Box *** -->
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td class="s">
<xsl:if test="$show_res_snippet != '0'">
<xsl:call-template name="reformat_keyword">
<xsl:with-param name="orig_string" select="S"/>
</xsl:call-template>
</xsl:if>
Custom Description Snippet Box
<!-- *** Snippet Box *** -->
<table cellpadding="0" cellspacing="0" border="0">
<tr>
<td class="s">
<!--Use description meta tag, if non-empty, in place of snippet-->
<xsl:choose>
<xsl:when test="MT/@N='description' and MT/@V!=''">
<xsl:value-of select="MT[@N = 'description']/@V"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="reformat_keyword">
<xsl:with-param name="orig_string" select="S"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
The custom description snippet block displays the description for each result that has a description meta tag, or MT. If the XSLT engine does not find a valid description tag, it calls the standard template rules to display the auto-generated snippet element S.
The custom version includes the rule to display a standard snippet, but applies that template only if there is no valid description tag in the result. If you use this approach, make sure you have only one instance of the reformat_keyword template that selects the snippet element.
Most of the product pages in this example includes a meta tag named description that contains a brief description of the product. For example, the copper john nymph page includes this meta tag:
<meta name="description" content="An excellent nymph for pocket water or tight-line nymphing. The high proportion of wire tied into the body makes the copper john sink quickly to depth." />
All pages for which you want to present custom text must include a meta tag like the above example, with the name properly referenced in the stylesheet and retrieved in the search request using the query parameter getfields. For pages that do not contain valid description tags, the stylesheet uses the automated snippet derived from page text.
You must explicitly retrieve the meta tags in the result set in order for them to be transformed by the XSLT code. Do this by adding getfields=description to your search request. For more information on getfields, see the Search Protocol Reference.
To modify a stylesheet to replace the result snippet with custom text:
<!-- *** Snippet Box *** -->.<xsl:if test="$show_res_snippet != '0'">, with the following text:
<xsl:choose>
<xsl:when test="MT/@N='meta_tag_name' and MT/@V!=''">
<xsl:value-of select="MT[@N = 'meta_tag_name']/@V"/>
</xsl:when>
<xsl:otherwise>
</xsl:if>, with the following text:</xsl:otherwise> </xsl:choose>
By default a front end is configured to serve only public results. You can configure a front end to serve both secure and public results by editing the XSLT stylesheet.
To configure a front end to serve both secure and public results:
In the admin console, click Serving > Front Ends.
<xsl:variable name="access"> ... <xsl:otherwise>p</xsl:otherwise>
<xsl:otherwise>a</xsl:otherwise>
This section contains reference materials, including information on setting up and comparing the example pages and resources.
You do not need to set up the example materials in order to read and understand the custom code, but it may be helpful to see the customizations in the same context described in this document. Depending on whether you begin with index.html or iframe_index.html, the example site demonstrates the customizations depicted in the HTML Form Example Page or the Inline Frame Example Page.
To view the search functionality of the example site, you must deploy the example web pages in a web server and implement the example stylesheets in a search appliance.
To set up the materials for testing in your search appliance:
appliance_hostname with the host name of your search appliance.webserver_hostname with the host name of your web server. .txt extension from the filenames. For example, example-frontend_stylesheet.en.xslt.txt becomes example-frontend_stylesheet.en.xslt.After you have set up the example materials, run a test query on them by opening index.html and typing "nymph" or other key words from the example pages into the search box. The expected result looks like the HTML Form Example Page. To view the inline frame example, use the search box displayed in /pages/iframe_index.html.
The example consists of web pages and stylesheets designed for a fictional e-commerce site dedicated to selling fishing flies. It includes the directories and files described below.
The example directory contains these subdirectories:
The following files reside directly under the /example directory:
index.html
example-frontend_stylesheet.en.xslt.txt
iframe-example-frontend_stylesheet.en.xslt.txt
The following files reside under /example/css:
The following files reside under /example/images:
adams_large.jpg
adams_small.jpg
ak_bugger_large.jpg
ak_bugger_small.jpg
ap_large.jpg
ap_small.jpg
boss_large.jpg
boss_small.jpg
bugger_large.jpg
bugger_small.jpg
caddis_large.jpg
caddis_small.jpg
cj_large.jpg
cj_small.jpg
dark_lord_large.jpg
dark_lord_small.jpg
fox_poopah_large.jpg
fox_poopal_small.jpg
prince_large.jpg
prince_small.jpg
royal_large.jpg
royal_small.jpg
sculpin_large.jpg
sculpin_small.jpg
The following files reside under /example/pages
adams.html
ak_bugger.html
ap.html
boss.html
bugger.html
caddis.html
cj.html
dark_lord.html
flyframe.html
fox_poopah.html
iframe_index.html
prince.html
royal.html
sculpin.htm
To locate and review customized XSLT code, it can be helpful to have a side-by-side comparison of the default and customized stylesheets. You can readily find freeware tools for preparing such comparisons.
To view comparisons of the example XSLT stylesheets and the version 5.0 default search appliance stylesheet on which they are based, see the following pages: