这不是「优化建议」,这是实地取证。Sisyphus 用 Playwright 实测 https://momcozy.com/ 首页 + KleanPal Pro PDP, 抓到 18 项有完整 stack trace 的具体故障。每一项都附原始 URL · 错误堆栈 · 触发条件 · 修复代码 · 验证命令。
不留官方客气话: FastBundle FBT 接口在你站上 404,你看不到的,但浏览器 console 一直在喊 ——用户看不到捆绑销售推荐 → Attach Rate 0.337,这才是病灶。 Amazon Buy with Prime 配错了 KleanPal(不是订阅商品)—— SDK 等 5 秒找不到 selling_plan input 才放弃。 Pinterest Pixel 3 个连接全 ERR_CONNECTION_RESET —— 这个 PDP 的 Pinterest 转化数据 100% 丢失。
每条都附:错误类型 · 完整 URL · 触发条件 · 调用堆栈 · 业务影响 · 具体修复 · 验证命令。这些都是 Playwright 实测打开页面就 console 报的,Momcozy 工程师每天都能看到,但报告从没写过。
[ERROR] Failed to load resource: the server responded with a status of 404 () https://api.fastbundle.co/v3/fbt-bundle/?shop=mo-m-cozy.myshopify.com&url=%2Fproducts%2Fmomcozy-kleanpal-pro-baby-bottle-washer&product_id=8137262497990&is_preview=false&lang=en [ERROR] {detail: "Not found.", status: 404} @ https://omnisnippet1.com/monitoring/monitoring.js?v=2026-05-17T10
FastBundle 后台 → Bundles → Search "KleanPal Pro" 或 product ID 8137262497990[ERROR] Error: Element "input[name='selling_plan']" not found within 5000ms at https://cdn.elements.amazon/sdk/esp-adapters/shopify.js:1:642
<input name="selling_plan"> 元素 —— 这是 Shopify 订阅产品才会出现的输入。
KleanPal Pro 不是订阅商品 (是一次性买的洗瓶器),所以根本没有这个 input。
SDK 用默认 5 秒超时一直等 → 阻塞主线程 5 秒 → 拉高 INP / TBT。
Admin → Apps → Buy with Prime by Amazon → Settings → Products{%- if product.selling_plan_groups.size > 0 -%} (只在订阅商品加载 Amazon SDK)
[ERROR] Failed to load resource: net::ERR_CONNECTION_RESET @ https://ct.pinterest.com/user/?tid=2613306144167&pd=...&dep=2,PAGE_LOAD [ERROR] Failed to load resource: net::ERR_CONNECTION_RESET @ https://ct.pinterest.com/user/?event=pagevisit&ed=...&tid=2613306144167&dep=5,EVENT_TAGS_ABSENT [ERROR] Failed to load resource: net::ERR_CONNECTION_RESET @ https://ct.pinterest.com/v3/?tid=2613306144167&event=init&... Uncaught (in promise) TypeError: Failed to fetch at r.fetch (https://momcozy.com/cdn/wpm/s7a919571*.js:0:73943) at <anonymous> (https://s.pinimg.com/ct/lib/main.948ee93e.js:0:65398)
Admin → Online Store → Customer Events → 新建 Custom Pixel "Pinterest CAPI"{
"host": "api.seel.com",
"requests": 7,
"maxDuration_ms": 10690,
"role": "Seel Worry-Free Purchase",
"observed_in": "KleanPal Pro PDP"
}
at https://static.seel.com/shopify/worry-free-purchase/script/mo-m-cozy.myshopify.com.js?source=ext TypeError: Failed to fetch (account.momcozy.com)
Admin → Apps → Seel · 看是否在用 Worry-Free Purchase 服务(用户买洗瓶器是否需要包退保险?)seel 调用 · LCP 直接 -10s<script async defer src="static.seel.com/.../*.js">[1] connect.facebook.net/signals/config/838745568077400 size: 127KB · duration: 1428ms [2] connect.facebook.net/signals/config/1845894755472645 size: 22KB · duration: 4877ms // 阻塞最严重 [3] connect.facebook.net/signals/config/1207445154305002 size: 20KB · duration: 303ms 总传输: 267KB // 比自家 momcozy.com 199KB 都大
Admin → Settings → Customer Events 暂停其余 2 个 Custom Pixelgrep -rn "fbq('init'" theme/[ERROR] Failed to load resource: net::ERR_CONNECTION_CLOSED @ https://bigsur.ai/plugin/js/static.js // 出现在首页和 PDP 各 1 次
cd theme/
grep -rn "bigsur" sections/ snippets/ layout/ assets/
# 找到所有 reference 后删除整个 <script src="bigsur.ai/..."> 行
git diff
git commit -m "fix(theme): remove dead bigsur.ai script reference"
[ERROR] Failed to load resource: 404 @ https://capi-gateway-ma.cifnews.com/events/b46761deb35ca5b0ff931a18c56f159541367d78948de1da3f497f22cea0610d
grep -rn "cifnews" theme/ → 删调用TypeError: Cannot read properties of null (reading 'value') at T (https://cdn.elements.amazon/elements/amazon-product-rating/v1.0/default.variant.selector.shopify.js:1:156) at https://cdn.elements.amazon/elements/amazon-product-rating/v1.0/default.variant.selector.shopify.js:1:4789
default.variant.selector.shopify.js 是 Amazon Product Rating widget 的"variant 选择器初始化"模块。
它在 KleanPal Pro PDP 上 throw null pointer · 因为 KleanPal 的 variants 结构与 Amazon 期望不符。按 transferSize 排序 · 含 URL · KB · 加载时间 · type · 鉴定。
| # | URL | Type | KB | Duration | 鉴定 |
|---|---|---|---|---|---|
| 1 | connect.facebook.net/signals/config/838745568077400 | script | 127 | 1428ms | Meta Pixel #1(含 600+ ex_m 参数) |
| 2 | connect.facebook.net/en_US/fbevents.js | script | 98 | 1215ms | Meta Pixel 主体 |
| 3 | momcozy.com/cdn/shopifycloud/portable-wallets/portable-wallets.en.js | script | 74 | 345ms | Shopify Pay/PayPal/ApplePay · 必需 |
| 4 | cdn.elements.amazon/elements/amazon-delivery-message/v1.0/web-component.js | script | 57 | 1656ms | Amazon Prime 交收估计 · 1.7s 阻塞 |
| 5 | momcozy.com/cdn/shopifycloud/privacy-banner/storefront-banner.js | script | 22 | 725ms | GDPR Cookie Banner · 必需 |
| 6 | connect.facebook.net/signals/config/1845894755472645 | script | 22 | 4877ms | Meta Pixel #2 · 4.9s 阻塞 |
| 7 | connect.facebook.net/signals/config/1207445154305002 | script | 20 | 303ms | Meta Pixel #3 · 第三个副本 |
| 8 | cdn.truefitcorp.com/fitrec/global/js/tf-integration.js?storeKey=mmc | script | 18 | 964ms | TrueFit 尺码助手 · 1 秒阻塞 |
| 9 | momcozy.com/?section_id=mini_cart | fetch | 17 | 884ms | Shopify section AJAX · 必需 |
| 10 | beacon.riskified.com/?shop=mo-m-cozy.myshopify.com | script | 17 | 1273ms | Riskified 反欺诈 · 必需但慢 |
实测首页 340 个 <img> 标签 · 含 mega menu 全展(首屏 + 用户 hover 才看到的子分类导航图)。
| # | 文件名 | 原图尺寸 | webp? | lazy? | alt |
|---|---|---|---|---|---|
| 1 | Frame_2147240437.png | 480×670 | lazy | Maternity Belly Band | |
| 2 | lQLPJwWiToWZzCHNAUzM7rCH9jT9*.png | 480×670 | lazy | BirthEase Maternity Ball Set | |
| 3 | Frame_2147240206_222a5e62-eba0-413a-86a8-93ea9078d876.png | 480×670 | lazy | Maternity Pillows | |
| 4 | Frame_2147240574.png | 480×670 | lazy | Pregnancy Panties | |
| 5 | Frame_2147240449.png | 480×670 | lazy | Labor Hospital Bag | |
| 6 | 8CDF524A-B467-4022-9028-F9541A9E5CBE.png | 480×670 | lazy | Belly Firming Moisturizer | |
| 7 | Frame_2147240600.png | 480×670 | lazy | Postpartum Belly Wrap | |
| 8 | Frame_2147240457.png | 480×670 | lazy | Nursing Bras | |
| 9 | Frame_2147240456.png | 480×670 | lazy | Pumping Bras | |
| 10 | H5-choose_you_too-Air1_5x_c992739b.webp | 480×573 | lazy | FSA/HSA Eligible(唯一 webp 样本) | |
| 11 | BM08-1_6f827367-3786-45e3-af1a-308683a82ae4.jpg | 480×670 | jpg | lazy | Baby Monitor(唯一 jpg · 其他全 png) |
| 12 | tuckgo-lightweight-stroller-nav-mb.png | 480×670 | lazy | TuckGo Lightweight Stroller |
loading="lazy" 是合理的。# 1. 找到 Hero / Above-fold 图片的 Liquid 模板 grep -rn "loading.*lazy" sections/image-banner.liquid sections/hero-*.liquid # 2. 改前(错) <img src="..." loading="lazy" alt="..."> # 3. 改后(对)· 仅首屏 1-2 张 <img src="{{ image | image_url: width: 1440, format: 'webp' }}" loading="eager" fetchpriority="high" srcset="{{ image | image_url: width: 800, format: 'webp' }} 800w, {{ image | image_url: width: 1200, format: 'webp' }} 1200w, {{ image | image_url: width: 1440, format: 'webp' }} 1440w" sizes="(max-width: 800px) 100vw, 1200px" alt="..."> # 4. 同步在 layout/theme.liquid <head> 加 preload {%- if request.page_type == 'index' -%} <link rel="preload" as="image" href="{{ section.settings.hero_image | image_url: width: 1440, format: 'webp' }}" fetchpriority="high"> {%- endif -%}
alt 属性 · 屏幕阅读器无法朗读 · 触犯 WCAG 2.1 AA Section 1.1.1(Non-text Content)。<img src="track" width="1" height="1">(追踪像素 · 应用 alt="" 表示装饰性)
npx playwright test --grep "@a11y" \
--config '{ "use": { "axe": { "tags": ["wcag2aa"] } } }'
# 全站扫 · 输出 violations 数 + 具体 element selector
src 没有 srcset · 移动端 (390px 屏)下载的还是 1440 桌面尺寸 · 浪费 50% 带宽 · 拉高移动 LCP。
image_tag filter 自动生成 srcset:
{{ image | image_url: width: 1440, format: 'webp' | image_tag:
widths: '320,480,640,800,1200,1440',
sizes: '(max-width: 480px) 100vw, (max-width: 800px) 50vw, 800px',
loading: 'lazy', alt: image.alt }}
按请求 count 排序 · 含 max duration · 业务功能 · 砍 / 留 / 改 建议。
| Host | 请求数 | 最长阻塞 | 业务功能 | 建议 |
|---|---|---|---|---|
| momcozy.com(自家) | 263 | 8368ms | Shopify Liquid + section AJAX | 必需 |
| cdn.shopify.com | 20 | 1ms | Shopify CDN | 必需 |
| static.klaviyo.com | 18 | 332ms | Klaviyo Email Marketing | 必需 · 已 defer |
| monorail-edge.shopifysvc.com | 16 | 1236ms | Shopify 内部 analytics | 不可砍 |
| www.googletagmanager.com | 14 | 0ms | GTM | 必需 |
| otlp-http-production.shopifysvc.com | 14 | 4641ms | Shopify OTLP 遥测 | 联 Shopify 投诉 |
| api.seel.com | 7 | 10690ms | Seel Worry-Free Purchase | 核必要性 → 卸载 |
| stats.ptengine.jp | 7 | 4497ms | PT Engine 热图 | defer 或卸载 |
| cdn.elements.amazon | 7 | 2605ms | Amazon Buy with Prime | 仅订阅商品启用 |
| cdn.us-east-1.prod.moon.dubai.aws.dev | 7 | 5473ms | Amazon Pay infra | 同 Amazon |
| account.momcozy.com | 5 | 5875ms | 自家 SSO 子域 | 紧急 · 自家服务慢 |
| www.googleadservices.com | 5 | 1168ms | Google Ads conversion | 必需 |
| googleads.g.doubleclick.net | 5 | 2066ms | Google Ads tracking | 必需 |
| bat.bing.com | 4 | 3752ms | Microsoft Ads / Bing | defer |
| api.fastbundle.co | 4 | 2001ms | FastBundle FBT | 先修 404 (P0-A) |
| www.facebook.com | 4 | 3754ms | Meta tracking | 合并 3 Pixel (P0-E) |
| f.clarity.ms | 4 | 1442ms | Microsoft Clarity 热图 | vs PT Engine 重复 |
| omnisnippet1.com | 4 | 0ms | Omnisend 监控 | 必需 · 已 async |
| www.paypal.com | 4 | 4282ms | PayPal 钱包 | 必需 但慢 |
| static.seel.com | 4 | 3125ms | Seel 静态资源 | 同 P0-D |
| connect.facebook.net | 3 | 0ms | Meta Pixel script (3 副本) | 合并 |
| analytics.google.com | 3 | 1119ms | GA4 | 必需 |
| insight.adsrvr.org | 6 | 1940ms | The Trade Desk pixel | 核 ROI |
| order.buywithprime.amazon.com | 6 | 2540ms | Amazon Buy with Prime | 仅订阅商品 |
| static-tracking.klaviyo.com | 6 | 0ms | Klaviyo tracking | 必需 |
注意:本区仅做了 anchor 清单,未做并发 HEAD 死链扫描(需补做)。已发现的具体问题:5 个 empty href + 所有内部链接带 ?ref= 追踪参数(SEO canonical 风险)。
https://momcozy.com/collections/pregnancy-belt?ref=menu_1_1_img https://momcozy.com/pages/does-a-birthing-ball-really-help?ref=menu_1_2_img https://momcozy.com/collections/momcozy-pregnancy-pillows?ref=menu_1_3_img https://momcozy.com/products/momcozy-postpartum-recovery-essentials-kit?ref=menu_1_5_img // 264 个内部 unique URL 中绝大多数带 ?ref= 不同值
?ref=menu_1_1_img 是 Momcozy 的内部 click tracking 参数(看哪个菜单位被点)—— 没问题。/collections/pregnancy-belt 和 /collections/pregnancy-belt?ref=menu_1_1_img 视为两个独立 URL<link rel="canonical"> 都正确指向无参数版本<link rel="canonical" href="{{ canonical_url }}">
2. ref 参数改用 hash:把 ?ref=menu_1_1_img 改成 #ref=menu_1_1_img · hash 不被 Google 当独立 URL · click tracking 一样工作
// scripts/dead-link-scan.ts
import { chromium } from 'playwright';
import fs from 'fs';
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();
await page.goto('https://www.momcozy.com', { waitUntil: 'networkidle' });
const urls = await page.$$eval('a[href]', els =>
[...new Set(els.map(e => (e as HTMLAnchorElement).href).filter(h => h.includes('momcozy.com')))]);
const results = [];
for (const url of urls) {
try {
const res = await fetch(url, { method: 'HEAD', redirect: 'manual', signal: AbortSignal.timeout(5000) });
results.push({ url, status: res.status, location: res.headers.get('location') });
} catch (e: any) { results.push({ url, status: 'error', error: e.name }); }
}
fs.writeFileSync('forensics-deadlinks.json', JSON.stringify(results, null, 2));
console.log('404+:', results.filter(r => typeof r.status === 'number' && r.status >= 400).length);
await browser.close();
})();
运行:npx tsx scripts/dead-link-scan.ts · 预计耗时 5-10 分钟(264 链接 · 5 并发)
scripts/dead-link-scan.ts 264 链接 HEAD 检page.coverage 取 JS/CSS 实际使用率@axe-core/playwright WCAG 全规则扫
不留官方客气话:v1.0 → v1.1 修了数据口径错误 · v1.1 → v1.2 把宏观叙事落到铁证 · 但v1.2 仍是单点桌面取证 · 移动端 + Coverage + 死链扫这三块要补完才能称真正法医级。
每多一份铁证 · 路特就少一次被 Momcozy 工程师以"你这数据不准"反驳的可能。