CodeGym /課程 /ChatGPT Apps /Privacy Policy、Terms、Support:必備的法律頁面

Privacy Policy、Terms、Support:必備的法律頁面

ChatGPT Apps
等級 18 , 課堂 1
開放

1. 為什麼需要 Privacy Policy、Terms 和 Support

先說殘酷的事實:對 ChatGPT Store 而言,公開的隱私權政策與支援聯絡資訊並不是「禮貌」,而是硬性要求。OpenAI 的指引明確寫道,每個 App 都必須有已發佈的 Privacy Policy,清楚說明收集哪些資料、如何使用,並提供支援聯絡方式。

但這件事不只是「讓審核員別來煩」。這些文件同時解決多個問題。

其一,這是給使用者的基本信任門檻。他會看到這個應用背後有真人或公司、遊戲規則是什麼,遇到問題有地方可去。在「又一個 AI 服務」天天冒出的世界裡,這已經是競爭優勢。

其二,這是把你在架構上已經做的事正式文字化。你在安全、記錄、保留期、資料刪除與金流處理等模組做過的決定,都需要被文字清楚表述。若你承諾「不保存對話」,卻把所有 tool‑input 永久寫進日誌,這不只是不好看——還可能引發嚴重投訴。

其三,這是你與 OpenAI 之間的另一層契約。Store 等於是在說:「我們願意把你的 App 展示給數百萬人,但你必須誠實說明你會怎麼處理他們,且在出問題時保持聯絡暢通。」

總結一下:法律頁面不是「被法務逼的」。它用來對齊預期:App 做什麼、會觸碰哪些資料、你願意承擔何種責任,以及使用者如何與你聯繫。

2. 這些法律 URL 在 ChatGPT App 裡應該放哪?

技術上,對 ChatGPT App 而言,法律頁面就是你在應用中繼資料與 Store 列表中填入的公開 URL。指引裡通常把它們叫作 privacy_policy_urlterms_of_service_url 與支援聯絡方式(support contact)。

這些 URL 應符合幾個簡單但重要的條件:

  1. 它們放在你產品或公司的穩定網域上。 不要用臨時的 ngrok 連結,否則一週後 Store 會把使用者帶到無處可去。
  2. 它們在未登入的情況下可存取。 使用者(與審核者)應能直接以瀏覽器開啟,無需登入或繁瑣步驟。
  3. 內容要即時且與實際一致。 如果你更動了資料處理的架構,之後也要更新文件文字。

在我們的教學專案 GiftGenius 裡,已有使用 Next.js 的前端,部署在 Vercel。那麼法律頁面最合適的位置就是這些路由:

  • /legal/privacy
  • /legal/terms
  • /support

本質上它們只是應用中的另外三個頁面,但你會在 App 送審表單裡引用這些頁面。

3. Privacy Policy:如何誠實描述你對資料做了什麼

Privacy Policy 的角色

Privacy Policy(隱私權政策,下文簡稱「Policy」)回答的核心問題是: 「這個 App 對我的(使用者)資料做了什麼?」它應描述你處理哪些資料類別、來源是什麼、用途為何、在哪裡保存、保存多久、會提供給誰,以及使用者如何要求刪除。

ChatGPT Apps 的特殊性在於,使用者需要知道你究竟從對話中拿到了什麼。OpenAI 另外強調:你的 App 不應嘗試還原整段對話,而只能處理模型或使用者明確送進工具的片段。這點也應在 Policy 中說明。

別從寫文案開始,先盤點架構

在寫任何法律文字之前,先用 SRE/架構師的視角看你的 App:實際有哪些資料流過系統。

以我們的例子 GiftGenius,大致可長這樣:

資料類別 來源 儲存位置 保留期 / 行為
請求文字(聊天片段 snippet) 來自 ChatGPT 的工具呼叫 後端請求日誌 保留 N 天或立刻刪除
使用者選擇的禮物 小工具中的操作 GiftGenius 資料庫 保留至帳號刪除
使用者 Email(若啟用 OAuth) 身分驗證提供者 使用者資料庫 只要帳號仍啟用
技術量測(IP、時間戳、錯誤) HTTP 請求 日誌 / 監控系統 依日誌政策保留 N 天

建議把這樣的表格直接放進專案文件(例如 /docs):對開發、安全模組與 Policy 本身都很有用。

接著把這個結構「翻譯」成一般人看得懂的語句。

GiftGenius 的 Privacy Policy 結構

在教學專案裡不必寫 20 頁長文;內容精簡但誠實即可。通常會包含這些章節:

  1. 前言:你是誰、這個 App 是做什麼的。
  2. 你收集哪些資料。
  3. 你如何使用這些資料。
  4. 你會把資料提供給誰。
  5. 在哪裡儲存、保存多久。
  6. 使用者的權利(包含刪除請求)。
  7. 隱私問題聯絡方式。

要理解的是,即使是教學專案也不是「樣板文」。你在安全模組裡已經思考過日誌保留期、刪除政策、備份等——現在需要精準地寫出來。

在 Next.js 中的最簡實作

讓我們在應用裡建立 /legal/privacy 頁面。在 App Router 中這基本上一個檔案就搞定:

// app/legal/privacy/page.tsx
export default function PrivacyPage() {
  return (
    <main className="mx-auto max-w-3xl p-8 prose">
      <h1>Privacy Policy – GiftGenius</h1>
      <p>Last updated: {new Date().toLocaleDateString()}</p>
      {/* 以下是政策的各節內容 */}
    </main>
  );
}

這個範例刻意簡單:目的是固定一個靜態 URL。真實專案中,政策文字幾乎都獨立保存(例如放在 .md 檔),以避免把大量文字灑在 JSX。

例如,可以做一個通用的載入器:

// app/legal/privacy/page.tsx
import policyHtml from "./policy.html"; // 預先編譯好的 HTML

export default function PrivacyPage() {
  return (
    <main
      className="mx-auto max-w-3xl p-8 prose"
      dangerouslySetInnerHTML={{ __html: policyHtml }}
    />
  );
}

此處很適合補一句「不要在不理解風險時照抄」:dangerouslySetInnerHTML 只有在你能控制 HTML 來源時(例如在 CI 以 markdown 自行編譯)才是安全的。

與實際流程的連動

最重要的一點:Policy 不能寫著你在程式碼裡沒有做到的事。如果你聲稱:

  • 不會保存請求文字超過 7 天;
  • 可在使用者要求時完全刪除其個人檔案;
  • 不會用這些資料訓練你自己的模型,

那麼你應該具備:

  • 日誌的保留期設定;
  • 刪除使用者的 endpoint 或管理流程;
  • 沒有把日誌外洩到第三方儲存「拿去做 Data Science」的程式碼。

反過來說:如果你啟用了使用量量測、A/B 測試或依國家/地區的分析,就要在 Policy 中誠實說明。並至少給使用者基本權利:知道保存了什麼,以及能提出刪除請求。

資料與 Privacy Policy 講完了。接著要不只固定資料處理,也要固定「遊戲規則」本身——這就是 Terms 的任務。

4. Terms of Use / Service:使用規則與 AI 免責

如果已有 Policy,為什麼還需要 Terms

Privacy Policy 回答的是「你如何處理資料」。Terms Of Use/Service(下稱 Terms)則是「使用本 App 的條件是什麼」。它是你與使用者之間的法律契約。

其中會描述:

  • 什麼是 GiftGenius,以及它提供哪些功能;
  • 哪些使用者行為可接受、哪些不可;
  • AI 的「魔法邊界」(AI 免責);
  • 你的責任限制;
  • 如何解決爭議與適用法域。

對 AI 應用而言,尤其重要的是兩件事:準確性的免責與責任限制。

AI 的特性:「模型可能會出錯」

我們的 GiftGenius 提供送禮建議。這很可愛而且相對安全,但仍可能踩雷:使用者要求「對堅果過敏者的禮物」,模型給了不恰當的建議,結果對方受害,大家都不好受。

當然,Terms 不是萬靈丹,但它能清楚界定:

  • 結果由 AI 產生,可能不準確、過時或離奇;
  • 使用者有義務自行核實重要資訊,尤其與健康、財務或其他敏感領域相關者;
  • 你不保證建議「完美無瑕」,也不對不當使用結果負責。

具體措辭之後應與法務合作打磨,但對技術開發者來說,理解這個精神最重要。

金流/商務細節

若你的 App 涉及任何付款動作(關於 ACP 與 commerce 的模組之後會更深入,但課程已涵蓋),在 Terms 中需仔細闡述:

  • 款項透過誰處理(Stripe、ACP 或其他系統);
  • 你實際能看到哪些付款資料;
  • 退費與取消的條件;
  • 什麼被視為成功交易。

平台的一般建議是:明確指出卡片資料由支付供應商處理,而非你的伺服器;你只保存最小必要資訊(例如交易 ID)。

在 Next.js 實作 /legal/terms

技術面與 Privacy Policy 很相似。建立頁面:

// app/legal/terms/page.tsx
export default function TermsPage() {
  return (
    <main className="mx-auto max-w-3xl p-8 prose">
      <h1>Terms of Use – GiftGenius</h1>
      <p>Last updated: {new Date().toLocaleDateString()}</p>
      {/* 章節:服務描述、限制、AI 免責、責任 */}
    </main>
  );
}

同樣地,最好把正文放在獨立檔案或 CMS,程式碼中只保留最少的標記。

可以抽出法律頁面的共用外殼:

// app/legal/LegalLayout.tsx
export function LegalLayout(props: { title: string; children: React.ReactNode }) {
  return (
    <main className="mx-auto max-w-3xl p-8 prose">
      <h1>{props.title}</h1>
      <p>Last updated: {new Date().toLocaleDateString()}</p>
      {props.children}
    </main>
  );
}

之後在 Policy 與 Terms 中共用它。這不是為了「漂亮」,而是避免忘記放更新日期,並維持一致風格。

5. Support / Contact:使用者遇到問題要去哪裡

最低要求與「良好做法」

OpenAI 的指引指出,App 必須提供清楚的方式讓使用者能與開發者聯絡以取得支援。可以只是個簡單的 email,但它必須存在、能收信,且至少偶爾有人回覆。

教學專案的極簡做法:

  • 獨立的 /support 頁面,內含簡短說明與 mailto:support@yourdomain.com

更成熟的做法:

  • 回報表單;
  • 指向文件或 Help Center 的連結;
  • 如果你在打造社群,或許還有 Slack/Discord 連結。

在 Next.js 實作 /support 頁面

先從最簡單的版本開始:

// app/support/page.tsx
export default function SupportPage() {
  return (
    <main className="mx-auto max-w-xl p-8 prose">
      <h1>GiftGenius Support</h1>
      <p>
        If you have issues or questions, email us at{" "}
        <a href="mailto:support@giftgenius.app">support@giftgenius.app</a>.
      </p>
    </main>
  );
}

稍進階的版本——加上一個簡單的表單:

// app/support/page.tsx
"use client";

export default function SupportPage() {
  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();
    // 這裡會呼叫 API 傳送信件/工單
  };

  return (
    <main className="mx-auto max-w-xl p-8 prose">
      <h1>GiftGenius Support</h1>
      <form onSubmit={handleSubmit}>
        <input name="email" placeholder="Your email" className="border p-2 w-full" />
        <textarea name="message" placeholder="How can we help?" className="border p-2 w-full mt-2" />
        <button type="submit" className="mt-4 px-4 py-2 border rounded">
          Send
        </button>
      </form>
    </main>
  );
}

即使你在教學專案中不實作這個表單的後端,清楚的 URL 與頁面結構本身就讓你更接近 Store 的要求。

與事故管理的關聯

Support 頁面不只是「當一切掛掉時去哪裡留言」,也是你營運圖景的一部分。在後續模組你會談到事故與 App 的營運生命週期。到時,Support 頁面會成為使用者的「入口」:他們透過它回報 bug、提出問題、發起資料刪除請求。此刻至少要先確保這扇門存在,且不會連到「404 Not Found」。

6. 將法律頁面整合到應用與列表

在專案內集中管理 URL 設定

為了避免把「魔法字串」的 URL 到處散落於程式碼,建議建立簡單的設定:

// lib/appConfig.ts
export const legalLinks = {
  privacy: "https://giftgenius.app/legal/privacy",
  terms: "https://giftgenius.app/legal/terms",
  support: "https://giftgenius.app/support",
} as const;

你也會在下面這些地方使用相同的 URL:

  • ChatGPT App 的設定(中繼資料);
  • 產品的登陸頁;
  • 若實作 email 通知,則在郵件內。

在小工具中,你可以透過 openExternal 讓使用者快速開啟這些頁面。

// 在 GiftGenius 的 React 小工具內
import { legalLinks } from "../lib/appConfig";

function FooterLinks() {
  const handleOpen = (url: string) => {
    window.openai?.openExternal({ url }); // Apps SDK helper
  };

  return (
    <footer className="mt-4 text-xs text-gray-500">
      <button onClick={() => handleOpen(legalLinks.privacy)}>Privacy</button>
      <span> · </span>
      <button onClick={() => handleOpen(legalLinks.terms)}>Terms</button>
    </footer>
  );
}

在實際的小工具程式碼裡,建議使用 Apps SDK 的 useOpenExternal hook;此處為了簡潔,示範了透過 window.openai 的直接呼叫。

這能提升透明度:使用者可在小工具中一鍵打開法律文件,而不是去 Store 另一處慢慢找。

使用者與審核者的流程

用一個小圖看互動流程:

flowchart TD
  A[ChatGPT Store 的列表頁] --> B[使用者閱讀 App 的說明]
  B --> C[透過連結開啟 Privacy / Terms]
  B --> D[安裝 / 開始使用 App]
  D --> E[啟動 GiftGenius 小工具]
  E --> F["需要時點擊 'Support' 或 'Privacy'"]

ChatGPT Store 的審核者也大致遵循同樣的路徑,只是會更「挑剔」。他會檢視:

  • 列表頁上寫了什麼;
  • Policy 與 Terms 承諾了什麼;
  • App 在真實場景中的行為;
  • 行為是否與你所寫相符。

若一切誠實且可預期——通過審核的機率會大幅提升。

7. 屬於你自己 App 的實作練習

別停留在理論上;現在就為你的應用草擬文件。

做法可以這樣:

先在架構層面描述:

  • 你處理哪些資料類別(請求文字、訂單、email、量測);
  • 是否保存文字請求,若是,保存多久;
  • 接了哪些外部服務(託管、資料庫、金流、分析)。

之後:

  1. 擬一份 Privacy Policy 的結構,含「收集什麼」、「用途為何」、「提供給誰」、「保存多久」、「如何刪除資料」。
  2. 擬一份 Terms 的結構:服務描述、使用規則、限制(禁止內容與濫用)、AI 免責、責任限制、連結至 Policy。
  3. 建立 /support 頁面,放上簡短文字與 email。
  4. 在專案內新增 lib/appConfig.ts,集中管理法律頁面的 URL,並在小工具與所有外部連結中使用它們。

即便文字暫時只是草稿、你打算「之後給法務看」,你已經完成一件重要的事:把技術實作與法律描述銜接起來。

8. 準備法律頁面時的常見錯誤

錯誤 №1:複製網路上的隨機隱私權政策,不做任何修改。
有時會想直接拿一份現成的政策,改掉產品名稱就算完成。問題在於,那份文字幾乎不會與你的架構一致。它可能包含你沒有的東西(行動 App、推播、特定分析服務),反之卻沒提到你有的內容(MCP 伺服器、工具日誌、透過 ChatGPT 的工作方式)。審核者會注意到不一致,使用者也會覺得「這文本不是在講你」。

錯誤 №2:在 Policy 承諾了程式碼沒有實作的事。
經典案例是「我們應要求會刪除你的所有資料」,但程式碼裡既沒有刪除的 endpoint,也沒有搜尋特定使用者資料的機制。對日誌保留期與「我們不保存你的訊息文字」亦然——若你其實把 tool‑input 丟進沒有保留期的日誌系統。這種落差對審核與真實使用者都很危險。

錯誤 №3:在 Terms 中忽略 AI 的特性。
如果 Terms 完全沒提到答案由模型生成、可能不準確,使用者就可能期待你的 App 「永遠正確」。對推薦類服務(禮物、旅遊、商品選擇)或許還能接受,但在醫療、金融、法律建議等領域,這個缺口會有很嚴重的後果。請明確、誠實地說清楚限制與責任。

錯誤 №4:Support 頁面沒有真實聯絡方式,或使用死信信箱。
一個指向 /support 的頁面,但只放了 mailto:hello@example.com 且無人查看,形式上存在,實際上無用。使用者得不到回覆、bug 回報消失,App 的信任度下降。平台也期待你會回應投訴與問題。即使團隊很小,至少每隔幾天檢視收件匣並回應。

錯誤 №5:忘了文件的日期與版本。
有時法律頁面完全沒有標示最後更新時間。對審核者而言,這是警訊:文件是否反映產品現況不得而知。簡單的「Last updated: …」區塊就能同時幫助你與使用者,也有助於後續在架構演進時記錄 Policy/Terms 的更新歷史。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION