许多 Google Ads 应用的核心功能是检索账号数据,以用于数据分析、客户查询和政策合规性检查等用例。 在提取数据时,您应优化使用方式,以免 Google 服务器过载或面临速率限制。如需了解详情,请参阅有关 速率限制和保持联系电子邮件地址为 最新状态的指南。
了解 Google 的报告资源使用政策
为确保服务器的稳定性,Google Ads API 会限制
GoogleAdsService.Search 和
GoogleAdsService.SearchStream 查询模式,因为它们会消耗过多的
API 资源。如果某个特定查询句式受到限制,其他服务、方法和查询句式将继续正常运行,不受影响。对于受限请求,系统会抛出以下错误:
| 错误代码 |
|---|
QuotaError.EXCESSIVE_SHORT_TERM_QUERY_RESOURCE_CONSUMPTION 或 QuotaError.EXCESSIVE_LONG_TERM_QUERY_RESOURCE_CONSUMPTION,具体取决于高资源使用率的持续时间。 |
如果您遇到这些错误,请等待 5 分钟,然后再重试因 QuotaError.EXCESSIVE_SHORT_TERM_QUERY_RESOURCE_CONSUMPTION 而失败的请求;对于因 QuotaError.EXCESSIVE_LONG_TERM_QUERY_RESOURCE_CONSUMPTION 而失败的请求,请等待 30 分钟。
为了帮助您识别和监控费用较高的报告,我们还会返回各个报告的费用指标。
| 方法 | 费用字段 |
|---|---|
GoogleAdsService.Search |
SearchGoogleAdsResponse.query_resource_consumption |
GoogleAdsService.SearchStream |
SearchGoogleAdsStreamResponse.query_resource_consumption |
这些字段返回的费用指标取决于多种因素,例如
- 账号的大小
- 您在报告中提取的视图和列
- Google Ads API 服务器上的负载。
为了帮助您跟踪费用较高的查询,我们发布了有关服务器上各种查询模式的资源消耗的初始汇总统计信息。我们会定期发布更新后的数据,以帮助您微调查询。
| 时间窗口 | 平均值 (p50) | P70(较高) | P95(很高) |
|---|---|---|---|
| 短期(5 分钟) | 6000 | 30000 | 1800000 |
| 长期(24 小时) | 16000 | 90000 | 8400000 |
例如,假设您运行的查询句式如下,每个报告消耗 600 个单位的资源。
SELECT campaign.id, campaign.name, metrics.cost_micros FROM campaign WHERE
segments.date = "YYYY-MM-DD"
您可以通过修改查询来替换 segments.date 过滤器的不同值,针对多个客户账号运行此查询,以获取多个单独日期的报告。下表显示了您在给定的时间窗口内可以运行的报告数量,以便您的资源使用量符合各种资源使用量范围。
| 时间窗口 | 平均值 | 较高 | 很高 |
|---|---|---|---|
| 短期(5 分钟) | 10 | 50 | 3000 |
| 长期(24 小时) | 26 | 150 | 14000 |
在 5 分钟内运行此查询句式 10 次将被视为平均使用量,而在 5 分钟内运行 3000 个报告将被视为非常高的使用量。
您可以通过多种策略来优化报告的资源消耗。本指南的其余部分将介绍其中一些策略。
缓存数据
您应将从 API 服务器提取的实体详细信息缓存在本地数据库中,而不是每次需要数据时都调用服务器,尤其是对于经常访问或很少更改的实体。尽可能使用更改事件和更改状态来 检测自上次同步结果以来哪些对象发生了更改。
优化报告的运行频率
Google Ads 已发布有关数据新鲜度和数据更新频率的指南。您应使用此指南来确定提取报告的频率。
如果您需要定期更新账号,建议您将此类账号的数量限制为一小部分,例如仅限前 20 个 Google Ads 账号。其余账号可以较低的频率更新,例如每天一次或两次。
优化报告的大小
您的应用应提取大量数据,而不是运行大量小型报告。影响此选择的一个因素是账号 限制。
例如,请考虑以下代码,该代码会提取特定广告组的统计信息并更新统计信息数据库表:
List<long> adGroupIds = FetchAdGroupIdsFromLocalDatabase();
foreach (long adGroupId in adGroupIds)
{
string query = "SELECT ad_group.id, ad_group.name, metrics.clicks, " +
"metrics.cost_micros, metrics.impressions, segments.date FROM " +
"ad_group WHERE segments.date DURING LAST_7_DAYS AND " +
"ad_group.id = ${adGroupId}";
List<GoogleAdsRow> rows = RunGoogleAdsReport(customerId, query);
InsertRowsIntoStatsTable(adGroupId, rows);
}
此代码在小型测试账号上运行良好。不过,Google Ads 每个广告系列最多支持 20,000 个广告组,每个账号最多支持 10,000 个广告系列。因此,如果此代码针对大型 Google Ads 账号运行,可能会导致 Google Ads API 服务器过载,从而导致速率限制和限制。
更好的方法是运行单个报告,并在本地处理该报告。下图展示了使用内存映射的一种方法。
Hashset<long> adGroupIds = FetchAdGroupIdsFromLocalDatabase();
string query = "SELECT ad_group.id, ad_group.name, metrics.clicks, " +
"metrics.cost_micros, metrics.impressions, segments.date FROM " +
"ad_group WHERE segments.date DURING LAST_7_DAYS";
List<GoogleAdsRow> rows = RunGoogleAdsReport(customer_id, query);
var memoryMap = new Dictionary<long, List<GoogleAdsRow>>();
for each (GoogleAdsRow row in rows)
{
var adGroupId = row.AdGroup.Id;
if (adGroupIds.Contains(adGroupId))
{
CheckAndAddRowIntoMemoryMap(row, adGroupId, memoryMap);
}
}
foreach (long adGroupId in memoryMap.Keys())
{
InsertRowsIntoStatsTable(adGroupId, rows);
}
由于运行的报告数量较少,这降低了 Google Ads API 服务器上的负载。
如果您发现报告太大,无法保存在内存中,还可以通过添加如下所示的 LIMIT 子句将查询分解为较小的组:
SELECT
ad_group.id,
ad_group.name,
metrics.clicks,
metrics.cost_micros,
metrics.impressions,
segments.date
FROM ad_group
WHERE segments.date DURING LAST_7_DAYS
AND ad_group.id IN (id1, id2, ...)
LIMIT 100000
标签是另一种对实体进行分组并减少报告查询数量的方法。如需了解详情,请参阅标签指南。
优化提取的内容
运行报告时,您应注意查询中包含的列。请考虑以下示例,该示例计划每小时运行一次:
SELECT
customer.id,
customer.currency_code,
campaign.id,
campaign.name,
ad_group.id,
ad_group.name,
ad_group_criterion.keyword.match_type,
ad_group_criterion.keyword.text,
ad_group_criterion.criterion_id,
ad_group_criterion.quality_info.creative_quality_score,
ad_group_criterion.system_serving_status,
ad_group_criterion.negative,
ad_group_criterion.quality_info.quality_score,
ad_group_criterion.quality_info.search_predicted_ctr,
ad_group_criterion.quality_info.post_click_quality_score,
metrics.historical_landing_page_quality_score,
metrics.search_click_share,
metrics.historical_creative_quality_score,
metrics.clicks,
metrics.impressions
FROM keyword_view
WHERE segments.date DURING LAST_7_DAYS
可能每小时都会更改的列只有 metrics.clicks 和 metrics.impressions。所有其他列的更新频率较低,甚至根本不会更新,因此每小时提取一次效率非常低。您可以将这些
值存储在本地数据库中,并运行更改事件或
更改状态报告,以便每天下载一次或两次更改。
在某些情况下,您可以通过应用适当的过滤器来减少下载的行数。
清理未使用的账号
如果您的应用管理第三方客户账号,那么您在开发应用时需要考虑到客户流失。您应定期清理流程和数据存储区,以移除不再使用您的应用的客户的账号。清理未使用的 Google Ads 账号时,请注意以下指南:
- 撤消客户授予您的应用的管理其账号的授权。
- 停止向客户的 Google Ads 账号发出 API 调用。这尤其适用于离线作业,例如旨在无需用户干预即可运行的 Cron 作业和数据流水线。
- 如果客户撤消了授权,您的应用应妥善处理这种情况,避免向 Google 的 API 服务器发送无效的 API 调用。
- 如果客户已取消其 Google Ads 账号,您应检测 到这种情况,避免向 Google 的 API 服务器发送无效的 API 调用。
- 在适当的时间段后,从本地数据库中删除您从客户的 Google Ads 账号下载的数据。