Configurer et recevoir des notifications push

Vous pouvez utiliser les méthodes de la collection Watches pour recevoir des notifications lorsque des données sont modifiées dans les formulaires. Cette page fournit un aperçu conceptuel et des instructions pour configurer et recevoir des notifications push.

Présentation

La fonctionnalité de notifications push de l'API Google Forms permet aux applications de s'abonner aux notifications lorsque des données sont modifiées dans les formulaires. Les notifications sont envoyées à un sujet Cloud Pub/Sub, généralement quelques minutes après la modification.

Pour recevoir des notifications push, vous devez configurer un sujet Cloud Pub/Sub et fournir le nom de ce sujet lorsque vous créez une surveillance pour le type d'événement approprié.

Vous trouverez ci-dessous les définitions des concepts clés utilisés dans cette documentation :

  • Une cible est un emplacement où les notifications sont envoyées. La seule cible acceptée est un sujet Cloud Pub/Sub.
  • Un type d'événement est une catégorie de notifications auxquelles une application tierce peut s'abonner.
  • Une surveillance est une instruction envoyée à l'API Forms pour qu'elle envoie des notifications pour un type d'événement spécifique sur un formulaire donné à une cible.

Une fois que vous avez créé une surveillance pour un type d'événement sur un formulaire spécifique, la cible de cette surveillance (qui est un sujet Cloud Pub/Sub) reçoit des notifications de ces événements sur ce formulaire jusqu'à l'expiration de la surveillance. Votre abonnement dure une semaine, mais vous pouvez le prolonger à tout moment avant son expiration en envoyant une requête à watches.renew().

Votre sujet Cloud Pub/Sub ne reçoit que les notifications concernant les formulaires que vous pouvez consulter avec les identifiants que vous fournissez. Par exemple, si l'utilisateur révoque l'autorisation d'accès à votre application ou perd l'accès en modification à un formulaire suivi, les notifications ne sont plus envoyées.

Types d'événements disponibles

L'API Google Forms propose actuellement deux catégories d'événements :

  • EventType.SCHEMA, qui envoie des notifications concernant les modifications apportées au contenu et aux paramètres d'un formulaire.
  • EventType.RESPONSES, qui envoie une notification lorsque des réponses à un formulaire (nouvelles ou modifiées) sont envoyées.

Réponses aux notifications

Les notifications sont encodées au format JSON et contiennent les éléments suivants :

  • ID du formulaire déclencheur
  • ID de la montre ayant déclenché l'événement
  • Type d'événement qui a déclenché la notification
  • Autres champs définis par Cloud Pub/Sub, tels que messageId et publishTime

Les notifications ne contiennent pas de données détaillées sur les formulaires ou les réponses. Une fois chaque notification reçue, un appel d'API distinct est nécessaire pour récupérer les données actualisées. Pour savoir comment procéder, consultez Utilisation suggérée.

L'extrait de code suivant montre un exemple de notification de modification de schéma :

{
  "attributes": {
    "eventType": "SCHEMA",
    "formId": "18Xgmr4XQb-l0ypfCNGQoHAw2o82foMr8J0HPHdagS6g",
    "watchId": "892515d1-a902-444f-a2fe-42b718fe8159"
  },
  "messageId": "767437830649",
  "publishTime": "2021-03-31T01:34:08.053Z"
}

L'extrait de code suivant montre un exemple de notification pour une nouvelle réponse :

{
  "attributes": {
    "eventType": "RESPONSES",
    "formId": "18Xgmr4XQb-l0ypfCNGQoHAw2o82foMr8J0HPHdagS6g",
    "watchId": "5d7e5690-b1ff-41ce-8afb-b469912efd7d"
  },
  "messageId": "767467004397",
  "publishTime": "2021-03-31T01:43:57.285Z"
}

Configurer un sujet Cloud Pub/Sub

Les notifications sont envoyées aux sujets Cloud Pub/Sub. Depuis Cloud Pub/Sub, vous pouvez recevoir des notifications sur un webhook ou en interrogeant un point de terminaison d'abonnement.

Pour configurer un sujet Cloud Pub/Sub, procédez comme suit :

  1. Remplissez les conditions préalables de Cloud Pub/Sub.
  2. Configurez un client Cloud Pub/Sub.
  3. Consultez les tarifs de Cloud Pub/Sub et activez la facturation pour votre projet dans la console Developer.
  4. Créez un sujet Cloud Pub/Sub de l'une des trois manières suivantes :

  5. Créez un abonnement dans Cloud Pub/Sub pour indiquer à Cloud Pub/Sub comment distribuer vos notifications.

  6. Enfin, avant de créer des abonnements qui ciblent votre sujet, vous devez accorder l'autorisation au compte de service des notifications Forms (forms-notifications@system.gserviceaccount.com) de publier sur votre sujet.

Créer une montre

Une fois que vous disposez d'un sujet sur lequel le compte de service de notifications push de l'API Forms peut publier, vous pouvez créer des notifications à l'aide de la méthode watches.create(). Cette méthode valide que le sujet Cloud Pub/Sub fourni est accessible par le compte de service des notifications push. Elle échoue si le sujet n'est pas accessible (par exemple, s'il n'existe pas ou si vous ne lui avez pas accordé l'autorisation de publier sur ce sujet).

Python

forms/snippets/create_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secret.json", SCOPES)
  creds = tools.run_flow(flow, store)

service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

watch = {
    "watch": {
        "target": {"topic": {"topicName": "<YOUR_TOPIC_PATH>"}},
        "eventType": "RESPONSES",
    }
}

form_id = "<YOUR_FORM_ID>"

# Print JSON response after form watch creation
result = service.forms().watches().create(formId=form_id, body=watch).execute()
print(result)

Node.js

forms/snippets/create_watch.js
import path from 'node:path';
import {authenticate} from '@google-cloud/local-auth';
import {forms} from '@googleapis/forms';

// TODO: Replace with a valid form ID.
const formID = '<YOUR_FORM_ID>';

/**
 * Creates a watch on a form to get notifications for new responses.
 */
async function createWatch() {
  // Authenticate with Google and get an authorized client.
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Forms API client.
  const formsClient = forms({
    version: 'v1',
    auth: authClient,
  });

  // The request body to create a watch.
  const watchRequest = {
    watch: {
      target: {
        topic: {
          // TODO: Replace with a valid Cloud Pub/Sub topic name.
          topicName: 'projects/<YOUR_TOPIC_PATH>',
        },
      },
      // The event type to watch for. 'RESPONSES' is the only supported type.
      eventType: 'RESPONSES',
    },
  };

  // Send the request to create the watch.
  const result = await formsClient.forms.watches.create({
    formId: formID,
    requestBody: watchRequest,
  });

  console.log(result.data);
  return result.data;
}

Supprimer une montre

Python

forms/snippets/delete_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secret.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"
watch_id = "<YOUR_WATCH_ID>"

# Print JSON response after deleting a form watch
result = (
    service.forms().watches().delete(formId=form_id, watchId=watch_id).execute()
)
print(result)

Node.js

forms/snippets/delete_watch.js
import path from 'node:path';
import {authenticate} from '@google-cloud/local-auth';
import {forms} from '@googleapis/forms';

// TODO: Replace with a valid form ID.
const formID = '<YOUR_FORM_ID>';
// TODO: Replace with a valid watch ID.
const watchID = '<YOUR_FORMS_WATCH_ID>';

/**
 * Deletes a watch from a form.
 */
async function deleteWatch() {
  // Authenticate with Google and get an authorized client.
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Forms API client.
  const formsClient = forms({
    version: 'v1',
    auth: authClient,
  });

  // Send the request to delete the watch.
  const result = await formsClient.forms.watches.delete({
    formId: formID,
    watchId: watchID,
  });

  console.log(result.data);
  return result.data;
}

Autorisation

Comme tous les appels à l'API Forms, les appels à watches.create() doivent être autorisés avec un jeton d'autorisation. Le jeton doit inclure un champ d'application qui accorde un accès en lecture aux données sur lesquelles les notifications sont envoyées.

  • Pour les modifications de schéma, cela signifie tout champ d'application qui accorde un accès en lecture à forms à l'aide de forms.get().
  • Pour les réponses, cela signifie tout champ d'application qui accorde un accès en lecture aux réponses du formulaire, par exemple en utilisant forms.responses.list().

Pour que les notifications soient envoyées, l'application doit conserver une autorisation OAuth de l'utilisateur autorisé avec les niveaux d'accès requis. Si l'utilisateur déconnecte l'application, les notifications cessent et la montre peut être suspendue avec une erreur. Pour rétablir les notifications après avoir récupéré l'autorisation, consultez Renouveler une montre.

Lister les montres d'un formulaire

Python

forms/snippets/list_watches.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secrets.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"

# Print JSON list of form watches
result = service.forms().watches().list(formId=form_id).execute()
print(result)

Node.js

forms/snippets/list_watches.js
import path from 'node:path';
import {authenticate} from '@google-cloud/local-auth';
import {forms} from '@googleapis/forms';

// TODO: Replace with a valid form ID.
const formID = '<YOUR_FORM_ID>';

/**
 * Lists the watches for a given form.
 */
async function listWatches() {
  // Authenticate with Google and get an authorized client.
  const auth = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/forms.responses.readonly',
  });

  // Create a new Forms API client.
  const formsClient = forms({
    version: 'v1',
    auth,
  });

  // Get the list of watches for the form.
  const result = await formsClient.forms.watches.list({
    formId: formID,
  });

  console.log(result.data);
  return result.data;
}

Renouveler une montre

Python

forms/snippets/renew_watch.py
from apiclient import discovery
from httplib2 import Http
from oauth2client import client, file, tools

SCOPES = "https://www.googleapis.com/auth/drive"
DISCOVERY_DOC = "https://forms.googleapis.com/$discovery/rest?version=v1"

store = file.Storage("token.json")
creds = None
if not creds or creds.invalid:
  flow = client.flow_from_clientsecrets("client_secrets.json", SCOPES)
  creds = tools.run_flow(flow, store)
service = discovery.build(
    "forms",
    "v1",
    http=creds.authorize(Http()),
    discoveryServiceUrl=DISCOVERY_DOC,
    static_discovery=False,
)

form_id = "<YOUR_FORM_ID>"
watch_id = "<YOUR_WATCH_ID>"

# Print JSON response after renewing a form watch
result = (
    service.forms().watches().renew(formId=form_id, watchId=watch_id).execute()
)
print(result)

Node.js

forms/snippets/renew_watch.js
import path from 'node:path';
import {authenticate} from '@google-cloud/local-auth';
import {forms} from '@googleapis/forms';

// TODO: Replace with a valid form ID.
const formID = '<YOUR_FORM_ID>';
// TODO: Replace with a valid watch ID.
const watchID = '<YOUR_FORMS_WATCH_ID>';

/**
 * Renews a watch on a form.
 */
async function renewWatch() {
  // Authenticate with Google and get an authorized client.
  const authClient = await authenticate({
    keyfilePath: path.join(__dirname, 'credentials.json'),
    scopes: 'https://www.googleapis.com/auth/drive',
  });

  // Create a new Forms API client.
  const formsClient = forms({
    version: 'v1',
    auth: authClient,
  });

  // Send the request to renew the watch.
  const result = await formsClient.forms.watches.renew({
    formId: formID,
    watchId: watchID,
  });

  console.log(result.data);
  return result.data;
}

Limitations

Les notifications sont limitées : chaque montre peut recevoir au maximum une notification toutes les 30 secondes. Ce seuil de fréquence est susceptible d'être modifié.

En raison de la limitation du nombre de notifications, une seule notification peut correspondre à plusieurs événements. En d'autres termes, une notification indique qu'un ou plusieurs événements se sont produits depuis la dernière notification.

Limites

À tout moment, pour un formulaire et un type d'événement donnés, chaque projet de la console Cloud peut avoir :

  • Jusqu'à 20 visionnages au total
  • Jusqu'à une montre par utilisateur final

De plus, chaque formulaire est limité à 50 surveillances par type d'événement au total pour tous les projets Cloud Console.

Une montre est associée à un utilisateur final lorsqu'elle est créée ou renouvelée avec les identifiants de cet utilisateur. Une montre est suspendue si l'utilisateur final associé perd l'accès au formulaire ou révoque l'accès de l'application au formulaire.

Fiabilité

Chaque montre reçoit au moins une notification après chaque événement, sauf dans des circonstances exceptionnelles. Dans la grande majorité des cas, une notification est envoyée quelques minutes après un événement.

Erreurs

Si les notifications d'une montre ne sont pas distribuées de manière persistante, l'état de la montre devient SUSPENDED et le champ errorType de la montre est défini. Pour réinitialiser l'état d'une montre suspendue sur ACTIVE et réactiver les notifications, consultez Renouveler une montre.

Utilisation suggérée

  • Utilisez un seul sujet Cloud Pub/Sub comme cible de plusieurs observations.
  • Lorsque vous recevez une notification sur un sujet, l'ID du formulaire est inclus dans la charge utile de la notification. Utilisez-le avec le type d'événement pour savoir quelles données extraire et de quel formulaire.
  • Pour récupérer les données mises à jour après une notification avec EventType.RESPONSES, appelez forms.responses.list().
    • Définissez le filtre de la requête sur timestamp > timestamp_of_the_last_response_you_fetched.
  • Pour récupérer les données mises à jour après une notification avec EventType.SCHEMA, appelez forms.get().