Crea passaggi iniziali e azioni personalizzati di Workspace Studio

1. Introduzione

In questo codelab, creerai un Support Quick Portal interattivo che interagisce direttamente con Google Workspace Studio. Imparerai a creare un passaggio iniziale personalizzato e un passaggio di azione personalizzato che possono essere testati immediatamente senza fare affidamento su infrastrutture di terze parti.

Utilizzeremo Google Apps Script per creare:

  • Un'app web con un modulo semplice per consentire agli utenti di inviare manualmente le richieste di assistenza.
  • Un comando iniziale personalizzato che acquisisce gli invii dell'app web e attiva un flusso di Workspace Studio.
  • Un passaggio personalizzato che analizza la descrizione del ticket in entrata per identificare i livelli di urgenza ("Elevata" o "Normale").

Obiettivi didattici

  • Come configurare gli starter e i passaggi nel manifest appsscript.json.
  • Come costruire il notifyUri durante il ciclo di vita della registrazione iniziale.
  • Come attivare in modo programmatico un flusso di Workspace Studio da codice esterno utilizzando UrlFetchApp.
  • Come creare variabili di output nei passaggi personalizzati per trasferire i dati a valle.

Prerequisiti

  • Un account Google Workspace con Google Workspace Studio attivato.
  • L'impostazione Consenti passaggi personalizzati non pubblicati (test) abilitata nella Console di amministrazione del tuo dominio (in App > Google Workspace > Workspace Studio > Impostazioni passaggi personalizzati).
  • Familiarità con Google Apps Script.

2. Configura il progetto Apps Script

Innanzitutto, creiamo un nuovo progetto Apps Script per ospitare il nostro codice:

  1. Vai a script.google.com e fai clic su Nuovo progetto.
  2. Assegna al progetto il nome Support Quick Portal.
  3. Fai clic su Impostazioni progetto Impostazioni progetto nella barra laterale a sinistra.
  4. Seleziona la casella per Mostrare il file manifest appsscript.json nell'editor.
  5. Torna alla visualizzazione Editor Editor.

Per impostazione predefinita, i progetti Apps Script sono associati a un progetto Google Cloud predefinito nascosto. Per chiamare l'API Google Workspace Studio ed evitare errori PERMISSION_DENIED, devi passare lo script a un progetto Cloud standard, abilitare l'API e configurare correttamente la piattaforma Google Auth.

  1. Seleziona o crea un progetto:vai alla console Google Cloud e utilizza il menu a discesa del progetto nella parte superiore della pagina per scegliere un progetto esistente o crearne uno nuovo.
  2. Abilita l'API:una volta che il progetto scelto è attivo nella barra in alto, apri il flusso di abilitazione dell'API e fai clic su Avanti e Abilita per l'API Workspace Studio.
  3. Configura il branding OAuth:apri la pagina Branding della piattaforma Google Auth.
    1. Se richiesto, fai clic su Inizia. Se è già configurato, vai al passaggio 4.
    2. In Informazioni sull'app, inserisci un nome dell'app e un'email di assistenza utenti. Fai clic su Avanti.
    3. In Pubblico, seleziona Interno (o Esterno se Interno non è disponibile) e fai clic su Avanti.
    4. Fornisci i dati di contatto, accetta le Norme relative ai dati e fai clic su Crea.
  4. Configura l'accesso ai dati:apri la pagina Accesso ai dati e fai clic su Aggiungi o rimuovi ambiti.
    1. Nella sezione Aggiungi ambiti manualmente, incolla https://www.googleapis.com/auth/workspace.studio.trigger.
    2. Fai clic su Aggiungi alla tabella, poi su Aggiorna e infine su Salva in fondo alla pagina.
  5. Vai a IAM e amministrazione > Impostazioni (o alla dashboard della console Cloud) e copia il numero di progetto.
  6. Torna al progetto Apps Script e fai clic su Impostazioni progetto Impostazioni progetto nella barra laterale sinistra.
  7. Nella sezione Progetto Google Cloud (GCP), fai clic su Cambia progetto.
  8. Inserisci il numero di progetto Google Cloud che hai copiato e fai clic su Imposta progetto.

Configurare il manifest

Apri il file appsscript.json appena visibile. Sostituisci i contenuti con il codice che segue. Questo manifest elenca esplicitamente gli ambiti OAuth richiesti e definisce il nostro starter come workflowTrigger e la nostra azione come workflowAction nel blocco 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. Crea l'UI dell'app web

Per fornire un modo visivo e testabile per attivare il nostro starter senza utilizzare strumenti terminali o webhook di terze parti, creeremo un'app web Apps Script.

Nell'editor di script di Apps Script, fai clic su Aggiungi un file Aggiungi un file accanto a File e seleziona HTML. Assegna il nome index.html (l'estensione .html viene aggiunta automaticamente).

Incolla il seguente codice dell'interfaccia utente semplificata:

<!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. Crea gli script di backend

Ora colleghiamo tutto. Per mantenere il codice leggibile, separeremo la logica dell'app web, di Starter e del passaggio dell'azione in tre diversi file di script.

WebApp.gs

Rinomina il file Code.gs predefinito nell'editor in WebApp.gs, elimina il boilerplate myFunction e copia e incolla il blocco seguente. Questo file gestisce l'hosting dell'app 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

Poi, passa il mouse sopra File, fai clic su Aggiungi un file Aggiungi un file, seleziona Script e assegnagli il nome Starter.gs. Copia e incolla il blocco riportato di seguito. Questo file gestisce la configurazione dello starter e la gestione del ciclo di vita di 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

Poi, passa il mouse sopra File, fai clic su Aggiungi un file Aggiungi un file, seleziona Script e assegnagli il nome Action.gs. Copia e incolla la logica del passaggio Urgenza riportata di seguito:

/** --- 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. Deployment e test

Ora che abbiamo scritto il codice, eseguiamo il deployment del progetto e configuriamolo.

Passaggio 1: autorizza nuovamente lo script

Poiché hai collegato un nuovo progetto Google Cloud standard, devi autorizzare esplicitamente gli ambiti dello script (come script.external_request utilizzato da UrlFetchApp) rispetto al nuovo progetto.

  1. Nell'editor Apps Script, seleziona WebApp.gs in File, poi seleziona la funzione doGet dal menu a discesa della barra degli strumenti in alto.
  2. Fai clic su Esegui.
  3. Verrà visualizzato il messaggio "Autorizzazione richiesta". Fai clic su Rivedi autorizzazioni.
  4. Scegli il tuo account e autorizza lo script. Se visualizzi l'avviso "App non verificata", fai clic su Avanzate -> Vai a Support Quick Portal per ignorarlo.
  5. Attendi che nel log di esecuzione venga visualizzato il messaggio Esecuzione completata, che conferma che lo script è ora completamente autorizzato.

Passaggio 2: testa l'estensione e l'app web

Poiché il tuo appsscript.json definisce sia un componente aggiuntivo sia un'app web, puoi configurarli entrambi contemporaneamente.

  1. Fai clic su Implementa > Test di implementazione nell'angolo in alto a destra di Apps Script.
  2. Accanto a Seleziona tipo, fai clic su Abilita i tipi di deployment Attiva tipi di deployment e assicurati che Componenti aggiuntivi di Google Workspace sia selezionato, poi fai clic su Installa.
  3. Fai di nuovo clic su Abilita i tipi di deployment Attiva tipi di deployment, assicurati che la casella App web sia selezionata e copia l'URL (terminerà con /dev). Questo è l'URL dell'app web Support Quick Portal che hai creato.
  4. Fai clic su Fine. Potrebbe essere necessario aggiornare il browser prima che Workspace Studio registri il componente aggiuntivo.

Passaggio 3: configura il flusso di Studio

  1. Apri Google Workspace Studio all'indirizzo studio.workspace.google.com.
  2. Fai clic su Aggiungi strumento Aggiungi strumento a sinistra e seleziona Flusso.
  3. Per configurare il comando iniziale, fai clic su Scegli un comando iniziale, quindi seleziona l'estensione di assistenza installata > Nuova richiesta di assistenza. Se viene visualizzato il messaggio "Autorizzazione richiesta", fai clic su Concedi autorizzazione per consentire al componente aggiuntivo di accedere ai tuoi dati.
  4. Poi, in Azioni, fai clic su Scegli un passaggio, scorri fino a "Estensione supporto" e seleziona il passaggio Rileva urgenza.
  5. In Descrizione origine, fai clic su Aggiungi Variabili e seleziona Passaggio 1: nuovo ticket di assistenza > The full description of the issue (ticketDescription).
  6. Fai di nuovo clic su Scegli un passaggio e seleziona un passaggio integrato come Gmail > Invia un'email o Chat > Avvisami in Chat.
    • Se hai scelto Gmail:
      • A: inserisci il tuo indirizzo email.
      • Oggetto: la priorità del ticket ticketTitle è urgencyLevel
      • Messaggio: ticketDescription
    • Se hai scelto la chat:
      • Messaggio: la priorità del ticket ticketTitle è urgencyLevel. ticketDescription
  7. Attiva il workflow. Se ti viene chiesto di rinominare il flusso, inserisci un nome come Support Ticket Router e salva. Questo attiva il ciclo di vita di onManageTrigger, salvando notifyUri.

Passaggio 4: esegui la simulazione

  1. Apri l'URL dell'app web che hai copiato in precedenza nel passaggio 2 di questa pagina in una nuova scheda del browser (termina con /dev).
  2. Compila il modulo. Assicurati di includere una parola chiave di attivazione (ad esempio "urgente" o "arresto anomalo") nella descrizione.
  3. Fai clic su Invia. Attendi il messaggio "Ticket inviato correttamente".
  4. Controlla il log attività di Workspace Studio, la posta in arrivo di Gmail o Google Chat (a seconda dell'azione scelta). Dovresti visualizzare un messaggio o un'email contrassegnati come "Priorità alta" integrati in modo nativo utilizzando gli elementi Apps Script personalizzati.

6. Elimina

Per evitare di sovraccaricare il tuo spazio di lavoro e l'account Google Cloud, puoi liberare spazio dalle risorse che hai creato durante questo codelab.

  1. Elimina il flusso di Workspace Studio:
    • Apri studio.workspace.google.com.
    • Trova il tuo ritmo di Support Ticket Router.
    • Fai clic sul menu con tre puntini accanto e seleziona Elimina.
  2. Elimina il progetto Apps Script:
    • Vai alla pagina script.google.com.
    • Trova il progetto Support Quick Portal.
    • Fai clic sul menu con tre puntini e seleziona Rimuovi.
  3. Chiudi il progetto Google Cloud:
    • Vai alla console Google Cloud.
    • Assicurati che il nuovo progetto sia selezionato nel menu a discesa in alto.
    • Vai a IAM e amministrazione > Impostazioni e fai clic su Chiudi.

7. Conclusione

Hai creato un ecosistema completo per le estensioni personalizzate di Google Workspace Studio senza fare affidamento su abbonamenti di terze parti esterni.

Argomenti trattati:

  • Utilizzo di workflowTrigger insieme a onManageFunction per acquisire e gestire correttamente gli eventi del ciclo di vita di Google.
  • Autenticazione delle richieste di backend utilizzando ScriptApp.getOAuthToken() rispetto agli endpoint API workspacestudio.googleapis.com.
  • Utilizzo di workflowAction per elaborare le variabili di input in modo sincrono e generare output downstream.

Ora puoi fare lo scale out di questi principi per connetterti a piattaforme SaaS reali come Jira, Salesforce o Zendesk modificando la posizione da cui viene attivata l'app web (o il webhook in entrata).