商品上架时间实测:43912件里老货没掉队,漏的是新货

商品上架时间实测:43912件里老货没掉队,漏的是新货
张文保 更新 23 分钟阅读 2,127 阅读
本文目录
  1. 想知道一件货在店里放了多久,该看哪个字段?
  2. 三个日期,名字都很像
  3. 先看看它们各自的年份分布
  4. 隔十小时再抓一次,哪个字段会变?
  5. 对照是怎么设计的
  6. 一个字段一件没动,另一个字段一件不剩
  7. 分类那边的数字不一样,这一点很关键
  8. 这四万多件货,到底有多老?
  9. 整体分布:一半不到一年,一成二超过三年
  10. 逐站差得很远,而且跟品类有关
  11. 最老的那批,长什么样
  12. 从建档到上架,中间隔了多久?
  13. 中位44天,尾巴长得吓人
  14. 那109件负数是怎么回事
  15. 老货是不是更容易掉出sitemap?
  16. 先看总量,看不出规律
  17. 换成同站配对,结论反过来了
  18. 唯一那个反例,值得单说
  19. 从首页点两下,还找得到老货吗?
  20. 这一层,老货确实吃亏
  21. 三分之一,不是全部
  22. 最老的那件货,现在还卖得动吗?
  23. 56个站的最老商品,全部回200
  24. 缺货比例:配对之后差别很小
  25. 那3个404,核对完只剩1个
  26. 这次的尺子坏在哪三处?
  27. 接口给的顺序,一半的站跟页面上不一样
  28. 脚本被限流的那半小时,浏览器一路畅通
  29. 还有一件事:我的采集被当成了亚太访客
  30. 这套查法搬到自己站上,该怎么做?
  31. 三步,做完之前先别删东西
  32. 判据:三个都是同一个问题的不同问法
  33. 什么情况下不用管
  34. 常见问题解答
  35. 商品的最后更新时间为什么完全不能用?
  36. 那要判断一个页面有没有真的改过,该看什么?
  37. 老商品到底该不该下架?
  38. 新品迟迟不被收录,最该先查哪一步?
  39. 建档时间和上架时间差很多,说明有问题吗?
  40. 我的站不是Shopify,这套方法还能用吗?
  41. 为什么强调要用浏览器核对,脚本不够吗?
  42. 这些数字多久会过时?
  43. 权威参考资料

摘要:从60个英文电商站取回43912件在售商品的全部时间字段,三年以上的有5361件,占12.2%;五年以上2331件,占5.3%;最老的一件已经挂在货架上4704天。原本以为老货会被系统性遗忘,逐站配对之后并没有——33个站里只有1个站的老货进sitemap的比例明显低于新货,13个站反而比新货更高。56个站各自最老的那件商品,前台逐个打开全部回200,一个404都没有。

先问一个很少有人认真回答的问题:你店里现在卖得最久的那件商品,是哪一年上架的?

大部分人的第一反应是去后台翻。翻到的通常是一个叫“最后更新”的时间,显示今天或者昨天。于是结论就成了:我的商品都很新,都在维护。

这个结论几乎一定是错的。不是因为你记错了,而是因为那个字段根本不记录你想知道的事。

想知道一件货在店里放了多久,该看哪个字段?

Shopify的商品对象上挂着三个时间戳,名字长得都差不多,含义差很远。

三个日期,名字都很像

Shopify官方的product对象文档created_at是这条商品记录被建出来的时刻,published_at是它对外可见的时刻,updated_at是它最后一次被写入的时刻。前两个由人的动作决定,第三个由系统的动作决定——而系统的动作,比人频繁得多。

这次的分母来自各站自己的商品清单出口,就是那个不用登录就能读的/products.json。这个出口保哥单独写过一篇,那篇讲的是它泄露了什么,这次只把它当尺子用,读三个日期。60个站里有4个拿不到有效清单(域名解析不了或者清单为空),剩下56个站合计43912件商品,每一件都同时带着这三个字段,没有一件缺。

先看看它们各自的年份分布

把43912件商品按这三个字段各自的年份摊开,画面立刻分成两个世界。

年份按created_at按published_at按updated_at
202615869(36.1%)23613(53.8%)43912(100%)
202516169(36.8%)12532(28.5%)0
20245929(13.5%)3672(8.4%)0
20231789(4.1%)1066(2.4%)0
2022及更早4156(9.5%)3029(6.9%)0

第三列没有分布可言,它是一根竖线。43912件商品的updated_at全部落在采集时刻往前24小时以内,一件例外都没有。中位数是1天,最大值也是1天。

换句话说,如果你拿这个字段去回答“这件货多久没人碰过”,那么无论走进哪一家店,答案都是“昨天刚碰过”。这个字段在这个问题上,信息量精确地等于零。

隔十小时再抓一次,哪个字段会变?

上面那句话还只是一次快照的推断。快照能得出的最强结论也只是“看起来都很新”,得再做一次才能把话说死。

对照是怎么设计的

第二天早上,用完全相同的方式把同一批站再抓一遍,间隔中位10.2小时。然后按商品id逐件对齐,看三个字段各变了多少件。这一步的关键不在于观察updated_at变没变,而在于同一次测量里还有两个字段可以当基线——如果三个都变了,那说明是我的采集不稳;如果只有一个变,那就是字段本身的行为。补一组对照再下结论这件事,吃过一次亏就再也不会省了。

一个字段一件没动,另一个字段一件不剩

49个站顺利对齐,共9426件商品可逐件比对。结果干净得不像实测数据。

字段10.2小时内变动占比
created_at0件0.00%
published_at105件1.11%
updated_at9426件100.00%

49个站,每一个站都是100%。不是“大部分站”,不是“绝大多数商品”,是每个站的每一件。同一时刻、同一段网络、同一个脚本,created_at一件都没动。

那105件变了published_at的商品也值得看一眼:其中104件出自同一个站,剩下1件出自另一个站。也就是说,这个字段在47个站里纹丝不动,只有一个站在半夜做过一次批量重新上架。它不是不会变,是变的时候真的对应了一件事。

分类那边的数字不一样,这一点很关键

同一次复抓里还比了7423个分类。分类的published_at变动0个,updated_at变动1764个,占23.76%,商品数变动159个,占2.14%。

这个对比很说明问题。如果updated_at的刷新是平台的定时任务,那分类那边也该是100%。它不是,只有不到四分之一。所以商品那边的100%不是平台在空转,而是每一件商品每天都真的被写了一次——库存、价格、变体、第三方应用同步,任何一样都够。sitemap里那个修改时间记的是请求时刻,那是生成环节的问题;这里是数据层面的问题,两者机制不同,后果一样:你拿到的时间戳跟内容改没改无关。

顺带说一句,这也解释了为什么很多站的sitemap看起来天天全量更新。平台的lastmod就是从这个字段来的,而这个字段每天都在动。谷歌的sitemap构建文档要求这一列填的是内容最后一次实质性变更的时间,填得不诚实会被直接忽略。手工改修改日期骗不骗得到搜索引擎是另一个话题,那个是人主动做的;这个是平台默认行为,店主多半不知道自己每天在向爬虫宣布“我全站都变了”

这四万多件货,到底有多老?

updated_at扔掉,用created_at重新量一遍,站点的年龄结构立刻显形。

整体分布:一半不到一年,一成二超过三年

货龄件数占比
不到1年2295352.3%
1到2年1211827.6%
2到3年34807.9%
3到5年30306.9%
5年以上23315.3%

中位数342天,四分位是189天和649天,P90是1278天。最老的一件建于2013年,到采集那天已经4704天,将近13年。

这个分布本身没什么惊人的——电商本来就是新品驱动。真正有意思的是它跟“最后更新时间”给出的画面完全对不上:一个说全站昨天刚碰过,另一个说有5361件货已经在架子上待了三年以上。

提醒一句,这里说的是商品的年龄,跟域名年龄是不是排名因素不是一回事,跟用网页存档倒推域名什么时候真正开始有内容也不是一回事。那两件事量的是站,这里量的是站上的东西。

逐站差得很远,而且跟品类有关

把货龄中位数按站排开,跨度大得离谱。

站点商品数货龄中位三年以上占比
taylorstitch.com30001510天65.7%
wusthof.com4441413天82.2%
snowpeak.com8521175天50.4%
decathlon.com518700天35.3%
allbirds.com294643天22.8%
beistravel.com460161天7.2%
dollarshaveclub.com128140天24.2%

刀具站82.2%的商品超过三年,行李箱站只有7.2%,这不是运营水平的差别,是品类的物理属性。一把厨刀的产品周期以十年计,一只箱子的配色一年一换。所以“商品平均多老”这个指标不能横着比,只能跟自己的去年比。

最老的那批,长什么样

五年以上的2331件里,随便抽几件看:allbirds那双womens-wool-runners-natural-white建于2018年11月,2857天;untuckit有一件4107天;thirdlove 4001天;brooklinen 4025天。都是主力款的基础色,不是清仓尾货。

这一点很重要,它直接影响后面所有结论的解释方向。这些老货不是忘了删的垃圾,是店里最经典的那几件。僵尸SKU那套救活逻辑对它们并不适用——它们不是没人买,是卖了七八年。

从建档到上架,中间隔了多久?

既然created_atpublished_at是两个字段,那它们的差值本身就是一条信息:一件货从录进系统到对外可见,中间等了多久。

中位44天,尾巴长得吓人

43912件里,两个日期不在同一天的有37874件,占86.2%。差值中位44天,P75是170天,P90是429天,最大4074天——有一件货在库里躺了11年才上架。

44天这个中位数很符合直觉:拍照、写文案、定价、等库存到仓,一个多月不算慢。真正值得注意的是P90那个429天,意味着每十件里就有一件在系统里等了一年多。如果你在做上新节奏的复盘,这个差值比任何后台报表都诚实。

那109件负数是怎么回事

有109件商品的published_at早于created_at,最极端的一件早了1499天。按字面理解,这件货在被创建之前四年就已经上架了。

当然不是时间旅行。这109件分布在12个站,其中一个站独占69件。这是数据迁移的指纹:换平台、换主题、批量重建商品记录的时候,新记录拿到了新的created_at,但published_at从旧系统原样带了过来。占比只有0.2%,成不了普遍结论,但它是个很好的排查线索——如果你的站上突然冒出一批负数,多半是有人动过底层数据。

老货是不是更容易掉出sitemap?

到这里,实测该回答那个真正的问题了:待得久,会不会就被系统忘掉。

先看总量,看不出规律

把所有商品按货龄分桶,逐桶算在sitemap里的比例:不到1年85.4%,1到2年84.3%,2到3年92.2%,3到5年90.4%,5年以上82.3%。

五个数字上上下下,没有单调趋势。这种时候最容易发生的事,是从里面挑一个符合预期的数字讲故事。但这个百分比是被大站主导的——taylorstitch一家就贡献了3000件商品,它的口径歪一点,整个桶就跟着歪。

换成同站配对,结论反过来了

正确的做法是把每个站当成自己的对照组:在同一个站里,比较三年以上的老货和两年以内的新货,各自进sitemap的比例。两组都至少有20件的站才进统计,一共33个。

配对结果站数
老货明显更差(低于新货1个百分点以上)1
基本一样(相差1个百分点以内)19
老货反而更好(高于新货1个百分点以上)13

差值的中位数是0.0个百分点。19个站里老货和新货的收录比例分毫不差,多数是双双100%。

而13个老货更好的站里,差距大得很难忽略:dreametech的老货88.5%在sitemap里,新货只有36.4%;dollarshaveclub老货100%、新货66.3%;magicspoon老货64.6%、新货40.2%。这几个站真正漏掉的,是最近两年上架的那批。

原因不难猜。sitemap是按某种规则批量生成的,老货早就在里面了,新货要等下一次生成、等某个开关、等某个应用同步。这跟电商sitemap的进出场机制是同一回事——进场那一步,多数站根本没有验收。全站逐条查一遍代价太大,按页面模板抽样是更现实的做法,但抽样的前提是先知道该按什么维度分层,而“上架年份”正好是一个现成的分层轴。

唯一那个反例,值得单说

33个站里只有taylorstitch符合“老货更容易被漏掉”的直觉:老货68.3%在sitemap里,新货97.0%,差28.7个百分点。这个站的货龄中位1510天,三年以上占65.7%,是全样本里最老的一家。也就是说,只有当老货多到成为主体的时候,漏掉老货才会成为一个规模问题。

从首页点两下,还找得到老货吗?

收录是爬虫那一侧的事,用户这一侧还有另一道关:从首页出发,经过首页上点得到的分类,两跳之内能不能走到这件货。这个口径上一篇已经完整跑过一遍,这次直接把货龄这一维叠上去。

这一层,老货确实吃亏

同样做同站配对,28个站够条件:老货明显更差的10个站,基本一样的10个站,老货反而更好的8个站,差值中位仍然是0.0个百分点。

但更差的那10个站,差得非常明显:ice-watch老货可达率46.2%、新货95.9%,差49.8个百分点;tentree差43.5个;marinelayer差38.4个;decathlon差21.1个。

三分之一,不是全部

10比10比8这个分布,比“老货会被埋起来”这句话精确得多。真实情况是:三分之一的站会把老货从导航里挤出去,三分之一无差别,还有三分之一的老货反而站得更稳——因为老货往往是主力品类,主力品类的分类入口一直挂在首页上。

这里还要提一句货架本身。这些站一共开了19405个分类,首页真正点得到的只有一成七,其中一成的分类里一件货都没有。所以老货走不到,有时候不是它被挤下去了,而是装它的那个货架从来就没挂上去过。

会挤的那批站有个共同点:分类切得很细、上新很勤,新品会自动进“新品”“本周上新”这类入口,老货则要靠人手动维护分类归属。站点架构那笔账在这里体现得最直接——架构不是搭一次就完事,它每上一次新就退化一点,跟内链结构会自己烂掉是同一个道理。

最老的那件货,现在还卖得动吗?

清单里写着,不等于前台还在。这一步不能省——上一次做分类清单比对的时候,正是这道闸当场废掉了一条本来会被当成主要结论的判断。

56个站的最老商品,全部回200

做法是每个站取最老的一件和最新的一件,用真实浏览器打开,看状态码、看有没有加购按钮、看结构化数据里的库存状态。为什么用浏览器而不是脚本,后面那一节会讲。

结果是56个站的最老商品,56个200,一个404都没有。里面46件有加购按钮,按谷歌的商品结构化数据规范标着有货的41件。这批平均已经上架三到十年的商品,前台状态跟新品没有实质差别。

缺货比例:配对之后差别很小

53个站两件都正常打开,把“页面上出现缺货字样或者结构化数据标着无货”当成缺货,做同站配对:

老货缺货新货缺货站数
7
5
都缺货8
都有货33

7比5,基本对称。“老货多半已经断货,留着占位置”这个说法,在这个样本上不成立。页面正文长度也是同样的结论:老货中位4220字符,新货3944字符,老货甚至还长一点。

那3个404,核对完只剩1个

唯一出现404的是新货那一组,3件。这个数字看着很有故事性——最新上架的商品前台打不开,结论都能顺手写好了。但逐个核对之后,故事塌了三分之二。

ugreen那件的域名会按访问来源做地区路由,上一批已经因为同样的原因把整站扣掉;functionofbeauty连老货那一页的h1都渲染成了购物车,说明它的商品页在无头浏览器里根本没正常出来,整站数据都不能用。真正干净的只有peakdesign一件:出口里明明白白写着这个handle,前台回404,而且是自定义的404页。

所以最后能说的只有一句:每站抽一件的量级下,新货出现前台失效的情况有,老货一件都没有。想把它变成一个可外推的比例,还得再抓一轮。

这次的尺子坏在哪三处?

这一节是整轮实测里最贵的部分。三处读数出过问题,其中两处是靠浏览器才看出来的,脚本层面完全无感。

接口给的顺序,一半的站跟页面上不一样

本来还想量一件事:老货在分类页里排第几位。分类的商品清单接口是带顺序的,直接数位次就行——这个想法在脚本层面无懈可击。

于是挑了12个站,用浏览器打开对应的分类页,只数正文区里可见的商品链接,按DOM顺序去重,跟接口返回的前12个对照。结果:5个站前12位完全对上,5个站一个都对不上,1个站的/collections/all在前台压根是个系列列表页,正文区一个商品链接都没有,还有1个站的前台显示“这里什么都没有”,而接口说这个分类里有294件商品。

接口的顺序是集合的存储序,前台的顺序是主题模板套上默认排序规则之后的展示序,两者只在没人改过排序的站上重合。所以位次这条腿直接砍掉了——留着就是一条有一半概率是错的结论。商品列表页那97条准则里有相当一部分也栽在这个坑上:准则本身没问题,量它的尺子在页面上取不到值。同一个毛病用错请求方法查响应头时也会犯——工具没坏,问的方式不对。

脚本被限流的那半小时,浏览器一路畅通

复抓跑到第36个站的时候开始连续返回429,而且是跨域名的——36个不同品牌、不同域名的站同时开始拒绝,说明限流不在各家自己的服务器上,在平台的边缘层。响应里没有Retry-After,恢复用了大约35分钟。

关键在于同一时刻发生的另一件事:浏览器那一路的56个站、112个页面,一个429都没有,全部200。同一台机器、同一个出口地址、同一分钟。

公平起见补一句:后来又跑了一轮浏览器采集,114个页面里出现了3次429。所以浏览器通道并非完全免疫,只是阈值明显高得多——脚本那边是连续25个站全军覆没,浏览器这边是零星3个。

换句话说,被限的不是这个IP,是这个客户端。你用脚本去量一个站,量到的可能是这个站给脚本准备的那一份待遇。这跟决定收录哪一版页面的其实是十分钟前路过的那个用户是同一类问题的两个面:一个是内容因人而异,一个是通道因人而异。做审计的时候,两个通道都得留一条。

还有一件事:我的采集被当成了亚太访客

112次浏览器访问里,25次最终落到了不同的地址上——aloyoga和glossier跳进了/en-sg/,dollarshaveclub跳到了us.子域,casper和getquip收敛到了带变体参数的地址。前两类是按访问来源做的地区路由,这意味着这次看到的商品页并不都是这些站的主版本。

这不影响“老货还在不在”这个判断——404就是404,跟地区无关。但如果要做内容层面的对比,就必须先把地区这一维锁死,否则量的是两个站。

这套查法搬到自己站上,该怎么做?

不必等到有人来做审计,自己站上跑一遍,半小时就够。

三步,做完之前先别删东西

第一步,导出全部在售商品的建档时间,按年份分桶,看看三年以上的占多少。这一步只需要一次数据库查询或者一次接口翻页。第二步,把这批老货的地址跟当前sitemap比对,看有多少不在里面——反过来也要比,看sitemap里有多少地址在商品表里已经不存在。第三步,抽10到20件老货,用浏览器逐个打开,确认它们不是软404、不是跳转到了首页。

顺序重要在于:很多人拿到第一步的分桶结果就开始动手清理三年以上的那批,而保哥这次的实测说明,那批多半是最不该动的。等第二步和第三步跑完,名单会完全换一批人。

判据:三个都是同一个问题的不同问法

这三步问的其实是同一件事:这件东西还在不在你的管理范围里。在库里能查到、在sitemap里写着、在前台打得开,三者缺一样都算失联。

需要注意的是,这三个判据不能只查老货。这次实测最反直觉的一点就是,漏掉的更可能是新货——新货还没来得及被任何一套自动流程收进去。所以每次上新之后,最该做的一次检查是“这批刚上的货进sitemap了吗”,而不是“老货该不该清理了”。

什么情况下不用管

如果你的商品总数在三位数以内、上新频率低于每月一次,那么这套检查的价值有限,肉眼过一遍分类页就够了。它真正值钱的场景是SKU上千、有第三方应用在写商品数据、并且换过一次主题或者平台——这三个条件凑齐两个,出问题的概率就相当高。

还有一种情况值得单独提:如果你正在做内容审计的留改并删决策,别把商品页和内容页套同一套标准。文章会衰减,老内容的流量确实会悄悄掉,但一把卖了八年的厨刀不会因为上架久了就变差。判断商品该不该下架的依据是销量、库存和毛利,不是年龄。

常见问题解答

商品的最后更新时间为什么完全不能用?

因为它记录的是这条记录最后一次被写入的时刻,而不是内容最后一次被人修改的时刻。库存扣减、价格同步、第三方应用回写、批量任务扫过,任何一样都会刷新它。实测里43912件商品的这个字段全部落在24小时以内,49个站复抓的变动率是100.00%——一个每天都返回“刚刚”的字段,用来判断新旧没有任何意义。

那要判断一个页面有没有真的改过,该看什么?

看内容本身。取两次快照做正文差分,比看任何时间戳都可靠。如果只能用时间戳,优先用建档时间加上一份自己维护的变更记录——变更记录是你自己写的,它才对应真实的动作。sitemap里那个修改时间同样不能直接信,很多站的那一列就是生成文件的当下时刻。至于内容该不该更新,那是新鲜度与QDF机制要回答的问题,跟“它上次到底变没变”是两个层面。

老商品到底该不该下架?

先分清是“不卖了”还是“卖得久”。真正停售的商品,处置方式取决于有没有替代品和有没有外链,301、410和软404怎么选是另一套决策。而卖得久的商品不需要处置,这次实测里56个站最老的那件商品全部正常在售,其中相当一部分是主力款。

新品迟迟不被收录,最该先查哪一步?

先查它在不在sitemap里。这次配对实测发现,13个站的新货进sitemap的比例低于老货,最极端的一个站新货只有36.4%在里面。多数人会先去改标题、补结构化数据,但如果地址根本没进清单、站内又没有链接指过去,改什么都白搭——这跟孤岛页面检测要解决的是同一类问题。

建档时间和上架时间差很多,说明有问题吗?

不一定。整体中位是44天,一个多月完成拍照、文案、定价、备货是正常节奏。需要警惕的是两头:差值超过一年的那10%,多半是排期一直往后拖或者干脆忘了;差值是负数的,说明这批记录被迁移或者重建过,底层数据动过手脚。

我的站不是Shopify,这套方法还能用吗?

能,字段名要换。WooCommerce看post_datepost_modified,Magento看created_atupdated_at,自建站看你自己的表。判据不变:任何一个会被库存同步刷新的字段,都不能拿来判断新旧。

为什么强调要用浏览器核对,脚本不够吗?

这次三处读数出问题,两处是浏览器发现的:分类页的商品顺序跟接口对不上,以及脚本被平台限流的同时浏览器畅通无阻。脚本快、便宜、能跑全量,但它看到的是接口愿意给它的那一份。全量用脚本、抽样用浏览器,是目前最省力的组合。

这些数字多久会过时?

货龄分布本身是持续变化的,半年后重跑必然不同。但两条结论稳定性很高:一是更新时间字段被系统刷新这件事属于平台机制,不会因为站点不同而不同;二是“老货被遗忘”这个直觉在同站配对下站不住,因为它的成因是运营流程,而不是时间流逝本身。真要复现,重点复现方法,不是数字。

权威参考资料

分享到
标签
版权声明

本文标题:《商品上架时间实测:43912件里老货没掉队,漏的是新货》

本文链接:https://zhangwenbao.com/product-age-created-at-audit.html

版权声明:本文原创,转载与引用请注明作者与原文链接。许可协议: CC BY 4.0

继续阅读
发表评论
分享到微信 或在下方手动填写
支持 Ctrl + Enter 提交