Preview links from Google Books with smart chips

Coding level: Intermediate
Duration: 30 minutes
Project type: Google Workspace Add-on

Objectives

  • Understand what the add-on does.
  • Understand how to build an add-on using Apps Script, and understand what the Apps Script services do.
  • Set up your environment.
  • Set up the script.
  • Run the script.

About this Google Workspace Add-on

In this sample, you create a Google Workspace Add-on that previews links from Google Books in a Google Docs document. When you type or paste a Google Books URL into a document, the add-on recognizes the link and triggers a link preview. To preview the link, you can convert the link into a smart chip and hold the pointer over the link to view a card that displays more information about the book.

This add-on uses Apps Script's UrlFetch Service to connect to the Google Books API and get information about Google Books to display in Google Docs.

How it works

In the Google Workspace Add-on's manifest file, the script configures the add-on to extend Google Docs and trigger link previews for URLs that match certain patterns from the Google Books website (https://books.google.com).

In the code file, the script connects to the Google Books API and uses the URL to get information about the book (which is an instance of the Volume resource). The script uses this information to generate a smart chip that displays the book's title and a preview card that displays a summary, the page count, an image of the book cover, and number of ratings.

Apps Script services

This add-on uses the following services:

Prerequisites

To use this sample, you need the following prerequisites:

Set up your environment

The following sections set up your environment for building the add-on.

Open your Cloud project in the Google Cloud console

If it's not open already, open the Cloud project that you intend to use for this sample:

  1. In the Google Cloud console, go to the Select a project page.

    Select a Cloud project

  2. Select the Google Cloud project you want to use. Or, click Create project and follow the on-screen instructions. If you create a Google Cloud project, you might need to turn on billing for the project.

Turn on the Google Books API

This add-on connects to the Google Books API. Before using Google APIs, you need to turn them on in a Google Cloud project. You can turn on one or more APIs in a single Google Cloud project.

This add-on requires a Cloud project with a configured consent screen. Configuring the OAuth consent screen defines what Google displays to users and registers your app so that you can publish it later.

  1. In the Google Cloud console, go to Menu > APIs & Services > OAuth consent screen.

    Go to OAuth consent screen

  2. For User type select Internal, then click Create.
  3. Complete the app registration form, then click Save and Continue.
  4. For now, you can skip adding scopes and click Save and Continue. In the future, when you create an app for use outside of your Google Workspace organization, you must change the User type to External, and then, add the authorization scopes that your app requires.

  5. Review your app registration summary. To make changes, click Edit. If the app registration looks OK, click Back to Dashboard.

Get an API key for the Google Books API

  1. Go to the Google Cloud console. Make sure your billing-enabled project is open.
  2. In the Google Cloud console, go to Menu > APIs & Services > Credentials.

    Go to Credentials

  3. Click Create credentials > API key.

  4. Take note of your API key for use in a later step.

Set up the script

The following sections set up the script for building the add-on.

Create the Apps Script project

  1. Click the following button to open the Preview links from Google Books Apps Script project.
    Open the project
  2. Click Overview.
  3. On the overview page, click The icon for making a copy Make a copy.
  4. In your copy of the Apps Script project, go to the Code.gs file and replace YOUR_API_KEY with the API key that you generated in the previous section.

Copy the Cloud project number

  1. In the Google Cloud console, go to Menu > IAM & Admin > Settings.

    Go to IAM & Admin Settings

  2. In the Project number field, copy the value.

Set the Apps Script project's Cloud project

  1. In your Apps Script project, click The icon for project settings Project Settings.
  2. Under Google Cloud Platform (GCP) Project, click Change project.
  3. In GCP project number, paste the Google Cloud project number.
  4. Click Set project.

Test the add-on

The following sections test the add-on you created.

Install a test deployment

  1. In your Apps Script project, click Editor.
  2. Replace YOUR_API_KEY with the API key for the Google Books API, created in a previous section.
  3. Click Deploy > Test deployments.
  4. Click Install > Done.
  1. Create a Google Docs document at docs.new.
  2. Paste the following URL to the document, and press the tab key to convert the URL into a smart chip: https://www.google.com/books/edition/Software_Engineering_at_Google/V3TTDwAAQBAJ
  3. Hold the pointer over the smart chip, and when prompted, authorize access to execute the add-on. The preview card displays information about the book.

The following image shows the link preview:

A link preview of the book, Software Engineering at Google.

Review the code

To review the Apps Script code for this add-on, click View source code to expand the section:

View source code

appsscript.json

solutions/add-on/book-smartchip/appsscript.json
{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview",
    "https://www.googleapis.com/auth/script.external_request"
  ],
  "urlFetchWhitelist": [
    "https://www.googleapis.com/books/v1/volumes/"
  ],
  "addOns": {
    "common": {
      "name": "Preview Books Add-on",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/library-icon.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "bookLinkPreview",
          "patterns": [
            {
              "hostPattern": "*.google.*",
              "pathPrefix": "books"
            },
            {
              "hostPattern": "*.google.*",
              "pathPrefix": "books/edition"
            }
          ],
          "labelText": "Book",
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/book-icon.png",
          "localizedLabelText": {
            "es": "Libros"
          }
        }
      ]
    }
  }
}

Code.gs

solutions/add-on/book-smartchip/Code.js
function getBook(id) {
  const apiKey = 'YOUR_API_KEY'; // Replace with your API key
  const apiEndpoint = `https://www.googleapis.com/books/v1/volumes/${id}?key=${apiKey}&country=US`;
  const response = UrlFetchApp.fetch(apiEndpoint);
  return JSON.parse(response);
}

function bookLinkPreview(event) {
 if (event.docs.matchedUrl.url) {
    const segments = event.docs.matchedUrl.url.split('/');
    const volumeID = segments[segments.length - 1];

    const bookData = getBook(volumeID);
    const bookTitle = bookData.volumeInfo.title;
    const bookDescription = bookData.volumeInfo.description;
    const bookImage = bookData.volumeInfo.imageLinks.small;
    const bookAuthors = bookData.volumeInfo.authors;
    const bookPageCount = bookData.volumeInfo.pageCount;

    const previewHeader = CardService.newCardHeader()
      .setSubtitle('By ' + bookAuthors)
      .setTitle(bookTitle);

    const previewPages = CardService.newDecoratedText()
      .setTopLabel('Page count')
      .setText(bookPageCount);

    const previewDescription = CardService.newDecoratedText()
      .setTopLabel('About this book')
      .setText(bookDescription).setWrapText(true);

    const previewImage = CardService.newImage()
      .setAltText('Image of book cover')
      .setImageUrl(bookImage);

    const buttonBook = CardService.newTextButton()
      .setText('View book')
      .setOpenLink(CardService.newOpenLink()
        .setUrl(event.docs.matchedUrl.url));

    const cardSectionBook = CardService.newCardSection()
      .addWidget(previewImage)
      .addWidget(previewPages)
      .addWidget(CardService.newDivider())
      .addWidget(previewDescription)
      .addWidget(buttonBook);

    return CardService.newCardBuilder()
    .setHeader(previewHeader)
    .addSection(cardSectionBook)
    .build();
  }
}