~/blog/n8n-google-sheets-wordpress-dynamic-content-dashboard.md
API 串接與系統整合 · 2025 / 12 / 24 · 3 views

Google Sheets 當 CMS 用?用 n8n 打造 WordPress 動態內容『儀表板』,告別後台編輯地獄!

Eric — 浪花科技創辦人 / AI 架構師
Eric
浪花科技創辦人 · AI 架構師
Google Sheets 當 CMS 用?用 n8n 打造 WordPress 動態內容『儀表板』,告別後台編輯地獄!
目錄 table-of-contents.md

行銷同事丟來一張列了 50 場活動的 Excel 表,要你逐筆 key 進 WordPress 後台:標題、日期、講者、地點,複製貼上到眼花撩亂,一不小心還貼錯欄位。下禮拜表單更新了 20 筆,又得重玩一次「大家來找碴」。與其在後台編輯地獄裡輪迴,不如讓 Google Sheets 直接當 CMS,用 n8n 把它變成 WordPress 的動態內容儀表板。

身為一個有格調的工程師,這種重複性的勞動簡直是對靈魂的拷問。難道就沒有更優雅、更自動化的方式嗎?當然有。今天,我就要帶你玩點進階的,我們要把大家最熟悉的 Google Sheets,直接變成 WordPress 的動態內容「儀表板」,透過低程式碼自動化神器 n8n,實現一處修改、全網同步的魔法。這不只是單純的把 Google Sheets 的內容批次發佈到 WordPress,我們要做到的是「管理」——新增、更重要的是「更新」現有內容,真正把 Google Sheets 當作一個簡易的 CMS (內容管理系統) 來用。

為什麼要用 Google Sheets 管理 WordPress 內容?這不是自找麻煩嗎?

我知道,聽到這個點子,你腦中可能第一個浮現的是:「蛤?放著好好的 WordPress 後台不用,跑去用試算表?這不是脫褲子放屁嗎?」先別急著下定論,聽我這個老司機分析一下,在某些特定情境下,這招簡直是神兵利器:

  • 協作便利性無可比擬: 你不可能期待所有行銷、營運、PM 同事都熟悉 WordPress 後台的操作,尤其是那些充滿了 ACF 或 Metabox 客製化欄位的複雜後台。但 Google Sheets?幾乎是人人上手的基本技能。你只需要把表單權限開給他們,定義好欄位,他們就能輕鬆協作,而你,身為工程師,再也不用當人肉資料搬運工。
  • 無敵的批次處理能力: 想像一下,你需要一次更新 100 個產品的規格參數,或是一次調整 30 位團隊成員的職稱。在 WordPress 後台,這是一場點擊馬拉松。但在 Google Sheets,這不過是下拉、取代、公式運算的事,幾分鐘就能搞定。
  • 內建版本控制與歷史紀錄: 「欸,Eric,上週二下午是誰把 A 活動的日期改錯了?」這種問題在 WordPress 裡很難追溯,但在 Google Sheets,你可以輕鬆調閱完整的修訂歷史紀錄,誰在什麼時間改了哪個儲存格,一目了然,甩鍋都甩不掉。
  • 資料的再利用與分析: 當你的內容以結構化方式存在於 Google Sheets 時,你可以輕易地使用它的圖表、樞紐分析等功能來做數據分析,甚至將這份資料源串接到其他 BI 工具,這是關在 WordPress 資料庫裡的內容難以企及的彈性。

當然,我得囉嗦一句,這個方法不是萬靈丹。如果你的內容是像部落格文章這樣,包含大量複雜排版、圖文混編的非結構化內容,那還是乖乖用 WordPress 編輯器吧。但如果是管理活動列表、產品目錄、團隊成員、分店資訊、作品集...這類「資料驅動」的內容,那 Google Sheets + n8n 絕對是你的效率加速器。

實戰開始:架構我們的『Google Sheets 驅動』內容更新系統

好了,觀念溝通完,我們來動手。要打造這套系統,核心思想只有一個:建立一個獨一無二的「對應鑰匙 (Unique Key)」。這就像是每個人的身分證字號,確保我們在 Google Sheets 裡的每一列資料,都能精準地對應到 WordPress 裡的某一篇文章,這樣 n8n 才知道到底該「更新」誰,而不是傻傻地每次都「新增」。

第一步:準備 WordPress 環境 (CPT 與客製化欄位)

假設我們要管理一個「活動列表 (Events)」。首先,我們需要在 WordPress 建立一個名為 `event` 的自訂文章類型 (Custom Post Type, CPT),並用 ACF (Advanced Custom Fields) 外掛幫它加上幾個欄位:

  • 活動 ID (event_id): 這就是我們的 Unique Key! 欄位類型設為「文字」。它絕對不能重複。
  • 活動日期 (event_date): 欄位類型設為「日期選擇器」。
  • 活動地點 (event_location): 欄位類型設為「文字」。

如果你不想用外掛,也可以把下面這段程式碼加到你主題的 `functions.php` 檔案裡,來手動註冊 CPT。但老實說,為了後續維護,用 ACF 還是比較方便管理的。


<?php
function register_event_post_type() {
    $labels = array(
        'name'                  => _x( '活動', 'Post type general name', 'textdomain' ),
        'singular_name'         => _x( '活動', 'Post type singular name', 'textdomain' ),
        'menu_name'             => _x( '活動列表', 'Admin Menu text', 'textdomain' ),
        'name_admin_bar'        => _x( '活動', 'Add New on Toolbar', 'textdomain' ),
    );
    $args = array(
        'labels'             => $labels,
        'public'             => true,
        'publicly_queryable' => true,
        'show_ui'            => true,
        'show_in_menu'       => true,
        'query_var'          => true,
        'rewrite'            => array( 'slug' => 'events' ),
        'capability_type'    => 'post',
        'has_archive'        => true,
        'hierarchical'       => false,
        'menu_position'      => null,
        'supports'           => array( 'title', 'editor', 'thumbnail' ),
        'show_in_rest'       => true, // 非常重要!要讓 REST API 抓得到
    );
    register_post_type( 'event', $args );
}
add_action( 'init', 'register_event_post_type' );
?>

第二步:準備 Google Sheets 資料源

接著,建立一個 Google Sheet,欄位名稱最好跟 WordPress 的欄位對應起來,方便管理。注意,`event_id` 這一欄是我們自己定義的,必須是獨一無二的,例如 `EVENT-2024-001`、`EVENT-2024-002`。

你的表單看起來會像這樣:

  • Column A: event_id
  • Column B: title
  • Column C: event_date
  • Column D: event_location
  • Column E: content

n8n 工作流拆解:從讀取到更新,一步步打造自動化引擎

重頭戲來了!打開你的 n8n,我們要來畫一個聰明的自動化流程圖。

節點 1: 定時觸發 (Cron)

新增一個 `Cron` 節點,設定一個你認為合適的執行頻率,例如每 15 分鐘跑一次。這代表 n8n 會每 15 分鐘就去檢查一次 Google Sheets 有沒有更新。

節點 2: 讀取 Google Sheets 資料 (Google Sheets)

新增 `Google Sheets` 節點。驗證你的 Google 帳號後,選擇 `Read` 操作,指向你剛剛建立的那個試算表和工作表。記得勾選 `Read all data`。

節點 3: 迴圈處理每一列 (Split In Batches)

從 Google Sheets 拿回來的是一個包含很多列資料的陣列。我們需要一列一列地處理。使用 `Split In Batches` 節點,並將 `Batch Size` 設定為 1。這樣,後續的節點就會為每一列資料都執行一次。

節點 4: 查詢 WordPress 是否已存在 (WordPress)

這是整個流程最關鍵的核心!新增一個 `WordPress` 節點。

  • Resource: `Post`
  • Operation: `Get Many`
  • Post Type: 選擇你建立的 `event`
  • 點擊 `Add Filter`,選擇 `By Meta Key`
  • Key: 輸入 `event_id` (你 ACF 欄位的名稱)
  • Value: 點擊旁邊的齒輪,選擇 `Add Expression`,然後從 `Nodes > SplitInBatches > Output Data > JSON > columns` 裡面,拖曳 `event_id` 這個變數進來。完整的表達式會類似:`{{$json["columns"]["event_id"]}}`

這個節點的作用就是拿著 Google Sheets 每一列的 `event_id`,去 WordPress 資料庫裡問:「嘿!有沒有文章的 `event_id` 欄位是這個值的?」

節點 5: 判斷與分流 (IF)

新增一個 `IF` 節點。我們要用它來判斷上一步的查詢結果。

  • 在 `Value 1` 中,使用表達式 `{{$items(0).json.length}}` 來取得上一個 WordPress 節點回傳的資料筆數。
  • Operation: `Larger Than`
  • Value 2: `0`

如果回傳的資料筆數大於 0,代表 WordPress 裡「已經存在」這篇文章(走 `true` 路徑);如果等於 0,代表是新資料,需要被建立(走 `false` 路徑)。

節點 6A (True 路徑): 更新現有文章 (WordPress)

從 IF 節點的 `true` 輸出端拉一條線,再新增一個 `WordPress` 節點。

  • Resource: `Post`
  • Operation: `Update`
  • Post Type: `event`
  • Post ID: 這裡要填入上上一步(節點 4)查到的文章 ID。表達式會是: `{{$node["WordPress"].json[0].id}}`
  • Title: 從 `SplitInBatches` 節點拖曳 `title` 變數。
  • 點擊 `Add Field`,選擇 `Meta Data`,然後把 `event_date`, `event_location` 等欄位,一一對應到 `SplitInBatches` 的變數。

節點 6B (False 路徑): 建立新文章 (WordPress)

從 IF 節點的 `false` 輸出端拉一條線,新增最後一個 `WordPress` 節點。

  • Resource: `Post`
  • Operation: `Create`
  • Post Type: `event`
  • Status: `Publish`
  • 同樣地,把 `Title`, `Meta Data` (包含 `event_id` 本身也要存進去!) 等所有欄位都從 `SplitInBatches` 節點對應過來。

恭喜你!啟動這個 n8n workflow,現在你的 Google Sheets 就真的變成了一個動態儀表板。無論你在表單上新增一列,還是修改任何一個儲存格的內容,最慢在 15 分鐘內,你的 WordPress 網站就會自動同步更新,完全無需你手動介入。

進階思考與工程師的囉嗦

做到這裡,系統已經能跑了,但身為資深工程師,總是要多想幾步,讓系統更強固。

刪除怎麼辦?

目前的流程只處理了新增和更新,但如果你在 Google Sheets 刪除了一列,WordPress 裡的對應文章並不會消失。一個簡單的作法是在 Google Sheets 新增一個 `status` 欄位,當你想刪除某篇文章時,就把 status 改成 `archived` 或 `deleted`。然後在 n8n 的更新流程中,多一個判斷:如果 status 是 `archived`,就把 WordPress 裡的文章狀態改成「草稿」或「待審」,而不是真的刪除,這樣會比較安全。

效能與即時性

如果你的 Google Sheets 有幾千、幾萬列資料,每 15 分鐘全部掃描一次,對 API 的呼叫次數和執行時間都是不小的負擔。這時候,更好的作法是改用 Webhook。你可以透過 Google Apps Script 寫一小段程式,讓 Google Sheets 在「有編輯時」才主動發送一個 Webhook 通知給 n8n,n8n 只處理被變動的那一列資料。這就從「輪詢 (Polling)」變成了「事件驅動 (Event-driven)」,效率會高非常多。這也牽涉到更深層的Webhook 與 Polling 的架構選擇,值得深入研究。

錯誤處理的藝術

自動化流程最怕的就是「默默地壞掉」。萬一哪天 WordPress 主機掛了,或是 Google API 權限過期,你的 n8n 流程執行失敗,你卻不知道,那資料就會停止同步。專業的做法是在 n8n 流程中加入錯誤處理機制,例如設定一個「Error Trigger」節點,一旦主流程發生錯誤,就觸發另一個流程,發送一條 LINE Notify 或 Slack 通知給你,讓你能第一時間介入處理。這才是打造企業級強韌工作流的關鍵心法。

希望今天的分享能為你打開一扇新的大門,讓你看到 WordPress 與自動化工具結合的巨大潛力。下次再遇到需要大量更新資料的場景,別再埋頭苦幹了,試試看這個方法,把時間留給更有創造力的事情吧!

延伸閱讀

如果你對於打造更複雜的 WordPress 自動化流程,或是需要將現有系統與 WordPress 進行深度整合有任何想法,卻不知從何下手,浪花科技的團隊擁有豐富的 API 串接與客製化開發經驗。歡迎與我們聯繫,讓我們一起聊聊如何讓你的網站變得更聰明、更有效率!

// FAQ

常見問題

什麼情況適合用 Google Sheets 搭配 n8n 管理 WordPress 內容?
適合管理活動列表、產品目錄、團隊成員、分店資訊、作品集這類「資料驅動」的結構化內容。它的優勢在於協作便利、批次處理能力強、內建版本與修訂歷史,以及資料可再利用做分析。但若是含大量複雜排版、圖文混編的非結構化內容(例如部落格文章),仍建議直接使用 WordPress 編輯器。
如何確保 n8n 是「更新」既有文章而不是每次都新增?
關鍵是為每列資料建立一個獨一無二的「對應鑰匙(Unique Key)」,例如在 ACF 設一個不可重複的 event_id 欄位(如 EVENT-2024-001)。n8n 先拿這個 event_id 透過 WordPress 節點的 Get Many 加上 By Meta Key 篩選去查詢文章是否已存在,藉此判斷該執行更新還是新增。
用程式碼註冊自訂文章類型(CPT)時,為什麼要設定 show_in_rest 為 true?
因為要讓 WordPress REST API 能夠抓取到該自訂文章類型的資料。n8n 是透過 REST API 與 WordPress 溝通的,若沒有開啟 show_in_rest,n8n 就無法讀取或操作這個 CPT 的內容。
n8n 一次處理 Google Sheets 多列資料時要如何逐列處理?
從 Google Sheets 讀回的是一個包含多列的陣列,可使用 Split In Batches 節點並將 Batch Size 設為 1,這樣後續節點就會針對每一列資料各執行一次,達到逐列處理的效果。
~/roamer-tech/newsletter // FREE
// newsletter

訂閱免費電子報

把 AI 自動化、企業系統設計與 WordPress / Laravel 開發的真實案例和可直接照做的技巧,整理成電子報寄給你。只寄精選內容、不灌垃圾信,一鍵就能退訂。

$
// final.exec()

準備好讓你的網站開始為你工作了嗎?