Active Entities

Introduction

The Active Entities endpoint is designed to be used in conjunction with our synchronous and asynchronous analytics endpoints as it provides information about which campaigns to request analytics for. It does this by returning details about ads entities and when their metrics changed. Using this endpoint will greatly simplify your code and analytics fetching logic.

This guide includes information and context about the endpoint and its data source. It also provides usage guidelines and a series of example requests, demonstrating how to use Active Entities in conjunction with our analytics endpoints. The Summary section provides a high-level description of the recommended approach.

Data

Whenever an ads entity metric changes, we record information about that change. These change events are stored in hourly buckets and include details about the entity as well as the time that the change applies to. The latter is necessary because change events do not always correspond to when they were recorded. Billing adjustments are a common reason for this, but there are others, too.

Endpoint

Request

Active Entities requests are scoped under ads accounts and have three required query parameters: entity, start_time, and end_time.

twurl -H ads-api.twitter.com "/6/stats/accounts/18ce54d4x5t/active_entities?entity=PROMOTED_TWEET&start_time=2019-03-05T00:00:00Z&end_time=2019-03-06T00:00:00Z"

The following entity values are supported: CAMPAIGN, FUNDING_INSTRUMENT, LINE_ITEM, MEDIA_CREATIVE, PROMOTED_ACCOUNT, and PROMOTED_TWEET. This reflects the entity types that our analytics endpoints support.

The start_time and end_time values must be expressed in ISO 8601 and specify which hourly buckets to query. These must be expressed in whole hours.

This endpoint also supports three optional parameters that can be used to filter results: funding_instrument_ids, campaign_ids, and line_item_ids. These work at all levels of the ads hierarchy and with any specified entity type.

Response

The Active Entities response for the request above is shown below.

{
  "request": {
    "params": {
      "account_id": "18ce54d4x5t",
      "entity": "PROMOTED_TWEET",
      "start_time": "2019-03-05T00:00:00Z",
      "end_time": "2019-03-06T00:00:00Z"
    }
  },
  "data": [
    {
      "entity_id": "2r0wxw",
      "activity_start_time": "2019-03-04T20:55:20Z",
      "activity_end_time": "2019-03-05T03:43:56Z",
      "placements": [
        "ALL_ON_TWITTER"
      ]
    },
    {
      "entity_id": "2r30fn",
      "activity_start_time": "2019-03-05T08:11:08Z",
      "activity_end_time": "2019-03-05T14:40:59Z",
      "placements": [
        "ALL_ON_TWITTER",
        "PUBLISHER_NETWORK"
      ]
    }
  ]
}

The data array includes an object for every entity that should be included in a subsequent analytics request. You should not request analytics for IDs outside of this set.

Each object includes four fields: entity_id, activity_start_time, activity_end_time, and placements. The activity start and end times represent the time range that the associated entity's change events apply to and, thus, determine the dates that should be specified in subsequent analytics requests. The placements array can include either or both of the following values: ALL_ON_TWITTER, PUBLISHER_NETWORK. It indicates which placements should be requested for the given entity ID.

Usage

The Active Entities endpoint should dictate how analytics requests are made. The following usage guidelines are written to support analytics synchronization, enabling partners to keep their data stores in sync with Twitter. In other words, it describes how to perform regularly-scheduled background syncs.

There are two decisions a developer must make.

  1. How often to request active entities information and, thus, how often to pull analytics.
  2. How to use the activity start and end times to determine the analytics request's start_time and end_time values.

These are discussed in greater detail in each of the two subsections, below, after the summary.

Summary

Use the Active Entities endpoint in the following way to dictate how analytics requests are made. Follow this after you've decided how often to request active entities information and, thus, how often to pull analytics.

  1. Make the Active Entities request.
  2. Split the response by placement. One group for ALL_ON_TWITTER and one for PUBLISHER_NETWORK.
  3. For each placement group, do the following.
    1. Extract the entity IDs.
    2. Determine the analytics start_time and end_time values.
      • Find the minimum activity_start_time. Round this value down.
      • Find the maximum activity_end_time. Round this value up.
    3. Make the analytics request(s).
      • Group entity IDs into batches of 20.
      • Use the start_time and end_time values from #3b.
      • Specify the appropriate placement value.
    4. Write to your data store.

Please see active_entities.py as an example that uses the Python SDK.

Frequency

The answer to the first question determines the time range that should be used in Active Entities requests. For example, if requesting active entities information every hour, the time range should be an hour. If requesting active entities information once a day, the time range should be a day. In other words, time ranges should be selected such that the current request's start_time is equal to the previous request's end_time.

Note: A time window should only be requested once. Requesting a time window more than once will lead to unnecessary analytics requests. (Exception below.)

For partners wishing to request analytics multiple times an hour for the current hour, a slightly different pattern applies. For each of the 15 minute segments in a given hour, each request will use the same start_time and end_time value. The table below shows example Active Entities start and end timestamps for this scenario.

Request time start_time timestamp end_time timestamp
00:15:00 00:00:00 01:00:00
00:30:00 00:00:00 01:00:00
00:45:00 00:00:00 01:00:00
01:00:00 00:00:00 01:00:00

Given the way that change events are stored, all four Active Entities requests above query the same hourly bucket, which is necessary for this use case. However, after the current hour, this hourly bucket should no longer be queried.

Activity Times

We recommend the following approach to working with activity start and end times. Across all objects in the Active Entities response, find the minimum activity_start_time and the maximum activity_end_time. Modify these values by rounding the minimum activity start time down and rounding the maximum activity end time up. Specifically, set the timestamps to zero for both and add one day to the end time, as illustrated in the following table. These are the start and end times that should be specified in subsequent analytics requests.

Min, max activity times Derived times
2019-03-04T20:55:20Z

2019-03-05T14:40:59Z
2019-03-04T00:00:00Z

2019-03-06T00:00:00Z

Note: It's important to include the timestamps with hours, minutes, and seconds set to zero. Otherwise, if only the date is passed in, we will assume you're requesting analytics starting and ending at midnight in the ads account's timezone, which may not be desirable. For example, if the minimum activity start time is 2019-02-28T01:30:07Z and the timestamp is omitted for an ads account with an offset of -08:00:00, the analytics request will miss changes that happened between 01:30 and 08:00.

Alternatively, if you would prefer to request analytics for just the returned activity time window without expanding to full days, you can. Using this approach, the derived start and end times would be 2019-03-04T20:00:00Z and 2019-03-05T15:00:00Z, respectively. (Note that ranges like these are not accepted if you specify DAY granularity in the analytics request.)

Example

This section demonstrates how to use Active Entities in conjunction with the synchronous analytics endpoint. (The responses have been slightly modified for readability.) In this example, the Active Entities endpoint is called at the top of each hour, with each request looking at the previous hour. The response determines how the synchronous analytics endpoint is used.

The first Active Entities request is made at 03:00:00. The response indicates that line item dvcz7's metrics changed and that those change events apply to the window between 02:02:55 and 02:28:12.

twurl -H ads-api.twitter.com "/6/stats/accounts/18ce54d4x5t/active_entities?entity=LINE_ITEM&start_time=2019-02-11T02:00:00Z&end_time=2019-02-11T03:00:00Z"

{
  "request": {},
  "data": [
    {
      "entity_id": "dvcz7",
      "activity_start_time": "2019-02-11T02:02:55Z",
      "activity_end_time": "2019-02-11T02:58:12Z",
      "placements": [
        "ALL_ON_TWITTER"
      ]
    }
  ]
}

Based on these activity start and end times and using the approach described above, the analytics start_time and end_time values are set to 2019-02-11T00:00:00Z and 2019-02-12T00:00:00Z, respectively. We see that the third element in each of the metrics arrays below are non-zero, as we expected based on the active entities information.

twurl -H ads-api.twitter.com "/6/stats/accounts/18ce54d4x5t?entity=LINE_ITEM&entity_ids=dvcz7&start_time=2019-02-11T00:00:00Z&end_time=2019-02-12T00:00:00Z&granularity=HOUR&metric_groups=ENGAGEMENT,VIDEO&placement=ALL_ON_TWITTER"

{
  "data_type": "stats",
  "time_series_length": 24,
  "data": [
    {
      "id": "dvcz7",
      "id_data": [
        {
          "segment": null,
          "metrics": {
            "impressions": [
              0,0,2792,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ],
            "engagements": [
              0,0,60,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ],
            "video_mrc_views": [
              0,0,1326,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ]
          }
        }
      ]
    }
  ],
  "request": {}
}

The next Active Entities request happens at 04:00:00 and only looks at the previous hour. As mentioned above, a time window should only be requested once. Based on the response, we see that change events for this line item apply to both 02:00:00 and 03:00:00. In the subsequent analytics request, we expect to see changes for both hours.

twurl -H ads-api.twitter.com "/6/stats/accounts/18ce54d4x5t/active_entities?entity= LINE_ITEM&start_time=2019-02-11T03:00:00Z&end_time=2019-02-11T04:00:00Z"

{
  "request": {},
  "data": [
    {
      "entity_id": "dvcz7",
      "activity_start_time": "2019-02-11T02:07:17Z",
      "activity_end_time": "2019-02-11T03:49:22Z",
      "placements": [
        "ALL_ON_TWITTER"
      ]
    }
  ]
}

In addition to seeing non-zero metrics for 03:00:00, we see that the impressions, spend, and MRC video views have been updated from their previous values. Impressions, for example, are now 2,995 for the 02:00:00 hour, up from 2,792. This demonstrates how change events that were recorded during the 03:00:00 hour apply to the 02:00:00 hour.

twurl -H ads-api.twitter.com "/6/stats/accounts/18ce54d4x5t?entity=LINE_ITEM&entity_ids=dvcz7&start_time=2019-02-11T00:00:00Z&end_time=2019-02-12T00:00:00Z&granularity=HOUR&metric_groups=ENGAGEMENT,VIDEO&placement=ALL_ON_TWITTER"

{
  "data_type": "stats",
  "time_series_length": 24,
  "data": [
    {
      "id": "dvcz7",
      "id_data": [
        {
          "segment": null,
          "metrics": {
            "impressions": [
              0,0,2995,734,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ],
            "engagements": [
              0,0,65,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ],
            "video_mrc_views": [
              0,0,1449,342,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ]
          }
        }
      ]
    }
  ],
  "request": {}
}

The Active Entities request at 05:00:00, again looking at just the previous hour, shows that change events apply to the 03:00:00 hour only. The changes to analytics metrics in the subsequent request reflect this.

twurl -H ads-api.twitter.com "/6/stats/accounts/18ce54d4x5t/active_entities?entity=LINE_ITEM&start_time=2019-02-11T04:00:00Z&end_time=2019-02-11T05:00:00Z"

 

{
  "request": {},
  "data": [
    {
      "entity_id": "dvcz7",
      "activity_start_time": "2019-02-11T03:42:39Z",
      "activity_end_time": "2019-02-11T03:48:48Z",
      "placements": [
        "ALL_ON_TWITTER"
      ]
    }
  ]
}

The analytics response shows that only metrics for the 03:00:00 hour have changed; the values for the 02:00:00 hour are the same as they were during the previous analytics request.

twurl -H ads-api.twitter.com "/6/stats/accounts/18ce54d4x5t?entity=LINE_ITEM&entity_ids= dvcz7&start_time=2019-02-11T00:00:00Z&end_time=2019-02-12T00:00:00Z&granularity=HOUR&metric_groups=ENGAGEMENT,VIDEO&placement=ALL_ON_TWITTER"

{
  "data_type": "stats",
  "time_series_length": 24,
  "data": [
    {
      "id": "dvcz7",
      "id_data": [
        {
          "segment": null,
          "metrics": {
            "impressions": [
              0,0,2995,753,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ],
            "engagements": [
              0,0,65,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ],
            "video_mrc_views": [
              0,0,1449,351,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
            ]
          }
        }
      ]
    }
  ],
  "request": {}
}

Finally, at 06:00:00 we see that there are no additional change events. Note: This does not imply that metrics for this line item cannot change in the future, though.

twurl -H ads-api.twitter.com "/6/stats/accounts/18ce54d4x5t/active_entities?entity=LINE_ITEM&start_time=2019-02-11T05:00:00Z&end_time=2019-02-11T06:00:00Z"

{
  "request": {},
  "data": []
}