這次幫客戶「MU 沐藍輕履」做 1Shop 的首頁客製化,本來以為就是加兩組按鈕的事,結果花了一整個晚上才搞懂 1Shop 的「官網」跟「獨立銷售頁」差在哪,為什麼我貼在「全網站」的 JavaScript 有些頁面吃得到、有些頁面吃不到。
這篇是給其他也在接 1Shop 客製化案子的工程師、或者自己是 1Shop 店家想搞懂為什麼某些程式碼沒效的人看的。
客戶的需求其實不複雜:
做法也很直覺:寫好 HTML + CSS + JavaScript,貼到 1Shop 後台的「全網站」自訂區塊,應該就搞定了對吧?
事情當然沒這麼簡單。
我原本寫的 JS 用了這樣的邏輯:找到 nav.navbar 把按鈕插在它後面。在首頁測試完美,所以放心交給客戶驗收。
然後客戶回覆:「某某商品頁怎麼沒有按鈕?」
我打開那個頁面 F12 查 DOM,傻眼了 — 這頁根本沒有 nav.navbar,連 chat-list(右下角的 LINE/FB 浮動按鈕群組)都沒有。同樣是 1Shop 的銷售頁,為什麼結構差這麼多?
去後台一查,發現 MU 的銷售頁列表有個篩選 tab:「全部 / 官網 / 非官網」。而且每個銷售頁旁邊有個兩碼英文編號,像是 GF、PJ、VQ、NI、HW。
我原本以為這些代碼是不同的模板類型,查了 1Shop 官方文件才發現 — 這些只是「銷售頁編號前綴」,單純拿來標記訂單歸屬用的(例如訂單號 GF20260422001 就代表這筆訂單來自 GF 開頭的那個銷售頁)。
真正的差別在「有沒有加入官網」。根據 1Shop 官方文件,銷售頁分成兩種:
也就是說,當我把程式碼貼在後台「全網站 → Body 最上方」,只有「隸屬於官網」的銷售頁會執行這段 JavaScript。那些沒加入官網的「獨立銷售頁」,就算網址長得一樣、一樣是 1Shop 平台,根本不會載入我貼的程式碼。
有三個方法可以判斷某個頁面是不是「隸屬官網」:
兩種都是 https://商店網址/xxxxxx 的 6 碼格式,從網址上看不出來。
進後台「銷售頁」列表,頂部有「全部 / 官網 / 非官網」三個篩選 tab,直接看是哪一組。
按 F12 打開開發者工具,跑這段指令:
console.log('navbar:', !!document.querySelector('nav.navbar'));
console.log('chat-list:', !!document.querySelector('.chat-list'));
console.log('page-sale:', !!document.querySelector('.page-sale'));
官網銷售頁會有 nav.navbar 和 chat-list,獨立銷售頁可能只有 page-sale。
搞清楚架構後,我重新設計了程式碼的邏輯。既然不同頁面結構不同,就不能只靠一個選擇器,得準備多套方案:
function insertCategoryButtons() {
// 策略 1: 首頁 → 插在 navbar 後面
var navbar = document.querySelector('nav.navbar');
if (navbar) {
navbar.insertAdjacentHTML('afterend', html);
return;
}
// 策略 2: 商品頁 → 插在 page-sale 容器開頭
var pageSale = document.querySelector('.page-sale');
if (pageSale) {
pageSale.insertAdjacentHTML('afterbegin', html);
return;
}
// 策略 3: 找「精選單品」標題,插在它前面
var headings = document.querySelectorAll('h1, h2, h3');
for (var i = 0; i < headings.length; i++) {
if (headings[i].textContent.indexOf('精選單品') !== -1) {
headings[i].insertAdjacentHTML('beforebegin', html);
return;
}
}
// 策略 4: 最終 fallback,插在 body 最上面
document.body.insertAdjacentHTML('afterbegin', html);
}
回首頁按鈕也一樣:有 chat-list 的頁面融入原生按鈕群組;沒有的頁面就用 position: fixed 做獨立浮動按鈕。
DOMContentLoaded 觸發時目標元素可能還沒出現。要用 setInterval 每 300ms 檢查一次,最多試 30 次(9 秒)。這個比預期重要很多。
就算把 fallback 做好,獨立銷售頁還是完全沒反應。因為問題不在 DOM 找不找得到,是 1Shop 根本不會把我貼在「全網站」的程式碼載入到獨立銷售頁。
三個解法:
| 解法 | 優點 | 缺點 |
|---|---|---|
| A. 把獨立銷售頁加入官網 | 一鍵解決,程式碼不用改 | 金流、物流、優惠會被官網覆蓋 |
| B. 每個獨立銷售頁各自貼程式碼 | 不影響原本設定 | 維護麻煩,改版要改 N 次 |
| C. 分類按鈕只連官網銷售頁 | 程式碼最簡單 | 客戶可能想連獨立銷售頁 |
我最後跟客戶溝通,他們建立這些獨立銷售頁的本意就是給官網分類用,只是沒勾「加入官網」。所以走方案 A,客戶在後台勾個勾,全部搞定。
這次案子的技術面其實不難,卡關的都是平台知識的坑。反省一下:
setInterval)比 DOMContentLoaded 實用。在 SPA 或動態渲染的平台上,前者幾乎是標配。chat-list,視覺、RWD、定位通通自動對齊,省了一大堆 position: fixed 的微調功夫。如果你也在做 1Shop 的客製化,或你是 1Shop 的店家想優化網站體驗,歡迎聯絡我聊聊。這次的踩坑經驗之後會整理成一份標準化的 1Shop 客製化方案,適合需要首頁按鈕、分類選單、全站 UI 調整的店家。
畢竟踩過的坑,不做第二次就是賺到嘛。