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

JavaScript实现谷歌广告多格式价格字符串转数字及适配线上异常格式

问题描述

我用Google Web Designer制作Google Ads模板广告时遇到价格处理难题:

  • Feed提供的原始价格格式多样:
    • 1,200.99 USD(货币在末尾)
    • 1.200,99 EUR(西班牙格式,点为千分位、逗号为小数点)
    • AED 1,200.99(货币在开头)
  • 需将价格转为数字计算折扣率,预览环境正常,但上线后价格格式被篡改,变为:
    • $120099
    • €120099
    • 120099AED
  • 当前处理逻辑存在缺陷:
    1. 用replace(/[^\d.]/g, '')清除非数字和小数点
    2. Number()转换为数字
    3. Intl.NumberFormat()重新格式化(仍有问题)

当前完整代码:

const frames = this.querySelectorAll('.frame')
for (var i = 0; i < frames.length; i++) {
  const country = 'UK' //CHANGE COUNTRY HERE, use NA for AU, NL for BE_nl and FR for BE_fr
  const value = frames[i].querySelector('[data-gwd-grp-id="value"]')
  const price = frames[i].querySelector('[data-gwd-grp-id="price"]')
  const salePrice = frames[i].querySelector('[data-gwd-grp-id="sale-price"]')
  const description = frames[i].querySelector('[data-gwd-grp-id="description"]')
  const cta = frames[i].querySelector('[data-gwd-grp-id="cta"]')
  const priceNumber = Number(price.innerHTML.replace(/[^.\d]/g, ''))
  const salePriceNumber = Number(salePrice.innerHTML.replace(/[^.\d]/g, ''))
  const percentage = Math.floor(100 - ((salePriceNumber * 100) / priceNumber))
  const countries = {
    NA: {
      cta: "See Deal",
      value: `${percentage}% OFF`,
      price: `$${priceNumber}`,
      salePrice: `$${salePriceNumber}`
    },
    UK: {
      cta: "See Deal",
      value: `${percentage}% OFF`,
      price: `£${priceNumber}`,
      salePrice: `£${salePriceNumber}`
    },
    IE: {
      cta: "See Deal",
      value: `${percentage}% OFF`,
      price: `${priceNumber} €`,
      salePrice: `${salePriceNumber} €`
    },
    AE: {
      cta: "See Deal",
      value: `${percentage}% OFF`,
      price: `AED${priceNumber}`,
      salePrice: `AED${salePriceNumber}`
    },
    NL: {
      cta: "Zie deal",
      value: `${percentage}% KORTING`,
      price: `${priceNumber} €`,
      salePrice: `${salePriceNumber} €`
    },
    FR: {
      cta: "Voir l'offre",
      value: `${percentage}% Réduction`,
      price: `${priceNumber} €`,
      salePrice: `${salePriceNumber} €`
    },
    DE: {
      cta: "Siehe Deal",
      value: `${percentage}% SPAREN`,
      price: `€${priceNumber}`,
      salePrice: `€${salePriceNumber}`
    },
    IT: {
      cta: "Scopri",
      value: `${percentage}% di sconto`,
      price: `${priceNumber} €`,
      salePrice: `${salePriceNumber} €`
    },
    ES: {
      cta: "Ver oferta",
      value: `${percentage}% dto.`,
      price: `${priceNumber} €`,
      salePrice: `${salePriceNumber} €`
    },
    PL: {
      cta: "Patrz oferta",
      value: `${percentage}% ZNIŻKI`,
      price: `${priceNumber} zł`,
      salePrice: `${salePriceNumber} zł`
    }
  }
  cta.innerHTML = countries[country].cta
  price.innerHTML = countries[country].price
  salePrice.innerHTML = countries[country].salePrice
  if (percentage > 0 && percentage < 100 && price && salePrice) {
    value.innerHTML = countries[country].value
  } else {
    value.style.display = "none"
  }
  if (priceNumber === salePriceNumber) price.style.display = "none"
  if (price < 0.01) price.style.display = "none"
  if (salePriceNumber < 0.01) salePrice.style.display = "none"
  if (description.innerHTML === '') description.style.display = "none"
}
解决方案

1. 编写通用价格解析函数

核心是识别不同地区的千分位/小数点规则,同时兼容谷歌上线后篡改的异常格式:

function parsePriceToNumber(priceStr) {
  // 移除货币符号、空格等非数字/分隔符字符
  const cleaned = priceStr.replace(/[^\d.,]/g, '');
  
  const dotCount = (cleaned.match(/\./g) || []).length;
  const commaCount = (cleaned.match(/,/g) || []).length;
  
  let numStr;
  if (commaCount > 0 && dotCount > 0) {
    // 两种分隔符共存:以最后出现的符号作为小数点
    if (cleaned.lastIndexOf('.') > cleaned.lastIndexOf(',')) {
      numStr = cleaned.replace(/,/g, ''); // 逗号为千分位,保留点为小数点
    } else {
      numStr = cleaned.replace(/\./g, '').replace(',', '.'); // 点为千分位,替换逗号为小数点
    }
  } else if (commaCount > 0) {
    // 仅含逗号:若逗号后为两位则视为小数点,否则为千分位
    const parts = cleaned.split(',');
    numStr = parts[1]?.length === 2 ? cleaned.replace(',', '.') : cleaned.replace(/,/g, '');
  } else if (dotCount > 0) {
    // 仅含点:若点后为两位则视为小数点,否则为千分位
    const parts = cleaned.split('.');
    numStr = parts[1]?.length === 2 ? cleaned : cleaned.replace(/\./g, '');
  } else {
    // 无分隔符(上线后异常格式):默认最后两位为小数位
    numStr = cleaned.length > 2 ? `${cleaned.slice(0, -2)}.${cleaned.slice(-2)}` : cleaned;
  }
  
  return Number(numStr) || 0;
}

2. 替换原价格解析逻辑

把原代码中两行价格转换代码替换为:

const priceNumber = parsePriceToNumber(price.innerHTML);
const salePriceNumber = parsePriceToNumber(salePrice.innerHTML);

3. 修复代码错误

原代码中if (price < 0.01)是DOM元素与数字比较的错误,修改为:

if (priceNumber < 0.01) price.style.display = "none"

4. 优化价格格式化(推荐)

用Intl.NumberFormat根据地区自动格式化价格,避免手动拼接的错误:

  • 更新countries对象,加入locale和货币配置
  • 使用格式化器生成符合地区规范的价格字符串

修改后的countries对象及格式化代码:

const countries = {
  NA: {
    locale: 'en-US',
    currency: 'USD',
    cta: "See Deal",
    value: `${percentage}% OFF`
  },
  UK: {
    locale: 'en-GB',
    currency: 'GBP',
    cta: "See Deal",
    value: `${percentage}% OFF`
  },
  IE: {
    locale: 'en-IE',
    currency: 'EUR',
    cta: "See Deal",
    value: `${percentage}% OFF`
  },
  AE: {
    locale: 'ar-AE',
    currency: 'AED',
    cta: "See Deal",
    value: `${percentage}% OFF`
  },
  NL: {
    locale: 'nl-NL',
    currency: 'EUR',
    cta: "Zie deal",
    value: `${percentage}% KORTING`
  },
  FR: {
    locale: 'fr-FR',
    currency: 'EUR',
    cta: "Voir l'offre",
    value: `${percentage}% Réduction`
  },
  DE: {
    locale: 'de-DE',
    currency: 'EUR',
    cta: "Siehe Deal",
    value: `${percentage}% SPAREN`
  },
  IT: {
    locale: 'it-IT',
    currency: 'EUR',
    cta: "Scopri",
    value: `${percentage}% di sconto`
  },
  ES: {
    locale: 'es-ES',
    currency: 'EUR',
    cta: "Ver oferta",
    value: `${percentage}% dto.`
  },
  PL: {
    locale: 'pl-PL',
    currency: 'PLN',
    cta: "Patrz oferta",
    value: `${percentage}% ZNIŻKI`
  }
};

// 获取当前国家配置并创建格式化器
const countryConfig = countries[country];
const priceFormatter = new Intl.NumberFormat(countryConfig.locale, {
  style: 'currency',
  currency: countryConfig.currency,
  minimumFractionDigits: 2,
  maximumFractionDigits: 2
});

// 替换原手动拼接价格的代码
price.innerHTML = priceFormatter.format(priceNumber);
salePrice.innerHTML = priceFormatter.format(salePriceNumber);

5. 测试边界场景

确保以下情况均可正确解析:

  • 原始格式:1,200.99 USD → 1200.99
  • 西班牙格式:1.200,99 EUR → 1200.99
  • 货币在前:AED 1,200.99 → 1200.99
  • 上线后异常格式:$120099 → 1200.99
  • 整数价格:1200 USD → 1200

内容的提问来源于stack exchange,提问作者Butzke

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 05:25:54