<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Digital Humanities - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Digital Humanities - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Wed, 24 Jun 2026 20:19:33 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/digital-humanities/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Build a Best Sellers List with New York Times and Google Books API ]]>
                </title>
                <description>
                    <![CDATA[ By Andrew Bales A single API may not always have all of the data you need. In this article, we’ll walk through the steps to combine two APIs by using unique identifiers from the New York Times API to grab book covers from the Google Books API. You ca... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/build-a-best-sellers-list-with-new-york-times-google-books-api-46201c30aec7/</link>
                <guid isPermaLink="false">66c346538ced2460cf9e9b5f</guid>
                
                    <category>
                        <![CDATA[ Digital Humanities ]]>
                    </category>
                
                    <category>
                        <![CDATA[ api ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Google ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Mon, 04 Dec 2017 03:13:27 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*bVvh3q1aNXWnfkjXNp_vwQ.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Andrew Bales</p>
<p>A single API may not always have all of the data you need. In this article, we’ll walk through the steps to combine two APIs by using unique identifiers from the New York Times API to grab book covers from the Google Books API.</p>
<p>You can find the full project on <a target="_blank" href="https://github.com/agbales/best-sellers">GitHub</a> and view a demo on <a target="_blank" href="https://codepen.io/agbales/full/LNWPYW/">CodePen</a>.</p>
<p>Here are the steps we’ll cover:</p>
<ol>
<li>Fetch best selling books data from the New York Times API.</li>
<li>Append listings to the DOM.</li>
<li>Query the Google Books API with ISBN numbers to add cover images to the listings.</li>
</ol>
<p>At the end of the tutorial, you’ll have a best sellers list! Here’s a peek:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ckGF3oZ3cWjkItnuviz8K66gLSGPI3Va9xil" alt="Image" width="800" height="467" loading="lazy"></p>
<h3 id="heading-wait-but-why">Wait, but why?</h3>
<p>I first began working on this project a little over a year ago. I was learning about APIs and requesting keys to practice accessing and displaying data.</p>
<p>While exploring the <em>New York Times</em> API, I found that it was possible to get a list of best selling books. For each book on the list, the API provides a current rank and number of weeks on the list. It also offers info like a synopsis and an Amazon link.</p>
<p>I was able to populate textual info, but the list lacked the natural visual component of book covers. At the time, I didn’t see a clear road forward, so I put the project on the shelf.</p>
<p><strong>This is an instance where having access to an API is helpful, but incomplete.</strong></p>
<p>This week, I returned with the goal of adding books covers. I found that Google Books API will return thumbnails for books when provided an ISBN, a unique identifying number. As luck would have it, the New York Times API provides that ISBN.</p>
<p>We’re in business!</p>
<h3 id="heading-getting-started">Getting Started</h3>
<p>First, we want to generate a list of the top selling fiction books with a bit of info about each. It would be nice to display information about how long the book has been on the list. We also need to see the cover and provide a link for users to learn more about the book or buy a copy.</p>
<p>The New York Times API provides all of that information except for the book cover. Grab a free <a target="_blank" href="https://developer.nytimes.com">NYT API key</a> to get started.</p>
<p>We’ll use the <a target="_blank" href="https://developers.google.com/web/updates/2015/03/introduction-to-fetch">Fetch API</a> to get the best seller data for hardcover works of fiction:</p>
<pre><code>fetch(<span class="hljs-string">'https://api.nytimes.com/svc/books/v3/lists.json?list-name=hardcover-fiction&amp;api-key='</span> + apiKey, {    <span class="hljs-attr">method</span>: <span class="hljs-string">'get'</span>,  })  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> { <span class="hljs-keyword">return</span> response.json(); })  .then(<span class="hljs-function"><span class="hljs-params">json</span> =&gt;</span> { <span class="hljs-built_in">console</span>.log(json); });
</code></pre><p>If you inspect the browser, you’ll see a JSON object logged in the console. If you haven’t used an API before, it will be helpful to spend a moment looking through this object. Burrowing into the data to access exactly what you’re looking for may take a while to get used to.</p>
<p>The response returns 15 objects within “results”. Each result is one book. For clarity, this example uses <code>.forEach()</code> to drill down into the API response <code>nytimesBestSellers</code> looping over each book.</p>
<pre><code>nytimesBestSellers.results.forEach(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">book</span>) </span>{  <span class="hljs-keyword">var</span> isbn = book.isbns[<span class="hljs-number">1</span>].isbn10;  <span class="hljs-keyword">var</span> bookInfo = book.book_details[<span class="hljs-number">0</span>];  <span class="hljs-keyword">var</span> lastWeekRank = book.rank_last_week || ‘n/a’;  <span class="hljs-keyword">var</span> weeksOnList = book.weeks_on_list || ‘New <span class="hljs-built_in">this</span> week’;
</code></pre><pre><code>  <span class="hljs-comment">// ...</span>
</code></pre><pre><code>});
</code></pre><p>As we loop over each individual book, the variables are set to the data for their specific listing, which we’ll use when making the entry.</p>
<p>In the code listing above,</p>
<ul>
<li>the ISBN number is located within the book’s <code>isbns</code> array</li>
<li>we select the 10-digit version of the ISBN number at <code>book_details[0]</code></li>
<li>the last week ranking is at <code>rank_last_week</code> and defaults to ‘n/a’</li>
<li>the number of weeks it has been on the best sellers list, is at <code>weeks_on_list</code> and defaults to “New this week” for books that appear on the list for the first time</li>
</ul>
<p>Next, we can make an HTML object to append to the <code>best-seller-titles</code> list. Be sure your project includes <a target="_blank" href="https://jquery.com/">jQuery</a>. On CodePen, you can go to settings and add it in the JavaScript panel.</p>
<pre><code><span class="hljs-keyword">var</span> listing =   <span class="hljs-string">'&lt;div id="'</span> + book.rank + <span class="hljs-string">'" class="entry"&gt;'</span> +     <span class="hljs-string">'&lt;p&gt;'</span> +       <span class="hljs-string">'&lt;img src="" class="book-cover" id="cover-'</span> + book.rank + <span class="hljs-string">'"&gt;'</span> +     <span class="hljs-string">'&lt;/p&gt;'</span> +     <span class="hljs-string">'&lt;h2&gt;&lt;a href="'</span> + book.amazon_product_url + <span class="hljs-string">'" target="_blank"&gt;'</span> + bookInfo.title + <span class="hljs-string">'&lt;/a&gt;&lt;/h2&gt;'</span> +    <span class="hljs-string">'&lt;h4&gt;By '</span> + bookInfo.author + <span class="hljs-string">'&lt;/h4&gt;'</span> +    <span class="hljs-string">'&lt;h4 class="publisher"&gt;'</span> + bookInfo.publisher + <span class="hljs-string">'&lt;/h4&gt;'</span> +    <span class="hljs-string">'&lt;p&gt;'</span> + bookInfo.description + <span class="hljs-string">'&lt;/p&gt;'</span> +     <span class="hljs-string">'&lt;div class="stats"&gt;'</span> +      <span class="hljs-string">'&lt;hr&gt;'</span> +       <span class="hljs-string">'&lt;p&gt;Last Week: '</span> + lastWeekRank + <span class="hljs-string">'&lt;/p&gt;'</span> +       <span class="hljs-string">'&lt;p&gt;Weeks on list: '</span> + weeksOnList + <span class="hljs-string">'&lt;/p&gt;'</span> +    <span class="hljs-string">'&lt;/div&gt;'</span> +  <span class="hljs-string">'&lt;/div&gt;'</span>;
</code></pre><pre><code>$(<span class="hljs-string">'#best-seller-titles'</span>).append(listing);
</code></pre><p>Notice that the image is left blank. On <a target="_blank" href="https://codepen.io/agbales/pen/LNWPYW">CodePen</a>, I’ve added a placeholder image to fill in any undefined responses from Google.</p>
<p>Finally, we’ll can update the book rank number and pass along the rank and ISBN number to <code>updateCover()</code>.</p>
<pre><code>$(<span class="hljs-string">'#'</span> + book.rank).attr(<span class="hljs-string">'nyt-rank'</span>, book.rank);
</code></pre><pre><code>updateCover(book.rank, isbn);
</code></pre><p>We can now write <code>updateCover()</code>, which will handle retrieving the thumbnail from the Google Books API.</p>
<h3 id="heading-google-books-api">Google Books API</h3>
<p>We’ve gathered the textual parts of the listing, but to add a book cover, one of the easiest ways I came across was to call upon the Google Books API. Be sure to grab an API Key from the <a target="_blank" href="https://developers.google.com/books/">Google Books API</a>.</p>
<p>Using the 10-digit ISBN number, we can get a thumbnail book cover image by again using <code>fetch()</code>. As before, we have to drill down into the object to find the single link referencing the thumbnail image we’re looking for:</p>
<pre><code><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">updateCover</span>(<span class="hljs-params">id, isbn</span>) </span>{  fetch(<span class="hljs-string">'https://www.googleapis.com/books/v1/volumes?q=isbn:'</span> + isbn + <span class="hljs-string">"&amp;key="</span> + apiKey, {    <span class="hljs-attr">method</span>: <span class="hljs-string">'get'</span>  })  .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> { <span class="hljs-keyword">return</span> response.json(); })  .then(<span class="hljs-function"><span class="hljs-params">data</span> =&gt;</span> {    <span class="hljs-keyword">var</span> img = data.items[<span class="hljs-number">0</span>].volumeInfo.imageLinks.thumbnail;    img = img.replace(<span class="hljs-regexp">/^http:\/\//i</span>, <span class="hljs-string">'https://'</span>);    $(<span class="hljs-string">'#cover-'</span> + id).attr(<span class="hljs-string">'src'</span>, img);  })    .catch(<span class="hljs-function"><span class="hljs-params">error</span>=&gt;</span> {       <span class="hljs-built_in">console</span>.log(error);  });}
</code></pre><p>After the image is secured, <code>replace()</code> swaps any HTTP links to secure HTTPS versions. We then update the book cover by selecting the proper cover ID and updating its image source.</p>
<h3 id="heading-style">Style</h3>
<p>I’ve added additional styles with SASS. If you’re more comfortable with CSS or SCSS, use the drop down button in that window to compile the code.</p>
<p>The last bit of JavaScript you’ll see controls the logo scaling. This code is triggered when the window scrolls. As the window scrolls down, the logo condenses from a height of 80px down to 35px.</p>
<pre><code>$(<span class="hljs-built_in">window</span>).scroll(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">event</span>) </span>{  <span class="hljs-keyword">var</span> scroll = $(<span class="hljs-built_in">window</span>).scrollTop();  <span class="hljs-keyword">if</span> (scroll &gt; <span class="hljs-number">50</span>) {    $(‘#masthead’).css({‘height’:’<span class="hljs-number">50</span><span class="hljs-string">', ‘padding’ : ‘8’});    $(‘#nyt-logo’).css({‘height’:’35'</span>});  } <span class="hljs-keyword">else</span> {    $(‘#masthead’).css({‘height’:’<span class="hljs-number">100</span><span class="hljs-string">', ‘padding’:’10'</span>});    $(‘#nyt-logo’).css({‘height’:’<span class="hljs-number">80</span><span class="hljs-string">'});  }});</span>
</code></pre><h3 id="heading-final-thoughts">Final Thoughts</h3>
<p>It was exciting to return to a project and build on its features. While I may have approached this problem differently if I’d begun from scratch, this example shows a way to take a typical API call and add upon that work.</p>
<p>In fact, one reason I particularly wanted to share this project was remembering how frustrating it could get for me when I first started working with APIs. I’d get overwhelmed with the documentation, not sure which features or syntax were leading me in the right direction. I often wished for a clear example or walk-through of something a touch beyond the Hello World.</p>
<p>APIs each provide a specific service, and sometimes it’s necessary to combine them. This is just one way of bringing together multiple services, but I hope it’s a bit of inspiration for those exploring ways to combine APIs to create richer content.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
