This guide explains how to use webhooks to receive asynchronous notifications
for the status of your audience export requests. This feature is available only
in the [v1alpha version of the Data API](https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha).

[Webhook notifications](https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/properties.audienceLists#AudienceList.FIELDS.webhook_notification)
are an advanced feature of the Google Analytics [Data
API](https://developers.google.com/analytics/devguides/reporting/data/v1/rest). For an introduction to the
audience export feature, see [create an audience export](https://developers.google.com/analytics/devguides/reporting/data/v1/audience-export-basics).

Without webhooks, you'll need to periodically poll the API to
determine when a request is complete.

> [!IMPORTANT]
> **Key Term:** In v1alpha and following guide, audience exports are called "audience lists".

## Create a sample webhook application using Cloud Run

You can create a sample webhook application using Google Cloud by following
the tutorial [Quickstart: Deploy a sample service to Cloud Run](https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-nodejs-service).

In order for the sample service to listen to POST webhook notification requests,
replace the `index.js` file from the quickstart tutorial with the following
code:

      import express from 'express';

      const app = express();
      app.use(express.json());

      app.post('/', (req, res) => {
        const channelToken = req.get('X-Goog-Channel-Token');
        const bodyJson = JSON.stringify(req.body);

        console.log(`channel token: ${channelToken}`);
        console.log(`notification body: ${bodyJson}`);

        res.sendStatus(200);
      });

      const port = parseInt(process.env.PORT) || 8080;
      app.listen(port, () => {
        console.log(`helloworld: listening on port ${port}`);
      });

For every incoming webhook notification sent as a POST request, this code prints
out the webhook notification JSON body and a channel token value, and
returns the HTTP code `200` to indicate successful operation.

Once you've reached the end of the Cloud Run quickstart tutorial and deployed
the webhook application using the `gcloud run deploy` command, save
the URL where your service is deployed.

The service URL is displayed in the console, for example:

      Service URL: https://webhooks-test-abcdef-uc.a.run.app

This is the [server notification URI](https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/properties.audienceLists#FIELDS.uri)
where your application listens to webhook notifications from
Google Analytics.

## Create an audience list and turn on webhook notifications

To request webhook notifications, specify the following values in the [`webhookNotification`](https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/properties.audienceLists#AudienceList.FIELDS.webhook_notification)
object:

- The [server notification URI](https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/properties.audienceLists#FIELDS.uri)
  containing the web address that will receive webhook notifications.

- (Optional) An arbitrary string [`channelToken`](https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/WebhookNotification#FIELDS.channel_token)
  to guard against the message being spoofed. Specify the `channelToken`
  in the `X-Goog-Channel-Token` HTTP header of the
  webhook POST request.

Here's a sample request using webhooks:

### HTTP Request

    POST https://analyticsdata.googleapis.com/v1alpha/properties/1234567/audienceLists
    {
      "webhookNotification": {
        "uri": "https://webhooks-test-abcdef-uc.a.run.app",
        "channelToken": "123456"
      },
      "audience": "properties/1234567/audiences/12345",
      "dimensions": [
        {
          "dimensionName": "deviceId"
        }
      ]
    }

The response from the `audienceLists.create` method contains the
`webhookNotification`, which confirms that the specified webhook successfully
responded in under 5 seconds.

Here's a sample response:

### HTTP Response

    {
      "response": {
        "@type": "type.googleapis.com/google.analytics.data.v1alpha.AudienceList",
        "name": "properties/1234567/audienceLists/123",
        "audience": "properties/1234567/audiences/12345",
        "audienceDisplayName": "Purchasers",
        "dimensions": [
          {
            "dimensionName": "deviceId"
          }
        ],
        "state": "ACTIVE",
        "beginCreatingTime": "2024-06-10T04:50:09.119726379Z",
        "creationQuotaTokensCharged": 51,
        "rowCount": 13956,
        "percentageCompleted": 100,
        "webhookNotification": {
          "uri": "https://webhooks-test-abcdef-uc.a.run.app",
          "channelToken": "123456"
        }
      }
    }

If a webhook fails to respond, or if you provide an incorrect service URL,
an error message is returned instead.

Here's an example error you might receive:

    {
      "error": {
        "code": 400,
        "message": "Expected response code of 200 from webhook URI but instead
        '404' was received.",
        "status": "INVALID_ARGUMENT"
      }
    }

## Process webhook notifications

The POST request to a webhook service contains both a JSON version of the
[long running operation resource](https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/properties.audienceLists#resource:-audiencelist)
in the body, and a `sentTimestamp` field. The sent timestamp specifies
the Unix epoch time in microseconds that the request was sent. You can use this
timestamp to identify replayed notifications.

Either one or two POST requests are sent to the webhook during an
audience list creation:

1. The first POST request is sent immediately, showing the newly created audience list in its `CREATING` state. If the first request to the webhook fails, the `audienceLists.create` operation returns an error and the webhook failure details.
2. The second POST request is sent after the audience list completes creation. Creation is complete when the audience list reaches either the `ACTIVE` or `FAILED` state.

Here's an example of the first notification for an audience list, in the
`CREATING` state:

      {
        "sentTimestamp":"1718261355692983",
        "name": "properties/1234567/audienceLists/123",
        "audience": "properties/1234567/audiences/12345",
        "audienceDisplayName":"Purchasers",
        "dimensions":[{"dimensionName":"deviceId"}],
        "state":"CREATING",
        "beginCreatingTime": "2024-06-10T04:50:09.119726379Z",
        "creationQuotaTokensCharged":0,
        "rowCount":0,
        "percentageCompleted":0,
        "webhookNotification":
          {
            "uri": "https://webhooks-test-abcdef-uc.a.run.app",
            "channelToken":"123456"
          }
      }

Here's an example of the second notification for an audience list, in the
`ACTIVE` state:

      {
        "sentTimestamp":"1718261355692983",
        "name": "properties/1234567/audienceLists/123",
        "audience": "properties/1234567/audiences/12345",
        "audienceDisplayName":"Purchasers",
        "dimensions":[{"dimensionName":"deviceId"}],
        "state":"ACTIVE",
        "beginCreatingTime": "2024-06-10T04:50:09.119726379Z",
        "creationQuotaTokensCharged":68,
        "rowCount":13956,
        "percentageCompleted":100,
        "webhookNotification":
          {
            "uri": "https://webhooks-test-abcdef-uc.a.run.app",
            "channelToken":"123456"
          }
      }

The second notification confirms that the audience list has been created and is
ready to be queried using the [`audienceLists.query`](https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/properties.audienceLists/query)
method.

To test webhooks after calling the `audienceLists.create` method, you can
[inspect the logs](https://cloud.google.com/run/docs/logging)
of your sample Cloud Run webhook application, and see the JSON body of every
notification sent by Google Analytics.