JavaScript实现谷歌广告多格式价格字符串转数字及适配线上异常格式
问题描述
我用Google Web Designer制作Google Ads模板广告时遇到价格处理难题:
- Feed提供的原始价格格式多样:
- 1,200.99 USD(货币在末尾)
- 1.200,99 EUR(西班牙格式,点为千分位、逗号为小数点)
- AED 1,200.99(货币在开头)
- 需将价格转为数字计算折扣率,预览环境正常,但上线后价格格式被篡改,变为:
- $120099
- €120099
- 120099AED
- 当前处理逻辑存在缺陷:
- 用
replace(/[^\d.]/g, '')清除非数字和小数点 Number()转换为数字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
相关产品推荐
相关产品推荐

