Codementor Events

How I bypassed Google books API rate limits or quota ?

Published Jun 07, 2019
How I bypassed Google books API rate limits or quota ?

If you have ever integrated google books api in your web or mobile app, you'd know there are rate-limits or quota on the number of requests. Usually, the rate limit is approx. 1000 requests per day.

The limits or quotas can be seen on your google cloud platform dashboard & you can always appeal for more quota right through the dashboard options provided. However, most of the times, these appeals tend to take a lot of time & often rejected.

Now, you do not want your users or customers to get stuck or start getting errors as soon as the limit is reached. I was desperate to come up with a solution for a better user experience. So, I developed a hack or you could say an innovative approach to provide a seamless experience for the users. This is developed in react native & google firebase, but you can create a similar approach in your choice of language.

Firstly, I integrated the books search feature with Alogolia. Now, these are the steps I followed to provide a hassle-free book search experience:

1). Every time a user search for a book, the call is made to the google books api and subsequently algolia search api. Now, there are 2 scenarios:

a. Google API Success (quota limit not reached): In this case, the result-set from google books (books returned) creates the corresponding records with book title, author, description, publisher etc. to the Algolia indices. Goto Step 2)

b. Google API Fails (quota limit reached): Goto Step 2)

2). Call Algolia API with the user search input. The result-set returned is shown to the users on the front-end screen or page.

So, as people search for books on your app, the matching books (from google api) are incrementally added to your algolia indices. Over-time gradually, you'd start accumulating or storing thousands of books with relevant data (isbn, title, image, author, desc. etc.)

Sample Code in react native & firebase:

searchFilterFunction = text => {
    var algoliaSearchResults = [];        
    this.setState({loadingProducts: true, data: [], searchText: text});
    var searchResults = [];
    if(text.length >= 3) 
    {
      var baseURL = 'https://www.googleapis.com/books/v1/volumes?q=';
      baseURL = baseURL + encodeURIComponent('intitle:' + text);
      baseURL = baseURL + '&key=******Google Books API Key******';
      baseURL = baseURL + '&maxResults=5&country=IN&langRestrict=en';

      fetch(baseURL).then((response) => response.json()).then((responseData) => {
        if(responseData.items)
        {
          responseData.items.map((topLevel, key1) => {
            var description = '';
            var category = '';
            var google_id = '';
            var google_link = '';
            var page_count = '';
            var language = '';
            var publisher = '';
            var published_date = '';
            
            if(topLevel.volumeInfo.title && topLevel.volumeInfo.authors && topLevel.volumeInfo.industryIdentifiers && topLevel.volumeInfo.categories && topLevel.volumeInfo.imageLinks)
            {
              if(topLevel.volumeInfo.authors[0] && topLevel.volumeInfo.industryIdentifiers[0].identifier && topLevel.volumeInfo.categories[0] && topLevel.volumeInfo.imageLinks.thumbnail)
              {
                if(topLevel.volumeInfo.description) 
                  description = topLevel.volumeInfo.description;
                if(topLevel.id) 
                  google_id = topLevel.id;
                if(topLevel.volumeInfo.infoLink) 
                  google_link = topLevel.volumeInfo.infoLink;
                if(topLevel.volumeInfo.pageCount) 
                  page_count = topLevel.volumeInfo.pageCount;
                if(topLevel.volumeInfo.language) 
                  language = topLevel.volumeInfo.language;
                if(topLevel.volumeInfo.publisher) 
                  publisher = topLevel.volumeInfo.publisher;
                if(topLevel.volumeInfo.publishedDate) 
                  published_date = topLevel.volumeInfo.publishedDate;
                
                searchResults.push({
                  title: topLevel.volumeInfo.title, 
                  isbn: topLevel.volumeInfo.industryIdentifiers[0].identifier, 
                  author_1: topLevel.volumeInfo.authors[0], 
                  thumbnail: topLevel.volumeInfo.imageLinks.thumbnail,
                  description: description,
                  category: topLevel.volumeInfo.categories[0],
                  google_id: google_id,
                  google_link: google_link,
                  page_count: page_count,
                  language: language,
                  publisher: publisher,
                  published_date: published_date,
                  objectID: topLevel.volumeInfo.industryIdentifiers[0].identifier
                });
                firebase.database().ref('products/'+topLevel.volumeInfo.industryIdentifiers[0].identifier+'/').once('value').then((snapshot) => {
                  if(!snapshot.val()) 
                  {
                    firebase.database().ref('products/'+topLevel.volumeInfo.industryIdentifiers[0].identifier).update({
                      title: topLevel.volumeInfo.title, 
                      isbn: topLevel.volumeInfo.industryIdentifiers[0].identifier, 
                      author_1: topLevel.volumeInfo.authors[0], 
                      thumbnail: topLevel.volumeInfo.imageLinks.thumbnail,
                      description: description,
                      category: topLevel.volumeInfo.categories[0],
                      google_id: google_id,
                      google_link: google_link,
                      page_count: page_count,
                      language: language,
                      publisher: publisher,
                      published_date: published_date,
                      objectID: topLevel.volumeInfo.industryIdentifiers[0].identifier        
                    });
                  }
                });                
              }
            }  
          });
        }
      }).then(() => {
        index.saveObjects(searchResults)
        .then(() => {
          var clientSearch = algoliasearch(ALGOLIA_ID, ALGOLIA_SEARCH_KEY);
          var indexSearch = clientSearch.initIndex('products');
          index.setSettings({'searchableAttributes': ['title', 'author_1']});
          index.search({query: text})
          .then(function(responses) {
            // Response from Algolia:
            // https://www.algolia.com/doc/api-reference/api-methods/search/#response-format
            responses.hits.map((value, key) => {
              
              algoliaSearchResults.push(value);
            });
          }).then(() => {
            if(algoliaSearchResults.length >= searchResults.length)
              this.setState({loadingProducts: false, data: algoliaSearchResults});
            else
              this.setState({loadingProducts: false, data: searchResults});
          });
        })
        .catch(error => {
          //alert('Error when importing products into Algolia:',error);
        });
      }).catch((error) => {
        var clientSearch = algoliasearch(ALGOLIA_ID, ALGOLIA_SEARCH_KEY);
        var indexSearch = clientSearch.initIndex('products');
        index.setSettings({'searchableAttributes': ['title', 'author_1']});
        index.search({query: text})
        .then(function(responses) {
          // Response from Algolia:
          // https://www.algolia.com/doc/api-reference/api-methods/search/#response-format
          responses.hits.map((value, key) => {
            algoliaSearchResults.push(value);
          });
        }).then(() => {
          if(algoliaSearchResults.length >= searchResults.length)
            this.setState({loadingProducts: false, data: algoliaSearchResults});
          else
            this.setState({loadingProducts: false, data: searchResults});
        });
      }).done();
    }
    else {
      this.setState({loadingProducts: false, data: []});
    }
  }
Discover and read more posts from Saurabh Kataria
get started
post commentsBe the first to share your opinion
Samuel Peterson
3 years ago

The Google books terms clearly states the books shouldn’t be cached beyond the time mentioned in the cache header
Seems like you are storing the data forever.

Show more replies