This page explains how to preview links in Google Docs from a third-party or non-Google service.
To integrate content from a third-party service into Google Docs, you can configure link previews for your Google Workspace Add-on. When users preview links from your service, they can access and interact with the service within the document.
How users preview links
To preview links in Google Docs, users interact with smart chips and cards.
When users type or paste a link into a document, Google Docs prompts them to replace the URL with a smart chip. The chip displays an icon and short title or description of the link's content. When users hover over the URL or chip, they see a card that displays more information about the link.
The following video demonstrates how a Google Docs user pastes and then previews a third-party link in a document:
You can configure a Google Workspace Add-on to preview links for multiple URL patterns. For example, you can create custom link previews for each of the following:
- Support case URLs that preview the case ID, title, status, and the employee assigned to the case.
- Sales lead URLs that preview the lead's name, title, company, and last contacted date.
- Company profile URLs that preview the team member's name, title, and office location.
Set up authorization for your service
To preview links from a service that is external to Google, users must be able to access or sign in to the service. If your service requires authorization, your add-on must be able to invoke the authorization flow when users paste a link from your service into a Google Docs document for the first time.
To set up an OAuth service or custom authorization prompt, see Connecting to non-Google Services from a Google Workspace Add-on.
Turn on link previews for your add-on
This section explains how to turn on link previews for your add-on, which includes the following steps:
- Configure link previews in your add-on's manifest file.
- Build the smart chip and card interface for your link previews.
- Publish the updated add-on to the Google Workspace Marketplace, so that new and existing users can access link previews.
Configure link previews
You configure link previews in the
addons
resource of
your add-on's manifest
file. Your add-on must extend Google Docs and include a linkPreviewTriggers
object.
In your Google Workspace Add-on's manifest file, add or update the following fields:
- Add the
addOns.docs
field to extend Google Docs in your add-on. Under the
addOns.docs
field, implement thelinkPreviewTriggers
trigger with the following fields:labelText
: The text that prompts users to preview the link, such asExample: Support case
. This text is static and displays before users execute the add-on.localizedLabelText
(Optional): AlabelText
that is localized into another language. You must specify the language and country/region identifier in the format of ISO 639 language code-ISO 3166 country/region code. For example,en-US
.runFunction
: The callback function that returns a smart chip and card for the link preview. If required, the function must also invoke the authorization flow for the third-party service. To create this function, see the following section, Build the smart chip and card.Icon
(Optional): The icon that displays in the smart chip. If omitted, the chip uses your add-on's toolbar icon,logoUrl
.Patterns
: An array of URL patterns that trigger the add-on to preview links. For each pattern, include the following fields:hostPattern
: The domain of the URL pattern that your add-on previews. To preview links for a specific subdomain, likesubdomain.example.com
, include the subdomain. To preview links for the entire domain, specify a wildcard character with an asterisk (*) as the subdomain.For example,
*.example.com
matchessubdomain.example.com
andanother.subdomain.example.com
.pathPrefix
(Optional): The path that appends thehostPattern
‘s domain. To match all URLs in the host pattern domain, leavepathPrefix
empty.For example, if the host pattern is
support.example.com
, to match URLs for cases hosted atsupport.example.com/cases
, entercases
.
Add the scope
https://www.googleapis.com/auth/documents.readonly
to youroauthScopes
field so that users can authorize the add-on to preview links on their behalf.
In the following example, the Altostrat company has a Google Workspace Add-on
that previews links for the company's customer issues service. The code shows
the addOns
and oauthScopes
portion of the add-on's manifest file. In the
linkPreviewTriggers
object, the add-on specifies three URL patterns to preview
links. Whenever a link matches one of the URL patterns, the callback function
issuesLinkPreview
builds and displays a smart chip and card in the
Google Docs document.
"oauthScopes": [
"https://www.googleapis.com/auth/documents.readonly"
],
"addOns": {
"common": {
"name": "Altostrat Add-on",
"logoUrl": "https://www.altostrat.com/images/company-logo.png",
"layoutProperties": {
"primaryColor": "#dd4b39"
},
"docs": {
"linkPreviewTriggers": [
{
"labelText": "Altostrat customer issues",
"runFunction": "issuesLinkPreview",
"icon":"https://altostrat.com/images/support-icon.png",
"patterns" : [ {
"hostPattern": "issues.altostrat.com",
},{
"hostPattern": "*.altostrat.com",
"pathPrefix": "issues"
},{
"hostPattern": "altostrat.com",
"pathPrefix": "support/issues"
},
]
}
]
},
}
Build the smart chip and card
To build a smart chip and card, you must implement any functions that you
specified in the linkPreviewTriggers
object.
When a user interacts with a link that matches a specified URL pattern, the
linkPreviewTriggers
trigger fires and its callback function passes the event
object
docs.matchedUrl.url
as an argument. You use this event object to build the smart chip and card for
your link preview.
To create the card interface, you use widgets to display information about the link. You can also build actions that let users open the link or modify its contents. For a list of available widgets and actions, see Supported interactions for preview cards.
In the following example, a chip and card display an issue's priority, status, assignee, and summary for a third-party customer support service:
To build the smart chip and card for a link preview:
- Implement the function that you specified in the
linkPreviewTriggers
section of your add-on's manifest file:- The function must accept an event object containing
docs.matchedUrl.url
as an argument and return a single Card object. - If your third-party service requires authorization, the function must also invoke the authorization flow.
- The function must accept an event object containing
- For each preview card, implement the callback functions used to provide widget interactivity for the interface. For example, if you include a button in the interface, it should have an attached Action and an implemented callback function that runs when the button is clicked.
The following code creates the callback function issuesLinkPreview
from the
earlier example for Altostrat:
// Creates a function that passes an event object as a parameter:
function issuesLinkPreview(event) {
if (event.docs.matchedUrl.url) {
// Uses docs.matchedUrl event object to identify the issue ID from the URL:
const segments = event.docs.matchedUrl.url.split('/');
const issueId = segments[segments.length - 1];
// Builds a card header with the issue ID:
const issueHeader = CardService.newCardHeader().setTitle("Issue " + issueId +": Title bar looks cramped");
const issueDescription = CardService.newTextParagraph()
.setText("Customer can't view title on mobile device.");
// Returns a card with a header that contains the issue's ID and
// title and a text paragraph that contains the issue description:
return CardService.newCardBuilder().setHeader(issueHeader)
.addSection(CardService.newCardSection().addWidget(issueDescription)).build();
}
}
Supported interactions for preview cards
Google Workspace Add-ons support the following widgets and actions for link preview cards:
Card Service field | Type |
---|---|
TextParagraph |
Widget |
IconImage |
Widget |
TextButton |
Widget |
DecoratedText |
Widget |
Image |
Widget |
Divider |
Widget |
ButtonSet |
Widget |
Grid |
Widget |
ImageButton |
Widget |
OpenLink |
Action |
Navigation |
Action Only the updateCard method is supported. |
Publish your updated add-on on the Google Workspace Marketplace
After you configure link previews for your add-on, you must update the OAuth consent screen and app configuration in the Google Workspace Marketplace so that new and existing users can access the updated add-on.
To update your add-on, you complete the following steps:
- Deploy a new version of your add-on.
- Update your add-on's configuration in the Google Workspace Marketplace.
Add the scope
https://www.googleapis.com/auth/documents.readonly
to your OAuth consent screen.
For details on these steps, see Update and manage your published add-on.
After saving your changes to your listing on the Google Workspace Marketplace, your add-on is immediately updated. Your add-on prompts existing users to authorize the new scope the next time that they use the add-on.
Complete example: Support case add-on
The following Apps Script code sample is for a Google Workspace Add-on that previews links to a company's support cases and employee profiles.
The sample includes the following files:
- The add-on's manifest file,
appscript.json
, that extends Google Docs and configures thelinkPreviewTriggers
function. The trigger is configured to preview links for a company's support cases (such ashttps://www.example.com/support/cases/1234
) and employee profiles (such ashttps://www.example.com/people/rosariocruz
). A code file,
code.gs
, that configures arunFunction
response for support case links and employee profile links.
Manifest file
{
"timeZone": "America/New_York",
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8",
"oauthScopes": [
"https://www.googleapis.com/auth/documents.readonly"
],
"addOns": {
"common": {
"name": "Support Case Add-on",
"logoUrl": "https://www.example.com/support.png",
"layoutProperties": {
"primaryColor": "#dd4b39"
}
},
"docs": {
"linkPreviewTriggers": [
{
"runFunction": "userLinkPreview",
"patterns": [
{
"hostPattern": "example.com",
"pathPrefix": "people"
}
],
"labelText": "People",
"localizedLabelText": {
"es": "Personas"
}
},
{
"runFunction": "supportLinkPreview",
"patterns": [
{
"hostPattern": "example.com",
"pathPrefix": "support/cases"
}
],
"labelText": "Support",
"localizedLabelText": {
"es": "Asistencia"
}
},
]
}
}
}
Code.gs
/**
* Entry point for an support case link preview
*
* @param {!Object} event
* @return {!Card}
*/
function caseLinkPreview(event) {
// If the event object matches the pattern https://www.example.com/support/cases/* pattern that was specified in the link preview trigger:
if (event.docs.matchedUrl.url) {
// Parses the URL at the forward slash to identify the case ID that follows the slash:
const segments = event.docs.matchedUrl.url.split('/');
const caseId = segments[segments.length - 1];
// Sets constants for a card header and a text paragraph for the case description:
const caseHeader = CardService.newCardHeader().setTitle("Case " + caseId +": Customer needs assistance.");
const caseDescription = CardService.newTextParagraph()
.setText("Customer needs support with our latest feature.");
// Returns the card. Uses the text from the card's header for the title of the smart chip:
return CardService.newCardBuilder().setHeader(caseHeader)
.addSection(CardService.newCardSection().addWidget(caseDescription)).build();
}
}
/**
* Entry point for a user profile link preview
*
* @param {!Object} event
* @return {!Card}
*/
function userLinkPreview(event) {
// If the event object matches the pattern https://www.example.com/people/* that was specified in the link preview trigger:
if (event.docs.matchedUrl.url) {
// Sets constants for the header and profile image for the company's CEO, Rosario Cruz:
const userHeader = CardService.newCardHeader().setTitle("Rosario Cruz: CEO");
const userImage = CardService.newImage().setImageUrl("https://www.example.com/rosario-cruz-headshot.jpg");
// Returns the card. Uses the text from the card's header for the title of the smart chip:
return CardService.newCardBuilder().setHeader(userHeader)
.addSection(CardService.newCardSection().addWidget(userImage)).build();
}
}