Google Cus­tom Search

For ExpressionEngine 6, ExpressionEngine 3+, ExpressionEngine 2 • Current Version: 1.2.3

Purchase for $19

Dis­play search results from your Google Cus­tom Search Engine using stan­dard EE tem­plate tags via the Google Cus­tom Search API. A great search solu­tion for your site if:

  • you have a low-to-medi­um traf­fic site
  • you want bet­ter rel­e­vance when search­ing, includ­ing the abil­i­ty to add syn­onyms for search terms and more
  • you need to include the con­tents of PDF files in your search results
  • you need to search non-EE con­tent (e.g., sta­t­ic HTML files) or con­tent from oth­er domains or sites, in addi­tion to your EE content

The Google Cus­tom Search API cur­rent­ly lim­its search­es to 100 results per query, and 100 free queries per day. There is no dai­ly query lim­it if you enable billing on your account (Google will bill $5 per addi­tion­al 1000 queries, per day.)

Google Cus­tom Search also inte­grates with Snaptcha to pre­vent spam search­es from using up your queries and fill­ing your search log with junk. (A sim­pler, but less-ruth­less hon­ey­pot” anti-spam mea­sure is includ­ed for those who don’t use Snaptcha.)


  • Expres­sio­nEngine® 3.0.0 or greater, or Expres­sio­nEngine® 2.8.0 or greater
  • A Google Cus­tom Search Engine ID or Linked Cus­tom Search Engine file
  • A Google Cus­tom Search API key
  • cURL and OpenSSL sup­port on your server



Upload the includ­ed google_​custom_​search fold­er to your /​system/​user/​addons/​ direc­to­ry (or /​system/​expressionengine/​third_​party/​ direc­to­ry if you’re run­ning EE2), then install Google Cus­tom Search from the Add-On Man­ag­er screen (or the Add-Ons → Mod­ules screen if you’re run­ning EE2).

You will need to obtain a Google Cus­tom Search API key and either a Google Cus­tom Search Engine ID or the link to a Cus­tom Search Engine file.

The API key is what autho­rizes you to make requests to the Google Cus­tom Search API (and keeps an eye on your dai­ly request lim­it, and billing if enabled). The CSE ID (or alter­nate­ly, the CSE cref” file) is what gives the API the var­i­ous para­me­ters it needs to per­form your search. (Many of these can be over­rid­den via para­me­ters applied to the results tem­plate tag).

Tem­plate Tags


This tag pair out­puts the search form you’ll use to per­form your cus­tom search. It accepts six tag parameters:

  • results_page="template_group/template"(required) the tem­plate path where your search results code is located
  • id="form_id" – the id” attribute for your form
  • class="form_class" – the class” attribute for your form
  • honeypot="yes" – whether or not to add a hid­den hon­ey­pot” field to the form, use­ful if you’re expe­ri­enc­ing search spam. Defaults to no”.
  • snaptcha="yes" – if you have the Snaptcha exten­sion installed, you can add Snaptcha pro­tec­tion to your search form with this parameter.
  • snaptcha_level="high" – if you are using the Snaptcha para­me­ter, you can option­al­ly set a cus­tom Snaptcha secu­ri­ty lev­el which dif­fers from your default secu­ri­ty lev­el. Valid val­ues are low”, medi­um”, and high”.


        <input type="text" name="keywords" size="20" placeholder="Enter keywords" />
        <input type="submit" name="submit" value="Search" />

This tag pair out­puts your CSE search results. It accepts sev­er­al parameters: 

  • api_key — (required if no access_​token) your Google Cus­tom Search API key
  • access_token — (required if no api_​key) your Google Cus­tom Search API OAuth 2.0 access token
  • cse — (required if no cref) your Google Cus­tom Search Engine unique ID
  • cref — (required if no cse) URL to an XML-for­mat­ted Cus­tom Search Engine file
  • keywords — (required) the URL seg­ment which holds your encod­ed key­words. It will be the seg­ment which fol­lows the cur­rent tem­plate segment.
  • limit — the num­ber of results to return per-page. Valid val­ues are any num­ber between 1 and 10 (default).
  • sort_attribute — name of the struc­tured data attribute by which you’d like to sort the search results. If the site you’re search­ing does­n’t have any struc­tured data, then you can like­ly only use date” as a val­ue here. Pass mul­ti­ple val­ues sep­a­rat­ed by a pipe (“|”) character.
  • sort_order — the order by which you’d like to sort the results when using the sort_attribute para­me­ter. Valid val­ues are asc” and desc”. Pass mul­ti­ple val­ues sep­a­rat­ed by a pipe (“|”) character.
  • sort_bias — whether you want to bias your results based on the sort_attribute para­me­ter. Valid val­ues are strong” and weak”. Pass mul­ti­ple val­ues sep­a­rat­ed by a pipe (“|”) character.
  • include_terms — an exact phrase to include along­side your key­word search.
  • exclude_terms — terms which will exclude results from your search.
  • and_terms — terms to include via the AND oper­a­tor in your search.
  • or_terms — terms to include via the OR oper­a­tor in your search.
  • site — URL with which to fur­ther restrict your search to.
  • exclude_site — URL to exclude from your search results.
  • link_site — URL which must be present as a link in all returned results
  • related_site — URL which all search results should be relat­ed to (as deter­mined by Google).
  • filetype — search only for files of a spe­cif­ic type (file extension).
  • days — only return results from the past N num­ber of days.
  • weeks — only return results from the past N num­ber of weeks.
  • months — only return results from the past N num­ber of months.
  • years — only return results from the past N num­ber of years.
  • safe — search safe­ty lev­el (for mature con­tent). Valid val­ues are high”, medi­um”, or off” (default).
  • filter — dupli­cate con­tent fil­ter. Valid val­ues are off” or on” (default).
  • language — restrict the search to doc­u­ments writ­ten in a par­tic­u­lar lan­guage. See accept­ed val­ues. Default is all languages.
  • single_chinese — set to yes” to dis­able your Chi­nese-lan­guage search from dis­play­ing both Sim­pli­fied and Tra­di­tion­al Chi­nese results.
  • country — restrict the search to results deter­mined to orig­i­nate in a par­tic­u­lar coun­try. See accept­ed val­ues.
  • google_host — restrict search results to those found via a local­ized Google engine (e.g., google​.fr).
  • replace_title — a com­mon string of text in your page titles that you’d like removed from titles in your results (e.g. your site name).
  • paginate — where to place the pag­i­na­tion code in your tem­plate. Valid val­ues are top”, bot­tom”, or both”.

The fol­low­ing vari­ables are avail­able with­in the {exp:google_custom_search:results} tag, both as vari­ables and conditionals: 

  • {keywords} — your search phrase
  • {count}, {total_results}, and {absolute_results} — these all func­tion iden­ti­cal­ly to the native Chan­nel Entries vari­ables of the same names *
  • {paginate} — this tag pair func­tions iden­ti­cal­ly to the native Chan­nel Entries tag pair *
  • {title} — the page title of the search result
  • {title_formatted} — the page title of the search result, with Google’s search phrase empha­sis intact
  • {excerpt} — the rel­e­vant con­tent snip­pet of the search result
  • {excerpt_formatted} — the rel­e­vant con­tent snip­pet of the search result, with Google’s search phrase empha­sis intact
  • {url} — the URL to the search result
  • {image} — URL to Google’s cho­sen image for this result, if available
  • {thumbnail_image} — URL to the Google-cached, thumb­nail ver­sion of Google’s cho­sen image for this result, if available
  • {format} — the file for­mat of the search result (based on the result’s file extension)
  • {google_results_url} — the URL to per­form this search direct­ly on Google
  • {total_google_search_results} — the total num­ber of search results avail­able for your query when per­formed direct­ly on Google
  • {request_url} — the full URL of the cur­rent API request to Google (use­ful for debugging)

* Note that as when search­ing via Google’s web­site, results counts are always approx­i­mate, and some­times even vary when pag­ing between result sets, so you may find result and page counts vary.


    {if no_results}<p>Sorry, your search returned no results.</p>{/if}
    {if count == 1}
        <p>Your search for <strong>{keywords}</strong> received {absolute_results} results.</p>
                {if image}<a href="{url}"><img src="{image}" alt="{title}" /</a>{/if}
                <a href="{url}" class="result_{format}">{title}</a> - {excerpt} <small>({url})</small>
        {if count == total_results}</ol>{/if}
            <p>Page {current_page} of {total_pages} pages {pagination_links}</p>

This sin­gle tag out­puts the cur­rent search key­words, with sim­ple for­mat­ting applied. It accepts one required parameter:

  • keywords="{segment_3}"(required) the seg­ment which con­tains the md5 hash of your search terms.


{exp:google_custom_search:keywords keywords="{segment_3"}


Since the mod­ule inter­acts with Google’s remote API, and since that API does employ a lim­it (or charge) on queries per day, it’s advis­able to employ some man­ner of local caching to avoid exces­sive serv­er requests. At the most basic, we sug­gest employ­ing Expres­sio­nEngine’s native tag caching — or you may want to look at a more advanced solu­tion such as CE Cache.


  • 1.2.3 (August 14th, 2019)
    • Fixed issue with the {exp:google_custom_search:keywords} tag
  • 1.2.2 (July 18th, 2019)
    • Fixed issue when using Snaptcha inte­gra­tion under EE5
    • Fixed issue with search­ing for words con­tain spe­cial characters
  • 1.2.1 (November 16th, 2015)
    • Fixed bug in EE2 ver­sion intro­duced with code refac­tor­ing in ver­sion 1.2.0
  • 1.2.0 (November 1st, 2015)
    • Changed vari­able nam­ing and pag­i­na­tion in the results” tag to be con­sis­tent with Chan­nel Entries vari­ables (see docs for examples)
    • Added EE3-com­pat­i­ble version
    • EE2 ver­sion now requires EE 2.8.0 or greater, and is feature-frozen
  • 1.1.5 (January 27th, 2015)
    • Added sort_attribute, sort_order, and sort_bias parameters
    • Removed bun­dled documentation
  • 1.1.4 (March 3rd, 2014)
    • Fixed con­trol pan­el error when run­ning under EE 2.8
    • Removed XID hash-check­ing from search form
  • 1.1.3 (April 17th, 2013)
    • Added inte­gra­tion with Snaptcha
    • Added new snaptcha and snaptcha_level para­me­ters to the form tag
    • Added com­pat­i­bil­i­ty with EE 2.6’s Local­ize class
  • 1.1.2 (February 6th, 2013)
    • Added the {absolute_result_count} variable
    • Added XID hash-check­ing to search form
    • Fixed bug where you would not be redi­rect­ed to Google for your search after hit­ting your dai­ly API limit
  • 1.1.1
    • Fixed pag­i­na­tion bug when ordering/​sorting by dif­fer­ent fields in the search log
  • 1.1.0 (September 17th, 2012)
    • Added {image} and {thumbnail_image} vari­ables for results which include image metadata
    • Added a slew of new para­me­ters to catch up with the updat­ed ver­sion of the Cus­tom Search API
    • Now using par­tial fields in the API call to speed up requests
    • Fix for issues with IPv6 on some servers
    • Pag­i­na­tion fix in con­trol pan­el under MSM
    • Added abil­i­ty to sort the search log by key­word, search count, or date
    • Added abil­i­ty delete terms from the search log
  • 1.10.11 (August 29th, 2012)
    • Fix for com­pat­i­bil­i­ty with EE 2.5+ on PHP 5.2
  • 1.10.10 (June 10th, 2012)
    • Fix for results pag­i­na­tion numbering
  • 1.0.9 (February 7th, 2012)
    • Fix for PHP errors when returned results have no titles or summaries
  • 1.0.8 (November 14th, 2011)
    • Added new (option­al) honeypot para­me­ter to the search form to trap search spam
  • 1.0.7
    • Added new vari­ables: {current_page}, {total_pages}, {current_results_start}, and {current_results_end}
  • 1.0.6 (July 22nd, 2011)
    • Added more use­ful error mes­sages when the API call fails
  • 1.0.5
    • Fixed issues with servers run­ning PHP 5.2 where the sup­ple­men­tal JSON library was not loading
    • Added some tem­plate debug­ger messages
  • 1.0.4 (July 1st, 2011)
    • Fixed poten­tial issue with load­ing con­trol pan­el view files
  • 1.0.3
    • Changed default results lan­guage from Eng­lish to any language
  • 1.0.2
    • Now using md5 hash­es for key­word seg­ments instead of base64 encod­ing due to poten­tial issues with equals (=) char­ac­ters in the URL
  • 1.0.1
    • Added {format} vari­able, removed {is_pdf} variable
  • 1.0 (June 22nd, 2011)
    • Ini­tial release

Browse more software