SWAG / Profile SEO 執行規格 本機 完成 0 / 0
執行規格書 · v1.2 · 2026-06-16 · 基於線上實測 + 5 月 GSC 數據

Creator Profile
SEO 改版執行清單

每一項獨立、可分開做、可打勾追蹤 — 不必一口氣全做

/user 創作者頁月點擊 54,018 現掛在 noindex 上 · 急
/category/ 月點擊 9,284 在排名的標籤頁
/user-feed-grid/ 月點擊 777 profile 標籤現在連這裡
/u 創作者頁月點擊 49 幾乎還沒被收錄
這份文件怎麼用
  1. 點任一張卡片標題 會展開,裡面有「現況 / 為什麼 / 怎麼做 / 怎麼算完成」。
  2. 做完一項就勾左邊大方框 — 卡片會變灰、進度條前進。進度自動存在這台電腦的瀏覽器,關掉再開還在。
  3. 卡片裡的小方框是 該項的驗收細項,可以一條一條勾。
  4. 第 1 區(止血)三項必須一起上線,其餘各區可獨立排程、分開做。不必一口氣全做。
  5. 每張卡片右上角有 / 高效益 / 後做 與工程量標示,照這個排順序。
已驗證完成 / 進行中 · 2026-06-16 實測

這些已經處理了(不列入待辦)

以下為實測確認已完成或團隊正在修復的項目,從待辦清單獨立出來,讓下面的卡片只剩真正要做的事。

URL 翻轉:/user/<uuid> → 301 → /u/<handle> 已生效
/u 原始 HTML H1:已 SSR 出 display name(實測「榛果🌰」),不再是 @null
hreflang:raw + rendered 都正確指向各語言 profile URL(非語言首頁)
robots.txt:200、只擋 settings/archive/revenue,無 Disallow: /,整站可爬
榜單雙向連結:榜單→創作者、創作者→榜單都已實作(= Task 4.3)
Profile 標籤:已是可點擊連結(惟現指 feed-grid,改連 /category 見 Task 2.1)
noindex 移除:/u 主頁與 /u/<tab> 子頁 — 團隊修復中(見 Batch 1 / Task 4.4)
Tab 子頁去留:決策已定為保留(28k clicks 依據,見 Task 4.4)
01 Batch 1 · 止血 · 最高優先

阻止創作者頁被踢出 Google

現在 /user/<uuid> 全部 301 跳到 /u/<handle>,但 /u 還是 noindex沒有 JSON-LD。Google 沿著跳轉走到 /u 看到 noindex,就會把這頁丟出索引。5 月有 5.4 萬點擊的創作者頁正暴露在這個風險裡。

⚠ 這三項必須「同一次發版」一起上線 — 中間有任何時間差都會持續掉收錄
P1.1 · 止血
移除 /u/<handle> 的 noindex
🔴 急工程量 小
現況

實測 /u/olivia__ 的原始 HTML 仍有 <meta name="robots" content="noindex, nofollow">

為什麼

sitemap 提交的 /user 全部 301 到這頁,Google 跟過來看到 noindex 就會放棄收錄。這是目前最直接的流量風險。

怎麼做

/u/<handle> profile 頁的 robots meta 從 noindex, nofollow 改成 index, follow(或直接移除這個 meta,預設就是可索引)。

只改「有效、可公開、有 handle」的 profile。沒有 handle 或被停權的帳號維持 noindex,且不要進 sitemap。
怎麼算完成
P1.2 · 止血
創作者 sitemap 換成 /u/<handle> 網址
🔴 急工程量 小
現況

實測 /sitemaps/creators-0.xmlcreators-5.xml 裡全是舊的 /user/<uuid> 網址 — 這些現在每一個都會 301。

為什麼

sitemap 不該放會跳轉的網址。應該直接提交最終的 canonical 網址 /u/<handle>,Google 才不用多繞一層,GSC 也不會報「Sitemap 含跳轉」。

怎麼做

產生 sitemap 時,把每筆 <loc>https://swag.live/user/<uuid> 改成 https://swag.live/u/<handle>(沒有 handle 的創作者不要放進 sitemap)。

怎麼算完成
P1.3 · 止血
把 JSON-LD 結構化資料補回 /u
🔴 急工程量 中
現況

實測 /u/olivia__ 原始 HTML 與 rendered DOM 都是 0 個 JSON-LD。舊的 /user 頁本來有 Person/ProfilePage,翻轉後反而消失了。

為什麼

JSON-LD 是給 Google / AI 抽取創作者身分(名字、粉絲數、貼文數)的機器可讀資料。少了它,這頁對搜尋與 AI 引用的辨識度大幅下降。

怎麼做

/u/<handle> 的 server HTML 裡輸出一段 JSON-LD,至少包含:

<!-- 伺服器端直接渲染在 <head> 或 <body> --> <script type="application/ld+json"> { "@context":"https://schema.org", "@type":"ProfilePage", "mainEntity":{ "@type":"Person", "name":"榛果", "alternateName":"olivia__", "url":"https://swag.live/u/olivia__", "image":"https://.../olivia-avatar.jpg", "interactionStatistic":[ {"@type":"InteractionCounter","interactionType":"https://schema.org/FollowAction","userInteractionCount":16500} ] } } </script>
只宣告畫面上真的看得到的東西(visible-content parity)。例如 schema 寫了粉絲數,頁面上也要顯示粉絲數。
怎麼算完成
02 Batch 2 · Profile 內鏈 · 高效益

把 profile 接上會排名的分類頁

方案:保留現有標籤不動,另外在 profile 上加一排「創作者分類按鈕」,連到既有、已經在排名的 /category/ 頁。資料現成(創作者內容本來就掛在分類上),不用建新頁、不用對照表。

P2.1 · 內鏈核心
Profile 加「創作者分類按鈕」,連既有 /category/
🟠 高效益工程量 中
一句話

巨乳的主播,profile 上就放一顆寫著「巨乳」的按鈕,點了連到巨乳分類頁 /category/big_tits 每個創作者依他自己的內容分類,放對應的幾顆按鈕。

為什麼這樣做

實測:同一個詞「巨乳」,/category/big_tits 月點擊 134(排第 3),profile 標籤現在連的 /user-feed-grid/... 只有 28(排第 5)。整個 /category/ 有 9,284 點擊、feed-grid 只有 777。把 30 萬個 profile 的內鏈導向會排名的 /category/,等於把內鏈接到真正有效的頁。

怎麼做 — 三個一定要做對的點

① 連對網址:一定是 /category/,不是 /user-feed-grid/

同一個「巨乳」分類站上有兩個網址,按鈕的連結要填會排名的那個:

用途網址月點擊
✅ 要連這個/category/big_tits134
❌ 不要連這個/user-feed-grid/user_hashtag_big_tits28

② 必須是「真的連結」而且伺服器就先寫好(SSR)

「SSR」= 伺服器送出的原始 HTML 裡就要有這個 <a> 標籤,不是等網頁在瀏覽器跑完 JavaScript 才生出來。因為 Google 和 AI 爬蟲讀的是原始 HTML;如果按鈕是 JS 點擊跳轉、或載入後才出現,爬蟲看不到這條連結,內鏈分數就傳不過去。

③ 按鈕上看得到的文字 = 中文分類名(「巨乳」),不要寫「看更多」

連結文字(anchor text)本身就是排名信號。用「巨乳」當文字連到巨乳分類頁,等於告訴 Google「那頁是講巨乳的」,幫它衝這個關鍵字。寫成「看更多」「探索」或只放 icon 就浪費了。

✅ 正確 — 真 <a>、伺服器渲染、文字是中文分類名、連 /category/
<a href="/category/big_tits">巨乳</a> <a href="/category/legs">美腿</a> <a href="/category/uniform">制服</a>
❌ 這幾種都會讓 SEO 效果歸零
<!-- 不是 <a>,是 JS 點擊 → 爬蟲看不到連結 --> <div onclick="go('big_tits')">巨乳</div> <!-- 文字不是分類名 → 浪費 anchor text --> <a href="/category/big_tits">看更多 ›</a> <!-- 連到排不動的 feed-grid --> <a href="/user-feed-grid/user_hashtag_big_tits">巨乳</a>
只連「白名單內的真分類」。 注意:/category/<任何字串> 都會回 200(catch-all),所以連到不存在的 slug 不會 404,反而生出垃圾頁。按鈕只能用「創作者實際所屬、且在 74 個真分類白名單內」的分類。例:美腿用 /category/legs(真分類),不要用 /category/long_legs(不存在、catch-all 假頁)。personality 詞(lovely 等)目前無分類 → 先不放,等 Task 5.2 建好再加。
怎麼算完成
03 Batch 3 · Metadata 修正 · 高效益、工程量都很小

讓 SERP 顯示正確的創作者身分

三項都很小,可以一起做。目標:搜尋結果裡每個 profile 都穩定顯示同一個創作者(名字 + handle + 頭像),不出現空模板。

P3.1 · Metadata
Title 改成 顯示名稱 (@handle) 格式
🟠 高效益工程量 小
現況

實測 title = olivia__ 直播、影片及限時動態 — 只有 handle,沒有顯示名稱「榛果」。但 H1 其實有「榛果」。

怎麼做

改成:<顯示名稱> (@<handle>)|SWAG 創作者直播、短影音與照片

範例 榛果 Olivia (@olivia__)|SWAG 創作者直播、短影音與照片
有的資料Title 用
名稱 + handle<名稱> (@<handle>)|SWAG 創作者…
只有 handle@<handle>|SWAG 創作者…
兩者都沒有不要 index,也不要放進 sitemap

og:title 用同一份資料來源。

怎麼算完成
P3.2 · Metadata
og:image 改用創作者頭像
🟠 高效益工程量 小
現況

實測 og:image = static/img/share.c190bf8a.jpg(全站通用分享圖),不是這個創作者的頭像。

為什麼

分享到社群、出現在預覽卡時,每個創作者都用同一張通用圖,辨識度與點擊率都差。

怎麼做

og:image 用該創作者的頭像或 profile 專屬公開圖。只有當創作者完全沒有圖、且該頁 noindex 時,才允許退回通用圖。

怎麼算完成
P3.3 · Metadata · 重點
Meta description 改用創作者資料拼接(不再同一模板)
🟠 高效益工程量 小
現況

實測每個 profile 的 description 是同一句模板,只換 handle:

發掘更多 olivia__ 限時私密影片,和 olivia__ 進行更深入的交流!立即註冊與追蹤,和 olivia__ 1 對 1 私訊!還有機會與創作者當面約會!

問題:30 萬頁描述幾乎一樣,Google 視為 boilerplate 重複描述;且沒有任何 creator-specific 事實、還有雙空格殘留。

為什麼這個做法「最小改動、最大成效」

標題用到的那幾個數字(貼文、粉絲、內容類型)畫面上 / stats card 裡本來就有。description 只要「拿同一份資料拼成一句」,不需要新後端、不需要 AI,就讓每頁描述天然不同。一個字串組裝函式 + 缺值整句省略即可。

怎麼做

模板(變數用現成資料):

<名稱>(@<handle>)的 SWAG 主頁:<posts> 則貼文、<followers> 粉絲, 內容有<content_types>。<固定直播句>追蹤即可看限時私密內容與 1 對 1 私訊。
✅ 拼出來的範例(每個創作者數字不同 → 天然唯一)
榛果 Olivia(@olivia__)的 SWAG 主頁:6 則貼文、16.5k 粉絲,內容有限時動態、短影音、照片。固定直播 21:00–22:00。追蹤即可看限時私密內容與 1 對 1 私訊。
缺值規則(關鍵): 沒粉絲就省粉絲、沒貼文就省貼文句、沒直播就省直播句 —— 不要填 0、不要留空格。最後做一次「連續空白縮成一個」清理。名稱缺就用 @handle 開頭。
怎麼算完成
04 Batch 4 · Profile 結構化 · 接著做

把 profile 從孤島變成節點

補上 breadcrumb、相關創作者、榜單回連、子頁處理。讓 profile 跟分類、其他創作者、榜單互相連起來。

P4.1 · 結構化
加 Breadcrumb(麵包屑)+ schema
🟢 後做工程量 小
現況

實測 profile 無 breadcrumb。

怎麼做

頁面上方加:首頁 › 探索 › <主分類> › <創作者>主分類取「該創作者擁有 creator 數最多」的那個分類(不是隨機第一個),語意最準。每層都是真 <a>,再配 BreadcrumbList schema。

怎麼算完成
P4.2 · 結構化
加「相關創作者」區塊(第一版用同分類抽樣)
🟢 後做工程量 中
現況

實測 profile 上 0 個其他創作者連結 — 每頁都是孤島。

怎麼做

第一版不要做複雜演算法。 直接抓「該創作者主分類 hub 底下的 top 8~12 個其他創作者」做成卡片,每張卡是 <a href="/u/<handle>">。這就補上了創作者之間的互鏈。之後再升級成多因子推薦。

怎麼算完成
P4.3 · 結構化
Profile 回連它上榜的榜單(spoke → hub)
✅ 已實作工程量 小
已實作(2026-06-16 確認)。 profile 原始 HTML 已含 /leaderboard/... 回連;榜單頁 → 創作者(hub→spoke)原本就有。雙向都通了,此項可勾完成。
現況

榜單頁 → 連到創作者(hub→spoke)已經做好了(實測 /leaderboard/asia/... 原始 HTML 有 10 個創作者連結)。反方向:創作者 → 連回榜單,也已實作

怎麼做

若創作者出現在某榜單(如「亞洲熱門」),profile 上就放一個連到 /leaderboard/asia/livestream/24h 的真連結。順手做,不急。

怎麼算完成
P4.4 · 結構化 · 已確認保留
Tab 子頁(flix/short/story…)— 救回收錄,不要放棄
✅ 決策:保留🔧 noindex 修復中工程量 中
決策已定(2026-06-16):保留 tab 子頁,noindex 團隊修復中(與主頁同批)。 依據:GSC 實測 tab 子頁 5 月 = 28,284 clicks / 249,122 曝光(1,650 URL)— 比整個 /category/ 還多,屬獨立搜尋需求,不放棄。
/user/<id>/flix 已 301 到 /u/<handle>/flix,後者目前仍 noindex(修復中)。修復完成前這 28k 持續暴露於 deindex,故與 Batch 1 同批處理。
現況(實測)
/user/<id>/flix → 301 → /u/<handle>/flix /u/olivia__/flix → 200 · noindex,nofollow · title「olivia__ | 色情影片」 /u/olivia__/short → 200 · noindex,nofollow · title 卻跟主頁一樣(錯)
決策:保留(不要放棄)

28k 是「創作者名 + 短影音/flix」這類獨立搜尋需求,不是 cannibalize 主頁。放棄(維持 noindex 或 canonical 回主頁)= 直接丟掉 28k 月點擊。

怎麼做
    1. 跟 Batch 1 一起,把 /u/<handle>/<tab>noindex 移除
    2. 維持 self-canonical(指自己)— 不要 canonical 回主 profile,否則會被刪
    3. tab 子頁進 sitemap(用 /u/<handle>/<tab>)
    4. 修 tab 專屬 title(如 short 的 title 不該跟主頁一樣)
若你仍想「集中信號到主頁」而放棄這些頁,代價是這 28k —— 需明確決策後再執行,預設保留。
怎麼算完成
05 Batch 5 · 分類路由修復 · 可獨立排程

堵住 catch-all soft-404

這區跟 Batch 2 解耦,可另外排程。實測重大發現:/category/<任何字串> 都回 200 — 連 /category/asdfqwerty12345 都回 200、H1 印 category_asdfqwerty12345。所以 /category/lovely 這類「不是分類」,只是路由不會 404。真正的分類是 sitemap 裡那 74 個。

P5.1 · 分類路由
未知分類 slug 應回 404 / noindex,不要 soft-200
🟢 後做工程量 小
現況(實測)

/category/<不存在的slug> 一律回 200,H1/title 顯示原始 key category_<slug>

/category/asdfqwerty12345 → 200 · H1「category_asdfqwerty12345」 /category/lovely → 200 · H1「category_lovely」 ← 不是真分類 /category/big_tits → 200 · H1「巨乳」 ← 真分類
為什麼要修

任何打錯字的內部連結、外部亂連、或猜測式爬取,都會生出一個可索引的 category_xxx 垃圾頁(soft-404 / index bloat)。Google 會浪費 crawl budget 在不存在的分類上。

怎麼做

分類路由先比對「合法分類白名單」(就是那 74 個 + 任何已上線的真分類):

    1. slug 在白名單 → 正常渲染分類頁
    2. slug 不在白名單 → 回 HTTP 404(最好),或至少 noindex + 不在 sitemap
    3. 絕對不要再把 category_<slug> 這種原始 key 當標題印出來
怎麼算完成
P5.2 · 未來方向(用戶規劃中)
分類組合頁(如 巨乳 + 熟女 = 新分類)
🅿️ 之後做工程量 中
預告(尚無正式規劃)。 用戶之後計畫做「分類組合頁」:把兩個既有分類交集成一個新分類,例如 巨乳 × 熟女。此處僅記方向佔位,正式規劃出來再展開細節與護欄。
06 Batch 6 · 加值大工程 · 後期

結構化深化 ·具體實現方案

前面做完已能解除風險 + 接上排名;這區是把 profile 變成完整 entity document。執行順序:6.2(純查詢,馬上能上)→ 6.3(加一個欄位)→ 6.1 階段 2(加多個欄位)。先做 6.2。

P6.1 · 大工程
Attribute table(結構化屬性表)
🟢 後做工程量 大
分兩階段,不要一次到位

階段 1(現在、零後台): 只渲染「已經是結構化欄位」的屬性(如地區、語言若本來就有 column)。不要去 parse 自介散文(易出錯、不可靠)。

階段 2(要排程): 後台加 dropdown / number / multi-select 欄位 — 星座(12 下拉)、身高(number)、地區、語言、體型 tag — 由創作者填。

前台 + Schema

前台:兩欄屬性表;自介散文(情緒/故事)另放一個 block,不混進結構化 facts。Schema 對應 Person 欄位:

"height":"164 cm", "knowsLanguage":["zh-TW","en"], "homeLocation":{"@type":"Place","name":"台灣"}
鐵則:visible parity — schema 只宣告畫面上那張表真的顯示的列。沒顯示的不要寫進 schema。
怎麼算完成
P6.2 · 大工程
Stats card 強化(從既有資料 aggregate,零 AI)
🟢 後做工程量 中
為什麼先做這個

全部用既有資料表 aggregate,零後台 schema 改動、零 AI,卻直接補滿 stats card + JSON-LD 的 InteractionCounter。CP 值最高,Batch 6 先做。

資料來源(SQL 範例)
影片數 = COUNT(*) FROM contents WHERE creator_id=? AND type='video' AND is_public 照片數 = COUNT(*) FROM contents WHERE creator_id=? AND type='photo' AND is_public 限時動態數 = COUNT(*) FROM contents WHERE creator_id=? AND type='story' 加入日期 = users.created_at 最近上線 = MAX(streams.started_at) WHERE creator_id=? 平均週直播 = COUNT(streams) / weeks_since_join 固定直播日 = MODE(day_of_week) FROM streams (近 90 天)
畫面 + Schema

畫面:6–12 格 stat grid。Schema 只放真有的數據(沒有評分就不要放 AggregateRating):

<script type="application/ld+json"> "interactionStatistic":[ {"@type":"InteractionCounter","interactionType":"https://schema.org/FollowAction","userInteractionCount":16500}, {"@type":"InteractionCounter","interactionType":"https://schema.org/WatchAction","userInteractionCount":<影片數>} ]
怎麼算完成
P6.3 · 大工程
直播時間改成結構化 schedule
🟢 後做工程量 中
現況

直播時間目前是自介裡的一句散文(如「本月固定 21:00-22:00」),機器無法抽取。

怎麼做

後台加「週一~週日 × 時段 × 類型」結構化欄位(取代散文)。前台用週表呈現,每個時段一個 BroadcastEvent:

{"@type":"BroadcastEvent","name":"榛果固定直播", "startDate":"2026-06-22T21:00+08:00","endDate":"2026-06-22T22:00+08:00", "isAccessibleForFree":false}
順序很重要: 若目前只有散文、還沒有結構化欄位,先別硬塞 schema(會與畫面不一致)。等後台欄位上線、畫面真的顯示週表,再加 schema。
怎麼算完成
P6.4 · 大工程
Template entropy(不同類型創作者不同版面)
🟢 後做工程量 大
內容

新人/高人氣/直播型/內容型/退役 用不同的 block 順序與強調,避免 30 萬頁完全同模板。後台規則引擎判斷類型,前端依類型套版。

怎麼算完成
P6.5 · 大工程
Image sitemap title/caption 驗證強化
🟢 後做工程量 中
內容

image sitemap 已有 image:image。驗證 image:title/image:caption 是否 entity-real(含創作者名 + 內容類型),若是模板填充就改成動態生成。

怎麼算完成