## Build new reports in the UI first

Reports are subject to a number of restrictions and requirements pertaining to
reporting types, filters, dimensions, and metrics. These limitations are
enforced in the API, returning an `HTTP 400` error. **In order to avoid errors
when building reports, we recommend that you first build new reports in
the Display \& Video 360 UI.**

After building your report, click the
["Try this API" feature](https://developers.google.com/bid-manager/reference/rest/current/queries/get?apix=true) on the reference docs page to
perform a [`queries.get`](https://developers.google.com/bid-manager/reference/rest/current/queries/get) of the `Query` resource. You can use the
returned JSON to build future reports.

> [!WARNING]
> **Warning:** [Queries](https://developers.google.com/bid-manager/reference/rest/current/queries#Query) and their resulting [reports](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#Report) are only accessible in the API by the user that created them. Permission to run queries and retrieve reports using the API cannot be granted through the UI's share settings.

## Use metrics and filters specific to the report type

Some [metric and filter](https://developers.google.com/bid-manager/reference/rest/current/filters-metrics) values are specific to certain
report types. In addition to [building your reports in the UI
first](https://developers.google.com/bid-manager/guides/general/best-practices#build_new_reports_in_the_ui_first), you can also identify the metrics and filters
that belong to certain [`ReportType`](https://developers.google.com/bid-manager/reference/rest/current/Parameters#ReportType) values by their
Bid Manager API value.

Here are some ways to identify relevant Bid Manager API filter and
metric values. This table isn't an exhaustive list of filters and metrics
that can be used in these types of reports. Not all values can be used together
in a single report.

| `ReportType` | Relevant Filters and Metrics |
|---|---|
| `YOUTUBE` | - Filters with prefix `FILTER_TRUEVIEW`. - Metrics with prefix `METRIC_TRUEVIEW`. |
| `GRP` | - Metrics with prefix `METRIC_GRP`. |
| `YOUTUBE_PROGRAMMATIC_GUARANTEED` | - Filters with prefix `FILTER_YOUTUBE_PROGRAMMATIC_GUARANTEED`. - Metrics with prefix `METRIC_PROGRAMMATIC_GUARANTEED`. |
| `REACH` | - Metrics with prefix `METRIC_UNIQUE_REACH`. |
| `UNIQUE_REACH_AUDIENCE` | - Metrics with prefix `METRIC_UNIQUE_REACH`. |

## Save and re-use reports

We recommend that you create and save reports for queries you run regularly
because inserting and deleting the same report multiple times wastes resources.
Using the set [`Range`](https://developers.google.com/bid-manager/reference/rest/current/queries#Range) values, such as
[`PREVIOUS_DAY`](https://developers.google.com/bid-manager/reference/rest/current/queries#Range.ENUM_VALUES.PREVIOUS_DAY) or [`LAST_7_DAYS`](https://developers.google.com/bid-manager/reference/rest/current/queries#Range.ENUM_VALUES.LAST_7_DAYS), in
the [`dataRange`](https://developers.google.com/bid-manager/reference/rest/current/queries#QueryMetadata.FIELDS.data_range) field makes reports more reusable.

## Schedule reports

Ad hoc or one-off reports can be wasteful of resources because they are run
individually and may execute against an incomplete dataset. Scheduled reports
make the best use of reporting resources because they are run in bulk and are
guaranteed not to execute until the previous day's data has completed
processing. See the [available scheduling fields](https://developers.google.com/bid-manager/reference/rest/current/queries#Query.FIELDS.schedule) for details.

## Combine similar reports

If you regularly generate reports with identical metrics and date ranges for
different advertisers or partners, we recommend that you
combine the reports to optimize their report volume.

You can combine similar reports by appending the [filters](https://developers.google.com/bid-manager/reference/rest/current/Parameters#FIELDS.filters) of all
of the reports and adding all filter types as [dimensions](https://developers.google.com/bid-manager/reference/rest/current/Parameters#FIELDS.group_bys).
After generation, you can split the rows of the resulting report along the
original filter values to produce the original reports.

## Consider reporting quotas

Responsible use of the Display \& Video 360 reporting feature is enforced through
the following product-wide usage quotas.

#### Ad hoc report executions per day

Limits the number of ad hoc reports a user can run in a 24-hour period.
To stay under this quota:

- [Combine similar reports](https://developers.google.com/bid-manager/guides/general/best-practices#combine_similar_reports) to reduce report volume.
- [Schedule recurring ad hoc reports](https://developers.google.com/bid-manager/guides/general/best-practices#schedule_reports) to specifically reduce ad hoc report volume.
- Deactivate unnecessary API scripts.

#### Active scheduled reports

Limits the number of reports a user can have actively scheduled at a given
time. To stay under this quota:

- [Combine similar scheduled reports](https://developers.google.com/bid-manager/guides/general/best-practices#combine_similar_reports) to reduce the overall number of scheduled reports.
- Deactivate unnecessary scheduled reports.
- Deactivate unnecessary API scripts.

#### Concurrent reports

Limits the number of reports a user can run simultaneously.
To stay under this quota:

- Schedule reports that run regularly.
- Deactivate unnecessary API scripts.
- Track when your reports are done by polling using [exponential backoff
  logic](https://developers.google.com/bid-manager/guides/general/best-practices#use_exponential_backoff_when_polling_for_report_status).

If you have optimized your reporting implementation and you still find yourself
exceeding your given quota, contact Display \& Video 360 support using the
[contact form](https://support.google.com/displayvideo/contact/nghelp_contact_form).

## Use exponential backoff when polling for report status

It's not possible to predict how long a report will take to run. The length of
time can range from seconds to hours depending on many factors including date
range and the amount of data to be processed, for instance. There's also no
correlation between report run-time and the number of rows returned in the
report. You therefore need to regularly retrieve the report resource using
[`queries.reports.get`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports/get) method and check if the resource's
[`metadata.status.state`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#ReportStatus.FIELDS.state) field has been updated to
[`DONE`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#State.ENUM_VALUES.DONE) or [`FAILED`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#State.ENUM_VALUES.FAILED) to determine
whether it has finished running. This is a process known as "polling".

While polling is necessary, an inefficient implementation may quickly exhaust
your quota when encountering a long running report. Thus we recommend that you
use exponential backoff to limit retries and conserve quota.

### Exponential backoff

Exponential backoff is a standard error handling strategy for network
applications in which the client periodically retries request over an increasing
amount of time. Used properly, exponential backoff increases the efficiency of
bandwidth usage, reduces the number of requests required to get a successful
response, and maximizes the throughput of requests in concurrent environments.

> [!NOTE]
> **Note:** This flow assumes that you have the ID for the report you are polling. If you want to poll the most recently run report for a query, you can call [`queries.reports.list`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports/list) with the [`orderBy`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports/list#body.QUERY_PARAMETERS.order_by) parameter value `key.reportId desc` and use the [`reportId`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#ReportKey.FIELDS.report_id) of the first report in the list.

The flow for implementing simple exponential backoff is as follows:

1. Make a [`queries.reports.get`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports/get) request to the API.
2. Retrieve the report object. If the [`metadata.status.state`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#ReportStatus.FIELDS.state) field is not `DONE` or `FAILED`, that indicates that the report is not finished running should continue polling.
3. Wait 5 seconds + a random number of milliseconds and retry the request.
4. Retrieve the report object. If the [`metadata.status.state`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#ReportStatus.FIELDS.state) field is not `DONE` or `FAILED`, that indicates that the report is not finished running should continue polling.
5. Wait 10 seconds + a random number of milliseconds and retry the request.
6. Retrieve the report object. If the [`metadata.status.state`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#ReportStatus.FIELDS.state) field is not `DONE` or `FAILED`, that indicates that the report is not finished running should continue polling.
7. Wait 20 seconds + a random number of milliseconds and retry the request.
8. Retrieve the report object. If the [`metadata.status.state`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#ReportStatus.FIELDS.state) field is not `DONE` or `FAILED`, that indicates that the report is not finished running should continue polling.
9. Wait 40 seconds + a random number of milliseconds and retry the request.
10. Retrieve the report object. If the [`metadata.status.state`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#ReportStatus.FIELDS.state) field is not `DONE` or `FAILED`, that indicates that the report is not finished running should continue polling.
11. Wait 80 seconds + a random number of milliseconds and retry the request.
12. ***Continue this pattern until the report object is updated or a maximum time
    elapsed is reached.***

If the report finishes running and ends in a `DONE` state, then you can retrieve
the generated report file from Google Cloud Storage at the path given in the
[`metadata.googleCloudStoragePath`](https://developers.google.com/bid-manager/reference/rest/current/queries.reports#ReportMetadata.FIELDS.google_cloud_storage_path) field.