Linkvorschau mit Smartchips (Entwicklervorschau)

Auf dieser Seite wird erläutert, wie Sie ein Google Workspace-Add-on erstellen, mit dem Google Docs-Nutzer Links von Drittanbietern ansehen können.

Ein Google Workspace-Add-on kann die Links Ihres Dienstes erkennen und Google Docs-Nutzer auffordern, sich eine Vorschau davon anzusehen. Sie können ein Add-on so konfigurieren, dass eine Vorschau mehrerer URL-Muster erstellt wird, z. B. Links zu Supportanfragen, Leads und Mitarbeiterprofile.

Wenn Nutzer eine Vorschau von Links in einem Google Docs-Dokument ansehen möchten, interagieren Nutzer mit Smartchips und Karten:

Nutzer ruft eine Vorschau einer Karte auf

Wenn Nutzer eine URL eingeben oder in ein Dokument einfügen, werden sie in Google Docs aufgefordert, den Link durch einen Smartchip zu ersetzen. Der Smartchip zeigt ein Symbol und einen kurzen Titel oder eine kurze Beschreibung des Linkinhalts an. Wenn der Nutzer den Mauszeiger auf den Chip bewegt, wird eine Kartenoberfläche mit weiteren Informationen zur Datei oder zum Link angezeigt.

Im folgenden Video sehen Sie, wie ein Nutzer einen Link in einen Smartchip umwandelt und eine Karte als Vorschau ansieht:

Voraussetzungen

Apps Script

Node.js

Python

Java

Optional: Authentifizierung bei einem Drittanbieterdienst einrichten

Wenn das Add-on eine Verbindung zu einem Dienst herstellt, für den eine Autorisierung erforderlich ist, müssen sich die Nutzer beim Dienst authentifizieren, um eine Vorschau der Links aufrufen zu können. Wenn also Nutzer ihren Link zum ersten Mal in ein Google Docs-Dokument einfügen, müssen sie mit dem Add-on aufgerufen werden.

Informationen zum Einrichten eines OAuth-Dienstes oder einer benutzerdefinierten Autorisierungsaufforderung finden Sie in einer der folgenden Anleitungen:

In diesem Abschnitt wird beschrieben, wie Sie die Linkvorschau für Ihr Add-on einrichten. Gehen Sie dazu so vor:

  1. Konfigurieren Sie Linkvorschauen in der Deployment-Ressource oder Manifestdatei Ihres Add-ons.
  2. Erstellen Sie den Smartchip und die Kartenschnittstelle für Ihre Links.

Linkvorschau konfigurieren

Geben Sie die folgenden Abschnitte und Felder in der Bereitstellungsressource oder in der Manifestdatei des Add-ons an, um Linkvorschauen zu konfigurieren:

  1. Fügen Sie im Abschnitt addOns das Feld docs hinzu, um Google Docs zu erweitern.
  2. Implementieren Sie im Feld docs den linkPreviewTriggers-Trigger, der einen runFunction enthält. Sie definieren diese Funktion im folgenden Abschnitt Smartchip und Karte erstellen.

    Informationen zu den Feldern, die Sie im linkPreviewTriggers-Trigger angeben können, finden Sie in der Referenzdokumentation zu Apps Script-Manifestdateien oder unter Bereitstellungsressourcen für andere Laufzeiten.

  3. Fügen Sie im Feld oauthScopes den Bereich https://www.googleapis.com/auth/workspace.linkpreview hinzu, damit Nutzer das Add-on für die Vorschau von Links in ihrem Namen autorisieren können.

Sehen Sie sich beispielsweise die Abschnitte oauthScopes und addons einer Bereitstellungsressource an, die die Linkvorschauen für einen Supportfalldienst konfigurieren:

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://www.example.com/images/company-logo.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "caseLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "logoUrl": "https://www.example.com/images/support-icon.png",
          "localizedLabelText": {
            "es": "Caso de soporte"
          }
        }
      ]
    }
  }
}

Im Beispiel wird im Google Workspace-Add-on eine Vorschau der Links für den Supportfall eines Unternehmens angezeigt. Das Add-on gibt drei URL-Muster für die Vorschau von Links an. Wenn ein Link mit einem der URL-Muster in einem Google Docs-Dokument übereinstimmt, erstellt die Callback-Funktion caseLinkPreview einen Smartchip und eine Karte.

Smartchip und Karte erstellen

Damit ein Smartchip und eine Smartcard für einen Link zurückgegeben werden, müssen Sie alle Funktionen implementieren, die Sie im Objekt linkPreviewTriggers angegeben haben.

Wenn ein Nutzer mit einem Link interagiert, der mit einem bestimmten URL-Muster übereinstimmt, wird der Trigger linkPreviewTriggers ausgelöst und die Callback-Funktion übergibt das Ereignisobjekt docs.matchedUrl.url als Argument. Sie verwenden die Nutzlast dieses Ereignisobjekts, um den Smartchip und die Karte für die Linkvorschau zu erstellen.

Für ein Add-on, das beispielsweise das URL-Muster example.com/cases angibt, wird die folgende Ereignisnutzlast zurückgegeben, wenn ein Nutzer eine Vorschau des Links https://www.example.com/cases/123456 aufruft:

JSON

{
  "docs": {
    "matchedUrl": {
        "url": "https://www.example.com/support/cases/123456"
    }
  }
}

Zum Erstellen der Kartenschnittstelle verwenden Sie Widgets, um Informationen zum Link anzuzeigen. Sie können auch Aktionen erstellen, mit denen Nutzer den Link öffnen oder seinen Inhalt ändern können. Eine Liste der verfügbaren Widgets und Aktionen finden Sie unter Unterstützte Komponenten für Vorschaukarten.

So erstellen Sie den Smartchip und die Karte für eine Linkvorschau:

  1. Implementieren Sie die Funktion, die Sie im Abschnitt linkPreviewTriggers der Deployment-Ressource oder Manifestdatei des Add-ons angegeben haben:
    1. Die Funktion muss ein Ereignisobjekt, das docs.matchedUrl.url enthält, als Argument akzeptieren und ein einzelnes Card-Objekt zurückgeben.
    2. Wenn für Ihren Dienst eine Autorisierung erforderlich ist, muss die Funktion auch den Autorisierungsvorgang aufrufen.
  2. Implementieren Sie für jede Vorschaukarte die Callback-Funktionen, die zur Interaktion mit dem Widget verwendet werden. Wenn Sie beispielsweise eine Schaltfläche in die Benutzeroberfläche einfügen, sollte diese eine angehängte Action und eine implementierte Callback-Funktion haben, die beim Klicken auf die Schaltfläche ausgeführt wird.

Mit dem folgenden Code wird die Callback-Funktion caseLinkPreview erstellt:

Apps Script

apps-script/preview-links/preview-link.gs
/**
* Entry point for a support case link preview
*
* @param {!Object} event
* @return {!Card}
*/
// Creates a function that passes an event object as a parameter.
function caseLinkPreview(event) {

  // If the event object URL matches a specified pattern for support case links.
  if (event.docs.matchedUrl.url) {

    // Uses the event object to parse the URL and identify the case ID.
    const segments = event.docs.matchedUrl.url.split('/');
    const caseId = segments[segments.length - 1];

    // Builds a preview card with the case ID, title, and description
    const caseHeader = CardService.newCardHeader()
      .setTitle(`Case ${caseId}: Title bar is broken.`);
    const caseDescription = CardService.newTextParagraph()
      .setText('Customer can\'t view title on mobile device.');

    // 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();
  }
}

Node.js

Knoten/Vorschau-Links/Index.js
/**
 * 
 * A support case link preview.
 *
 * @param {!string} url
 * @return {!Card}
 */
function caseLinkPreview(url) {

  // Parses the URL to identify the case ID.
  const segments = url.split('/');
  const caseId = segments[segments.length - 1];

  // Returns the card.
  // Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: `Case ${caseId}: Title bar is broken.`
    },
    sections: [{
      widgets: [{
        textParagraph: {
          text: `Customer can't view title on mobile device.`
        }
      }]
    }]
  };
}

Python

python/preview-links/main.py

def case_link_preview(url):
    """A support case link preview.
    Args:
      url: The case link.
    Returns:
      A case link preview card.
    """

    # Parses the URL to identify the case ID.
    segments = url.split("/")
    case_id = segments[-1]

    # Returns the card.
    # Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": f"Case {case_id}: Title bar is broken."},
        "sections": [
            {
                "widgets": [
                    {
                        "textParagraph": {
                            "text": "Customer can't view title on mobile device."
                        }
                    }
                ]
            }
        ],
    }

Java

java/preview-links/src/main/java/PreviewLink.java
/**
 * Creates a case link preview card.
 *
 * @param url A URL.
 * @return A case link preview card.
 */
Card caseLinkPreview(String url) {
  String[] segments = url.split("/");
  String caseId = segments[segments.length - 1];

  CardHeader cardHeader = new CardHeader();
  cardHeader.setTitle(String.format("Case %s: Title bar is broken.", caseId));

  TextParagraph textParagraph = new TextParagraph();
  textParagraph.setText("Customer can't view title on mobile device.");

  WidgetMarkup widget = new WidgetMarkup();
  widget.setTextParagraph(textParagraph);
  Section section = new Section();
  section.setWidgets(List.of(widget));

  Card card = new Card();
  card.setHeader(cardHeader);
  card.setSections(List.of(section));

  return card;
}

Unterstützte Komponenten für Vorschaukarten

Google Workspace-Add-ons unterstützen die folgenden Widgets und Aktionen für Karten mit Linkvorschau:

Apps Script

Feld „Kartendienst“ Typ
TextParagraph Widget
DecoratedText Widget
Image Widget
IconImage Widget
ButtonSet Widget
TextButton Widget
ImageButton Widget
Grid Widget
Divider Widget
OpenLink Aktion
Navigation Aktion
Nur die Methode updateCard wird unterstützt.

JSON

Feld „Karte“ (google.apps.card.v1) Typ
TextParagraph Widget
DecoratedText Widget
Image Widget
Icon Widget
ButtonList Widget
Button Widget
Grid Widget
Divider Widget
OpenLink Aktion
Navigation Aktion
Nur die Methode updateCard wird unterstützt.

Vollständiges Beispiel: Add-on für Supportanfragen

Im folgenden Beispiel sehen Sie ein Google Workspace-Add-on, mit dem Links zu Supportfällen und Mitarbeiterprofilen eines Unternehmens angezeigt werden.

Das Beispiel führt Folgendes aus:

  • Vorschauen enthalten Links zu Supportanfragen, z. B. https://www.example.com/support/cases/1234. Der Smartchip zeigt ein Supportsymbol an. Die Vorschaukarte enthält die Fall-ID und eine Beschreibung.
  • Vorschau von Links zu Supportfall-Agents wie https://www.example.com/people/rosario-cruz anzeigen. Auf dem Smartchip ist ein Personensymbol zu sehen und auf der Vorschaukarte sind Name, E-Mail-Adresse, Stellenbezeichnung und Profilbild des Mitarbeiters zu sehen.
  • Wenn die Sprache des Nutzers auf Spanisch festgelegt ist, lokalisiert der Smartchip labelText in Spanisch.

Deployment-Ressource

Apps Script

{
  "timeZone": "America/New_York",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/link-icon.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "caseLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "localizedLabelText": {
            "es": "Caso de soporte"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-icon.png"
        },
        {
          "runFunction": "peopleLinkPreview",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "people"
            }
          ],
          "labelText": "People",
          "localizedLabelText": {
            "es": "Personas"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/person-icon.png"
        }
      ]
    }
  }
}

JSON

{
  "oauthScopes": [
    "https://www.googleapis.com/auth/workspace.linkpreview"
  ],
  "addOns": {
    "common": {
      "name": "Preview support cases",
      "logoUrl": "https://developers.google.com/workspace/add-ons/images/link-icon.png",
      "layoutProperties": {
        "primaryColor": "#dd4b39"
      }
    },
    "docs": {
      "linkPreviewTriggers": [
        {
          "runFunction": "URL",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "support/cases"
            },
            {
              "hostPattern": "*.example.com",
              "pathPrefix": "cases"
            },
            {
              "hostPattern": "cases.example.com"
            }
          ],
          "labelText": "Support case",
          "localizedLabelText": {
            "es": "Caso de soporte"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/support-icon.png"
        },
        {
          "runFunction": "URL",
          "patterns": [
            {
              "hostPattern": "example.com",
              "pathPrefix": "people"
            }
          ],
          "labelText": "People",
          "localizedLabelText": {
            "es": "Personas"
          },
          "logoUrl": "https://developers.google.com/workspace/add-ons/images/person-icon.png"
        }
      ]
    }
  }
}

Code

Apps Script

apps-script/preview-links/preview-link.gs
/**
* Entry point for a support case link preview
*
* @param {!Object} event
* @return {!Card}
*/
// Creates a function that passes an event object as a parameter.
function caseLinkPreview(event) {

  // If the event object URL matches a specified pattern for support case links.
  if (event.docs.matchedUrl.url) {

    // Uses the event object to parse the URL and identify the case ID.
    const segments = event.docs.matchedUrl.url.split('/');
    const caseId = segments[segments.length - 1];

    // Builds a preview card with the case ID, title, and description
    const caseHeader = CardService.newCardHeader()
      .setTitle(`Case ${caseId}: Title bar is broken.`);
    const caseDescription = CardService.newTextParagraph()
      .setText('Customer can\'t view title on mobile device.');

    // 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 an employee profile link preview
*
* @param {!Object} event
* @return {!Card}
*/
function peopleLinkPreview(event) {

  // If the event object URL matches a specified pattern for employee profile links.
  if (event.docs.matchedUrl.url) {

    // Builds a preview card with an employee's name, title, email, and profile photo.
    const userHeader = CardService.newCardHeader().setTitle("Rosario Cruz");
    const userImage = CardService.newImage()
      .setImageUrl("https://developers.google.com/workspace/add-ons/images/employee-profile.png");
    const userInfo = CardService.newDecoratedText()
      .setText("rosario@example.com")
      .setBottomLabel("Case Manager")
      .setIcon(CardService.Icon.EMAIL);
    const userSection = CardService.newCardSection()
      .addWidget(userImage)
      .addWidget(userInfo);

    // Returns the card. Uses the text from the card's header for the title of the smart chip.
    return CardService.newCardBuilder()
      .setHeader(userHeader)
      .addSection(userSection)
      .build();
  }
}

Node.js

Knoten/Vorschau-Links/Index.js
const UrlParser = require('url');

/**
 * Responds to any HTTP request.
 *
 * @param {Object} req HTTP request context.
 * @param {Object} res HTTP response context.
 */
exports.createLinkPreview = (req, res) => {
  const event = req.body;
  if (event.docs.matchedUrl.url) {
    res.json(createCard(event.docs.matchedUrl.url));
  }
};

/**
 * Creates a preview link card for either a case link or people link.
 * 
 * @param {!String} url
 * @return {!Card}
 */
function createCard(url) {
  const parsedUrl = UrlParser.parse(url);
  if (parsedUrl.hostname === 'www.example.com') {
    if (parsedUrl.path.startsWith('/support/cases/')) {
      return caseLinkPreview(url);
    }

    if (parsedUrl.path.startsWith('/people/')) {
      return peopleLinkPreview();
    }
  }
}


/**
 * 
 * A support case link preview.
 *
 * @param {!string} url
 * @return {!Card}
 */
function caseLinkPreview(url) {

  // Parses the URL to identify the case ID.
  const segments = url.split('/');
  const caseId = segments[segments.length - 1];

  // Returns the card.
  // Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: `Case ${caseId}: Title bar is broken.`
    },
    sections: [{
      widgets: [{
        textParagraph: {
          text: `Customer can't view title on mobile device.`
        }
      }]
    }]
  };
}


/**
 * An employee profile link preview.
 *
 * @return {!Card}
 */
function peopleLinkPreview() {

  // Builds a preview card with an employee's name, title, email, and profile photo.
  // Returns the card. Uses the text from the card's header for the title of the smart chip.
  return {
    header: {
      title: "Rosario Cruz"
    },
    sections: [{
      widgets: [
        {
          image: {
            imageUrl: 'https://developers.google.com/workspace/add-ons/images/employee-profile.png'
          }
        }, {
          keyValue: {
            icon: "EMAIL",
            content: "rosario@example.com",
            bottomLabel: "Case Manager"
          }
        }
      ]
    }]
  };
}

Python

python/preview-links/main.py
from typing import Any, Mapping
from urllib.parse import urlparse

import flask
import functions_framework


@functions_framework.http
def create_link_preview(req: flask.Request):
    """Responds to any HTTP request.
    Args:
      req: HTTP request context.
    Returns:
      The response object.
    """
    event = req.get_json(silent=True)
    if event["docs"]["matchedUrl"]["url"]:
        return create_card(event["docs"]["matchedUrl"]["url"])


def create_card(url):
    """Creates a preview link card for either a case link or people link.
    Args:
      url: The matched url.
    Returns:
      A case link preview card or a people link preview card.
    """
    parsed_url = urlparse(url)
    if parsed_url.hostname != "www.example.com":
        return {}

    if parsed_url.path.startswith("/support/cases/"):
        return case_link_preview(url)

    if parsed_url.path.startswith("/people/"):
        return people_link_preview()

    return {}




def case_link_preview(url):
    """A support case link preview.
    Args:
      url: The case link.
    Returns:
      A case link preview card.
    """

    # Parses the URL to identify the case ID.
    segments = url.split("/")
    case_id = segments[-1]

    # Returns the card.
    # Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": f"Case {case_id}: Title bar is broken."},
        "sections": [
            {
                "widgets": [
                    {
                        "textParagraph": {
                            "text": "Customer can't view title on mobile device."
                        }
                    }
                ]
            }
        ],
    }




def people_link_preview():
    """An employee profile link preview.
    Returns:
      A people link preview card.
    """

    # Builds a preview card with an employee's name, title, email, and profile photo.
    # Returns the card. Uses the text from the card's header for the title of the smart chip.
    return {
        "header": {"title": "Rosario Cruz"},
        "sections": [
            {
                "widgets": [
                    {
                        "image": {
                            "imageUrl": "https:#developers.google.com/workspace/add-ons/images/employee-profile.png"
                        }
                    },
                    {
                        "keyValue": {
                            "icon": "EMAIL",
                            "content": "rosario@example.com",
                            "bottomLabel": "Case Manager",
                        }
                    },
                ]
            }
        ],
    }

Java

java/preview-links/src/main/java/PreviewLink.java
import com.google.api.services.chat.v1.model.Card;
import com.google.api.services.chat.v1.model.CardHeader;
import com.google.api.services.chat.v1.model.Image;
import com.google.api.services.chat.v1.model.KeyValue;
import com.google.api.services.chat.v1.model.Section;
import com.google.api.services.chat.v1.model.TextParagraph;
import com.google.api.services.chat.v1.model.WidgetMarkup;
import com.google.cloud.functions.HttpFunction;
import com.google.cloud.functions.HttpRequest;
import com.google.cloud.functions.HttpResponse;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;

public class PreviewLink implements HttpFunction {
  private static final Gson gson = new Gson();

  /**
   * Responds to any HTTP request.
   *
   * @param request  An HTTP request context.
   * @param response An HTTP response context.
   */
  @Override
  public void service(HttpRequest request, HttpResponse response) throws Exception {
    JsonObject body = gson.fromJson(request.getReader(), JsonObject.class);
    String url = body.getAsJsonObject("docs")
        .getAsJsonObject("matchedUrl")
        .get("url")
        .getAsString();

    response.getWriter().write(gson.toJson(createCard(url)));
  }

  /**
   * Creates a preview link card for either a case link or people link.
   *
   * @param url A URL.
   * @return A case link preview card or a people link preview card.
   */
  Card createCard(String url) throws MalformedURLException {
    URL parsedURL = new URL(url);

    if (!parsedURL.getHost().equals("www.example.com")) {
      return new Card();
    }

    if (parsedURL.getPath().startsWith("/support/cases/")) {
      return caseLinkPreview(url);
    }

    if (parsedURL.getPath().startsWith("/people/")) {
      return peopleLinkPreview();
    }

    return new Card();
  }


  /**
   * Creates a case link preview card.
   *
   * @param url A URL.
   * @return A case link preview card.
   */
  Card caseLinkPreview(String url) {
    String[] segments = url.split("/");
    String caseId = segments[segments.length - 1];

    CardHeader cardHeader = new CardHeader();
    cardHeader.setTitle(String.format("Case %s: Title bar is broken.", caseId));

    TextParagraph textParagraph = new TextParagraph();
    textParagraph.setText("Customer can't view title on mobile device.");

    WidgetMarkup widget = new WidgetMarkup();
    widget.setTextParagraph(textParagraph);
    Section section = new Section();
    section.setWidgets(List.of(widget));

    Card card = new Card();
    card.setHeader(cardHeader);
    card.setSections(List.of(section));

    return card;
  }


  /**
   * Creates a people link preview card.
   *
   * @return A people link preview card.
   */
  Card peopleLinkPreview() {
    CardHeader cardHeader = new CardHeader();
    cardHeader.setTitle("Rosario Cruz");

    Image image = new Image();
    image.setImageUrl("https://developers.google.com/workspace/add-ons/images/employee-profile.png");

    WidgetMarkup imageWidget = new WidgetMarkup();
    imageWidget.setImage(image);

    KeyValue keyValue = new KeyValue();
    keyValue.setIcon("EMAIL");
    keyValue.setContent("rosario@example.com");
    keyValue.setBottomLabel("Case Manager");

    WidgetMarkup keyValueWidget = new WidgetMarkup();
    keyValueWidget.setKeyValue(keyValue);

    Section section = new Section();
    section.setWidgets(List.of(imageWidget, keyValueWidget));

    Card card = new Card();
    card.setHeader(cardHeader);
    card.setSections(List.of(section));

    return card;
  }

}