You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GoogleAdsScript中按ID分组后如何对Cost等指标求和

核心问题梳理

原有代码存在两个影响功能的问题:

  1. main函数未调用reportToArray将报表对象转为结构化数组,直接使用未定义的reportArray变量会触发运行时报错
  2. 原有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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 08:46:34