Publishing data from an external API

Publishing anything pt. 2

Continuing on from the previous article (see Publishing anything) where we covered publishing a very simple set of static data, we'll now take a look at publishing data that we request from an external API.

For this example we'll use the Google Books API.

Just to note; with a public API such as this that does not require private authentication, a better approach may be to make the API call client side and simply insert the documents into the client side collection.

In the case where the API requires private authentication or perhaps we need to decorate the document with some other server side data, the publication method demonstrated here is the approach to take.

We're using a public API here simply for demonstration.


Let's start off once again with the client side code


    <input type="text" name="query">
    <input type="submit" value="Search">

  {{#if searching}}
    {{#if books.count}}
        {{#each books}}
          {{> book}}

<template name="book">
    <td class="image"><img src="{{thumb}}"></td>
      <a href="{{link}}" target="_blank">{{title}}</a>


Books = new Mongo.Collection('books');

Session.setDefault('searching', false);

Tracker.autorun(function() {
  if (Session.get('query')) {
    var searchHandle = Meteor.subscribe('booksSearch', Session.get('query'));
    Session.set('searching', ! searchHandle.ready());
  'submit form': function(event, template) {
    var query = template.$('input[type=text]').val();
    if (query)
      Session.set('query', query);

  books: function() {
    return Books.find();
  searching: function() {
    return Session.get('searching');

The important parts of what we're doing here are:

  • Creating a client side collection called books
  • Setting a Session variable once the form is submit
  • Subscribing to our publication called booksSearch within an autorun and passing in the Session value
  • We've also added a helper called loading which watches the subscription handle's ready method. This is to indicate when the search results are loading


Now let's take a look at what's going on over on the server. This is where the interesting stuff happens.

Meteor.publish('booksSearch', function(query) {
  var self = this;
  try {
    var response = HTTP.get('', {
      params: {
        q: query

    _.each(, function(item) {
      var doc = {
        thumb: item.volumeInfo.imageLinks.smallThumbnail,
        title: item.volumeInfo.title,
        link: item.volumeInfo.infoLink,
        snippet: item.searchInfo && item.searchInfo.textSnippet

      self.added('books',, doc);


  } catch(error) {

Our booksSearch publication has been set up to take an argument (query) which we'll use to pass through to the HTTP request.

In order to communicate with the Google Books API, we're using Meteor's HTTP package. On the server we can run it synchronously if we don't pass in a callback function. Which is exactly what we're doing here.

The first step is making the request and assigning the response to a variable called, well, response.

Next we're iterating over the resultset, taking what we need and assigning it to doc, then calling self.added for each.

Finally, to let the subscriber know that we're all ready, self.ready().

Example app
Check out the example application on GitHub.
Play around with the live app running on MeteorPad.