Google Books Integration
Google Books provides a comprehensive book database with excellent cover images and search capabilities. BookWish uses Google Books API as a secondary metadata source and for cover artwork.
Overview
BookWish uses Google Books for:
- Book Search: Full-text search across millions of books
- ISBN Lookup: Get book details by ISBN
- Cover Images: High-quality cover artwork
- Metadata: Title, authors, publisher, description
- International Coverage: Better global book coverage
- Free Tier: Generous free usage quota
Implementation
Location: /backend/src/integrations/google-books.ts
Configuration
Required environment variables:
GOOGLE_BOOKS_API_KEY=AIzaSy...
The integration uses Redis for caching with 24-hour TTL.
Features
1. Search Books
Search across Google's book database.
Text Search
import { createGoogleBooksClient } from '../integrations/google-books';
const googleBooks = createGoogleBooksClient(process.env.GOOGLE_BOOKS_API_KEY);
const books = await googleBooks.searchBooks('Great Gatsby', 20);
// Returns array of GoogleBookData:
// [
// {
// googleBooksId: 'iXn5U2IzVH0C',
// isbn13: '9780743273565',
// isbn10: '0743273565',
// title: 'The Great Gatsby',
// subtitle: undefined,
// authors: ['F. Scott Fitzgerald'],
// publisher: 'Scribner',
// publishedDate: Date('2004-05-01'),
// description: 'The exemplary novel of the Jazz Age...',
// pageCount: 180,
// categories: ['Fiction'],
// coverImageUrl: 'https://books.google.com/books/content?id=...&zoom=1',
// thumbnailUrl: 'https://books.google.com/books/content?id=...&zoom=5'
// },
// // ... more results
// ]
Query Operators
Google Books supports advanced search:
// Search by title
await googleBooks.searchBooks('intitle:Harry Potter');
// Search by author
await googleBooks.searchBooks('inauthor:Rowling');
// Search by ISBN
await googleBooks.searchBooks('isbn:9780743273565');
// Search by publisher
await googleBooks.searchBooks('inpublisher:Penguin');
// Combine operators
await googleBooks.searchBooks('intitle:gatsby inauthor:fitzgerald');
2. ISBN Lookup
Get book details by ISBN-10 or ISBN-13.
Get Book by ISBN
const book = await googleBooks.getBookByISBN('9780743273565');
if (book) {
console.log('Title:', book.title);
console.log('Authors:', book.authors.join(', '));
console.log('Cover:', book.coverImageUrl);
} else {
console.log('Book not found');
}
3. Get Book by ID
Retrieve book using Google Books volume ID.
Get by Volume ID
const book = await googleBooks.getBookById('iXn5U2IzVH0C');
// Returns GoogleBookData or null
Volume IDs are permanent identifiers in Google Books.
Data Structures
GoogleBookData
interface GoogleBookData {
googleBooksId: string; // Google Books volume ID
isbn13?: string; // ISBN-13 if available
isbn10?: string; // ISBN-10 if available
title: string; // Book title
subtitle?: string; // Subtitle if present
authors: string[]; // Array of authors
publisher?: string; // Publisher name
publishedDate?: Date; // Publication date
description?: string; // Book description
pageCount?: number; // Number of pages
categories: string[]; // Subject categories
coverImageUrl?: string; // Full-size cover (zoom=1)
thumbnailUrl?: string; // Small thumbnail (zoom=5)
}
Cover Image Sizes
Google Books provides cover images at different zoom levels:
zoom=0: Thumbnail (128px)zoom=1: Small (256px)zoom=2: Medium (512px)zoom=3: Large (1024px)zoom=5: Extra small (96px)
The integration uses:
coverImageUrl: zoom=1 (256px) - good for displaythumbnailUrl: zoom=5 (96px) - good for lists
API Details
Base URL
https://www.googleapis.com/books/v1/volumes
Authentication
Query parameter authentication:
?key={GOOGLE_BOOKS_API_KEY}
Rate Limits
Google Books API free tier:
- 1,000 requests per day per API key
- 100 requests per 100 seconds per user
Rate limits can be increased by:
- Using OAuth 2.0 authentication
- Purchasing additional quota
Caching Strategy
Cache Configuration
private cachePrefix = 'google-books:';
private cacheTTL = 24 * 60 * 60; // 24 hours
Cache Keys
- Search:
google-books:search:{query}:{maxResults} - ISBN:
google-books:isbn:{isbn} - Volume ID:
google-books:id:{volumeId}
Why Cache?
- Reduces API calls against quota
- Improves response time
- Book metadata rarely changes
- Handles API downtime gracefully
Error Handling
Rate Limit Errors
try {
const books = await googleBooks.searchBooks(query);
} catch (error) {
if (error.message === 'Rate limit exceeded for Google Books API') {
// Serve from cache or wait
}
}
Not Found
Returns null for ISBN lookups without throwing:
const book = await googleBooks.getBookByISBN('invalid-isbn');
// book === null
Network Errors
Returns empty array for search failures:
const results = await googleBooks.searchBooks('query');
// results === [] on error (fallback behavior)
Image URL Handling
HTTP to HTTPS Conversion
Google Books sometimes returns HTTP URLs. The integration automatically converts them:
const convertToHttps = (url?: string) =>
url?.replace(/^http:\/\//i, 'https://');
This prevents mixed content warnings in HTTPS apps.
Image Quality
To get higher quality images, modify zoom parameter:
// Original URL
const url = 'https://books.google.com/books/content?id=ABC&zoom=1';
// Higher quality
const highQuality = url.replace('zoom=1', 'zoom=2');
ISBN Extraction
Google Books returns ISBNs in industryIdentifiers:
{
industryIdentifiers: [
{ type: 'ISBN_13', identifier: '9780743273565' },
{ type: 'ISBN_10', identifier: '0743273565' }
]
}
The integration extracts both formats for maximum compatibility.
Integration with Book Service
Example fallback pattern:
import { createISBNdbClient } from '../integrations/isbndb';
import { createGoogleBooksClient } from '../integrations/google-books';
async function enrichBookMetadata(isbn: string) {
// Try ISBNdb first (more complete ISBN database)
const isbndb = createISBNdbClient(process.env.ISBNDB_API_KEY);
let book = await isbndb.getBookByISBN(isbn);
if (!book) {
// Fallback to Google Books
const googleBooks = createGoogleBooksClient(process.env.GOOGLE_BOOKS_API_KEY);
book = await googleBooks.getBookByISBN(isbn);
}
return book;
}
Cover Image Priority
async function getBestCoverImage(isbn: string) {
const googleBooks = createGoogleBooksClient(process.env.GOOGLE_BOOKS_API_KEY);
const book = await googleBooks.getBookByISBN(isbn);
if (book?.coverImageUrl) {
// Google Books usually has best cover images
return book.coverImageUrl;
}
// Fallback to ISBNdb or other sources
return null;
}
Best Practices
- Use as Secondary Source: Google Books is best for cover images and international books
- Cache Aggressively: Book metadata doesn't change
- Handle Quotas: Monitor daily quota usage
- HTTPS Conversion: Always convert image URLs to HTTPS
- Fallback Strategy: Have ISBNdb or other source as backup
- Advanced Search: Use query operators for better results
- Volume IDs: Store Google Books IDs for permanent references
Use Cases
1. Cover Art Enhancement
Get high-quality cover images:
async function updateBookCovers() {
const booksWithoutCovers = await getBooksWithoutCovers();
for (const book of booksWithoutCovers) {
const googleBook = await googleBooks.getBookByISBN(book.isbn);
if (googleBook?.coverImageUrl) {
await updateBookCover(book.id, googleBook.coverImageUrl);
}
}
}
2. International Books
Google Books has better coverage of non-US books:
async function searchInternationalBooks(query: string) {
// Google Books more reliable for international titles
return await googleBooks.searchBooks(query, 50);
}
3. Search Results
Power book search with Google's full-text search:
async function searchCatalog(query: string) {
const results = await googleBooks.searchBooks(query, 20);
return results.map(book => ({
id: book.googleBooksId,
title: book.title,
authors: book.authors,
cover: book.thumbnailUrl,
isbn: book.isbn13 || book.isbn10
}));
}
Comparison with ISBNdb
Google Books Advantages
- Free with generous quota
- Better cover images
- Full-text search
- International coverage
- Preview pages available
- No rate limits (within quota)
ISBNdb Advantages
- More complete ISBN database
- Better metadata for US books
- Includes MSRP pricing
- Higher reliability
- Commercial support
Recommended Strategy
Use both in combination:
- Use Google Books for:
- Cover images
- International books
- Full-text search
- Free tier usage
- Use ISBNdb for:
- US book metadata
- ISBN coverage
- Pricing data
- When Google Books quota exceeded
Testing
Mock Data
For testing without API key:
const mockBook: GoogleBookData = {
googleBooksId: 'iXn5U2IzVH0C',
isbn13: '9780743273565',
isbn10: '0743273565',
title: 'The Great Gatsby',
authors: ['F. Scott Fitzgerald'],
publisher: 'Scribner',
publishedDate: new Date('2004-05-01'),
description: 'A classic novel...',
pageCount: 180,
categories: ['Fiction'],
coverImageUrl: 'https://example.com/cover.jpg',
thumbnailUrl: 'https://example.com/thumb.jpg'
};
Test Volume IDs
Known volume IDs for testing:
iXn5U2IzVH0C- The Great GatsbyhFfhrCWiLSMC- The GiverPGR2AwAAQBAJ- To Kill a Mockingbird
Test Searches
Common test queries:
isbn:9780743273565- Exact ISBN matchintitle:gatsby- Title searchinauthor:fitzgerald- Author search
Timeout Configuration
The integration uses 5-second timeout:
const response = await axios.get(this.baseUrl, {
params: { q: query, maxResults, key: this.apiKey },
timeout: 5000
});
This prevents slow API responses from blocking requests.
Limitations
- No Pricing: Google Books doesn't provide wholesale/retail pricing
- Quota Limits: Free tier limited to 1,000 requests/day
- Search Relevance: Search results may include less relevant books
- Metadata Gaps: Some books missing authors or descriptions
- Preview Restrictions: Preview content limited by publisher agreements
- Date Formats: Published dates may be incomplete (year-only)
Monitoring
Track usage against quota:
// Log API calls
logger.info('google_books.api_call', {
query,
resultsCount: results.length,
cached: false
});
// Track daily quota
await redis.incr('metrics:google_books:daily_calls');