Créer des déclencheurs et des étapes d'action Workspace Studio personnalisés

1. Introduction

Dans cet atelier de programmation, vous allez créer un portail d'assistance rapide interactif qui interagit directement avec Google Workspace Studio. Vous apprendrez à créer une étape de déclencheur personnalisée et une étape d'action personnalisée qui peuvent être testées instantanément sans dépendre d'une infrastructure tierce.

Nous utiliserons Google Apps Script pour créer :

  • Une application Web avec un formulaire élégant permettant aux utilisateurs d'envoyer manuellement des demandes d'assistance.
  • Un déclencheur personnalisé qui capture ces envois d'applications Web et déclenche un flux Workspace Studio.
  • Une étape personnalisée qui analyse la description de la demande entrante pour identifier les niveaux d'urgence ("Élevée" ou "Normale").

Points abordés

  • Comment configurer les starters et les étapes dans le fichier manifeste appsscript.json.
  • Comment construire la notifyUri pendant le cycle de vie de l'enregistrement de l'application de démarrage.
  • Découvrez comment déclencher un flux Workspace Studio de manière programmatique à partir d'un code externe à l'aide de UrlFetchApp.
  • Découvrez comment construire des variables de sortie dans vos étapes personnalisées pour transmettre des données en aval.

Prérequis

  • Un compte Google Workspace avec Google Workspace Studio activé.
  • Le paramètre Autoriser les étapes personnalisées (test) non publiées est activé dans la console d'administration de votre domaine (sous Applications > Google Workspace > Workspace Studio > Paramètres des étapes personnalisées).
  • Connaissances de Google Apps Script

2. Configurer le projet Apps Script

Commençons par créer un projet Apps Script pour héberger notre code :

  1. Accédez à script.google.com, puis cliquez sur Nouveau projet.
  2. Nommez le projet Support Quick Portal.
  3. Cliquez sur Paramètres du projet Paramètres du projet dans la barre latérale de gauche.
  4. Cochez la case Afficher le fichier manifeste appsscript.json dans l'éditeur.
  5. Revenez à la vue Éditeur Éditeur.

Par défaut, les projets Apps Script sont associés à un projet Google Cloud par défaut masqué. Pour appeler l'API Google Workspace Studio et éviter les erreurs PERMISSION_DENIED, vous devez passer à un projet Cloud standard, activer l'API et configurer correctement la plate-forme Google Auth.

  1. Sélectionnez ou créez un projet : accédez à la console Google Cloud, puis utilisez le menu déroulant des projets en haut de la page pour choisir un projet existant ou en créer un.
  2. Activez l'API : une fois le projet de votre choix actif dans la barre supérieure, ouvrez le flux d'activation de l'API, puis cliquez sur Suivant et Activer pour l'API Workspace Studio.
  3. Configurer le branding OAuth : ouvrez la page Branding de Google Auth Platform.
    1. Si vous y êtes invité, cliquez sur Commencer. (Si vous l'avez déjà configuré, passez à l'étape 4.)
    2. Sous Informations sur l'application, saisissez le nom de l'application et l'adresse e-mail de l'assistance utilisateur. Cliquez sur Suivant.
    3. Sous Audience, sélectionnez Interne (ou Externe si l'option "Interne" n'est pas disponible), puis cliquez sur Suivant.
    4. Fournissez vos coordonnées, acceptez le règlement sur les données, puis cliquez sur Créer.
  4. Configurer l'accès aux données : ouvrez la page Accès aux données, puis cliquez sur Ajouter ou supprimer des niveaux d'accès.
    1. Sous Ajouter manuellement des niveaux d'accès, collez https://www.googleapis.com/auth/workspace.studio.trigger.
    2. Cliquez sur Ajouter au tableau, puis sur Mettre à jour, et enfin sur Enregistrer en bas de la page.
  5. Accédez à IAM et administration > Paramètres (ou au tableau de bord de la console Cloud) et copiez le numéro du projet.
  6. Revenez à votre projet Apps Script, puis cliquez sur Paramètres du projet Paramètres du projet dans la barre latérale de gauche.
  7. Dans la section Projet Google Cloud Platform (GCP), cliquez sur Changer de projet.
  8. Saisissez le numéro de projet GCP que vous avez copié, puis cliquez sur Définir le projet.

Configurer le fichier manifeste

Ouvrez le fichier appsscript.json qui est désormais visible. Remplacez son contenu par le code ci-dessous. Ce fichier manifeste liste explicitement nos champs d'application OAuth requis et définit notre déclencheur comme workflowTrigger et notre action comme workflowAction sous le bloc studio.flows.workflowElements.

{
  "timeZone": "America/Los_Angeles",
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "webapp": {
     "executeAs": "USER_ACCESSING",
     "access": "MYSELF"
  },
  "oauthScopes": [
    "https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/workspace.studio.trigger",
    "https://www.googleapis.com/auth/script.storage",
    "https://www.googleapis.com/auth/script.locale"
  ],
  "urlFetchWhitelist": [
    "https://workspacestudio.googleapis.com/"
  ],
  "addOns": {
    "common": {
      "name": "Support Extension",
      "logoUrl": "https://www.gstatic.com/images/branding/productlogos/buganizer/v1/192px.svg",
      "useLocaleFromApp": true
    },
    "studio": {
      "flows": {
        "workflowElements": [
          {
            "id": "supportTicketTrigger",
            "state": "ACTIVE",
            "name": "New Support Ticket",
            "description": "Fires when someone submits a ticket via the Web App.",
            "workflowTrigger": {
              "inputs": [],
              "outputs": [
                {
                  "id": "ticketTitle",
                  "description": "The title of the ticket",
                  "cardinality": "SINGLE",
                  "dataType": { "basicType": "STRING" }
                },
                {
                  "id": "ticketDescription",
                  "description": "The full description of the issue",
                  "cardinality": "SINGLE",
                  "dataType": { "basicType": "STRING" }
                }
              ],
              "onConfigFunction": "onConfigTrigger",
              "onManageFunction": "onManageTrigger"
            }
          },
          {
            "id": "urgencyDetectorStep",
            "state": "ACTIVE",
            "name": "Detect Urgency",
            "description": "Scans the ticket description to detect High or Normal urgency.",
            "workflowAction": {
              "inputs": [
                {
                  "id": "ticketDescription",
                  "description": "The ticket description",
                  "cardinality": "SINGLE",
                  "dataType": { "basicType": "STRING" }
                }
              ],
              "outputs": [
                {
                  "id": "urgencyLevel",
                  "description": "The urgency High/Normal",
                  "cardinality": "SINGLE",
                  "dataType": { "basicType": "STRING" }
                }
              ],
              "onConfigFunction": "onConfigUrgency",
              "onExecuteFunction": "onExecuteUrgency"
            }
          }
        ]
      }
    }
  }
}

3. Créer l'UI de l'application Web

Pour fournir un moyen visuel et testable de déclencher notre starter sans utiliser d'outils de terminal ni de Webhooks tiers, nous allons créer une application Web Apps Script.

Dans l'éditeur Apps Script, à côté de Fichiers, cliquez sur Ajouter un fichier Ajouter un fichier, puis sélectionnez HTML. Nommez-le index.html (l'extension .html est ajoutée automatiquement).

Collez le code d'interface utilisateur simplifié suivant :

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      body { font-family: Arial, sans-serif; padding: 20px; max-width: 500px; margin: auto; }
      label { font-weight: bold; display: block; margin-top: 15px; }
      input, textarea { width: 100%; margin-top: 5px; padding: 10px; box-sizing: border-box; }
      button { background-color: #1a73e8; color: white; border: none; padding: 10px 15px; margin-top: 15px; font-weight: bold; cursor: pointer; border-radius: 4px; }
      button:hover { background-color: #1557b0; }
      #status { margin-top: 15px; color: green; font-weight: bold; }
    </style>
  </head>
  <body>
    <h2>Support Quick Portal</h2>
    <p>Submit your issue below to trigger the Workspace Studio flow.</p>

    <label for="title">Ticket Title</label>
    <input type="text" id="title" placeholder="e.g. Broken monitor">

    <label for="description">Issue Description</label>
    <textarea id="description" rows="4" placeholder="Explain your issue (use words like 'urgent' to test the step!)..."></textarea>

    <button onclick="submitTicket()">Submit Ticket</button>
    <div id="status"></div>

    <script>
      function submitTicket() {
        const title = document.getElementById('title').value;
        const description = document.getElementById('description').value;
        const statusEl = document.getElementById('status');

        if (!title || !description) {
           statusEl.style.color = "red";
           statusEl.innerText = "Please fill out both fields.";
           return;
        }

        statusEl.style.color = "green";
        statusEl.innerText = "Submitting ticket...";

        google.script.run
          .withSuccessHandler(function(response) {
            statusEl.innerText = response;
          })
          .withFailureHandler(function(error) {
            statusEl.style.color = 'red';
            statusEl.innerText = 'Error: ' + error.message;
          })
          .submitTicketToStudio(title, description);
      }
    </script>
  </body>
</html>

4. Créer les scripts de backend

Maintenant, assemblons le tout. Pour que le code reste lisible, nous allons séparer la logique de l'application Web, du Starter et de l'Action Step dans trois fichiers de script différents.

WebApp.gs

Renommez le fichier Code.gs par défaut dans l'éditeur en WebApp.gs, supprimez le fichier myFunction de base, puis copiez-collez le bloc ci-dessous. Ce fichier gère l'hébergement de l'application Web :

/** --- WEB APP HOSTING --- **/

/**
 * Serves the HTML UI when users visit the web app URL.
 */
function doGet() {
  return HtmlService.createHtmlOutputFromFile('index')
      .setTitle('Support Quick Portal')
      .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}

/**
 * Called by the Web App form. It calls the Workspace Studio API.
 */
function submitTicketToStudio(title, description) {
  const props = PropertiesService.getUserProperties();
  const notifyUri = props.getProperty('notifyUri');
  const triggerId = props.getProperty('triggerId');

  if (!notifyUri || !triggerId) {
    throw new Error('Trigger URL missing! Make sure the flow is enabled in Workspace Studio.');
  }

  // Use ScriptApp.getOAuthToken() (requires the workspace.studio.trigger scope in manifest)
  const token = ScriptApp.getOAuthToken();
  const requestId = Utilities.getUuid();

  // Package our outputs mapped in appsscript.json
  const payload = {
    "name": "triggers/" + triggerId,
    "outputs": {
      "ticketTitle": { "stringValues": [title] },
      "ticketDescription": { "stringValues": [description] }
    },
    "requestId": requestId
  };

  const options = {
    "method": "POST",
    "contentType": "application/json",
    "headers": { "Authorization": "Bearer " + token },
    "payload": JSON.stringify(payload),
    "muteHttpExceptions": true
  };

  // Fire!
  const response = UrlFetchApp.fetch(notifyUri, options);
  if (response.getResponseCode() !== 200) {
    console.error(response.getContentText());
    throw new Error('Workspace Studio API Error: ' + response.getResponseCode());
  }
  return 'Ticket successfully routed to Workspace Studio!';
}

Starter.gs

Ensuite, pointez sur Fichiers, cliquez sur Ajouter un fichier Ajouter un fichier, sélectionnez Script, puis nommez-le Starter.gs. Copiez et collez le bloc ci-dessous. Ce fichier gère la configuration des déclencheurs et la gestion du cycle de vie de Workspace Studio :

/** --- STARTER LOGIC --- **/

/**
 * Workspace Studio calls this to display the config UI when the user adds the starter.
 * We just return a static message since there are no properties to configure.
 */
function onConfigTrigger() {
  const section = CardService.newCardSection()
      .setHeader("Configure Web App Starter")
      .addWidget(CardService.newTextParagraph().setText("Ready to go! Once you enable this flow, deploy your Apps Script project as a Web App to submit tickets."));

  return CardService.newCardBuilder().addSection(section).build();
}

/**
 * Workspace Studio posts data here to manage the lifecycle (enable/disable the trigger).
 * Critically, we must construct or save the `notifyUri` and `triggerId` to call it later.
 */
function onManageTrigger(event) {
  const triggerCreation = event.workflow.triggerCreation;
  const triggerDeletion = event.workflow.triggerDeletion;

  const props = PropertiesService.getUserProperties();

  if (triggerCreation) {
    // Save the unique URL and ID when the flow is enabled
    // Note: notifyUri might be omitted, so fallback to constructing it dynamically
    const notifyUri = triggerCreation.notifyUri || `https://workspacestudio.googleapis.com/v1/triggers/${triggerCreation.triggerId}:fire`;
    props.setProperty('notifyUri', notifyUri);
    props.setProperty('triggerId', triggerCreation.triggerId);
  } else if (triggerDeletion) {
    // Cleanup if the user deletes the flow
    props.deleteProperty('notifyUri');
    props.deleteProperty('triggerId');
  }
}

Action.gs

Ensuite, pointez sur Fichiers, cliquez sur Ajouter un fichier Ajouter un fichier, sélectionnez Script, puis nommez-le Action.gs. Copiez et collez la logique de l'étape d'urgence ci-dessous :

/** --- ACTION STEP LOGIC --- **/

/**
 * Workspace Studio configuration card for the Step.
 * We prompt the user to bind a variable to our "ticketDescription" input.
 */
function onConfigUrgency() {
  const input = CardService.newTextInput()
      .setFieldName("ticketDescription")
      .setTitle("Source Description")
      .setHint('Select the description variable outputted by the starter')
      .setHostAppDataSource(
        CardService.newHostAppDataSource().setWorkflowDataSource(CardService.newWorkflowDataSource().setIncludeVariables(true))
      );

  const section = CardService.newCardSection()
      .setHeader("Urgency Detector Step")
      .addWidget(input);

  return CardService.newCardBuilder().addSection(section).build();
}

/**
 * The synchronous logic executed during the Step.
 */
function onExecuteUrgency(event) {
  // Read mapped inputs
  let description = event.workflow.actionInvocation.inputs["ticketDescription"].stringValues[0];
  if (!description) description = "";

  const urgentKeywords = ['urgent', 'crash', 'broken', 'down', 'fire'];
  let urgencyLevel = 'Normal';

  if (urgentKeywords.some(keyword => description.toLowerCase().includes(keyword))) {
    urgencyLevel = 'High';
  }

  // Package outputs correctly
  const variableDataMap = {
    "urgencyLevel": AddOnsResponseService.newVariableData().addStringValue(urgencyLevel)
  };

  return outputVariables(variableDataMap);
}

/**
 * Helper strictly enforcing the expected Step object return type.
 */
function outputVariables(variableDataMap) {
  const workflowAction = AddOnsResponseService.newReturnOutputVariablesAction()
      .setVariableDataMap(variableDataMap);
  const hostAppAction = AddOnsResponseService.newHostAppAction()
      .setWorkflowAction(workflowAction);
  return AddOnsResponseService.newRenderActionBuilder()
      .setHostAppAction(hostAppAction)
      .build();
}

5. Déployer et tester

Maintenant que nous avons écrit notre code, déployons et configurons le projet.

Étape 1 : Réautoriser le script

Étant donné que vous avez associé un nouveau projet Google Cloud standard, vous devez autoriser explicitement les champs d'application du script (comme script.external_request utilisé par UrlFetchApp) par rapport au nouveau projet.

  1. Dans l'éditeur Apps Script, sélectionnez WebApp.gs sous Fichiers, puis sélectionnez la fonction doGet dans le menu déroulant de la barre d'outils supérieure.
  2. Cliquez sur Exécuter.
  3. L'invite "Autorisation requise" s'affiche. Cliquez sur Examiner les autorisations.
  4. Sélectionnez votre compte et autorisez le script. Si un avertissement "Application non validée" s'affiche, cliquez sur Avancé > Accéder au portail Quick Support pour le contourner.
  5. Attendez que le journal d'exécution affiche Exécution terminée, ce qui confirme que le script est désormais entièrement autorisé.

Étape 2 : Testez l'extension et l'application Web

Étant donné que votre appsscript.json définit à la fois un module complémentaire et une application Web, vous pouvez configurer les deux simultanément.

  1. Cliquez sur Déployer > Tester les déploiements en haut à droite d'Apps Script.
  2. En regard de Sélectionner le type, cliquez sur Activer les types de déploiement Activer les types de déploiement, assurez-vous que Modules complémentaires Google Workspace est coché, puis cliquez sur Installer.
  3. Cliquez à nouveau sur Activer les types de déploiement Activer les types de déploiement, assurez-vous que l'option Application Web est cochée, puis copiez l'URL (elle se terminera par /dev). Il s'agit de l'URL de l'application Web Support Quick Portal que vous avez créée.
  4. Cliquez sur OK. Vous devrez peut-être actualiser votre navigateur pour que Workspace Studio enregistre le module complémentaire.

Étape 3 : Configurer le flux Studio

  1. Ouvrez Google Workspace Studio sur studio.workspace.google.com.
  2. Cliquez sur Ajouter un outil Ajouter un outil à gauche, puis sélectionnez Flux.
  3. Pour configurer le déclencheur, cliquez sur Choisir un déclencheur, puis sélectionnez l'extension d'assistance que vous avez installée > Nouvelle demande d'assistance. Si le message "Autorisation requise" s'affiche, cliquez sur Accorder l'autorisation pour permettre au module complémentaire d'accéder à vos données.
  4. Ensuite, sous "Actions", cliquez sur Choisir une étape, faites défiler la page jusqu'à "Extension d'assistance", puis sélectionnez l'étape Détecter l'urgence.
  5. Dans Description de la source, cliquez sur Ajouter Variables, puis sélectionnez Étape 1 : Nouvelle demande d'assistance > Description complète du problème (ticketDescription).
  6. Cliquez à nouveau sur Choisir une étape, puis sélectionnez une étape intégrée comme Gmail > Envoyer un e-mail ou Chat > M'envoyer une notification dans Chat.
    • Si vous avez choisi Gmail :
      • À : saisissez votre adresse e-mail.
      • Objet : La priorité de la demande ticketTitle est urgencyLevel
      • Message  : ticketDescription
    • Si vous avez choisi Chat :
      • Message : La priorité de la demande ticketTitle est urgencyLevel. ticketDescription
  7. Activez le workflow. Si vous êtes invité à renommer votre flux, saisissez un nom tel que Support Ticket Router et enregistrez-le. Cela déclenche le cycle de vie onManageTrigger, ce qui enregistre le notifyUri.

Étape 4 : Exécuter la simulation

  1. Ouvrez l'URL de l'application Web que vous avez copiée à l'étape 2 de cette page dans un nouvel onglet du navigateur (elle se termine par "/dev").
  2. Remplissez le formulaire. Veillez à inclure un mot clé déclencheur (comme "urgent" ou "plantage") dans la description.
  3. Cliquez sur Envoyer. Attendez le message "Demande transmise".
  4. Consultez votre journal d'activité Workspace Studio, votre boîte de réception Gmail ou Google Chat (selon l'action que vous avez choisie). Vous devriez voir un message ou un e-mail marqué comme haute priorité, intégré de manière native à l'aide de vos éléments Apps Script personnalisés.

6. Effectuer un nettoyage

Pour éviter d'encombrer votre espace de travail et votre compte Google Cloud, vous pouvez nettoyer les ressources que vous avez créées lors de cet atelier de programmation.

  1. Supprimez le flux Workspace Studio :
    • Ouvrez studio.workspace.google.com.
    • Trouvez votre flow Support Ticket Router.
    • Cliquez sur le menu à trois points à côté de celui-ci, puis sélectionnez Supprimer.
  2. Supprimez le projet Apps Script :
    • Accédez à script.google.com.
    • Recherchez le projet Support Quick Portal.
    • Cliquez sur le menu à trois points, puis sélectionnez Supprimer.
  3. Arrêtez le projet Google Cloud :
    • Accédez à la console Google Cloud.
    • Assurez-vous que votre nouveau projet est sélectionné dans le menu déroulant en haut de la page.
    • Accédez à IAM et administration > Paramètres, puis cliquez sur Arrêter.

7. Conclusion

Vous avez réussi à créer un écosystème complet pour les extensions personnalisées Google Workspace Studio sans avoir recours à des abonnements tiers externes.

Points abordés :

  • Utiliser workflowTrigger avec onManageFunction pour capturer et gérer correctement les événements de cycle de vie de Google.
  • Authentification des requêtes de backend à l'aide de ScriptApp.getOAuthToken() par rapport aux points de terminaison de l'API workspacestudio.googleapis.com.
  • Utilisation de workflowAction pour traiter les variables d'entrée de manière synchrone et générer des sorties en aval.

Vous pouvez désormais effectuer un scaling horizontal de ces principes pour vous connecter à de véritables plates-formes SaaS comme Jira, Salesforce ou Zendesk en modifiant l'emplacement à partir duquel votre application Web (ou votre webhook entrant) se déclenche.