Felo API PlatformFelo API Platform

研究

做一份業務團隊能直接用的競品拆解

收集競品自己的頁面、圍繞它的報導,以及買家在 X 上的說法,再拼成一份拆解:每條主張都有來源、日期和狀態。

建置時間30 分鐘難度進階更新於2026-10-30
適合誰產品行銷競爭情報業務賦能

複製 prompt

把方括號裡的欄位替換掉,然後貼到 Claude Code、Codex 或任何能存取終端機的 AI。它會安裝 Felo skill、在花額度前詢問,並執行這套工作流程。

為[我們的產品]製作一份針對[競品名稱]的競品拆解。

範圍:[細分市場]、[地區]、[語言]。時間範圍:[過去 90 天 / 過去 12 個月]。它支援的決策:[調價 / 發布定位 / 異議處理]。
起始來源:[競品網域]、[定價頁 URL]、[更新日誌 URL]。

輸出一份 Markdown 拆解,包含:
1. 他們如何定位自己,用他們自己的話。
2. 證據表:主張、來源標題、URL、日期、狀態(Verified / Vendor claim / Third-party / Signal / Inference / Not verified)。
3. 定價:頁面寫了什麼,附連結和核對日期。沒有頁面和日期,絕不把價格寫進正文。
4. 買家在哪些地方反彈,附 X 帳號和日期,並標示為訊號。
5. 我們下一步該做什麼,標示為建議。
6. 完整來源清單。

規則:
- 引用他們的定位,不要改寫成更強的說法。
- 區分廠商主張、第三方報導和你自己的推論,每一列都加標籤。
- 不要編造價格、指標、客戶名稱或基準。資料缺失時寫「暫無資料」。
- 把時間範圍和地區落實為明確值。
- 消耗額度前,先展示預計執行的 API 呼叫並等待我批准。
- 不要發布、傳送、排程,或寫入任何 CRM。
- 將結果寫入 ./competitor-teardown.md,並在對話中總結。

複製的內容也包含安裝步驟和安全規則。

你會得到什麼

一次執行的範例輸出,不是即時生成。

競品拆解範例(節錄)

競品拆解 — [競品],2026-10-30 核對

他們如何定位自己

首頁標題:「為成長中的支援團隊打造的平台。」分類頁:「支援團隊需要的一切。」兩者都是廠商主張,依原文引用。

證據表

主張來源日期狀態
定位為平台而非單點工具https://example.com/competitor/home2026-10-30Verified
每週發布變更https://example.com/competitor/changelog2026-10-28Verified
被獨立評測收錄https://example.com/roundup2026-10-27Third-party
買家提到上手慢下文引用的 X 貼文2026-10-14Signal
企業是他們最大的細分暫無資料—Not verified

定價

定價頁列出分層方案與按量方案。這裡不重複費率;查看即時頁面與日期:https://example.com/competitor/pricing(2026-10-30)。

買家反彈的地方

@example_dev,2026-10-14:「安裝比示範說的更久。」一條有日期的貼文,是投訴,不是普遍性估計。

建議

在比較頁上突出「到第一個結果的時間」。這是我們的推論,不是競品主張。

來源

  • https://example.com/competitor/home
  • https://example.com/competitor/pricing
  • https://example.com/competitor/changelog

實際呼叫

給開發者:同一套工作流程的可複製程式碼,依執行順序排列。

展開實際 API 呼叫
  1. 從有來源的基線開始

    Chat 會回傳答案和它用過的頁面,等於給你一張「競品在哪裡被討論」的地圖。把答案當成線索而不是來源:真正要保留的是連結,它們提供證據表裡的第三方列。下方的 helper 只送出一次 Key,非 2xx 回應會拋錯。

    competitor.ts
    const BASE = "https://openapi.felo.ai";
    const headers = {
      Authorization: `Bearer ${process.env.FELO_API_KEY}`,
      "Content-Type": "application/json",
    };
    
    async function felo<T>(path: string, body?: unknown): Promise<T> {
      const res = await fetch(`${BASE}${path}`, {
        method: body ? "POST" : "GET",
        headers,
        body: body ? JSON.stringify(body) : undefined,
      });
      if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
      return res.json() as Promise<T>;
    }
    
    type ChatData = {
      data: {
        answer: string;
        resources: { link: string; title: string; snippet: string }[];
      };
    };
    
    const competitor = "Example Competitor";
    const segment = "mid-market support teams";
    
    const baseline = await felo<ChatData>("/v2/chat", {
      query: `How does ${competitor} position itself for ${segment}? Include pricing and recent launches.`,
    });
    
    const seedSources = baseline.data.resources.slice(0, 5);

    範例輸出

    {
      "answer": "The competitor positions itself as …",
      "sources": [
        { "link": "https://example.com/competitor", "title": "…", "snippet": "…" }
      ]
    }
  2. 抓取他們自己控制的頁面

    第三方報導告訴你別人怎麼想,競品自己的頁面告訴你他們怎麼宣稱。用 readability 把首頁、定價頁和 changelog 抽成 Markdown,並給每個頁面蓋上抓取日期——沒有日期的定價頁是個陷阱。

    competitor.ts
    type ExtractData = { data: { content: string } };
    
    const ownedPages = [
      { url: "https://example.com/competitor/home", title: "Homepage" },
      { url: "https://example.com/competitor/pricing", title: "Pricing" },
      { url: "https://example.com/competitor/changelog", title: "Changelog" },
    ];
    
    const fetched = await Promise.all(
      ownedPages.map(async (page) => {
        const res = await felo<ExtractData>("/v2/web/extract", {
          url: page.url,
          output_format: "markdown",
          with_readability: true,
          with_cache: true,
        });
        const checkedAt = new Date().toISOString().slice(0, 10);
        return { ...page, checkedAt, content: res.data.content };
      }),
    );

    範例輸出

    {
      "url": "https://example.com/competitor/pricing",
      "checkedAt": "2026-10-30",
      "content": "# Pricing\n\nExtracted page text…"
    }
  3. 看看買家在 X 上怎麼說

    在 X 搜尋人們對競品的異議和繞行方案。保留每個貼文的帳號和日期;一則帶日期的引語只是「有人抱怨過」的證據,不是「有多普遍」的證據,所以拆解把它標為訊號,絕不把幾則貼文變成百分比。

    competitor.ts
    type XData = {
      data: {
        tweets: {
          content: string;
          author: { username: string };
          created_at: string;
          metrics: { retweet_count: number; favorite_count: number };
        }[];
      };
    };
    
    const since = Math.floor((Date.now() - 90 * 24 * 60 * 60 * 1000) / 1000);
    
    const buyerSignal = await felo<XData>("/v2/x/tweet/search", {
      query: `"${competitor}" (pricing OR onboarding OR migration)`,
      limit: 25,
      since_time: since,
    });
    
    const objections = buyerSignal.data.tweets.slice(0, 5);

    範例輸出

    { "data": { "tweets": [
      {
        "content": "setup took longer than the demo suggested",
        "author": { "username": "example_dev" },
        "created_at": "2026-10-14T09:20:00Z",
        "metrics": { "retweet_count": 3, "favorite_count": 24 }
      }
    ] } }
  4. 用證據表組裝拆解

    這是編輯步驟:把抓到的頁面和 X 貼文變成一條條主張,再給每條主張配來源、日期和狀態。狀態欄讓文件保持誠實——頁面原文是 Verified,廠商行銷是 Vendor claim,外部報導是 Third-party,帶日期貼文是 Signal,你的解讀是 Inference,缺證據是 Not verified。

    competitor.ts
    const today = new Date().toISOString().slice(0, 10);
    
    const row = (claim: string, source: string, date: string, status: string) =>
      `| ${claim} | ${source} | ${date} | ${status} |`;
    
    const teardown = [
      `# Competitor teardown — ${competitor}`,
      `Scope: ${segment}. Checked ${today}.`,
      "",
      "| Claim | Source | Date | Status |",
      "| --- | --- | --- | --- |",
      row("Free tier listed on the pricing page", ownedPages[1].url, fetched[1].checkedAt, "Verified"),
      row("Positions as a platform, not a point tool", ownedPages[0].url, fetched[0].checkedAt, "Vendor claim"),
      row("Discussed in independent coverage", seedSources[0]?.link ?? "Not available", today, "Third-party"),
      row("Buyers report onboarding friction", "X post, quoted below", today, "Signal"),
      row("Most revenue comes from enterprise", "Not available", "—", "Not verified"),
      "",
      "## Recommendation",
      "Lead with time-to-first-result on the comparison page. Inference, not a competitor claim.",
    ].join("\n");
    
    console.log(teardown);

    範例輸出

    | Free tier listed on the pricing page | https://example.com/competitor/pricing | 2026-10-30 | Verified |
  5. 存進 LiveDoc,供下次更新

    每個競品建一個 LiveDoc,把抓到的頁面作為 URL 資源加進去,再把拆解本身作為文件資源加進去。重複加入 URL 會自動去重,下一季只需要抓變化的部分,上一季的拆解仍和新內容放在同一個歸檔裡。

    competitor.ts
    type LiveDocData = { data: { short_id: string } };
    
    const teardownDoc = await felo<LiveDocData>("/v2/livedocs", {
      name: `Teardown: ${competitor}`,
      description: `Sources and teardown checked ${today}`,
    });
    
    await felo(`/v2/livedocs/${teardownDoc.data.short_id}/resources/urls`, {
      urls: fetched.map((page) => ({ url: page.url, title: page.title })),
    });
    
    await felo(`/v2/livedocs/${teardownDoc.data.short_id}/resources/doc`, {
      title: `Teardown ${today}`,
      content: teardown,
    });
    
    console.log(teardownDoc.data.short_id); // the next refresh reuses this LiveDoc

    範例輸出

    { "short_id": "PvyKouzJirXjFdst4uKRK3" }

包含什麼

  • 來自 Chat API 的有來源基線,以及答案背後的頁面
  • 競品首頁、定價頁和 changelog 的 Markdown 擷取
  • X 上帶日期的買家評論,標記為訊號而不是證據
  • 把已驗證事實、廠商說法和推論分開的證據表
  • 保存來源的 LiveDoc,下一次更新不用從零開始

不做什麼

  • 只涵蓋公開來源;不做贏單/輸單訪談、CRM 備註或私有看板
  • 價格只做連結和日期,不把費率凍結進沒有檢查日期的表格
  • X 覆蓋不完整,不代表買家的有代表性樣本
  • 它不會替你決定定位;建議會明確標為推論
  • 它不會發佈拆解,也不會寫進 battlecard 工具

常見問題

證據從哪裡來?

Chat API 回傳有來源的基線及其用過的頁面,Web Fetch 把競品自己的頁面轉成 Markdown,X Search 補充帶日期的買家貼文。每一列都保留來源和日期,推論單獨有狀態。

可以同時涵蓋多個競品嗎?

可以。每個競品跑一次同樣的 prompt,並為每家公司保留一個 LiveDoc。做對比頁時只拼接標記為「已驗證」的列,不要把兩次執行的證據混在一起。

可以直接引用競品價格嗎?

工作流程會記錄定價頁上寫了什麼,並附上連結和檢查日期。它不會把費率寫死成文字,因為廠商價格會變,過時的數字比沒有數字更糟。

我們自己的贏單/輸單筆記能用嗎?

它只讀公開來源。把內部筆記作為獨立的文件資源加進 LiveDoc,並標記為內部;這些內容不會出現在面向客戶的材料裡。

應該多久更新一次?

依觸發條件更新,而不是依日曆:價格變化、產品發佈或業務週期開始時。對同一個 LiveDoc 重跑工作流程,讓上一季的拆解留在新拆解旁邊方便對比。

一份拆解要花多少?

每次 chat、擷取和 X 搜尋都會消耗按用量計費的額度;目前費率在價格頁面。prompt 會在花額度之前請求確認。

相關工作流程

改成你的版本

同一套配方,依你實際的交付方式調整。

依觸發條件更新,而不是依日曆

競品改價、發佈重要版本或大型業務週期開始前,重跑同一套工作流程。每份拆解都作為帶日期的文件資源留在同一個 LiveDoc 裡,下一季和上一季並排,而不是覆蓋。

把拆解變成 battlecard

用同一張證據表,依角色各寫一頁——經濟買家、擁護者和技術審查——只使用 `Verified` 列,並保留連結。任何面向客戶的材料都不要放 `Inference`。

把兩個競品並排比較

每個競品各跑一次,使用獨立的 LiveDoc;然後做一張只拼接兩次執行都標記為 `Verified` 的對比頁。沒有狀態欄時,絕不把兩次執行合併成一張證據表。

這套配方背後的參考頁面,以及下一步可以看什麼。