SEO 友好的分頁技術:改善網站結構與索引效率的實作要點

Published on: | Last updated:

先說結論

嗯…分頁 (Pagination) 這件事,想來想去,其實核心就一個:不要只給「上一頁、下一頁」。你得讓 Google 清楚看見整個結構,知道第 1 頁在哪,總共有幾頁。做對了,Google 能有效爬完你的東西;做錯了,就是浪費爬取預算 (Crawl Budget),很多頁面會跟消失沒兩樣。

大家好像都只談舊東西,但問題變了

我看了看,現在很多人談分頁 SEO,還在講 `rel="next/prev"`。但那東西 Google 早就公開說不用了。 雖然 Bing 可能還會參考,但我們主要還是看 Google。 所以,糾結在一個被棄用的標籤上,沒什麼意思。 現在的問題是,Google 不再幫你把分頁「串」成一個整體概念後,每一頁都變成獨立的頁面了。

這就帶來新的麻煩:

  • 重複內容的風險變高:如果你的標題、描述都差不多,Google 可能會覺得這些頁面很像,進而影響索引。
  • 爬取深度問題:如果你的網站有幾百、幾千頁,只靠「下一頁」連結,Googlebot 可能爬到第 10 頁就沒力氣了,後面的頁面等於進了黑洞。
  • 權重分散:外部連結的權重,沒辦法像以前一樣,透過 `rel="next/prev"` 集中到第一頁。

這跟 Google 官方開發者文件裡說的,要讓爬蟲能找到所有內容,是有點矛盾的。 文件建議用清楚的 `` 連結,確保 Google 能依序找到頁面。 但實務上,特別是在台灣很多電商網站,我看到的是大量用 JavaScript 產生的分頁按鈕,這對 SEO 其實很不利,因為 Googlebot 不會去「點擊」那些沒有 `href` 屬性的按鈕。

正確與錯誤的分頁連結結構示意
正確與錯誤的分頁連結結構示意

那…到底該怎麼做?

綜合 Google 的建議和一些實務經驗,我覺得安全的做法大概是這樣。

1. 最基本、最安全的:傳統 `` 連結
這就是最單純的作法。 你要提供像「1, 2, 3, 4, 5... 最後一頁」這樣的連結。 這樣能大幅降低爬取深度,讓 Googlebot 可以從第一頁直接跳到任何一頁,而不是一頁一頁慢慢走。 程式碼大概會長這樣:

<nav aria-label="分頁導覽">
  <ul class="pagination">
    <li class="page-item"><a class="page-link" href="/category?page=1">1</a></li>
    <li class="page-item active"><a class="page-link" href="/category?page=2">2</a></li>
    <li class="page-item"><a class="page-link" href="/category?page=3">3</a></li>
    <li class="page-item"><a class="page-link" href="/category?page=100">最後一頁</a></li>
  </ul>
 </nav>

重點是,每個分頁都要有自己獨一無二的 URL,像是 `?page=2`、`?page=3` 這樣。

2. `rel="canonical"` 的正確用法
這邊很多人會搞錯。分頁中的每一頁,例如第 2 頁、第 3 頁,都應該使用「自參考」的 canonical 標籤,也就是指向自己。 像這樣:

在 `https://example.com/category?page=2` 這個頁面上,你的 canonical 應該是:
``

千萬不要把所有分頁都 `canonical` 到第一頁。那等於在告訴 Google:「嘿,這些頁面都是第一頁的複製版,不用索引它們了。」結果就是除了第一頁,其他頁面的商品或文章都進不了索引庫。

3. 「載入更多」與「無限滾動」的處理
很多網站為了使用者體驗,喜歡用「載入更多」按鈕或無限滾動。 這對 SEO 來說是個災難,如果沒有處理好的話。因為內容是靠 JavaScript 動態載入的,Googlebot 一開始看不到。 Google 建議,即使你用無限滾動,也應該提供一個對應的分頁版本。 意思是,當使用者往下滾動觸發載入時,URL 也要用 History API 更新 (例如從 `/category` 變成 `/category?page=2`),而且這個 `/category?page=2` 的 URL 必須是真的可以被直接存取的。 簡單講,就是要讓非 JavaScript 的環境(像 Googlebot)也能看到分頁後的內容。

不同方法的比較

老實說,沒有一種方法是完美的,要看情境。我整理了一下,大概是這樣。

方法 優點 缺點 適合情境
標準分頁 對 SEO 最友善,結構最清楚。 Google 可以輕鬆爬完所有頁面。 使用者體驗可能差一點,每次都要點擊換頁。 內容數量龐大(例如超過幾十頁)的電商網站、論壇、文章列表。
載入更多 (Load More) 使用者體驗比傳統分頁好一點,還是在單一頁面操作。 如果沒做好對應的分頁 URL,SEO 會很慘。 對數量超級大的清單來說,載入到後面會變慢。 中小型清單,像是部落格首頁、或是幾百個商品的分類頁。
全部顯示 (View-all) 如果做得好,所有內容都在一頁,權重最集中。 頁面載入速度是個大問題。如果一個分類有上千個商品,使用者會等到天荒地老。 只有在內容數量很少(例如幾十個項目)的情況下才考慮。文章系列也還行。
修正分頁後,索引頁面數量提升的示意圖
修正分頁後,索引頁面數量提升的示意圖

實際案例會遇到的坑

想像一個有上萬筆商品的大型電商網站。他們一開始用了無限滾動,但沒有做分頁 URL 的對應。結果就是,在 Google Search Console 裡面,索引報告顯示「已檢索,目前尚未建立索引」的頁面數量非常多。 因為 Googlebot 只能看到第一頁的幾十個商品,後面的完全看不到。

後來,他們改成混合模式:保留無限滾動的體驗,但同時在背景生成了傳統的 `` 分頁連結,並確保每個分頁 URL 都能回傳正確的 HTML 內容。 這樣一來,使用者體驗沒變,但 Google 爬蟲卻能順利地爬完整個網站的商品。三個月後,被索引的產品頁面數量提升了差不多八成,長尾關鍵字的流量也跟著進來了。

最大的坑就是「自以為對 UX 好的設計,卻忘了搜尋引擎不是人類」。 Google 一直在強調要打造以人為本的內容 (people-first content),但前提是 Google 得先看懂你的網站結構。 如果結構本身就有問題,再好的內容也沒用。

當「全部顯示」頁面過於龐大,使用者只會看到無盡的等待
當「全部顯示」頁面過於龐大,使用者只會看到無盡的等待

所以,檢查一下你的網站吧

說了這麼多,其實重點還是得回頭看看自己的網站。你的分類頁、文章列表是怎麼處理分頁的?是用最單純的連結,還是用了一些 JavaScript 的酷炫效果?

你可以自己動手測試:

  1. 在你的分頁上,按右鍵「檢視網頁原始碼」。
  2. 搜尋看看有沒有 `?page=2` 這樣的 `href` 連結。
  3. 如果找不到,那你的分頁對 SEO 可能就有點問題了。

最後想問問大家,你的網站目前是用哪種分頁方式?是傳統的分頁數字,還是「載入更多」按鈕?有因為這樣遇到什麼索引上的問題嗎?在下面留言分享一下吧,也許大家的經驗可以互相幫助。

🎁 解鎖本篇限定Google外掛

輕鬆打造 SEO 分頁健檢神器:一招搞定網站結構檢查+優化記錄

你是不是常常煩惱網站分頁一多,連自己都搞不清楚哪裡有問題?分頁路徑設計沒注意,小心 Google 抓不到重點頁面!我自己幫朋友接案,檢查分頁結構常常眼花,靠手動記錄超累。這次直接教你用 Google Apps Script 做個「SEO 分頁結構健檢小工具」!路徑一貼馬上標記重複、抓出結構異常,還能把優化建議通通記下來。資料都存 Google Sheet,改過什麼都不怕忘記。真的超方便,SEO 新手、老手都能直接用!

一鍵複製,輕鬆開啟你的 SEO 分頁健檢工具

這個小工具會幫你紀錄每一個分頁路徑、檢查 SEO 結構問題,還能回顧歷史紀錄!


// === SEO 分頁結構健檢小工具 ===

function doGet(e) {
  var html = [];
  html.push('<html><head><title>SEO 分頁健檢</title>');
  html.push('<meta name="viewport" content="width=device-width">');
  html.push('<style>body{font-family:monospace;background:#f7f7ff;');
  html.push('padding:30px}input,select,textarea{margin:4px 0;}');
  html.push('.wrp{max-width:500px;background:#fff;padding:18px 22px;');
  html.push('margin:18px auto 0;box-shadow:0 3px 12px #eee;border-radius:8px}');
  html.push('.hist{margin:30px 0 0;}');
  html.push('th,td{padding:6px 10px;font-size:15px;}');
  html.push('td.err{color:#d32f2f;font-weight:bold;}');
  html.push('</style></head><body>');
  html.push('<div class="wrp">');
  html.push('<h2>SEO 分頁結構健檢</h2>');
  html.push('<form method="post" action="?">');
  html.push('<label>分頁網址(不含 domain):<br>');
  html.push('<input type="text" name="urlpath" style="width:96%" required></label><br>');
  html.push('<label>這頁有 canonical?');
  html.push('<select name="canonical"><option>是</option><option>否</option></select></label>');
  html.push('<label>自訂優化建議<br>');
  html.push('<textarea name="note" rows="2" style="width:96%"></textarea></label><br>');
  html.push('<button type="submit">送出紀錄 / 健檢</button></form>');

  if (e.parameter.urlpath) {
    var sheet = getSheet_();
    var url = (e.parameter.urlpath + '').trim();
    var canon = e.parameter.canonical || '';
    var note = (e.parameter.note || '').trim();
    var err = checkPathErr_(url, canon, sheet);
    sheet.appendRow([new Date(), url, canon, note, err]);
    html.push('<p style="color:green;font-weight:bold;">已寫入!</p>');
    if (err) {
      html.push('<p style="color:#d32f2f;">[健檢結果] ' + err + '</p>');
    } else {
      html.push('<p style="color:#388e3c;">[健檢結果] 沒問題!</p>');
    }
  }

  // 讀取近 10 筆歷史
  var sheet2 = getSheet_();
  var lastRows = Math.max(2, sheet2.getLastRow() - 9);
  var records = sheet2.getRange(lastRows, 1, sheet2.getLastRow()-lastRows+1, 5).getValues();
  html.push('<div class="hist"><h3>最近 10 筆分頁紀錄</h3>');
  html.push('<table border="1" style="border-collapse:collapse;">');
  html.push('<tr><th>時間</th><th>路徑</th>');
  html.push('<th>canonical</th><th>優化建議</th><th>健檢</th></tr>');
  for(var i=records.length-1;i>=0;i--){
    html.push('<tr><td>' + formatTime_(records[i][0]) + '</td>');
    html.push('<td>' + esc_(records[i][1]) + '</td>');
    html.push('<td>' + esc_(records[i][2]) + '</td>');
    html.push('<td>' + esc_(records[i][3]) + '</td>');
    var cellErr = records[i][4] ? '<span class="err">' 
      + esc_(records[i][4]) + '</span>' : 'OK';
    html.push('<td>' + cellErr + '</td></tr>');
  }
  html.push('</table></div>');
  html.push('</div></body></html>');
  return HtmlService.createHtmlOutput(html.join(''));
}

// 路徑健檢,重複/奇怪字元/有沒有加 canonical
function checkPathErr_(url, canon, sheet) {
  var err = [];
  if(!/^\/[a-zA-Z0-9\-_\/]+$/.test(url)){
    err.push("分頁路徑格式異常(需 / 開頭,英數、-、_)");
  }
  var list = sheet.getRange(2,2,sheet.getLastRow()-1,1).getValues();
  var found = list.filter(function(x){return (x[0]||'')==url;});
  if(found.length>0) err.push("這個分頁路徑已經登記過!");
  if(canon!="是") err.push("缺少 canonical,SEO 會扣分!");
  // TODO: 之後可再加 sitemap 檢查
  return err.join(';');
}

function getSheet_(){
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var name = "SEO分頁紀錄";
  var sh = ss.getSheetByName(name);
  if(!sh){
    sh = ss.insertSheet(name, 0);
    sh.appendRow(['時間','路徑','canonical','優化建議','健檢結果']);
  }
  return sh;
}

// 格式化時間
function formatTime_(d){
  try {
    return Utilities.formatDate(new Date(d), Session.getScriptTimeZone(), "MM/dd HH:mm");
  } catch(e){
    return '';
  }
}
// HTML escape(避免字串跑掉)
function esc_(s){
  if(!s) return '';
  return (s+'').replace(/&/g,'&').replace(/</g,'<')
    .replace(/>/g,'>').replace(/"/g,'"')
    .replace(/'/g,"'");
}

別怕新手搞混!超詳細的部署步驟看這邊

每個步驟都照著做,你一定也能成功!

  1. 開啟 Apps Script 編輯器
    先打開你要放紀錄的 Google 試算表 → 點「擴充功能」→「Apps Script」
    「擴充功能」在最上方選單,大概中間靠右。
    點下去會自動彈一個新分頁,進入 Apps Script 編輯器。
    ⚠️ 我之前公司帳號就是這裡會被擋,如果無法開啟,記得換用自己的 Gmail!有時候瀏覽器會擋掉彈出分頁,要自己允許。
  2. 清空並貼上程式碼
    按 Ctrl+A 全選,按 Delete 刪掉,然後把上面的程式碼 Ctrl+V 貼進去。
    編輯器中央白底那一格,就是貼這個的地方。
    原本的 function myFunction() 不用留,直接全部換掉就行。
    ⚠️ 有次我朋友沒全選到,結果一堆錯誤超難 debug!務必確認整份程式碼完整貼上。
  3. 儲存專案
    找左上角那個磁碟片(儲存)圖示點下去,或直接按 Ctrl+S。
    第一次儲存會跳出要你輸入專案名稱,隨便打都沒差,功能完全不受影響。
    沒存檔就直接部署,有時會爆出紅字,不存心裡會有陰影啊XD
  4. 部署為網頁應用程式
    右上角有個「部署」藍色按鈕,點下去選「新增部署作業」。
    會彈出設定畫面,記得:
    1. 齒輪選單選「網頁應用程式」
    2. 執行身份記得選「我」
    3. 「誰可以存取」必須選「任何人」
    4. 全部設好後點「部署」
    完成後會跳出一段網址(就是你的 SEO 分頁健檢工具啦)
    ⚠️ 「誰可以存取」一定要選「任何人」,有個新手朋友選錯結果連自己都打不開QQ
  5. 處理授權警告
    第一次部署一定會跳出紅色警告:「Google 尚未驗證這個應用程式」
    不用緊張!這是 Google 保護你,不是你中毒
    直接點「進階」→「前往 XXX(不安全)」→「允許」
    授權完就沒這問題了。
    ⚠️ 自己寫的 Apps Script,只要沒公開上架,Google 都會跳這個。我之前也是第一次看到嚇一跳,現在習慣了。
  6. 取得網址,開始使用
    授權完畢後會看到一個超長的網址,複製下來
    貼到新分頁,馬上就是自己的 SEO 分頁健檢工具
    ⚠️ 每次只要修改過 Apps Script 程式,都要重新部署一遍,不然網址不會自動更新。我朋友剛開始玩一直卡這邊。
⚠️ 關於紅色授權警告畫面:別怕,這是正常的!
Google 只要偵測到「你自己的 Apps Script 沒經過官方驗證」,就會跳出警告畫面。不是病毒,也不是被駭!這是保護大家的標準流程。只要點「進階」→「前往 XXX(不安全)」→「允許」就搞定了。我自己每次新寫一個工具都會遇到,朋友也常問我,真的超正常。如果以後工具要給客戶正式大量用,可以再去做 Google 驗證,但自用或團隊內部小工具這樣就很穩。

真實情境:你能怎麼用這個分頁健檢工具?

情境一,幫網站重整分頁結構時,一頁一頁記錄新的分頁路徑、標記是否 canonical,異常直接被提醒,還能備註未來要優化的重點,做完一輪有紀錄超安心。
情境二,行銷部門每次出新活動頁,PM 直接在表單輸入分頁、標記 canonical,歷史資料自動保存,回頭檢查還能看到之前有沒有人登記過重複分頁,SEO 團隊再也不會漏掉細節了!

Related to this topic:

Comments

  1. profile
    Guest 2025-05-09 Reply
    大家好!我對網站分頁的SEO策略很感興趣,尤其是如何平衡流量與用戶體驗。如果有人有相關資源或經驗分享,我非常想了解更多!謝謝!
  2. profile
    Guest 2025-04-22 Reply
    嘿,大家好!我是一位網站優化專家,最近對於分頁設計很有興趣。不知道是否可以請教一下各位的經驗或資源?希望能互相交流,共同提升SEO策略!謝謝!