The widgets provided by Google are a great way to get the functionality you’re looking for without writing any code, but sometimes there’s a need for a little more control and flexibility with layout, design, etc. Kris Hadlock explains the steps that are necessary to use the RESTful interface provided through the Google Ajax Search API in order to create a custom JavaScript Google News search widget.
The Google Ajax Search API is a JavaScript library that provides widgets you can easily embed into any web page. Google’s widgets provide a great way to get search functionality without writing any code, but sometimes there’s a need for a little more control and flexibility with layout, design and the information you want to present. Google provides a RESTful interface and refers to it as an offering for Flash and other non-JavaScript environments, but with a tiny bit of code we can access this interface remotely with JavaScript in order to create our own custom widget.
In this article, we will be using PHP and cURL to access the RESTful interface, which will return the JSON result set from Google to JavaScript. This article will explain the steps that are necessary to use the RESTful interface provided through the Google Ajax Search API in order to create a custom JavaScript news widget. The sample code used in this article is available for download here.
Making a Remote Request to the Google API
In order to access an external URL with Ajax, it is necessary to create what I like to call abridge or gateway file, which acts as an intermediate access point between JavaScript and the external destination. PHP can access remote files using the cURL library, which we’ll be using to access the Google News Search service, retrieve a JSON result set, and return it to JavaScript via Ajax.
<?php header("Content-Type: application/json"); $feed = (isset($_REQUEST['feed'])) ? $_REQUEST['feed'] : ''; if(!empty($feed) && is_string($feed)) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, str_replace(" ", "%20", $feed)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_REFERER, 'https://www.yourdomain.com'); $results = curl_exec($ch); curl_close($ch); echo $results; } ?>
In this example, the cURL library allows you to create a connection to a remote server and return the results, which allows us to make that external request and have it be a local response for JavaScript. In order to do this, we need to first make sure that the result set returned is seen as JSON; therefore, the content-type header is set to application/son.
Next, we’ll look for an argument named feed; if this argument doesn’t exist, then we’ll simply ignore the request and not return anything. This lends us some bit of security by making sure that whoever calls this gateway is required to at least offer the feed argument. If the feed argument does exist, we’ll use it to tell PHP where to access the remote content via cURL.
To use cURL, we first initialize the object using curl_init, then we set a few options. The first option is the CURLOPT_URL, which is simply the URL of the remote content—in this case, it will be represented by our feed argument. Because we know this is a search, we’ll replace spaces between words with URL-encoded spaces to avoid any issues. Next, we setCURLOPT_RETURNTRANSFER to true in order to return the results from the cURL execution that will be used as the response to JavaScript. The final option we’ll need to set is theCURLOPT_REFERER, which sets the referrer for the HTTP request. It’s important to set this option because the referrer is required by the Google Search API to identify your application. Be sure to replace the placeholder copy https://www.yourdomain.com with your actual domain to meet Google’s requirements.
Last, we’ll use curl_exec to perform the session, which returns the results from the request. Then we’ll close the session using curl_close and echo $results to the page. The results that are printed to the page are then returned as JSON to the requesting JavaScript object via Ajax.
Creating a Google API JavaScript Object
Using PHP to access the Google News Search service allows us to create a local JSON result set that is accessible to JavaScript via Ajax. To start parsing the results, we’ll need to download the jsonparser from https://www.json.org. Once you have the jsonparser, create a JavaScript object called GoogleAPI (Listing 2, GoogleAPI.js) and include the jsonparser file at the top of the file using the document.write function in order to keep the JavaScript self-contained. This GoogleAPI object will handle most of the functionality by making all the Ajax requests, parsing the JSON, and rendering the HTML elements in the web page.
Searching the Google News Search Service Using Ajax
We first need to ensure that the web page has fully loaded so that all the HTML elements and assets are also fully loaded before trying to access them programmatically. In order to do this, we can simply use the window.onloadfunction to activate the news search when the page has fully loaded. The function that initializes the search will be calledGoogleAPI.SearchNews. This function also sets a callback method to retrieve the JSON result set and makes the search request to the Google News Search API through our gateway.php file. In this example, the callback for the search isGoogleAPI.onNewsSearched. The gateway path will be the path of the gateway.php file with a feed argument that points to the Google News Search.
The Google search service has a number of arguments from which you can choose; the required arguments are listed in Table 1, while Table 2 lists the optional arguments.
Table 1—Required Arguments for the Google Ajax Search API
Argument | Definition | Description |
---|---|---|
v | Version | The only value available at this point is 1.0 |
q | Query | The search term you’re performing on the API |
Table 2—Optional Arguments for the Google Ajax Search API
Argument | Definition | Description |
---|---|---|
userip | User IP | Optional, but recommended by Google |
rsz | Number of results | Can have a value of small or large. small retrieves four results, and large retrieves eight results. |
hl | Host language | Corresponds to the host language. |
key | Application key | If this argument is supplied, it must match the passed referrer header in order to be validated. The referrer header is what we are passing in gateway.php. |
start | A powerful argument that allows you to retrieve pages of results—for example, the default is 0; therefore, if you request a small result set, you’ll receive news results 0-4. However, if you want to retrieve additional news results, you can change the start to 4, which will retrieve news results 4-8. This allows us to gather random news results, create controls to navigate through pages of news results, and so on. | |
callback | Allows you to alter the response format and trigger a function call. | |
context | When supplied with the callback argument, the context alters the response format normally associated with the callback. |
The optional news search specific arguments that can be used to filter results (Table 3).
Table 3—Google News Search Specific Arguments
Argument | Description |
---|---|
scoring | Order search results by relevance or date. |
geo | An optional argument that can be used to get news results from a specific location. |
qsid | An optional argument that can be used to filter results to quote type results, instead of typical news type results. |
topic | An optional argument that can be used to filter results to a particular topic. The value can be any of the following options: h – Top headlines w – World news b – Business news n – Nation news t – Science and technology news el – Elections news p – Politics news e – Entertainment news s – Sports news m – Health news |
ned | An optional argument that can be used to pull results from a specific edition. Editions are related to countries and can be defined as us, uk, fr_ca, etc. |
In this example, we are using rsz=small to retrieve four results, and as the start argument we’re also using the GoogleAPI.Index property to determine from what record to receive the search results. The GoogleAPI.Index property will later be used to increase the starting point for the search in order to page through results. The required arguments—v=1.0 and q, which is currently set to “Peachpit”—are also included. The search query or q property can be changed to any value using the GoogleAPI.Query variable in the window.onload event where we are initiating all of the object properties.
With the gateway URL constructed, we can make our Ajax request to the Google Search API through a reusable method called GoogleAPI.makeRequest. This method creates the request object as a property of GoogleAPI, sets the onreadystatechange callback method, opens the request to the gateway URL we are passing as the argument, and finally sends the request. Once the request has been made, the onreadystatechange callback method is triggered through each stage of the readyState. Once it reaches 4, the response is fully loaded and the callback method we set in GoogleAPI.onNewsSearched is triggered.
Parsing the JSON News Result Set
The results that are returned as the response from the news search are accessible via the request object. To access these results, we need to access the Ajax request’s responseText property and then parse the results into a valid JSON string. With the jsonparser included, this is very simple: all we do to parse the response as JSON is:
var gnews = this.request.responseText.parseJSON();
With the parsed response, we can access the results, which are always included in a responseData object. The responseData object includes an array named results, which can be iterated to access the properties of each news result and create an HTML structure to render the news results onto the web page.
var results = gnews.responseData.results;
Table 4—Specific Google News Search Properties
Property | Description |
---|---|
title | Title of the news result. |
titleNoFormatting | Title of the news result with no HTML. |
unescapedUrl | URL of the result. |
url | Escaped version of the URL of the result. |
clusterUrl | A landing page that points to related stories. |
content | Part of the content from the news story. |
publisher | The news story publisher. |
location | List of comma-delimited locations. |
publishedDate | Published date of news story. |
relatedStories[] | An optional array property that only appears when a story has related stories. If the property is present, the array will contain a subset of properties specific to those related stories. |
image{} | Optional property that only appears when an image is present that relates to the group of news articles related to the search result. If one exists, the following properties are available for the image: title – Title of image titleNoFormatting – Title of image with no HTML formatting url – URL of the image in the article originalContextUrl – URL of the article that contains the image publisher – Publisher of the news article related to the image tbUrl – URL of a thumbnail for the image tbWidth – Width of the thumbnail image tbHeight – Height of the thumbnail image |
language | Optional property that indicates the language of the news story. |
When the news service has been searched and the results have been parsed into JSON, we can start to iterate and render the results as HTML. The example we’re going to create is a simple list of news titles with the publisher, published date, and a link to related stories, if any exist. Each post will have its own containing div element that is tied to a CSS class named post.
To render the titles, we are creating an anchor tag that links to the unescapedUrl property and has an innerHTML value of titleNoFormatting property. This will give us a title that links to the original story in a new window. To render the publisher and published date, we’ll create an italic element and set the innerHTML to the publisher and publishedDateproperties. With the title and publisher/date elements created, we can add them to the post div. Next, we’ll check to see if there are any related stories to the current news result by checking the value of the clusterUrl property. If this property has a value, an anchor tag is created that links to the clusterUrl and is then added to the post div. Once the post is complete, it’s finally added to the gNews element.
To page through results, we simply add an anchor element that will be used to increase thestart argument in the search. To create this functionality, we create an onclick event that increases the GoogleAPI.Index property by four and triggers a new search via the GoogleAPI.SearchNews function. The reason we increase the GoogleAPI.Index property by four is because there are four results in the rsz argument because it is set to small, so we want to get the next four results each time we click more news.
document.write('<script type="text/javascript" src="assets/js/jsonparser.js"></script>'); var GoogleAPI = new Object(); GoogleAPI.SearchNews = function() { GoogleAPI.callback = GoogleAPI.onNewsSearched; var gateway = "service/gateway.php?feed="+ escape("https://ajax.googleapis.com/ ajax/services/search/news?v=1.0&rsz=small&start="+ GoogleAPI.Index +"&q=")+ GoogleAPI.Query; GoogleAPI.makeRequest(gateway); } GoogleAPI.onNewsSearched = function(request) { var divNews = document.getElementById('gnews'); divNews.innerHTML = ''; if(this.request.responseText) { var gnews = this.request.responseText.parseJSON(); var results = gnews.responseData.results; if(results.length > 0) { for(var i=0; i<results.length; i++) { var post = document.createElement('div'); post.className = 'post'; var postHref = document.createElement('a'); postHref.href = results[i].unescapedUrl; postHref.className = 'title'; postHref.target = "_blank"; postHref.innerHTML = results[i].titleNoFormatting; var postDate = document.createElement('i'); postDate.innerHTML = 'from '+ results[i].publisher + ' posted '+ results[i].publishedDate; post.appendChild(postHref); post.appendChild(postDate); if(results[i].clusterUrl) { var clusterHref = document.createElement('a'); clusterHref.href = results[i].clusterUrl; clusterHref.className = 'related'; clusterHref.target = "_blank"; clusterHref.innerHTML = 'Related Stories'; post.appendChild(clusterHref); } divNews.appendChild(post); } var moreBtn = document.createElement('a'); moreBtn.href = "#"+(GoogleAPI.Index+4); moreBtn.className = "more"; moreBtn.innerHTML = "More News >"; moreBtn.onclick = function() { GoogleAPI.Index+=4; GoogleAPI.SearchNews(); } divNews.appendChild(moreBtn); } else GoogleAPI.ThrowError("There were no news results"); } else GoogleAPI.ThrowError("There was an error receiving the news feed"); } GoogleAPI.makeRequest = function(gw) { this.request = (window.XMLHttpRequest) ? new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP"); this.request.onreadystatechange = function() { GoogleAPI.checkReadyState(); }; this.request.open('GET', gw, true); this.request.send(gw); } GoogleAPI.ThrowError = function(msg) { alert(msg); } GoogleAPI.checkReadyState = function() { switch(this.request.readyState) { case 1: break; case 2: break; case 3: break; case 4: this.callback(this.request); } } window.onload = function() { GoogleAPI.Index = 0; GoogleAPI.Query = "Peachpit"; GoogleAPI.SearchNews(); }
Rendering the Results as HTML
To render the results on a web page, we’ll need to create an HTML file that embeds the GoogleAPI.js file we just created. Because the GoogleAPI object is self-contained, there are no other files that need to be included, but we do need to create a div element with an id of gnews in order to write the widget to the HTML file (Listing 3).
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd> <html xmlns="https://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>Creating a Custom News Search Widget using the Google Search API</title> <script type="text/javascript" src="assets/js/GoogleAPI.js"></script> <link type="text/css" rel="stylesheet" href="assets/css/googleapi.css" /> </head> <body> <div id="gnews">Loading news posts...</div> </body> </html>
We’ve also included a CSS file called googleapi.css. The CSS offers a lot of flexibility, allowing us to control the design of the results in any way we choose.
Additional Resources
If you’re interested in learning more about the Google Ajax Search API, JSON, or the PHP cURL library, you can check out the following resources for more information.
The Google Ajax Search API: https://code.google.com/apis/ajaxsearch/documentation
JSON (JavaScript Object Notation) and the JSON Parser: https://www.json.org
PHP cURL (Client URL Library): https://php.net/manual/en/book.curl.php
Read the original article at Peachpit