Google Analytics Enhanced Ecommerce checkout payload 过大
结论
analytics.js 不会自动拆分超过 8192 bytes 的 hit。每次调用 ga('send', ...) 时,hit 都必须在这一限制以内。
如果 purchase 包含大量商品,需要将商品分批,通过多个 Enhanced Ecommerce hit 发送:
- 每一批都使用相同的 transaction ID。
- 交易金额、税费、运费等 transaction-level 字段只在第一批发送。
- 后续批次只发送 transaction ID 和本批商品,以免重复累计交易金额。
- 不要根据固定的商品数量估算大小,应检查编码后的请求字节数或实际发出的采集请求。
- 改用 POST、
transport: 'beacon'或 Measurement Protocol,也无法让单个 hit 超过 8192 bytes。
为什么会失败
调用 ga('ec:addProduct', ...) 时,商品不会立即发出,而是暂存在 tracker 的 Enhanced Ecommerce 数据模型中。执行下面的代码后:
ga('send', 'pageview');
商品、purchase action 和 pageview 参数才会合并为一个 hit。
也就是说,100 个商品不会产生 100 个请求,而会组成一个带有 pr1...pr100 等参数的大请求。如果编码后的 payload 超过 8192 bytes,analytics.js 就会拒绝发送。商品名称、SKU、分类、优惠券和 product-scoped custom dimensions 都会占用请求空间。
推荐发送方式
先发送普通 pageview,再通过非互动事件分批发送 purchase 数据。每次 send 完成后,再添加下一批商品和 action:
ga('require', 'ec');
ga('send', 'pageview');
function sendPurchaseInBatches(products, transaction, batchSize = 20) {
const batches = [];
for (let i = 0; i < products.length; i += batchSize) {
batches.push(products.slice(i, i + batchSize));
}
function sendBatch(index) {
if (index >= batches.length) {
return;
}
batches[index].forEach(product => {
ga('ec:addProduct', {
id: product.id,
name: product.name,
category: product.category,
brand: product.brand,
variant: product.variant,
price: product.price,
quantity: product.quantity,
coupon: product.coupon
});
});
if (index === 0) {
// 交易级字段只发送一次。
ga('ec:setAction', 'purchase', {
id: transaction.id,
affiliation: transaction.affiliation,
revenue: transaction.revenue,
tax: transaction.tax,
shipping: transaction.shipping,
coupon: transaction.coupon
});
} else {
// 后续批次仍需标明这些商品属于同一 purchase。
ga('ec:setAction', 'purchase', {
id: transaction.id
});
}
ga('send', 'event', {
eventCategory: 'Ecommerce',
eventAction: index === 0
? 'Purchase'
: 'Purchase Product Batch',
eventLabel: transaction.id,
nonInteraction: true,
transport: 'beacon',
hitCallback: function () {
sendBatch(index + 1);
}
});
}
sendBatch(0);
}
这里的 batchSize = 20 只是示例,并不是对所有情况都安全的数值。商品字段较长时,20 个商品仍可能超出限制;字段较短时,每批可以容纳更多商品。
大小控制
是否需要拆分,应以最终编码后的 hit 大小为准,不能只看商品数量。可以在浏览器的 Network 面板中检查发往以下端点的请求:
https://www.google-analytics.com/collect
需要计算 URL 编码后的查询字符串或 POST body 所占的 UTF-8 字节数。中文、特殊字符和 product-scoped custom dimensions 编码后可能占用多个字节,因此 JavaScript 字符串的 length 无法准确表示请求大小。
生产环境中应留出余量,让每个 hit 明显低于 8192 bytes。tracker 配置、campaign 参数和自定义维度也会写入 payload,占用一部分空间。
还可以删除不影响报表的字段,尤其是内容过长的字段,例如:
namecategoryvariantcoupon- product-scoped custom dimensions
但不要为了缩短请求而截断商品 ID、transaction ID,以及其他用于关联或去重的字段。
注意事项
把同一个 purchase 拆成多个 hit 后,需要在实际使用的 Universal Analytics property 中检查 Transactions、Revenue、Quantity 和 Product Revenue 等指标。如果每个批次都重复发送 revenue、tax、shipping 等字段,交易级金额很容易被重复累计。
所有批次还需要在页面卸载前发出。通过 hitCallback 串行发送,可以减少一次性排队带来的风险,但回调无法保证请求一定送达。如果结账完成后页面会立即跳转,可以推迟跳转,也可以让服务端通过 Measurement Protocol 分批发送。服务端发送仍须保证每个 hit 不超过 8192 bytes,并为各批次保留相同的 transaction ID 和 client ID。
如果系统已经迁移到 GA4,不要直接套用这套 analytics.js 写法。GA4 使用不同的事件模型、参数名称和限制,需要改用 GA4 的 purchase 事件方案。
备注:内容仅供参考。
