GoogleAdsScript中按ID分组后如何对Cost等指标求和
Google Ads Script 同ID跨系列指标聚合方案
核心问题梳理
原有代码存在两个影响功能的问题:
main函数未调用reportToArray将报表对象转为结构化数组,直接使用未定义的reportArray变量会触发运行时报错- 原有
groupBy函数仅实现同ID记录归组,未做数值字段累加,且Cost字段经formatMicros处理后为字符串类型,直接累加会出现字符串拼接错误
不需要先归组再二次遍历求和,可以直接在分组阶段完成数值聚合,执行效率更高。
修改后可直接运行的代码
function main() { var report = generateReport(); // 修复:先将报表转为结构化数组 var reportArray = reportToArray(report); // 调用带聚合计算的分组函数 var aggregatedResult = aggregateMetricsById(reportArray, "Id"); Logger.log(aggregatedResult); } function generateReport() { var report; var accountSelector = MccApp.accounts() .withIds(['123-456-7890']); var accountIterator = accountSelector.get(); while (accountIterator.hasNext()) { var account = accountIterator.next(); MccApp.select(account); report = AdsApp.report('SELECT segments.product_item_id, metrics.cost_micros, metrics.conversions_value, campaign.name, metrics.conversions, segments.product_custom_attribute4, segments.product_custom_attribute3, segments.product_custom_attribute2, segments.product_custom_attribute1 FROM shopping_performance_view WHERE campaign.name REGEXP_MATCH ".*_PPF_.*" AND campaign.name NOT REGEXP_MATCH ".*_PPF_Y.*" AND metrics.cost_micros > 50000000 AND segments.date DURING LAST_30_DAYS ORDER BY segments.product_item_id ASC'); } return report; } function formatMicros(value) { const micros = parseFloat(value / 1000000).toFixed(2); return Number(micros); // 直接返回数值类型,避免后续累加需要额外转类型 } /** * 按指定key分组并累加Cost、ConversionValue、Conversions三个指标 * @param {Array} xs 报表行数组 * @param {String} key 分组字段名(此处为Id) * @returns {Object} 聚合后的结果对象 */ function aggregateMetricsById(xs, key) { return xs.reduce(function(resultMap, currentRow) { const currentKey = currentRow[key]; // 如果当前ID第一次出现,初始化聚合记录 if (!resultMap[currentKey]) { resultMap[currentKey] = { Id: currentKey, // 存所有关联的推广系列名,自动去重,方便溯源 Kampagne: [currentRow.Kampagne], Cost: 0, // 注意:原有代码字段拼写为Converisons(少写一个s),此处保持和原代码一致避免报错 Converisons: 0, ConversionValue: 0 }; } else { // 已存在的ID,追加未收录的推广系列名 if (!resultMap[currentKey].Kampagne.includes(currentRow.Kampagne)) { resultMap[currentKey].Kampagne.push(currentRow.Kampagne); } } // 累加三个数值字段,统一转Number避免类型错误 resultMap[currentKey].Cost += Number(currentRow.Cost); resultMap[currentKey].Converisons += Number(currentRow.Converisons); resultMap[currentKey].ConversionValue += Number(currentRow.ConversionValue); return resultMap; }, {}); } function reportToArray (report){ var array = []; var rows = report.rows(); while (rows.hasNext()) { var row = rows.next(); var campaignName = row["campaign.name"]; var offerId = row["segments.product_item_id"]; var conversionValue = row["metrics.conversions_value"]; var cost = formatMicros(row["metrics.cost_micros"]); var conversions = row["metrics.conversions"]; var rowObject = { Kampagne: campaignName, Id: offerId, ConversionValue: Number(conversionValue), Cost: Number(cost), Converisons: Number(conversions) }; array.push(rowObject); } return array; }
关键改动说明
- 优化
formatMicros返回值:原来返回字符串类型,现在直接返回数值类型,减少累加时的类型转换步骤 - 替换原有纯分组逻辑为
aggregateMetricsById:遍历行数据时直接按ID聚合,同ID的推广系列名自动去重存为数组,三个指标直接累加 - 全链路数值类型校验:所有指标字段在生成行对象时就转为Number类型,从根源避免字符串拼接的计算错误
- 聚合结果示例:对于你给出的ID=45678的跨两条记录的场景,最终聚合结果为:
{ 45678: { Id: 45678, Kampagne: ["samplecampaignName1", "samplecampaignName2"], Cost: 143.07, Converisons: 4.0, ConversionValue: 2091.72 } }
如果需要对累加后的数值保留固定小数位,可以在累加完成后统一用toFixed(2)处理即可;如果不需要保留关联的推广系列名,直接删掉Kampagne相关的处理逻辑就行。
内容的提问来源于stack exchange,提问作者Jan-Besserwisser
相关产品推荐
相关产品推荐

