<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Automation 知識卡 on Tarragon</title><link>https://tarrragon.github.io/blog/automation/knowledge-cards/</link><description>Recent content in Automation 知識卡 on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 06 Jul 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/automation/knowledge-cards/index.xml" rel="self" type="application/rss+xml"/><item><title>Beacon</title><link>https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/</guid><description>&lt;p>Beacon 是瀏覽器主動送出、且送出後不等待回應的一則事件回報請求。它的用途是把「頁面上發生了某件事」（被瀏覽、被點擊、即將關閉）這個事實，從使用者的瀏覽器回傳到一個接收端記錄下來。在靜態站的 &lt;a href="https://tarrragon.github.io/blog/automation/00-mental-model/static-site-and-glue-layer/" data-link-title="靜態站的能力邊界與膠水層" data-link-desc="靜態站量不到自己流量的根本原因、膠水層補的是哪一塊伺服器能力、以及 client beacon 怎麼把資料送回你手上">client beacon 架構&lt;/a>裡，beacon 是唯一能把瀏覽資料送回你手上的途徑——因為靜態站沒有伺服器 access log 可以被動記錄。可先對照 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/web-app-deployment/" data-link-title="Web App Deployment（Web App 部署）" data-link-desc="把 Apps Script 專案掛成一個有公開網址、可被任何 HTTP 請求呼叫的端點時的部署模型與存取設定">web app 部署&lt;/a>（beacon 送達的接收端怎麼來的）。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>Beacon 跟一般 API 請求的差別在「不等回應」。發起者送出後就繼續做自己的事，不阻塞、不讀回應、不重試——這種模式叫 fire-and-forget。對流量統計這類「送到就好、漏一兩筆無所謂」的場景，fire-and-forget 讓回報完全不影響使用者體驗。beacon 送出的請求由接收端的 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doPost&lt;/a> 進入點接住處理。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>瀏覽器的 &lt;code>navigator.sendBeacon&lt;/code> 是專為此設計的 API：它保證即使頁面正在關閉，請求也會在背景送完，而且預設用 &lt;code>text/plain&lt;/code> 送出，這一點在打跨網域端點時關鍵——&lt;code>text/plain&lt;/code> 屬於 simple request、不觸發 CORS preflight。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>跨網域打 Apps Script 這類端點時，&lt;code>text/plain&lt;/code> 是否夠用決定要不要處理 CORS preflight。實作細節見&lt;a href="https://tarrragon.github.io/blog/automation/02-analytics-beacon/frontend-beacon/" data-link-title="前端 beacon 與 CORS 障礙" data-link-desc="靜態站用瀏覽器送瀏覽事件到 Apps Script 時，為什麼要用 sendBeacon 送 text/plain 才不會被 CORS preflight 擋下">前端 beacon 與 CORS 障礙&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Beacon 是瀏覽器主動送出、且送出後不等待回應的一則事件回報請求。它的用途是把「頁面上發生了某件事」（被瀏覽、被點擊、即將關閉）這個事實，從使用者的瀏覽器回傳到一個接收端記錄下來。在靜態站的 <a href="/blog/automation/00-mental-model/static-site-and-glue-layer/" data-link-title="靜態站的能力邊界與膠水層" data-link-desc="靜態站量不到自己流量的根本原因、膠水層補的是哪一塊伺服器能力、以及 client beacon 怎麼把資料送回你手上">client beacon 架構</a>裡，beacon 是唯一能把瀏覽資料送回你手上的途徑——因為靜態站沒有伺服器 access log 可以被動記錄。可先對照 <a href="/blog/automation/knowledge-cards/web-app-deployment/" data-link-title="Web App Deployment（Web App 部署）" data-link-desc="把 Apps Script 專案掛成一個有公開網址、可被任何 HTTP 請求呼叫的端點時的部署模型與存取設定">web app 部署</a>（beacon 送達的接收端怎麼來的）。</p>
<h2 id="概念位置">概念位置</h2>
<p>Beacon 跟一般 API 請求的差別在「不等回應」。發起者送出後就繼續做自己的事，不阻塞、不讀回應、不重試——這種模式叫 fire-and-forget。對流量統計這類「送到就好、漏一兩筆無所謂」的場景，fire-and-forget 讓回報完全不影響使用者體驗。beacon 送出的請求由接收端的 <a href="/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doPost</a> 進入點接住處理。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>瀏覽器的 <code>navigator.sendBeacon</code> 是專為此設計的 API：它保證即使頁面正在關閉，請求也會在背景送完，而且預設用 <code>text/plain</code> 送出，這一點在打跨網域端點時關鍵——<code>text/plain</code> 屬於 simple request、不觸發 CORS preflight。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>跨網域打 Apps Script 這類端點時，<code>text/plain</code> 是否夠用決定要不要處理 CORS preflight。實作細節見<a href="/blog/automation/02-analytics-beacon/frontend-beacon/" data-link-title="前端 beacon 與 CORS 障礙" data-link-desc="靜態站用瀏覽器送瀏覽事件到 Apps Script 時，為什麼要用 sendBeacon 送 text/plain 才不會被 CORS preflight 擋下">前端 beacon 與 CORS 障礙</a>。</p>
]]></content:encoded></item><item><title>Web App Deployment（Web App 部署）</title><link>https://tarrragon.github.io/blog/automation/knowledge-cards/web-app-deployment/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/automation/knowledge-cards/web-app-deployment/</guid><description>&lt;p>Web app 部署是把一段 Apps Script 程式掛成「有公開網址、可被 HTTP 呼叫」的端點的動作。部署前程式只能在編輯器裡手動執行；部署後它得到一個 &lt;code>https://script.google.com/macros/s/.../exec&lt;/code> 網址，任何符合存取權限的請求打這個網址就會觸發 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doGet 或 doPost&lt;/a>。這是讓 Apps Script 能當 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon&lt;/a> 接收端的前提。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>部署有兩個決定端點行為的設定。&lt;strong>執行身分（execute as）&lt;/strong> 決定程式用誰的權限跑：選「我」時，匿名訪客送來的請求也用你的身分執行，才能存取你的試算表。&lt;strong>誰可存取（who has access）&lt;/strong> 決定誰能呼叫這個網址：接收匿名訪客的 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon&lt;/a> 必須選「所有人」，因為訪客沒有登入 Google。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>一個實務要點是部署與網址的關係：每次「新增部署作業」會產生一個新網址，但改完程式後應該用「管理部署作業」更新既有部署，網址才不變。用錯方式會讓前端指向舊網址、以為程式沒生效。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>誰可存取設為「所有人」後，要判斷的是匿名端點被濫用的風險有多大：存取權限的安全含義見&lt;a href="https://tarrragon.github.io/blog/automation/05-deploy-quota-security/" data-link-title="模組五：部署、配額與安全" data-link-desc="把匿名可存取的 beacon 接收端上線後，怎麼守住免費配額、擋掉濫用、保持資料乾淨、以及判斷何時該換更重的工具">模組五&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>Web app 部署是把一段 Apps Script 程式掛成「有公開網址、可被 HTTP 呼叫」的端點的動作。部署前程式只能在編輯器裡手動執行；部署後它得到一個 <code>https://script.google.com/macros/s/.../exec</code> 網址，任何符合存取權限的請求打這個網址就會觸發 <a href="/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doGet 或 doPost</a>。這是讓 Apps Script 能當 <a href="/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon</a> 接收端的前提。</p>
<h2 id="概念位置">概念位置</h2>
<p>部署有兩個決定端點行為的設定。<strong>執行身分（execute as）</strong> 決定程式用誰的權限跑：選「我」時，匿名訪客送來的請求也用你的身分執行，才能存取你的試算表。<strong>誰可存取（who has access）</strong> 決定誰能呼叫這個網址：接收匿名訪客的 <a href="/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon</a> 必須選「所有人」，因為訪客沒有登入 Google。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>一個實務要點是部署與網址的關係：每次「新增部署作業」會產生一個新網址，但改完程式後應該用「管理部署作業」更新既有部署，網址才不變。用錯方式會讓前端指向舊網址、以為程式沒生效。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>誰可存取設為「所有人」後，要判斷的是匿名端點被濫用的風險有多大：存取權限的安全含義見<a href="/blog/automation/05-deploy-quota-security/" data-link-title="模組五：部署、配額與安全" data-link-desc="把匿名可存取的 beacon 接收端上線後，怎麼守住免費配額、擋掉濫用、保持資料乾淨、以及判斷何時該換更重的工具">模組五</a>。</p>
]]></content:encoded></item><item><title>doGet / doPost</title><link>https://tarrragon.github.io/blog/automation/knowledge-cards/doget-dopost/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/automation/knowledge-cards/doget-dopost/</guid><description>&lt;p>&lt;code>doGet&lt;/code> 與 &lt;code>doPost&lt;/code> 是 Apps Script web app 的兩個進入點函式：端點收到 GET 請求時平台呼叫 &lt;code>doGet(e)&lt;/code>，收到 POST 請求時呼叫 &lt;code>doPost(e)&lt;/code>。它們是 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/web-app-deployment/" data-link-title="Web App Deployment（Web App 部署）" data-link-desc="把 Apps Script 專案掛成一個有公開網址、可被任何 HTTP 請求呼叫的端點時的部署模型與存取設定">web app 部署&lt;/a>後對外行為的定義處——寫什麼在裡面，端點被呼叫時就執行什麼。參數 &lt;code>e&lt;/code> 帶著請求內容：&lt;code>doGet&lt;/code> 從 &lt;code>e.parameter&lt;/code> 拿 query string，&lt;code>doPost&lt;/code> 從 &lt;code>e.postData.contents&lt;/code> 拿請求主體。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>事件物件只帶請求的內容，&lt;strong>不帶任何 HTTP 標頭&lt;/strong>——&lt;code>User-Agent&lt;/code> 與來源 IP 在這裡都讀不到。伺服器端常見的 UA 比對與 IP 判斷因此不可用，需要那些資訊時只能由前端蒐集後放進請求主體送來（見&lt;a href="https://tarrragon.github.io/blog/automation/06-reading-the-data/automated-traffic/" data-link-title="辨識自動化流量" data-link-desc="接收端讀不到 HTTP 標頭時在前端蒐集訊號分辨機器與真人；多數 AI 訓練爬蟲不執行 JavaScript，因此不會出現在這份統計裡">辨識自動化流量&lt;/a>）。&lt;/p>
&lt;p>兩個函式都必須回傳一個 &lt;code>ContentService&lt;/code> 或 &lt;code>HtmlService&lt;/code> 的輸出，這是平台的硬性要求；不回傳會被當成執行沒有正常結束。接收 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon&lt;/a> 這類「送資料進來」的場景用 &lt;code>doPost&lt;/code>，因為 &lt;code>sendBeacon&lt;/code> 送的是 POST，主體放在 &lt;code>e.postData.contents&lt;/code>（是個字串，需要自己 &lt;code>JSON.parse&lt;/code>）。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>一個影響靜態站的關鍵限制是：Apps Script &lt;strong>沒有&lt;/strong> &lt;code>doOptions&lt;/code>。跨網域請求的 CORS preflight 會送 &lt;code>OPTIONS&lt;/code>，但它打不到你的程式、平台的預設回應也不帶 CORS 許可標頭，於是 preflight 失敗、真正的請求送不出去。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>這是「用 &lt;code>fetch&lt;/code> 送 &lt;code>application/json&lt;/code> 打 Apps Script 得到 CORS 錯誤」的根因，繞法是讓請求成為不觸發 preflight 的 simple request，見&lt;a href="https://tarrragon.github.io/blog/automation/02-analytics-beacon/frontend-beacon/" data-link-title="前端 beacon 與 CORS 障礙" data-link-desc="靜態站用瀏覽器送瀏覽事件到 Apps Script 時，為什麼要用 sendBeacon 送 text/plain 才不會被 CORS preflight 擋下">前端 beacon 與 CORS 障礙&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p><code>doGet</code> 與 <code>doPost</code> 是 Apps Script web app 的兩個進入點函式：端點收到 GET 請求時平台呼叫 <code>doGet(e)</code>，收到 POST 請求時呼叫 <code>doPost(e)</code>。它們是 <a href="/blog/automation/knowledge-cards/web-app-deployment/" data-link-title="Web App Deployment（Web App 部署）" data-link-desc="把 Apps Script 專案掛成一個有公開網址、可被任何 HTTP 請求呼叫的端點時的部署模型與存取設定">web app 部署</a>後對外行為的定義處——寫什麼在裡面，端點被呼叫時就執行什麼。參數 <code>e</code> 帶著請求內容：<code>doGet</code> 從 <code>e.parameter</code> 拿 query string，<code>doPost</code> 從 <code>e.postData.contents</code> 拿請求主體。</p>
<h2 id="概念位置">概念位置</h2>
<p>事件物件只帶請求的內容，<strong>不帶任何 HTTP 標頭</strong>——<code>User-Agent</code> 與來源 IP 在這裡都讀不到。伺服器端常見的 UA 比對與 IP 判斷因此不可用，需要那些資訊時只能由前端蒐集後放進請求主體送來（見<a href="/blog/automation/06-reading-the-data/automated-traffic/" data-link-title="辨識自動化流量" data-link-desc="接收端讀不到 HTTP 標頭時在前端蒐集訊號分辨機器與真人；多數 AI 訓練爬蟲不執行 JavaScript，因此不會出現在這份統計裡">辨識自動化流量</a>）。</p>
<p>兩個函式都必須回傳一個 <code>ContentService</code> 或 <code>HtmlService</code> 的輸出，這是平台的硬性要求；不回傳會被當成執行沒有正常結束。接收 <a href="/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon</a> 這類「送資料進來」的場景用 <code>doPost</code>，因為 <code>sendBeacon</code> 送的是 POST，主體放在 <code>e.postData.contents</code>（是個字串，需要自己 <code>JSON.parse</code>）。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>一個影響靜態站的關鍵限制是：Apps Script <strong>沒有</strong> <code>doOptions</code>。跨網域請求的 CORS preflight 會送 <code>OPTIONS</code>，但它打不到你的程式、平台的預設回應也不帶 CORS 許可標頭，於是 preflight 失敗、真正的請求送不出去。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>這是「用 <code>fetch</code> 送 <code>application/json</code> 打 Apps Script 得到 CORS 錯誤」的根因，繞法是讓請求成為不觸發 preflight 的 simple request，見<a href="/blog/automation/02-analytics-beacon/frontend-beacon/" data-link-title="前端 beacon 與 CORS 障礙" data-link-desc="靜態站用瀏覽器送瀏覽事件到 Apps Script 時，為什麼要用 sendBeacon 送 text/plain 才不會被 CORS preflight 擋下">前端 beacon 與 CORS 障礙</a>。</p>
]]></content:encoded></item><item><title>Execution Quota（執行配額）</title><link>https://tarrragon.github.io/blog/automation/knowledge-cards/execution-quota/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/automation/knowledge-cards/execution-quota/</guid><description>&lt;p>執行配額是 Apps Script 對免費個人帳號設的一組執行上限，決定膠水層能承受多大的量。對個人（gmail.com）帳號，關鍵的三條是：單次執行最長 6 分鐘、同時併發最多 30 個執行、觸發器每日總執行時間 90 分鐘。理解這些上限才能判斷免費夠不夠，選型的完整討論見&lt;a href="https://tarrragon.github.io/blog/automation/00-mental-model/free-tier-and-tool-choice/" data-link-title="免費額度的思考方式與工具選型" data-link-desc="判斷免費膠水層撐不撐得住自己流量時該看哪個限制、以及 Apps Script 與 Cloudflare Workers 各自適合什麼場景">免費額度的思考方式與工具選型&lt;/a>。配額同時限制 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/web-app-deployment/" data-link-title="Web App Deployment（Web App 部署）" data-link-desc="把 Apps Script 專案掛成一個有公開網址、可被任何 HTTP 請求呼叫的端點時的部署模型與存取設定">web app 部署&lt;/a> 端點的併發與&lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/time-driven-trigger/" data-link-title="Time-Driven Trigger（時間觸發器）" data-link-desc="讓 Apps Script 在固定時間自動執行的排程機制，把被動等呼叫的膠水層變成主動定時跑的任務">時間觸發器&lt;/a>的總執行時間。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>觸發器的 90 分鐘每日總時間是另一條線，影響的是&lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/time-driven-trigger/" data-link-title="Time-Driven Trigger（時間觸發器）" data-link-desc="讓 Apps Script 在固定時間自動執行的排程機制，把被動等呼叫的膠水層變成主動定時跑的任務">時間觸發器&lt;/a>做的排程彙總，不是接收 beacon。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>估算容量時該看的是&lt;strong>併發&lt;/strong>而非總量。接收 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon&lt;/a> 的膠水層，每次執行只寫一筆、幾百毫秒結束，遠用不到 6 分鐘；binding 的限制是「同一瞬間最多 30 個 beacon 在處理」。個人 blog 的流量分散在整天、任何瞬間的併發都遠低於 30，所以不會撞牆；會逼近上限的是「某篇文章短時間爆量」這種尖峰。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>值得注意的是個人帳號的配額比 Google Workspace 帳號低，所以同一段程式在測試帳號能過、在別的帳號可能撞限。碰到配額上限的處理見&lt;a href="https://tarrragon.github.io/blog/automation/05-deploy-quota-security/" data-link-title="模組五：部署、配額與安全" data-link-desc="把匿名可存取的 beacon 接收端上線後，怎麼守住免費配額、擋掉濫用、保持資料乾淨、以及判斷何時該換更重的工具">模組五&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>執行配額是 Apps Script 對免費個人帳號設的一組執行上限，決定膠水層能承受多大的量。對個人（gmail.com）帳號，關鍵的三條是：單次執行最長 6 分鐘、同時併發最多 30 個執行、觸發器每日總執行時間 90 分鐘。理解這些上限才能判斷免費夠不夠，選型的完整討論見<a href="/blog/automation/00-mental-model/free-tier-and-tool-choice/" data-link-title="免費額度的思考方式與工具選型" data-link-desc="判斷免費膠水層撐不撐得住自己流量時該看哪個限制、以及 Apps Script 與 Cloudflare Workers 各自適合什麼場景">免費額度的思考方式與工具選型</a>。配額同時限制 <a href="/blog/automation/knowledge-cards/web-app-deployment/" data-link-title="Web App Deployment（Web App 部署）" data-link-desc="把 Apps Script 專案掛成一個有公開網址、可被任何 HTTP 請求呼叫的端點時的部署模型與存取設定">web app 部署</a> 端點的併發與<a href="/blog/automation/knowledge-cards/time-driven-trigger/" data-link-title="Time-Driven Trigger（時間觸發器）" data-link-desc="讓 Apps Script 在固定時間自動執行的排程機制，把被動等呼叫的膠水層變成主動定時跑的任務">時間觸發器</a>的總執行時間。</p>
<h2 id="概念位置">概念位置</h2>
<p>觸發器的 90 分鐘每日總時間是另一條線，影響的是<a href="/blog/automation/knowledge-cards/time-driven-trigger/" data-link-title="Time-Driven Trigger（時間觸發器）" data-link-desc="讓 Apps Script 在固定時間自動執行的排程機制，把被動等呼叫的膠水層變成主動定時跑的任務">時間觸發器</a>做的排程彙總，不是接收 beacon。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>估算容量時該看的是<strong>併發</strong>而非總量。接收 <a href="/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon</a> 的膠水層，每次執行只寫一筆、幾百毫秒結束，遠用不到 6 分鐘；binding 的限制是「同一瞬間最多 30 個 beacon 在處理」。個人 blog 的流量分散在整天、任何瞬間的併發都遠低於 30，所以不會撞牆；會逼近上限的是「某篇文章短時間爆量」這種尖峰。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>值得注意的是個人帳號的配額比 Google Workspace 帳號低，所以同一段程式在測試帳號能過、在別的帳號可能撞限。碰到配額上限的處理見<a href="/blog/automation/05-deploy-quota-security/" data-link-title="模組五：部署、配額與安全" data-link-desc="把匿名可存取的 beacon 接收端上線後，怎麼守住免費配額、擋掉濫用、保持資料乾淨、以及判斷何時該換更重的工具">模組五</a>。</p>
]]></content:encoded></item><item><title>Time-Driven Trigger（時間觸發器）</title><link>https://tarrragon.github.io/blog/automation/knowledge-cards/time-driven-trigger/</link><pubDate>Mon, 06 Jul 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/automation/knowledge-cards/time-driven-trigger/</guid><description>&lt;p>時間觸發器（time-driven trigger）是讓 Apps Script 在固定時間自動執行某個函式的排程機制。它把膠水層從「被動等 HTTP 請求呼叫」（見 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doGet / doPost&lt;/a>）變成「主動定時執行」——不需要有人打網址，到點就自己跑。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>流量統計用它把 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon&lt;/a> 累積的原始 log 每天彙總成一張日報表，實作見&lt;a href="https://tarrragon.github.io/blog/automation/04-triggers-automation/" data-link-title="模組四：觸發器與排程" data-link-desc="用 Apps Script 的時間觸發器把累積的原始瀏覽 log 定時彙總成看得懂的日報，以及觸發器的每日執行配額">模組四&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>時間觸發器可以設成每分鐘、每小時、每天固定時段、或每週執行。典型用法是「每天凌晨把前一天的 raw log 依日期與路徑 group 成彙總表」，讓人打開試算表看到的是整理過的數字、而不是逐筆原始紀錄。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>觸發器的成本受&lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/execution-quota/" data-link-title="Execution Quota（執行配額）" data-link-desc="Apps Script 個人帳號的執行時間、同時併發與觸發器每日總時間上限，決定免費膠水層能承受多大的量">執行配額&lt;/a>約束：個人帳號所有觸發器每天總執行時間上限 90 分鐘。所以彙總邏輯要寫得有效率，資料量大時避免每次都全表掃描——這條線在原始 log 累積到很多列時才會逼近，判讀與最佳化見&lt;a href="https://tarrragon.github.io/blog/automation/03-sheet-as-database/" data-link-title="模組三：Sheets 當資料庫" data-link-desc="用 Google Sheet 存流量資料時，怎麼處理多個 beacon 同時寫入的並發、設計資料模型、以及判斷資料量到哪會撐不住">模組三：Sheets 的容量邊界&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>時間觸發器（time-driven trigger）是讓 Apps Script 在固定時間自動執行某個函式的排程機制。它把膠水層從「被動等 HTTP 請求呼叫」（見 <a href="/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doGet / doPost</a>）變成「主動定時執行」——不需要有人打網址，到點就自己跑。</p>
<h2 id="概念位置">概念位置</h2>
<p>流量統計用它把 <a href="/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon</a> 累積的原始 log 每天彙總成一張日報表，實作見<a href="/blog/automation/04-triggers-automation/" data-link-title="模組四：觸發器與排程" data-link-desc="用 Apps Script 的時間觸發器把累積的原始瀏覽 log 定時彙總成看得懂的日報，以及觸發器的每日執行配額">模組四</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>時間觸發器可以設成每分鐘、每小時、每天固定時段、或每週執行。典型用法是「每天凌晨把前一天的 raw log 依日期與路徑 group 成彙總表」，讓人打開試算表看到的是整理過的數字、而不是逐筆原始紀錄。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>觸發器的成本受<a href="/blog/automation/knowledge-cards/execution-quota/" data-link-title="Execution Quota（執行配額）" data-link-desc="Apps Script 個人帳號的執行時間、同時併發與觸發器每日總時間上限，決定免費膠水層能承受多大的量">執行配額</a>約束：個人帳號所有觸發器每天總執行時間上限 90 分鐘。所以彙總邏輯要寫得有效率，資料量大時避免每次都全表掃描——這條線在原始 log 累積到很多列時才會逼近，判讀與最佳化見<a href="/blog/automation/03-sheet-as-database/" data-link-title="模組三：Sheets 當資料庫" data-link-desc="用 Google Sheet 存流量資料時，怎麼處理多個 beacon 同時寫入的並發、設計資料模型、以及判斷資料量到哪會撐不住">模組三：Sheets 的容量邊界</a>。</p>
]]></content:encoded></item><item><title>Browser Fingerprint（瀏覽器指紋）</title><link>https://tarrragon.github.io/blog/automation/knowledge-cards/browser-fingerprint/</link><pubDate>Mon, 03 Aug 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/automation/knowledge-cards/browser-fingerprint/</guid><description>&lt;p>瀏覽器指紋是由多個環境屬性組合而成、足以辨識出特定裝置的特徵集合。單獨看每一項都不足以識別任何人——螢幕解析度、時區、語言偏好、已安裝字型、&lt;code>userAgent&lt;/code> 字串各自都被大量使用者共享；組合起來之後唯一性急遽上升，少數幾項就能把一台裝置從數百萬台中分出來，而且不需要寫入任何 cookie。這是在自建流量統計裡蒐集判別訊號時的能力上限，與 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon&lt;/a> 送出什麼欄位直接相關。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>指紋與識別碼是兩種不同的識別途徑。識別碼（存在 &lt;code>localStorage&lt;/code> 的隨機值）由網站產生、使用者可以清除、內容不從個人推導；指紋由使用者的環境被動產生、清除不掉、也不需要對方同意就能取得。這個差別決定了設計取向：&lt;strong>自建統計要辨識「是不是同一個瀏覽器」時用識別碼，用指紋做同一件事會在使用者無法拒絕的前提下達成，兩者的技術效果相近而性質不同&lt;/strong>。指紋的另一個用途是分辨自動化環境。在 Apps Script 這類接收端上，判別素材只能由前端蒐集後隨 beacon 送出——&lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doPost&lt;/a> 拿不到任何 HTTP 標頭，伺服器端的 UA 與 IP 比對都不可用。做法與邊界見&lt;a href="https://tarrragon.github.io/blog/automation/06-reading-the-data/automated-traffic/" data-link-title="辨識自動化流量" data-link-desc="接收端讀不到 HTTP 標頭時在前端蒐集訊號分辨機器與真人；多數 AI 訓練爬蟲不執行 JavaScript，因此不會出現在這份統計裡">辨識自動化流量&lt;/a>。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>高熵的屬性包括完整 &lt;code>userAgent&lt;/code>（含版本與作業系統細節）、螢幕解析度與色彩深度、時區、字型清單、WebGL 渲染器名稱。低熵而仍有分析價值的替代品是把這些降維成分類標籤——&lt;code>mobile&lt;/code> / &lt;code>tablet&lt;/code> / &lt;code>desktop&lt;/code> 三選一的裝置類別由 &lt;code>userAgent&lt;/code> 推導而來，但送出的是分類結果而非原始字串，唯一性大幅下降而排版決策所需的資訊仍然保留。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>判斷一個欄位該不該送，問它「單獨無害，但與已送出的欄位組合後唯一性有多高」。答案是「組合後接近唯一」時，改送降維後的分類標籤而非原始值。這條界線在&lt;a href="https://tarrragon.github.io/blog/automation/06-reading-the-data/visitor-identity/" data-link-title="訪客識別與 opt-out" data-link-desc="流量記錄裡的來源網址大量空白、任兩列之間看不出是不是同一個人時，補上識別欄位並保留退出機制">訪客識別與 opt-out&lt;/a>的隱私邊界段有完整的取捨說明，配額與 PII 的整體討論見 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/execution-quota/" data-link-title="Execution Quota（執行配額）" data-link-desc="Apps Script 個人帳號的執行時間、同時併發與觸發器每日總時間上限，決定免費膠水層能承受多大的量">execution quota&lt;/a> 所在的&lt;a href="https://tarrragon.github.io/blog/automation/05-deploy-quota-security/quota-abuse-privacy/" data-link-title="配額、濫用防護、隱私與遷移訊號" data-link-desc="免費配額實際碰撞時會怎樣、擋髒資料與過濾自己瀏覽的做法、不記 PII 的隱私立場、以及量大到該離開 Sheets 的訊號">模組五&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>瀏覽器指紋是由多個環境屬性組合而成、足以辨識出特定裝置的特徵集合。單獨看每一項都不足以識別任何人——螢幕解析度、時區、語言偏好、已安裝字型、<code>userAgent</code> 字串各自都被大量使用者共享；組合起來之後唯一性急遽上升，少數幾項就能把一台裝置從數百萬台中分出來，而且不需要寫入任何 cookie。這是在自建流量統計裡蒐集判別訊號時的能力上限，與 <a href="/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon</a> 送出什麼欄位直接相關。</p>
<h2 id="概念位置">概念位置</h2>
<p>指紋與識別碼是兩種不同的識別途徑。識別碼（存在 <code>localStorage</code> 的隨機值）由網站產生、使用者可以清除、內容不從個人推導；指紋由使用者的環境被動產生、清除不掉、也不需要對方同意就能取得。這個差別決定了設計取向：<strong>自建統計要辨識「是不是同一個瀏覽器」時用識別碼，用指紋做同一件事會在使用者無法拒絕的前提下達成，兩者的技術效果相近而性質不同</strong>。指紋的另一個用途是分辨自動化環境。在 Apps Script 這類接收端上，判別素材只能由前端蒐集後隨 beacon 送出——<a href="/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doPost</a> 拿不到任何 HTTP 標頭，伺服器端的 UA 與 IP 比對都不可用。做法與邊界見<a href="/blog/automation/06-reading-the-data/automated-traffic/" data-link-title="辨識自動化流量" data-link-desc="接收端讀不到 HTTP 標頭時在前端蒐集訊號分辨機器與真人；多數 AI 訓練爬蟲不執行 JavaScript，因此不會出現在這份統計裡">辨識自動化流量</a>。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>高熵的屬性包括完整 <code>userAgent</code>（含版本與作業系統細節）、螢幕解析度與色彩深度、時區、字型清單、WebGL 渲染器名稱。低熵而仍有分析價值的替代品是把這些降維成分類標籤——<code>mobile</code> / <code>tablet</code> / <code>desktop</code> 三選一的裝置類別由 <code>userAgent</code> 推導而來，但送出的是分類結果而非原始字串，唯一性大幅下降而排版決策所需的資訊仍然保留。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>判斷一個欄位該不該送，問它「單獨無害，但與已送出的欄位組合後唯一性有多高」。答案是「組合後接近唯一」時，改送降維後的分類標籤而非原始值。這條界線在<a href="/blog/automation/06-reading-the-data/visitor-identity/" data-link-title="訪客識別與 opt-out" data-link-desc="流量記錄裡的來源網址大量空白、任兩列之間看不出是不是同一個人時，補上識別欄位並保留退出機制">訪客識別與 opt-out</a>的隱私邊界段有完整的取捨說明，配額與 PII 的整體討論見 <a href="/blog/automation/knowledge-cards/execution-quota/" data-link-title="Execution Quota（執行配額）" data-link-desc="Apps Script 個人帳號的執行時間、同時併發與觸發器每日總時間上限，決定免費膠水層能承受多大的量">execution quota</a> 所在的<a href="/blog/automation/05-deploy-quota-security/quota-abuse-privacy/" data-link-title="配額、濫用防護、隱私與遷移訊號" data-link-desc="免費配額實際碰撞時會怎樣、擋髒資料與過濾自己瀏覽的做法、不記 PII 的隱私立場、以及量大到該離開 Sheets 的訊號">模組五</a>。</p>
]]></content:encoded></item><item><title>Executions（執行項目）</title><link>https://tarrragon.github.io/blog/automation/knowledge-cards/executions-page/</link><pubDate>Mon, 03 Aug 2026 00:00:00 +0800</pubDate><guid>https://tarrragon.github.io/blog/automation/knowledge-cards/executions-page/</guid><description>&lt;p>執行項目是 Apps Script 編輯器左側的一個頁面，列出這個專案每一次函式執行的時間、耗時、觸發方式與狀態。它記錄的是平台實際跑過什麼，因此是這類架構裡唯一不依賴推測的觀測點——程式碼只顯示它宣稱會做什麼，執行項目顯示它做了什麼。接收 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon&lt;/a> 的 &lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doPost&lt;/a> 每被呼叫一次就在這裡留下一列。&lt;/p>
&lt;h2 id="概念位置">概念位置&lt;/h2>
&lt;p>這個頁面回答的問題是「請求有沒有抵達端點」，而它把故障範圍切成兩半：&lt;strong>有執行紀錄但狀態失敗&lt;/strong>代表請求送達了、接收端出錯；&lt;strong>完全沒有對應時間的執行紀錄&lt;/strong>代表請求根本沒送出來，問題在瀏覽器端或網路。兩者的排查方向相反，而在此之前它們的症狀完全相同——試算表都沒有新資料。&lt;/p>
&lt;p>它與 &lt;code>Logger.log&lt;/code> 的分工也在這裡：&lt;code>Logger&lt;/code> 記錄的是程式自己選擇要說的話，執行項目記錄的是平台觀察到的事實，程式在第一行就爆掉時前者什麼都沒有、後者仍有一列失敗紀錄。判讀失敗紀錄時常要對照&lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/execution-quota/" data-link-title="Execution Quota（執行配額）" data-link-desc="Apps Script 個人帳號的執行時間、同時併發與觸發器每日總時間上限，決定免費膠水層能承受多大的量">執行配額&lt;/a>的三條上限，因為逼近上限的症狀（耗時拉長、密集失敗）都先出現在這一頁。&lt;/p>
&lt;h2 id="可觀察訊號與例子">可觀察訊號與例子&lt;/h2>
&lt;p>一次正常的 beacon 接收在這裡是「&lt;code>doPost&lt;/code> / 網頁應用程式 / 一秒出頭 / 已完成」。耗時異常拉長是逼近&lt;a href="https://tarrragon.github.io/blog/automation/knowledge-cards/execution-quota/" data-link-title="Execution Quota（執行配額）" data-link-desc="Apps Script 個人帳號的執行時間、同時併發與觸發器每日總時間上限，決定免費膠水層能承受多大的量">執行配額&lt;/a>單次上限的前兆；同一時段出現大量失敗則指向併發撞頂。&lt;/p>
&lt;p>版本欄位還洩漏另一件事：它顯示這次執行用的是哪一個部署版本，因此「程式碼改了但端點跑舊版」這個假故障在這裡看得出來。&lt;/p>
&lt;h2 id="判讀方式">判讀方式&lt;/h2>
&lt;p>排查「資料沒進來」時先開這一頁，再決定往哪個方向查——這一步的成本是開一個頁面，而它省下的是往錯誤方向排查的整段時間。實際運用見&lt;a href="https://tarrragon.github.io/blog/automation/06-reading-the-data/diagnosing-silent-failures/" data-link-title="假故障與靜默失效的診斷" data-link-desc="自建的 Apps Script 流量統計看起來壞了、或看起來正常但數字不對時，分辨症狀出現的位置與問題所在的位置">假故障與靜默失效的診斷&lt;/a>。&lt;/p></description><content:encoded><![CDATA[<p>執行項目是 Apps Script 編輯器左側的一個頁面，列出這個專案每一次函式執行的時間、耗時、觸發方式與狀態。它記錄的是平台實際跑過什麼，因此是這類架構裡唯一不依賴推測的觀測點——程式碼只顯示它宣稱會做什麼，執行項目顯示它做了什麼。接收 <a href="/blog/automation/knowledge-cards/beacon/" data-link-title="Beacon" data-link-desc="瀏覽器在頁面事件發生時主動送出、送出後不等回應的一則事件回報請求，用於靜態站把資料回傳給接收端">beacon</a> 的 <a href="/blog/automation/knowledge-cards/doget-dopost/" data-link-title="doGet / doPost" data-link-desc="Apps Script web app 的兩個進入點函式，分別接住 GET 與 POST 請求，決定端點收到請求時執行什麼">doPost</a> 每被呼叫一次就在這裡留下一列。</p>
<h2 id="概念位置">概念位置</h2>
<p>這個頁面回答的問題是「請求有沒有抵達端點」，而它把故障範圍切成兩半：<strong>有執行紀錄但狀態失敗</strong>代表請求送達了、接收端出錯；<strong>完全沒有對應時間的執行紀錄</strong>代表請求根本沒送出來，問題在瀏覽器端或網路。兩者的排查方向相反，而在此之前它們的症狀完全相同——試算表都沒有新資料。</p>
<p>它與 <code>Logger.log</code> 的分工也在這裡：<code>Logger</code> 記錄的是程式自己選擇要說的話，執行項目記錄的是平台觀察到的事實，程式在第一行就爆掉時前者什麼都沒有、後者仍有一列失敗紀錄。判讀失敗紀錄時常要對照<a href="/blog/automation/knowledge-cards/execution-quota/" data-link-title="Execution Quota（執行配額）" data-link-desc="Apps Script 個人帳號的執行時間、同時併發與觸發器每日總時間上限，決定免費膠水層能承受多大的量">執行配額</a>的三條上限，因為逼近上限的症狀（耗時拉長、密集失敗）都先出現在這一頁。</p>
<h2 id="可觀察訊號與例子">可觀察訊號與例子</h2>
<p>一次正常的 beacon 接收在這裡是「<code>doPost</code> / 網頁應用程式 / 一秒出頭 / 已完成」。耗時異常拉長是逼近<a href="/blog/automation/knowledge-cards/execution-quota/" data-link-title="Execution Quota（執行配額）" data-link-desc="Apps Script 個人帳號的執行時間、同時併發與觸發器每日總時間上限，決定免費膠水層能承受多大的量">執行配額</a>單次上限的前兆；同一時段出現大量失敗則指向併發撞頂。</p>
<p>版本欄位還洩漏另一件事：它顯示這次執行用的是哪一個部署版本，因此「程式碼改了但端點跑舊版」這個假故障在這裡看得出來。</p>
<h2 id="判讀方式">判讀方式</h2>
<p>排查「資料沒進來」時先開這一頁，再決定往哪個方向查——這一步的成本是開一個頁面，而它省下的是往錯誤方向排查的整段時間。實際運用見<a href="/blog/automation/06-reading-the-data/diagnosing-silent-failures/" data-link-title="假故障與靜默失效的診斷" data-link-desc="自建的 Apps Script 流量統計看起來壞了、或看起來正常但數字不對時，分辨症狀出現的位置與問題所在的位置">假故障與靜默失效的診斷</a>。</p>
]]></content:encoded></item></channel></rss>